机器学习的目标就是得到一个泛化能力好的模型,即模型不但在已给定的数据(训练数据)上性能表现良好,而且在没有见过的数据(测试数据)上也能达到同样的效果。通常在评估模型的时候,我们看到的只有训练集和测试集,但实际上,我们应将数据集划分为三个集合:训练集、验证集、测试集。
训练集自然是用来训练模型的,当一个模型训练好后,我们可以知道该模型在训练集上的表现,但是不知道在其他数据(全新数据)上是什么样的,于是就可以通过验证集来评估模型性能,然后再对模型做进一步的调节(调节本身就是学习的过程),也就是所谓的调参(超参数),寻找出最合适的模型配置。所以,验证集实际上就起到了一个反馈的作用,来告知我们这个模型调到什么样的程度其性能最优,但是,这里有个问题,如果,单纯的靠验证集的性能来调节模型配置,那么模型同样会在验证集上产生过拟合现象,所以,通常模型参数只调节一次,验证集仍然可以可靠的评估模型,但如果,反复的根据验证集的性能去修改模型,模型在验证集上的性能就会非常好,这并不是我们想要的,因为我们关心的是全新的数据在模型上的表现,于是就有了测试集。测试集不再像验证集那样把自己的数据透露给模型,验证集是为了调参才把自己的信息给模型达到一个反馈的效果,而测试集完全不用,它就是全新的数据,所以,测试集是对模型最终的评估。
通常情况下,我们见到的只有训练集和验证集,常常把验证集称为测试集。
有时候数据集很小,为了评估模型,有以下三种经典的方法:
1.简单的留出验证
留出一定比例的测试数据,在剩下的数据上训练模型,但是由于不能在测试集上调节模型,所以要留一个验证集,如图:
所以,平常我们看到的测试集就是这留出的验证集。
实现代码:
num_validation_samples=10000 np.random.shuffle(data)#打乱数据 validation_data=data[:num_validation_samples]#定义验证集 data=data[num_validation_samples:] training_data=data[:]#定义训练集 '''在训练数据上训练模型,并在验证数据上评估模型''' model=get_model() model.train(training_data) validation_score=model.evaluate(validation_data) #现在可以调节模型、重新训练、评估、然后再调节。。。 model=get_model() model.train(np.concatenate([training_data,validation_data])) test_score=model.evaluate(test_data
该方法的缺点:如果数据很少,测试部分包括的样本就很少,那么评估的结果就会有偏差。
2.K折交叉验证
将数据划分,为大小相同的K个分区。对于每个分区i,在剩余K-1个分区上训练模型,然后在分区i上评估模型。最终分数等于等于K个分数的平均值。对于不同的训练集-测试集划分,如果模型性能变化很大,那么这种方法很有用。如图:
实现代码:
k=4 num_validation_samples=len(data)//k np.random.shuffle(data)#打乱数据 validation_scores=[] for fold in range(k): validation_data=data[num_validation_samples*fold:num_validation_samples*(fold+1)]#选择验证数据分区 training_data=data[:num_validation_samples*fold]+data[num_validation_samples*(fold+1):]#使用剩余数据作为训练数据,+运算符是列表合并 #创建一个全新的模型实例(未训练) model=get_model() model.train(training_data) validation_score=model.evaluate(validation_data) validation_scores.append(validation_score) validation_score=np.average(validation_scores)#最终验证分数,k折验证分数的平均值 #在所有非测试数据上训练最终模型 model=get_model() model.train(data) test_score=model.evaluate(test_data
3.带有打乱数据的重复K折验证
这种方法是多次使用K折验证,在每次将数据划分为K个分区之前都先将数据打乱。最终分数是每次K折验证分数的平均值。这种方法对于数据相对较少,又想尽可能精确的评估模型来说很有效,但是缺点在于,它的计算代价很高,因为一共要训练和评估PK个模型(P是重复次数)。
模型评估注意事项:
1.数据代表性:划分数据集时随机打乱数据。
2.时间箭头:如果想根据过去预测未来,不能随机打乱数据,要确保测试数据的时间晚于训练数据。
3.数据冗余:如果数据中有多次重复的数据点,不能随机打乱数据,要确保训练集和验证集没有交集。