防止过拟合和机器学习通用流程

防止神经网络过拟合的常用方法:

  • 获取更多的训练数据
  • 减小网络容量
  • 添加权重正则化
  • 添加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正则化
尝试不同的超参数(每层单元格数或优化器的学习率)
(可选)反复做特征工程