Keras下深度学习模型性能评估

标签: keras  深度学习  性能评估

        Keras是一个易于使用和强大的Python库,用于深度学习。 在设计和配置深度学习模型时,需要做很多决定。大多数决策都必须通过试验和错误来解决,并通过实际数据进行评估。 因此,拥有一种可靠的方法来评估神经网络和深度学习模型的性能是至关重要的。 在本文中,您将发现一些使用Keras评估模型性能的方法。


数据切分

       大量的数据和模型的复杂性需要很长的训练时间。 因此,它通常使用简单的数据分离到训练和测试数据集或培训和验证数据集。 Keras提供了两种方便的方法来评估你的深度学习算法: 1)使用自动验证数据集; 2)使用手动验证数据集。

  使用自动验证数据集

        Keras可以将一部分训练数据分离到一个验证数据集中,并在每个时期对该验证数据集评估模型的性能。可以通过将fit()函数的validation_split参数设置为训练数据集大小的百分比来实现这一点,这里使用的数据集是一个人脸识别评分TopN的数据集且有对应的样本标签,形式如下所示:

       下面的例子演示了在一个小的二进制分类问题上使用自动验证数据集,代码如下所示:

import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Dropout

X = np.loadtxt('preprocess_final.txt',usecols=(0, 1, 2, 3, 4, 5, 6),delimiter='\t')

Y = np.loadtxt('preprocess_final.txt',usecols=(7),delimiter='\t')

model = Sequential()
model.add(Dense(16, input_dim=7, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(16, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(1, activation='sigmoid'))

model.compile(loss='binary_crossentropy',
              optimizer='rmsprop',
              metrics=['accuracy'])
model.fit(X, Y,
          epochs=100,
          validation_split=0.25,
          batch_size=32)

        运行这个示例,您可以看到每个epoch上的详细输出显示了训练数据集和验证数据集上的损失和准确性。

Epoch 1/100
13830/13830 [==============================] - 1s 44us/step - loss: 0.3361 - acc: 0.8907 - val_loss: 0.1682 - val_acc: 0.9601
Epoch 2/100
13830/13830 [==============================] - 1s 41us/step - loss: 0.2197 - acc: 0.9553 - val_loss: 0.1666 - val_acc: 0.9601
Epoch 3/100
13830/13830 [==============================] - 1s 52us/step - loss: 0.2085 - acc: 0.9553 - val_loss: 0.1656 - val_acc: 0.9601
Epoch 4/100
13830/13830 [==============================] - 1s 62us/step - loss: 0.1956 - acc: 0.9553 - val_loss: 0.1645 - val_acc: 0.9601
Epoch 5/100
13830/13830 [==============================] - 1s 47us/step - loss: 0.1947 - acc: 0.9553 - val_loss: 0.1624 - val_acc: 0.9601

使用手动验证数据集

       Keras还允许您手动指定用于训练期间验证的数据集。 在本例中,我们使用Python scikit- learning机器学习库中的train_test_split()函数将数据分离到训练和测试数据集中。我们将75%用于培训,其余25%用于验证。 验证数据集可以通过validation_data参数指定到在Keras中的fit()函数,它接受输入和输出数据集的元组。

import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Dropout
from sklearn.model_selection import train_test_split

X = np.loadtxt('preprocess_final.txt',usecols=(0, 1, 2, 3, 4, 5, 6),delimiter='\t')

Y = np.loadtxt('preprocess_final.txt',usecols=(7),delimiter='\t')

X_train, X_test, Y_train, Y_test = train_test_split(X,Y,random_state=0)

model = Sequential()
model.add(Dense(16, input_dim=7, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(16, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(1, activation='sigmoid'))

model.compile(loss='binary_crossentropy',
              optimizer='rmsprop',
              metrics=['accuracy'])
model.fit(X_train, Y_train,
          validation_data=(X_test,Y_test),
          epochs=100,
          batch_size=32)

         与前面一样,运行这个示例提供了详细的训练输出,其中包括每个阶段的训练和验证数据集上模型的丢失和准确性。

Train on 13830 samples, validate on 4610 samples
Epoch 1/100
13830/13830 [==============================] - 1s 41us/step - loss: 0.2456 - acc: 0.9539 - val_loss: 0.1725 - val_acc: 0.9592
Epoch 2/100
13830/13830 [==============================] - 1s 48us/step - loss: 0.2097 - acc: 0.9556 - val_loss: 0.1721 - val_acc: 0.9592
Epoch 3/100
13830/13830 [==============================] - 1s 46us/step - loss: 0.2066 - acc: 0.9556 - val_loss: 0.1699 - val_acc: 0.9592
Epoch 4/100
13830/13830 [==============================] - 1s 41us/step - loss: 0.1984 - acc: 0.9556 - val_loss: 0.1688 - val_acc: 0.9592
Epoch 5/100
13830/13830 [==============================] - 1s 41us/step - loss: 0.1947 - acc: 0.9556 - val_loss: 0.1670 - val_acc: 0.9592
Epoch 6/100
13830/13830 [==============================] - 1s 42us/step - loss: 0.1903 - acc: 0.9556 - val_loss: 0.1644 - val_acc: 0.9592

手动k-Fold交叉验证

        机器学习模型评估的黄金标准是k-fold交叉验证。 它提供了一个对未显示数据的模型性能的可靠估计。它将训练数据集分割成k个子集,并对除一个子集外的所有子集轮流进行训练模型,并对保存的验证数据集进行模型性能评估。这个过程会重复进行,直到所有子集都有机会被提交出去的验证集。然后在创建的所有模型中对性能度量进行平均。

       交叉验证通常不用于评估深度学习模型,因为计算费用更大。例如,k-fold交叉验证通常用于5或10个折叠。因此,必须构造和评估5或10个模型,这大大增加了模型的评估时间。然而,当问题足够小或者有足够的计算资源时,k-fold交叉验证可以使你对模型的性能有更小的偏差估计。在下面的示例中,我们使用来自scikit- learning Python机器学习库的方便的分层kfold类将训练数据集分割为10个折叠。折叠是分层的,这意味着该算法试图平衡每一个类中每个类的实例数。

        该示例使用10个数据分片创建并评估10个模型,并收集所有分数。通过将verbose=0传递给fit()并在模型上评估()函数,可以关闭每个epoch的详细输出。性能为每个模型打印并存储,然后在运行结束时打印出模型性能的平均和标准偏差,以提供模型精度的可靠估计。

import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Dropout
from sklearn.model_selection import StratifiedKFold

# fix random seed for reproducibility
seed = 7
np.random.seed(seed)

# load dataset
X = np.loadtxt('preprocess_final.txt',usecols=(0, 1, 2, 3, 4, 5, 6),delimiter='\t')
Y = np.loadtxt('preprocess_final.txt',usecols=(7),delimiter='\t')

# define 10-fold cross validation test harness
kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=seed)
cvscores = []

for train, test in kfold.split(X, Y):
    model = Sequential()
    model.add(Dense(16, input_dim=7, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(16, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(1, activation='sigmoid'))

    model.compile(loss='binary_crossentropy',
              optimizer='rmsprop',
              metrics=['accuracy'])
    model.fit(X[train], Y[train], epochs=10, batch_size=32, verbose=0)
    # evaluate the model
    scores = model.evaluate(X[test], Y[test], verbose=0)
    print("%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))
    cvscores.append(scores[1] * 100)
    
print("%.2f%% (+/- %.2f%%)" % (np.mean(cvscores), np.std(cvscores)))

        运行这个示例将花费不到两分钟,并将生成以下输出:

acc: 95.61%
acc: 95.61%
acc: 95.66%
acc: 95.66%
acc: 95.66%
acc: 95.66%
acc: 95.66%
acc: 95.66%
acc: 95.66%
acc: 95.66%
95.65% (+/- 0.02%)


Keras自定义评估函数

        由于Keras中并没有像scikit-learn那样很多丰富的API用于进行训练评估,故而要求我们自定义评估函数

    1、比较一般的自定义函数:

        需要注意的是,不能像sklearn那样直接定义,因为这里的y_true和y_pred是张量,不是numpy数组。示例如下:

from keras import backend

def rmse(y_true, y_pred):
    return backend.sqrt(backend.mean(backend.square(y_pred - y_true), axis=-1))

        用的时候直接:

model.compile(optimizer='adam', loss='binary_crossentropy', metrics=[rmse])

    2. 比较复杂的如AUC函数:

       AUC的计算需要整体数据,如果直接在batch里算,误差就比较大,不能合理反映整体情况。这里采用回调函数写法,每个epoch计算一次:

from sklearn.metrics import roc_auc_score

class roc_callback(keras.callbacks.Callback):
    def __init__(self,training_data, validation_data):
        
        self.x = training_data[0]
        self.y = training_data[1]
        self.x_val = validation_data[0]
        self.y_val = validation_data[1]
        
    
    def on_train_begin(self, logs={}):
        return
 
    def on_train_end(self, logs={}):
        return
 
    def on_epoch_begin(self, epoch, logs={}):
        return
 
    def on_epoch_end(self, epoch, logs={}):        
        y_pred = self.model.predict(self.x)
        roc = roc_auc_score(self.y, y_pred)      
        
        y_pred_val = self.model.predict(self.x_val)
        roc_val = roc_auc_score(self.y_val, y_pred_val)      
        
        print('\rroc-auc: %s - roc-auc_val: %s' % (str(round(roc,4)),str(round(roc_val,4))),end=100*' '+'\n')
        return
 
    def on_batch_begin(self, batch, logs={}):
        return
 
    def on_batch_end(self, batch, logs={}):
        return   

          调用回调函数示例:

model.fit(X_train, y_train, epochs=10, batch_size=4, 
          callbacks = [roc_callback(training_data=[X_train, y_train], validation_data=[X_test, y_test])] )

 

        整体示例

from tensorflow import keras
from sklearn import datasets
from sklearn import model_selection
from sklearn.metrics import roc_auc_score

def rmse(y_true, y_pred):
    return keras.backend.sqrt(keras.backend.mean(keras.backend.square(y_pred - y_true), axis=-1))

class roc_callback(keras.callbacks.Callback):
    def __init__(self,training_data, validation_data):
        
        self.x = training_data[0]
        self.y = training_data[1]
        self.x_val = validation_data[0]
        self.y_val = validation_data[1]
        
    
    def on_train_begin(self, logs={}):
        return
 
    def on_train_end(self, logs={}):
        return
 
    def on_epoch_begin(self, epoch, logs={}):
        return
 
    def on_epoch_end(self, epoch, logs={}):        
        y_pred = self.model.predict(self.x)
        roc = roc_auc_score(self.y, y_pred)      
        
        y_pred_val = self.model.predict(self.x_val)
        roc_val = roc_auc_score(self.y_val, y_pred_val)      
        
        print('\rroc-auc: %s - roc-auc_val: %s' % (str(round(roc,4)),str(round(roc_val,4))),end=100*' '+'\n')
        return
 
    def on_batch_begin(self, batch, logs={}):
        return
 
    def on_batch_end(self, batch, logs={}):
        return   
    
    
X, y = datasets.make_classification(n_samples=100, n_features=4, n_classes=2, random_state=2018)
X_train, X_test, y_train, y_test = model_selection.train_test_split(X, y, test_size=0.2, random_state=2018)
print("TrainSet", X_train.shape, "TestSet", X_test.shape)

model = keras.models.Sequential()
model.add(keras.layers.Dense(20, input_shape=(4,), activation='relu'))
model.add(keras.layers.Dense(1, activation='sigmoid'))
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=[rmse])

model.fit(X_train, y_train, epochs=10, batch_size=4, 
          callbacks = [roc_callback(training_data=[X_train, y_train], validation_data=[X_test, y_test])] )

        运行结果如下所示:

TrainSet (80, 4) TestSet (20, 4)
Epoch 1/10
roc-auc: 0.1604 - roc-auc_val: 0.2738                                                                                                    
80/80 [==============================] - 0s - loss: 0.8132 - rmse: 0.5298     
Epoch 2/10
roc-auc: 0.4874 - roc-auc_val: 0.619                                                                                                    
80/80 [==============================] - 0s - loss: 0.7432 - rmse: 0.5049     
Epoch 3/10
roc-auc: 0.7715 - roc-auc_val: 0.9643                                                                                                    
80/80 [==============================] - 0s - loss: 0.6821 - rmse: 0.4807     
Epoch 4/10
roc-auc: 0.9602 - roc-auc_val: 1.0                                                                                                    
80/80 [==============================] - 0s - loss: 0.6268 - rmse: 0.4560     
Epoch 5/10
roc-auc: 0.9842 - roc-auc_val: 1.0                                                                                                    
80/80 [==============================] - 0s - loss: 0.5747 - rmse: 0.4301     
Epoch 6/10
roc-auc: 0.9956 - roc-auc_val: 1.0                                                                                                    
80/80 [==============================] - 0s - loss: 0.5230 - rmse: 0.4025     
Epoch 7/10
roc-auc: 0.9975 - roc-auc_val: 1.0                                                                                                    
80/80 [==============================] - 0s - loss: 0.4743 - rmse: 0.3739     
Epoch 8/10
roc-auc: 0.9987 - roc-auc_val: 1.0                                                                                                    
80/80 [==============================] - 0s - loss: 0.4289 - rmse: 0.3454     
Epoch 9/10
roc-auc: 0.9987 - roc-auc_val: 1.0...] - ETA: 0s - loss: 0.4019 - rmse: 0.3301                                                                                                    
80/80 [==============================] - 0s - loss: 0.3830 - rmse: 0.3149     
Epoch 10/10
roc-auc: 0.9987 - roc-auc_val: 1.0                                                                                                    
80/80 [==============================] - 0s - loss: 0.3424 - rmse: 0.2865  


总结:

        在这篇文章中,介绍了一种可靠的方法来评估您的深度学习模型在未可见数据上的性能的重要性。使用Keras库评估Python中深度学习模型性能的三种方法: 1)使用自动验证数据集; 2)使用手动验证数据集; 3)使用手工k-Fold交叉验证。

        此外,对于其他自定义评估函数(各类的f-score、precision和recall等)都可以通过相似方法调用scikit-learn API实现。

原文链接:加载失败,请重新获取