模型出现过拟合,可采取Dropout的方式进行效率解决(仅针对神经网络模型的正则化方法)。该方法主要是在训练模型的过程中,随机抛弃一些神经元,使其不参与正向和反向传播过程。神经网络在训练过程中,权重对于某些特征的依赖关系较强,每次训练都随机抛下一些特征(对于非输入层则是神经元),将会强迫每一个神经元和随机挑选出来的其他神经元共同工作,据此网络模型对于神经元的特定权重不那么敏感,由此提高了模型整体泛化能力。
from sklearn import datasets
import numpy as np
from keras.models import Sequential
from keras.layers import Dropout
from keras.layers import Dense
from tensorflow.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)
可在输入层后加入一层Dropout,或是在隐藏层间加入。
# 构建模型函数
def create_model(init='glorot_uniform'):
# 构建模型
model = Sequential()
'''
# 在输入层后加入一层Dropout层,其速率0.2表示每一个更新周期将会有20%的特征被随即排除
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层,并且对权重约束,是其最大限度不超过3
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))
# 定义optimizer
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()))
此外,此外梯度下降也非常耗费时间,可用学习率衰减来解决。学习率指参数移动到最优值的速度,如果学习率过大,很可能直接越过最优值,如果学习率过小,优化效率过低,使得算法长时间无法收敛。使用学习率衰减的基本原理是:学习率随着训练的进行逐渐衰减。目前有两种学习率衰减方法:线性衰减(根据epoch逐步降低学习率)和指数衰减(在特定epoch使用分数快速减低学习率)
基于时间的学习率线性衰减,使用SGD类中的随机梯度下降优化算法实现,主要是调节decay衰减率参数。
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 tensorflow.keras.optimizers import SGD
# 导入数据
dataset = datasets.load_iris()
x = dataset.data
Y = dataset.target
# 设定随机种子
seed = 7
np.random.seed(seed)
# 创建模型函数
def creat_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=10,verbose=1)
model.fit(x,Y)
学习率指数衰减,通过在固定的epoch周期将学习速率降低50%实现。例如初始学习速率(initial learningrate)为0.1,设定每10个epochs(epoch drop)降低50%(drop rate),则前10个epochs的学习速率为0.1,后10个epochs的学习速率为0.05。 使用LearningRateScheduler回调实现。
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 tensorflow.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 creat_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)
需要注意:
神经网络一般使用20%-50%的Dropout率,且使用较高学习率、配合学习率衰减和巨大的动量值(momenum=0.8)。并且需要限制网络权重的大小(Dense中的kernel_constrin=maxnorm(x))。
该文代码源自魏贞原《深度学习:基于Keras的Python实践》