小批量梯度下降

每次使用训练数据的子集进行梯度下降,算法执行速度会更快,这些子集称为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回归,它将输出转换为各类别可能的概率,最大概率对应的类别判定为该模型的预测类别。