文章代码来源:《deep learning on keras》,非常好的一本书,大家如果英语好,推荐直接阅读该书,如果时间不够,可以看看此系列文章,文章为我自己翻译的内容加上自己的一些思考,水平有限,多有不足,请多指正,翻译版权所有,若有转载,请先联系本人。
个人方向为数值计算,日后会向深度学习和计算问题的融合方面靠近,若有相近专业人士,欢迎联系。
系列文章:
一、搭建属于你的第一个神经网络
二、训练完的网络去哪里找
三、【keras实战】波士顿房价预测
四、keras的function API
五、keras callbacks使用
六、机器学习基础Ⅰ:机器学习的四个标签
七、机器学习基础Ⅱ:评估机器学习模型
八、机器学习基础Ⅲ:数据预处理、特征工程和特征学习
九、机器学习基础Ⅳ:过拟合和欠拟合
十、机器学习基础Ⅴ:机器学习的一般流程十一、计算机视觉中的深度学习:卷积神经网络介绍
十二、计算机视觉中的深度学习:从零开始训练卷积网络
十三、计算机视觉中的深度学习:使用预训练网络
十四、计算机视觉中的神经网络:可视化卷积网络所学到的东西
我们将我们的数据分为训练集、验证集和测试集,我们不通过相同的数据来评估我们用来训练的模型,原因很明显:经过一些很少批次的训练以后,全部的模型都开始过拟合,也就是说,他们在未见过的数据上的表现跟见过的数据比,不光停滞,还有可能下降。
机器学习的目标就是要让我们的模型在它没见过的模型里面也表现得好,过拟合是主要的障碍,然而我们只能控制我们能观测到的,接下来我们将会介绍一些减缓过拟合和最大化泛化(generalization),如何评估机器学习模型。
训练、验证、测试集
评估模型归纳起来说就是将数据分为训练、验证和测试三个部分。你在训练集上训练模型,在验证集上评估模型,当你将模型训练准备好了以后,在测试集上最后测一次。
你或许会问为什么不直接来两个集合:一个训练集,一个测试集?在训练集上训练,测试集上评估,这会简单的多。
其实呢,除了我们的权重称为参数,还有层数和层数大小称为模型的超参数。你需要通过验证集的反馈来调整超参数,在验证集上训练会导致尽管你没有直接在其上训练,但是结果还是很快会过拟合。
这种现象的核心被称为“信息泄露”。每次你根据模型在验证集上面的表现来调超参数的时候,一些验证集中的数据就会泄露到你的模型中,如果你只这么做一次,对于一个参数来做,那么就只会有很少的信息泄露到你的模型中,验证集仍然是用来评估你的模型的可靠的方法。但若你多次重复同一个验证集,就会漏进来很多。
所以呢,如果你只选择一个训练集,一个测试集,就会导致最后我们在测试集虽然表现得可以,但是泛化性不好。
简单的坚持验证集
选一部分数据作为测试集,在剩余的数据上训练,最后在测试集上评估。
验证集选取大致如上图所示。
接下来用一个简单的例子来说明
num_validation_samples = 10000
# Shuffling the data is usually appropriate
np.random.shuffle(data)
# Define the validation set
validation_data = data[:num_validation_samples]
data = [num_validation_samples:]
# Define the training set
training_data = data[:]
# Train a model on the training data
# and evaluate it on the validation data
model = get_model()
model.train(training_data)
validation_score = model.evaluate(validation_data)
# At this point you can tune your model,
# retrain it, evaluate it, tune it again...
# Once you have tuned your hyperparameters,
# is it common to train your final model from scratch
# on all non-test data available.
model = get_model()
model.train(np.concatenate([training_data,
validation_data]))
test_score = model.evaluate(test_data)
np.random.shuffle用来随机打乱数据,以防原来存储数据的顺序对于训练产生影响,接下来两句分别表示从所有的数据中取前面的数量的作为验证集,然后总的数据量变为原来的剩下一部分,再赋给训练集。
然而上述的只是一个最简单的版本,对于稍微比较复杂的还有小样本的情况,我们随机的划分对于结果的影响就比较大,就需要用到k-fold来做。
k-fold验证
首先将你的手头的数据分成k等分,分别对第i份验证,剩余的训练。最后的score使用平均得到,这种方法能够有效的解决你的训练结果很受数据划分的情况。
k-fold方法如下
这里有一个简单的实例:
k = 4
num_validation_samples = len(data) // k
np.random.shuffle(data)
validation_scores = []
for fold in range(k):
# Select the validation data partition
validation_data = data[num_validation_samples * fold: num_validation_samples * (fold + 1)]
# The remainder of the data is used as training data.
# Note that the "+" operator below is list concatenation, not summation
training_data = data[:num_validation_samples * fold] + data[num_validation_samples * (fold + 1):]
# Create a brand new instance of our model (untrained)
model = get_model()
model.train(training_data)
validation_score = model.evaluate(validation_data)
validation_scores.append(validation_score)
# This is our validation score:
# the average of the validation scores of our k folds
validation_score = np.average(validation_scores)
# We train our final model on all non-test data available
model = get_model()
model.train(data)
test_score = model.evaluate(test_data)
首先k为所需要分的份数,又由于我们实际中不可能分的份数刚好都是总的数据量的约数,所以第二行采用//得到的就是结果的整数部分。
之后的划分就很简单了。比较需要注意的是,将训练的评估结果存下来最后k个循环结束以后再作平均。