防止神经网络过拟合的常用方法:
- 获取更多的训练数据
- 减小网络容量
- 添加权重正则化
- 添加dropout
减小网络容量
#原模型
from keras import models
from keras import layers
original_model = models.Sequential()
original_model.add(layers.Dense(16, activation='relu', input_shape=(10000,)))
original_model.add(layers.Dense(16, activation='relu'))
original_model.add(layers.Dense(1, activation='sigmoid'))
original_model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['acc'])
#现模型
smaller_model = models.Sequential()
smaller_model.add(layers.Dense(4, activation='relu', input_shape=(10000,)))
smaller_model.add(layers.Dense(4, activation='relu'))
smaller_model.add(layers.Dense(1, activation='sigmoid'))
smaller_model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['acc'])
#通过训练和画图评估
original_hist = original_model.fit(x_train, y_train,
epochs=20,
batch_size=512,
validation_data=(x_test, y_test))
smaller_model_hist = smaller_model.fit(x_train, y_train,
epochs=20,
batch_size=512,
validation_data=(x_test, y_test))
epochs = range(1, 21)
original_val_loss = original_hist.history['val_loss']
smaller_model_val_loss = smaller_model_hist.history['val_loss']
import matplotlib.pyplot as plt
# b+ is for "blue cross"
plt.plot(epochs, original_val_loss, 'b+', label='Original model')
# "bo" is for "blue dot"
plt.plot(epochs, smaller_model_val_loss, 'bo', label='Smaller model')
plt.xlabel('Epochs')
plt.ylabel('Validation loss')
plt.legend()
plt.show()
添加权重正则化
from keras import regularizers
l2_model = models.Sequential()
l2_model.add(layers.Dense(16, kernel_regularizer=regularizers.l2(0.001),
activation='relu', input_shape=(10000,)))
l2_model.add(layers.Dense(16, kernel_regularizer=regularizers.l2(0.001),
activation='relu'))
l2_model.add(layers.Dense(1, activation='sigmoid'))
l2_model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['acc'])
#训练和评估方法见上
添加dropout
dpt_model = models.Sequential()
dpt_model.add(layers.Dense(16, activation='relu', input_shape=(10000,)))
dpt_model.add(layers.Dropout(0.5))
dpt_model.add(layers.Dense(16, activation='relu'))
dpt_model.add(layers.Dropout(0.5))
dpt_model.add(layers.Dense(1, activation='sigmoid'))
dpt_model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['acc'])
机器学习通用工作流程
定义问题,收集数据集
你的输入数据是什么,你要预测什么
面对的是什么类型的问题
- 选择衡量成功的指标(将指引你选择损失函数)
平衡分类: 精度,接收者操作特征曲线下面积
非平衡分类: 精确率和召回率
排序问题或者多标签分类: 平均精确率均值
确定评估方法(训练集,验证集,测试集)
留出验证集: 数据量很大
K折交叉验证: 留出验证的样本量少
重复K折验证: 可用数据少,同时评估模型又需非常准确
准备数据
数据转化为张量
张量应该缩放到很小的值,比如[-1,1]或[0,1]区间
如果不同特征取值范围不同(异质数据),应该左标准化
mean = train_data.mean(axis=0)
train_data -= mean
std = train_data.std(axis=0)
train_data /= std
test_data -= mean
test_data /= std
可能需要做特征工程,尤其是小数据
开发比基准更好的模型
目的是获得统计功效,即开发一个模型,它能够打败随机的基准
#Our approach reaches an accuracy of ~78%. With a balanced binary classification problem, the accuracy reached by a purely random classifier would be 50%, but in our case it is closer to 19%, so our results seem pretty good, at least when compared to a random baseline:
import copy
test_labels_copy = copy.copy(test_labels)
np.random.shuffle(test_labels_copy)
float(np.sum(np.array(test_labels) == np.array(test_labels_copy))) / len(test_labels)
最后一层的激活
例如,IMDB在最后一层使用了sigmoid函数,回归的例子最后一层没有使用激活函数
损失函数
例如,IMDB使用binary_crossentropy,回归的例子使用mse
pre优化配置
大多数情况下,使用rmsprop及其默认学习率是稳妥的
但分类指标ROC AUC就不能被直接优化
rmsprop
ROC AUC
扩大模型规模:开发过拟合的模型
添加更多的层
让每一层变得更大
训练更多的轮次
模型正则化和调节超参数
添加dropout
尝试不同的框架:增加或者减少层数
添加L1 / L2正则化
尝试不同的超参数(每层单元格数或优化器的学习率)
(可选)反复做特征工程