版权声明:本文为博主原创文章,未经博主允许不得转载。https://blog.csdn.net/weixin_44474718/article/details/86510278
在机器学习中存在两类比较严重的问题(解决方法):过拟合(dropout)和学习时间开销非常大(学习率衰减)
dropout是一种针对神经网络模型的正则化方法。是在训练过程中,随机的忽略部分神经元。它强迫一个神经元单元和随机挑选出来的其他神经单元共同工作,达到较好的效果,减弱了神经节点间的联合适应性,增强了泛化能力。经过验证,隐含节点dropout率等于0.5的时候效果最好。此时dropout随机生成的网络结构最多,dropout也可以用在输入层,作为一种添加噪音的方法。
在keras的每个权重更新周期中,按照给定概率(如20%),随机选择要丢弃的节点,以实现dropout。dropout只能在模型的训练过程中使用,在评估模型时不能使用。
下例在输入层之后添加一个新的dropout层,dropout率设置为20%,这意味着每个更新周期中20%的输入将被随机排除。
SGD(随机梯度下降优化器)
keras.optimizers.SGD(lr=0.01, momentum=0.0, decay=0.0, nesterov=False)
包含扩展功能的支持: - 动量(momentum)优化, - 学习率衰减(每次参数更新后) - Nestrov 动量 (NAG) 优化
参数
lr: float >= 0
. 学习率。
momentum: float >= 0
. 参数,用于加速 SGD 在相关方向上前进,并抑制震荡。
decay: float >= 0
. 每次参数更新后学习率衰减值。
nesterov: boolean
. 是否使用 Nesterov 动量。
Dropout也可用于可见层,如神经网络的输入。在这种情况下,就要把Dropout层作为网络的第一层,并将input_shape参数添加到层中,来制定预期输入。
model.add(Dropout(rate=0.2, input_shape=(4,)))
from sklearn import datasets
import numpy as np
from keras.models import Sequential
from keras.layers import Dropout
from keras.layers import Dense
from keras.optimizers import SGD
from keras.wrappers.scikit_learn import KerasClassifier
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import KFold
# 导入数据
dataset = datasets.load_iris()
x = dataset.data
Y = dataset.target
# 设定随机种子
seed = 7
np.random.seed(seed)
# 构建模型函数
def create_model(init='glorot_uniform'):
# 构建模型
model = Sequential()
model.add(Dropout(rate=0.2, input_shape=(4,)))
model.add(Dense(units=4, activation='relu', kernel_initializer=init))
model.add(Dense(units=6, activation='relu', kernel_initializer=init))
model.add(Dense(units=3, activation='softmax', kernel_initializer=init))
# 定义Dropout
sgd = SGD(lr=0.01, momentum=0.8, decay=0.0, nesterov=False)
# 编译模型
model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
return model
model = KerasClassifier(build_fn=create_model, epochs=200, batch_size=5, verbose=0)
kfold = KFold(n_splits=10, shuffle=True, random_state=seed)
results = cross_val_score(model, x, Y, cv=kfold)
print('Accuracy: %.2f%% (%.2f)' % (results.mean()*100, results.std()))
下例中,将在两个隐藏层之间,以及最后一个隐藏层和输出层之间使用dropout,将dropout率设置为20%,并对权重进行约束,使其最大限度不超过3.
from sklearn import datasets
import numpy as np
from keras.models import Sequential
from keras.layers import Dropout
from keras.layers import Dense
from keras.constraints import maxnorm
from keras.optimizers import SGD
from keras.wrappers.scikit_learn import KerasClassifier
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import KFold
# 导入数据
dataset = datasets.load_iris()
x = dataset.data
Y = dataset.target
# 设定随机种子
seed = 7
np.random.seed(seed)
# 构建模型函数
def create_model(init='glorot_uniform'):
# 构建模型
model = Sequential()
model.add(Dense(units=4, activation='relu', input_dim=4, kernel_initializer=init, kernel_constraint=maxnorm(3)))
model.add(Dropout(rate=0.2))
model.add(Dense(units=6, activation='relu', kernel_initializer=init, kernel_constraint=maxnorm(3)))
model.add(Dropout(rate=0.2))
model.add(Dense(units=3, activation='softmax', kernel_initializer=init))
# 定义Dropout
sgd = SGD(lr=0.01, momentum=0.8, decay=0.0, nesterov=False)
# 编译模型
model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
return model
model = KerasClassifier(build_fn=create_model, epochs=200, batch_size=5, verbose=0)
kfold = KFold(n_splits=10, shuffle=True, random_state=seed)
results = cross_val_score(model, x, Y, cv=kfold)
print('Accuracy: %.2f%% (%.2f)' % (results.mean()*100, results.std()))
dropout率:20%-50%,太低(作用有限),太高(训练不充分)。
较大网络上使用,可能会有更好的表现,因为降低了模型训练过程中的干扰。
在网络的每一层使用效果都很好。
使用较高的学习率,并使用学习率衰减和巨大的动量值,将学习率提高10-100倍,且使用0.9或0.99的高动量值。
限制网络权重的大小。大的学习率可能导致非常大的网络权重。对网络权重的大小施加约束,例如大小为4或5的最大范数正则化。通过指定dense中的kernel_constraint=maxnorm(3)
来限制网络权重。
学习率过大(可能会越过最优值),学习率过小(长时间无法收敛)。
学习率衰减的基本思想是:学习率随着训练的进行逐渐衰减。
两种流行方法:线性衰减(根据epoch逐步降低学习率)和指数衰减(在特定epoch使用分数快速降低学习率)
在keras中,基于时间的线性学习率衰减是通过SGD类中的随机梯度下降优化算法实现的,该类具有一个decay衰减率参数。该参数的线性学习率衰减方程如下:
learning rate = learning rate * 1/(1+decay * epoch)
当decay衰减率为0(默认)的时候,对学习率没有影响;当使用非零学习率衰减的时候,学习率呈线性衰减。如学习率为0.1时,学习率衰减为0的结果如下:
learning rate = 0.1* 1/(1+0.0*1)
learning rate = 0.1
当decay衰减率为0.001时,最初的5个epoch的学习率如下:
epoch learning rate
1 0.1
2 0.0999000999
3 0.0997006985
4 0.09940249103
5 0.09900646517
下例学习率设定为较高的值0.1,epochs为200,decay为0.005,另外,动量值为0.9.
from sklearn import datasets
import numpy as np
from keras.models import Sequential
from keras.layers import Dense
from keras.wrappers.scikit_learn import KerasClassifier
from keras.optimizers import SGD
# 导入数据
dataset = datasets.load_iris()
x = dataset.data
Y = dataset.target
# 设定随机种子
seed = 7
np.random.seed(seed)
# 构建模型函数
def create_model(init='glorot_uniform'):
# 构建模型
model = Sequential()
model.add(Dense(units=4, activation='relu', input_dim=4, kernel_initializer=init))
model.add(Dense(units=6, activation='relu', kernel_initializer=init))
model.add(Dense(units=3, activation='softmax', kernel_initializer=init))
#模型优化
learningRate = 0.1
momentum = 0.9
decay_rate = 0.005
sgd = SGD(lr=learningRate, momentum=momentum, decay=decay_rate, nesterov=False)
# 编译模型
model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
return model
epochs = 200
model = KerasClassifier(build_fn=create_model, epochs=epochs, batch_size=5, verbose=1)
model.fit(x, Y)
通过固定的epoch周期将学习速率降低50%来实现的。例如,初始学习率设定为0.1,每10个epochs降低50%。前10个epochs使用0.1的学习率,接下来的10个epochs使用0.05的学习率,学习率以指数级进行衰减。
学习率指数衰减公式:
lrate = init_lrate * pow(drop, floor(1 + epoch) / epochs_drop)
from sklearn import datasets
import numpy as np
from keras.models import Sequential
from keras.layers import Dense
from keras.wrappers.scikit_learn import KerasClassifier
from keras.optimizers import SGD
from keras.callbacks import LearningRateScheduler
from math import pow, floor
# 导入数据
dataset = datasets.load_iris()
x = dataset.data
Y = dataset.target
# 设定随机种子
seed = 7
np.random.seed(seed)
# 计算学习率
def step_decay(epoch):
init_lrate = 0.1
drop = 0.5
epochs_drop = 10
lrate = init_lrate * pow(drop, floor(1 + epoch) / epochs_drop)
return lrate
# 构建模型函数
def create_model(init='glorot_uniform'):
# 构建模型
model = Sequential()
model.add(Dense(units=4, activation='relu', input_dim=4, kernel_initializer=init))
model.add(Dense(units=6, activation='relu', kernel_initializer=init))
model.add(Dense(units=3, activation='softmax', kernel_initializer=init))
#模型优化
learningRate = 0.1
momentum = 0.9
decay_rate = 0.0
sgd = SGD(lr=learningRate, momentum=momentum, decay=decay_rate, nesterov=False)
# 编译模型
model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
return model
lrate = LearningRateScheduler(step_decay)
epochs = 200
model = KerasClassifier(build_fn=create_model, epochs=epochs, batch_size=5, verbose=1, callbacks=[lrate])
model.fit(x, Y)