在深度学习中,批量归一化(batch normalization)以及对损失函数加一些正则项这两类方法,通常能够提高模型的性能。这两类方法基本上都属于权重约束,用于减小深度学习神经网络模型对训练数据的过拟合,并改善模型对新数据的性能。
目前,存在多种类型的权重约束方法,例如最大化或单位向量归一化,有些方法也必须须要配置超参数。
在本教程中,使用Keras API,用于向深度学习神经网络模型添加权重约束以减小过拟合。
完成本教程后,您将了解:python
下面,让咱们开始吧。算法
本教程分为三个部分:网络
Keras API支持权重约束,且约束能够按每层指定。
使用约束一般涉及在图层上为输入权重设置kernel_constraint
参数,误差权重设置为bias_constraint
。一般,权重约束方法不涉及误差权重。
一组不一样的向量规范在keras.constraints
模块能够用做约束:dom
例如,能够导入和实例化约束:机器学习
# import norm from keras.constraints import max_norm # instantiate norm norm = max_norm(3.0)
权重规范可用于Keras的大多数层,下面介绍一些常见的例子:函数
下面的示例是在全链接层上设置最大范数权重约束:性能
# example of max norm on a dense layer from keras.layers import Dense from keras.constraints import max_norm ... model.add(Dense(32, kernel_constraint=max_norm(3), bias_constraint==max_norm(3))) ...
下面的示例是在卷积层上设置最大范数权重约束:学习
# example of max norm on a cnn layer from keras.layers import Conv2D from keras.constraints import max_norm ... model.add(Conv2D(32, (3,3), kernel_constraint=max_norm(3), bias_constraint==max_norm(3))) ...
与其余图层类型不一样,递归神经网络容许咱们对输入权重和误差以及循环输入权重设置权重约束。经过图层的recurrent_constraint
参数设置递归权重的约束。
下面的示例是在LSTM图层上设置最大范数权重约束:测试
# example of max norm on an lstm layer from keras.layers import LSTM from keras.constraints import max_norm ... model.add(LSTM(32, kernel_constraint=max_norm(3), recurrent_constraint=max_norm(3), bias_constraint==max_norm(3))) ...
基于以上的基本知识,下面进行实例实践。优化
在本节中,将演示如何使用权重约束来减小MLP对简单二元分类问题的过拟合问题。
此示例只是提供了一个模板,读者能够触类旁通,将权重约束应用于本身的神经网络以进行分类和回归问题。
使用标准二进制分类问题来定义两个半圆观察,每一个类一个半圆。其中,每一个观测值都有两个输入变量,它们具备相同的比例,输出值分别为0或1,该数据集也被称为“ 月亮”数据集,这是因为绘制时,每一个类中出现组成的形状相似于月亮。
可使用make_moons()
函数生成观察结果,设置参数为添加噪声、随机关闭,以便每次运行代码时生成相同的样本。
# generate 2d classification dataset X, y = make_moons(n_samples=100, noise=0.2, random_state=1)
能够在图表上绘制两个变量x和y坐标,并将数据点所属的类别的颜色做为观察的颜色。
下面列出生成数据集并绘制数据集的完整示例:
# generate two moons dataset from sklearn.datasets import make_moons from matplotlib import pyplot from pandas import DataFrame # generate 2d classification dataset X, y = make_moons(n_samples=100, noise=0.2, random_state=1) # scatter plot, dots colored by class value df = DataFrame(dict(x=X[:,0], y=X[:,1], label=y)) colors = {0:'red', 1:'blue'} fig, ax = pyplot.subplots() grouped = df.groupby('label') for key, group in grouped: group.plot(ax=ax, kind='scatter', x='x', y='y', label=key, color=colors[key]) pyplot.show()
运行该示例会建立一个散点图,能够从图中看到,对应类别显示的图像相似于半圆形或月亮形状。
上图的数据集代表它是一个很好的测试问题,由于不能用直线划分,须要非线性方法,好比神经网络来解决。
只生成了100个样本,这对于神经网络而言较小,也提供了过拟合训练数据集的几率,而且在测试数据集上具备更高的偏差。所以,也是应用正则化的一个好例子。此外,样本具备噪声,使模型有机会学习不一致的样本的各个方面。
在机器学习力,MLP模型能够解决这类二进制分类问题。
MLP模型只具备一个隐藏层,但具备比解决该问题所需的节点更多的节点,从而提供过拟合的可能。
在定义模型以前,须要将数据集拆分为训练集和测试集,按照3:7的比例将数据集划分为训练集和测试集。
# generate 2d classification dataset X, y = make_moons(n_samples=100, noise=0.2, random_state=1) # split into train and test n_train = 30 trainX, testX = X[:n_train, :], X[n_train:, :] trainy, testy = y[:n_train], y[n_train:]
接下来,定义模型。隐藏层的节点数设置为500、激活函数为RELU,但在输出层中使用Sigmoid激活函数以预测输出类别为0或1。
该模型使用二元交叉熵损失函数进行优化,这类激活函数适用于二元分类问题和Adam版本梯度降低方法。
# define model model = Sequential() model.add(Dense(500, input_dim=2, activation='relu')) model.add(Dense(1, activation='sigmoid')) model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
而后,设置迭代次数为4,000次,默认批量训练样本数量为32。
# fit model history = model.fit(trainX, trainy, validation_data=(testX, testy), epochs=4000, verbose=0)
这里将测试数据集做为验证数据集验证算法的性能:
# evaluate the model _, train_acc = model.evaluate(trainX, trainy, verbose=0) _, test_acc = model.evaluate(testX, testy, verbose=0) print('Train: %.3f, Test: %.3f' % (train_acc, test_acc))
最后,绘制出模型每一个时期在训练和测试集上性能。若是模型确实对训练数据集过拟合了,对应绘制的曲线将会看到,模型在训练集上的准确度继续增长,而测试集上的性能是先上升,以后降低。
# plot history pyplot.plot(history.history['acc'], label='train') pyplot.plot(history.history['val_acc'], label='test') pyplot.legend() pyplot.show()
将以上过程组合在一块儿,列出完整示例:
# mlp overfit on the moons dataset from sklearn.datasets import make_moons from keras.layers import Dense from keras.models import Sequential from matplotlib import pyplot # generate 2d classification dataset X, y = make_moons(n_samples=100, noise=0.2, random_state=1) # split into train and test n_train = 30 trainX, testX = X[:n_train, :], X[n_train:, :] trainy, testy = y[:n_train], y[n_train:] # define model model = Sequential() model.add(Dense(500, input_dim=2, activation='relu')) model.add(Dense(1, activation='sigmoid')) model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) # fit model history = model.fit(trainX, trainy, validation_data=(testX, testy), epochs=4000, verbose=0) # evaluate the model _, train_acc = model.evaluate(trainX, trainy, verbose=0) _, test_acc = model.evaluate(testX, testy, verbose=0) print('Train: %.3f, Test: %.3f' % (train_acc, test_acc)) # plot history pyplot.plot(history.history['acc'], label='train') pyplot.plot(history.history['val_acc'], label='test') pyplot.legend() pyplot.show()
运行该示例,给出模型在训练数据集和测试数据集上的性能。
能够看到模型在训练数据集上的性能优于测试数据集,这是发生过拟合的标志。鉴于神经网络和训练算法的随机性,每次仿真的具体结果可能会有所不一样。由于模型是过拟合的,因此一般不会指望在相同数据集上可以重复运行获得相同的精度。
Train: 1.000, Test: 0.914
建立一个图,显示训练和测试集上模型精度的线图。从图中能够看到模型过拟合时的预期形状,其中测试精度达到一个临界点后再次开始减少。
为了和上面作对比,如今对MLP使用权重约束。目前,有一些不一样的权重约束方法可供选择。本文选用一个简单且好用的约束——简单地标准化权重,使得其范数等于1.0,此约束具备强制全部传入权重变小的效果。
在Keras中能够经过使用unit_norm
来实现,而且将此约束添加到第一个隐藏层,以下所示:
model.add(Dense(500, input_dim=2, activation='relu', kernel_constraint=unit_norm()))
此外,也能够经过使用min_max_norm
并将min
和maximum
设置为1.0 来实现相同的结果,例如:
model.add(Dense(500, input_dim=2, activation='relu', kernel_constraint=min_max_norm(min_value=1.0, max_value=1.0)))
可是没法经过最大范数约束得到相同的结果,由于它容许规范等于或低于指定的限制; 例如:
model.add(Dense(500, input_dim=2, activation='relu', kernel_constraint=max_norm(1.0)))
下面列出具备单位规范约束的完整代码:
# mlp overfit on the moons dataset with a unit norm constraint from sklearn.datasets import make_moons from keras.layers import Dense from keras.models import Sequential from keras.constraints import unit_norm from matplotlib import pyplot # generate 2d classification dataset X, y = make_moons(n_samples=100, noise=0.2, random_state=1) # split into train and test n_train = 30 trainX, testX = X[:n_train, :], X[n_train:, :] trainy, testy = y[:n_train], y[n_train:] # define model model = Sequential() model.add(Dense(500, input_dim=2, activation='relu', kernel_constraint=unit_norm())) model.add(Dense(1, activation='sigmoid')) model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) # fit model history = model.fit(trainX, trainy, validation_data=(testX, testy), epochs=4000, verbose=0) # evaluate the model _, train_acc = model.evaluate(trainX, trainy, verbose=0) _, test_acc = model.evaluate(testX, testy, verbose=0) print('Train: %.3f, Test: %.3f' % (train_acc, test_acc)) # plot history pyplot.plot(history.history['acc'], label='train') pyplot.plot(history.history['val_acc'], label='test') pyplot.legend() pyplot.show()
运行该示例,给出模型在训练数据集和测试数据集上的性能。
从下图能够看到,对权重进行严格约束确实提升了模型在验证集上的性能,而且不会影响训练集的性能。
Train: 1.000, Test: 0.943
从训练和测试精度曲线图来看,模型已经在训练数据集上再也不过拟合了,且模型在训练和测试数据集的精度保持在一个稳定的水平。
本节列出了一些读者可能但愿探索扩展的教程:
原文连接本文为云栖社区原创内容,未经容许不得转载。