机器&深度学习中的模型评估:评估方法和评估指标

  机器学习领域,无论是在工业界还是在学术界都存在着对模型的选择。如何选择一个好的模型,这需要一套标准来评估模型,从而让我们能选择。这里主要介绍模型的评估方法和评估指标,这将非常有用。

(一)评估方法[1]

(1)留出法(hold-out)

  将数据集分成3个互斥的集合:训练集、验证集、测试集。

(2)交叉验证法(cross validation)

  先将数据集划分成k个大小相似的互斥子集。然后,每次用k-1个子集的并集作为训练集,剩下那个子集作为测试集;这样就可以获得k组训练和测试集,从而可以进行k次训练和测试,最终返回的是这k个测试结果的均值。
  关于交叉验证(scikit-learn)

  a.按交叉验证的方式进行数据划分
from sklearn.model_selection import  KFold, StratifiedKFold, train_test_split
train,test = KFold(n_split=4, random_state=0, shuffle=False).split(X,y) # 适合于回归任务
train,test = StratifiedKFold(n_split=4, random_state=0, shuffle=False).split(X,y) # 适合于分类任务,因为它是分层采样,以确保训练集和测试各类别的比例与原始数据一致
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=0)
  b.按交叉验证的方式进行模型的训练、评估、调参(Keras based)
# 交叉验证比较耗时间相比于留出法要多耗费k倍时间,如果数据量大模型复杂则不建议使用;此时留出法更好
from keras.wrappers.scikit_learn import KerasClassifier, KerasRegressor
from keras.optimizers import Adadelta
from sklearn.model_selection import cross_validate
from keras.callbacks import TensorBoard
from keras.layers import Input, Dense, LSTM
from keras.models import Model


def build_model(input_size, categories, optimizer, lstm1_hs, lstm2_hs, drop_prob):
    """
    利用俩个堆叠的lstm层创建一个文本分类模型
    
    """
    X_input = Input(shape=input_size, name="X_input", dtype="float32") # (None,300,128) 
    X = LSTM(units=lstm1_hs, dropout=drop_prob, return_sequences=True, name="LSTM1")(X_input) # (None,300,64)
    X = LSTM(units=lstm2_hs, dropout=drop_prob, return_sequences=False, name="LSTM2")(X) # (None,300,32)
    # 3.transformer
    y_predict = Dense(categories, activation="softmax", name="model_output")(X) #(None,4)
    
    model = Model(inputs=X_input, outputs=y_predict, name='TextModel')
    model.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=["acc"])
    model.summary()
    print("Model Built")
    return model

model = build_model((300,128), 4, Adadelta(), 64, 32, 0.1)
# 通过keras提供的api KerasClassifier来包装我们keras模型,把它变成sklearn模型
sk_modle = KerasClassifier(build_fn=model, batch_size=64,
        epochs=80,
        verbose=2, # mode of log
        validation_split=0,
        validation_data=None,
        callbacks=[TensorBoard(log_dir='')])

# 交叉验证:训练和评估同时进行.执行流程是先按交叉验证法分割数据然后sk_modle自动调用fit()进行训练
result = cross_validate(sk_modle, X, y,scoring=["accuracy_macro"], cv=10, n_jobs=None, verbose=2, return_train_score=True)
print(result["train_accuracy_macro"], result["test_accuracy_macro"]) # cv个acc

# 调超参数:网格搜索法
# define the grid search parameters
batch_size = [10, 20, 40, 60, 80, 100]
epochs = [10, 50, 100]
param_grid = dict(batch_size=batch_size, nb_epoch=epochs)
grid = GridSearchCV(estimator=sk_model, param_grid=param_grid, n_jobs=-1)
grid_result = grid.fit(X, Y)
# summarize results
print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_))
for params, mean_score, scores in grid_result.grid_scores_:
    print("%f (%f) with: %r" % (scores.mean(), scores.std(), params))
# 保存及加载
# joblib.dump(sk_modle,"model.m")
# model = joblib.load("model.m")
# proba=model.predict_proba(**)
(3)自助法

  它的基本思想是这样的,对于含有m个样本的数据集D,我们对它进行有放回的采样m次,最终得到一个含有m个样本的数据集D’,这个数据集D’会有重复的数据,我们把它用作训练数据。按照概率论的思想,在m个样本中,有部分样本从来没有采到,将这些样本即D-D’当做测试集。

(二)评估指标

  针对不同的任务,需要选择不同的评估指标。

(1)分类任务
  a. accuracy:1.一般说准确率是指整体准确率亦称加权准确率(Weight Accuracy)或全局准确率(Overall Accuracy)。2.在类别样本失衡的情况下,使用整体准确率评估似乎不太恰当,所以也有人提出使用非加权准确率(Unweight Accuracy)或叫类准确率(Class Accuracy)。它们的计算方法如下:

参考自:Emotion Recognition From Speech With Recurrent Neural Networks第9页

机器&深度学习中的模型评估:评估方法和评估指标

  b.精度、查准率(precision):在预测为某个类的样本中,被正确预测的样本占比,体现了分类器的分类性能。
  c.召回率、查全率(recall):在数据集中某一个类簇被正确识别为该类的占比,体现了类的查全程度。
  d.f1分值(f1-score):precision和recall的调和平均,它们的综合指标。
  e.ROC曲线:针对二分类。
  f.混淆矩阵:可以查看分类器的误分情况。
(2)回归任务
  a.均方误差
  b.R2
(3)聚类任务
  a.adjust rand index
  b.齐次性
  c.完整性
  d.V-measure
  e.轮廓系数

提醒:以上评估指标均可通过sklearn包实现,具体参考sklearn metrics
参考:
[1]周志华.机器学习[M].北京:清华大学出版社,2015:24-27.