小批量梯度下降
每次使用训练数据的子集进行梯度下降,算法执行速度会更快,这些子集称为Mini-batch(小批量)。当选择的批量大小为1时,每次对一个训练样本执行梯度下降,称为随机梯度下降。当大小为所有训练样本的个数时,则为批量梯度下降,每次对所有训练样本执行梯度下降。
指数加权平均
指数加权平均实质上是一种近似求平均的方法。它可以减少数据的短期波动,并显示数据的趋势。主要函数如下:
$$ v_{t} = \beta v_{t-1}+(1-\beta)\theta_{t} $$
动量梯度下降
动量梯度下降法除了计算梯度外,还要计算梯度的指数加权平均数,并使用该数字代替原来的梯度进行参数更新。这种方法可以减少梯度下降时的参数波动,加快迭代速度。
RMSprop
在指数加权平均的梯度计算公式中,RMSprop将微分项dW和db进行平方,然后使用平方根进行参数更新。同样也可以加快迭代速度。
Adam优化算法
Adam(Adaptive Moment Estimation)优化算法是动量梯度下降和RMSprop的结合。
下面介绍一个完整的小批量梯度下降法代码的核心部分。
def model(X, Y, layers_dims, optimizer, learning_rate=0.0007, mini_batch_size=64, beta=0.9,
beta1=0.9, beta2=0.999, epsilon=1e-8, num_epochs=10000, print_cost=True):
L = len(layers_dims)
t = 0
seed = 10
# 初始化参数
parameters = initialize_parameters(layers_dims)
# 初始化优化器所需参数
if optimizer == "gd": # 梯度下降法不需要其他参数
pass
elif optimizer == "momentum": # 动量梯度下降法
v = initialize_velocity(parameters)
elif optimizer == "adam": # Adam优化
v, s = initialize_adam(parameters)
# 迭代
for i in range(num_epochs):
# 打乱训练集顺序,分配minibatch
seed = seed + 1
minibatches = random_mini_batches(X, Y, mini_batch_size, seed)
# 迭代各个minibatch,进行梯度下降
for minibatch in minibatches:
(minibatch_X, minibatch_Y) = minibatch
# 前向传播
a3, caches = forward_propagation(minibatch_X, parameters)
# 计算成本函数
cost = compute_cost(a3, minibatch_Y)
# 反向传播
grads = backward_propagation(minibatch_X, minibatch_Y, caches)
# 更新参数
if optimizer == "gd": # 梯度下降法
parameters = update_parameters_with_gd(parameters, grads, learning_rate)
elif optimizer == "momentum": # 动量梯度下降法
parameters, v = update_parameters_with_momentum(parameters, grads, v, beta, learning_rate)
elif optimizer == "adam": # Adam优化
t = t + 1
parameters, v, s = update_parameters_with_adam(parameters, grads, v, s,
t, learning_rate, beta1, beta2, epsilon)
return parameters
本函数的TenorFlow实现如下:
def model(X_train, Y_train, X_test, Y_test, learning_rate=0.0001,
num_epochs=1500, minibatch_size=32, print_cost=True):
ops.reset_default_graph()
tf.set_random_seed(1)
seed = 3
(n_x, m) = X_train.shape
n_y = Y_train.shape[0]
# 定义TensorFlow占位符
X, Y = create_placeholders(n_x, n_y)
# 初始化参数
parameters = initialize_parameters()
# 前向传播
Z3 = forward_propagation(X, parameters)
# 计算成本函数
cost = compute_cost(Z3, Y)
# 反向传播已定义在优化器中,使用Adam优化器
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)
# 初始化TensorFlow变量
init = tf.global_variables_initializer()
# 开启Session
with tf.Session() as sess:
sess.run(init)
# 迭代训练
for epoch in range(num_epochs):
epoch_cost = 0.
num_minibatches = int(m / minibatch_size) # minibatch个数
seed = seed + 1
# 打乱训练集顺序,分配minibatch
minibatches = random_mini_batches(X_train, Y_train, minibatch_size, seed)
# 迭代各个minibatch
for minibatch in minibatches:
(minibatch_X, minibatch_Y) = minibatch
# 执行梯度下降
_, minibatch_cost = sess.run([optimizer, cost], feed_dict={X: minibatch_X, Y: minibatch_Y})
epoch_cost += minibatch_cost / num_minibatches
# 保存参数
parameters = sess.run(parameters)
# 计算预测准确率
correct_prediction = tf.equal(tf.argmax(Z3), tf.argmax(Y))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
print("Train Accuracy:", accuracy.eval({X: X_train, Y: Y_train}))
print("Test Accuracy:", accuracy.eval({X: X_test, Y: Y_test}))
return parameters
超参数调试
在超参数选择的时候,某些参数需要按照一定比例在不同的小范围内均匀随机取值,如在$ 0.001,\ldots,1 $范围内,需要分别在 $0.001\sim0.001$ 、$0.001\sim0.01$ 、 $0.01\sim0.1$ 、 $0.1\sim1$ 子范围中进行均匀随机取值。
激活值归一化
在深层次的神经网络中,我们可以归一化隐藏层的输出,从而加速训练过程。常见的方式是将每层激活前的z函数进行归一化。归一化后,所有z都变为均值为0、方差为1的分布,有时候我们不需要让总是维持这样的分布,所以需要再添加步骤:
$\widetilde z^{(i)} = \gamma z^{(i)}_{\rm norm}+\beta$
其中$\gamma$和$\beta$都是在梯度下降中可以更新的参数。这钟方法称为Batch Norm。它削弱了前层参数与后层参数之间的联系,使得神经网络的每层有一定的独立性,有助于整个网络的学习。
Softmax回归
多分类问题常使用Softmax回归,它将输出转换为各类别可能的概率,最大概率对应的类别判定为该模型的预测类别。