参考书目:陈允杰.TensorFlow与Keras——Python深度学习应用实战.北京:中国水利水电出版社,2021

本系列基本不讲数学原理,只从代码角度去让读者们利用最简洁的Python代码实现深度学习方法。


神经网络模型在具体训练过程中有很多技巧,针对不同问题,例如过拟合,欠拟合,梯度爆炸,运算过慢等等,都有各自处理的方法。下面一一介绍。


过拟合和欠拟合

过拟合处理手段有三种,第一种是加惩罚项范数,又被成为权重衰减,L1和L2范数两者,例如搭建卷积层的时候:

model.add(Conv2D(32, kernel_size=(3, 3), padding="same",
                 input_shape=X_train.shape[1:], activation="relu",
                 kernel_regularizer=regularizers.l2(0.02),
                 bias_regularizer=regularizers.l2(0.02)))

kernel_regularizer=regularizers.l2(0.02)表示系数的惩罚。0.02表示惩罚力度,其他层也是一样。

第二种是增加dropout层,也叫丢包层,随机将神经网络里面的一部分神经元进行‘休眠’,即输出为0:

model.add(Dropout(0.25))

0.25表示丢包百分比。

第三种是早停机制,让神经网络训练周期变少就可以一定程度降低过拟合。后面再介绍Keras里面的早停机制如何便捷实现。

欠拟合就和过拟合反过来操作,不加权重衰减,减少丢包层,增加训练轮数等方法...


选择优化器

优化器也是有参数的,种类不一样也会导致训练时间和训练结果不一样。下面介绍怎么定义优化器。

# 编译模型
opt_sgd = optimizers.SGD(lr=0.05,decay=1e-6, momentum=.09)
opt_adam = optimizers.Adam(lr=0.001,decay=1e-6)
opt_rms = optimizers.RMSprop(lr=0.001,decay=1e-6)
model.compile(loss="categorical_crossentropy", optimizer=opt_sgd,metrics=["accuracy"])

在编译模型的时候去生成一个优化器的类,指定参数,然后放入。一般来说会选择Adma,综合来看Adma优化器最佳。


批量标准化

批量标准化的好处有:

1.加速神经网络收敛

2.可以使用更大的学习率,初始化权重也不那么重要

3.缓解梯度消失或者爆炸的问题。

标准化层在全连接(卷积层,循环层)层后,激活函数前,具体应该这样定义模型:

#  定义模型
#MLP层
model = Sequential()
model.add(Dense(11, input_dim=X_train.shape[1], use_bias=False))
model.add(BatchNormalization())
model.add(Activation("relu"))
model.add(Dense(11, use_bias=False))
model.add(BatchNormalization())
model.add(Activation("relu"))
model.add(Dense(1, activation="sigmoid"))
model.summary()   #显示模型摘要信息

#或者卷积层
model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3), padding="same",
                 input_shape=X_train.shape[1:], use_bias=False))
model.add(BatchNormalization())
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(64, kernel_size=(3, 3), padding="same",
                 use_bias=False))
model.add(BatchNormalization())
model.add(Activation("relu"))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(512, activation="relu"))
model.add(Dropout(0.5))
model.add(Dense(10, activation="softmax"))
model.summary()   # 显示模型摘要信息

正确时间停止模型

在Keras里面主要是利用EarlyStopping实现,训练时候加入就行

#  训练模型
from keras.callbacks import EarlyStopping
# 建立 EarlyStopping 物件
es = EarlyStopping(monitor="val_loss", mode="min",
                   verbose=1,patience=5)
history = model.fit(X_train, Y_train, validation_split=0.2, 
          epochs=30, batch_size=10, 
          verbose=0, callbacks=[es])

monitor表示监控指标,mode表示评估有改进的标准,最大值或最小值。verbose=1表示可以显示训练停在哪个周期。patience=5表示可以达到标准后延迟5个周期停止。

如果使用精度作为监控指标的话,那么mode应该改为最大值:

from keras.callbacks import EarlyStopping
# 建立 EarlyStopping 物件
es = EarlyStopping(monitor="val_accuracy", mode="max",
                   verbose=1, patience=5)
history = model.fit(X_train, Y_train, validation_split=0.2, 
          epochs=50, batch_size=10, 
          verbose=0, callbacks=[es])

自动储存最优权重

# 训练模型
from keras.callbacks import ModelCheckpoint
# 建立 ModelCheckpoint 物件
mc = ModelCheckpoint("best_model.h5", monitor="val_accuracy", 
                     mode="max", verbose=1,
                     save_best_only=True)
history = model.fit(X_train, Y_train, validation_split=0.2, 
          epochs=15, batch_size=10, 
          verbose=0, callbacks=[mc])

同时使用早停和自动储存

# 训练模型
from keras.callbacks import EarlyStopping
# 建立 EarlyStopping 物件
es = EarlyStopping(monitor="val_loss", mode="min",verbose=1)

from keras.callbacks import ModelCheckpoint
# 建立 ModelCheckpoint 物件
filename = "weights-{epoch:02d}-{val_accuracy:.2f}.h5"
mc = ModelCheckpoint(filename, monitor="val_acc", mode="max", verbose=1,
                     save_best_only=True)
history = model.fit(X_train, Y_train, validation_split=0.2, epochs=20, batch_size=10, 
          verbose=0, callbacks=[es, mc])