因为此部分在之前的博文中提及,所以不再详细赘述其中原理,代码只展示核心部分。

激活函数在神经网络中具有重要的地位,常见的激活函数有sigmoid、tanh、ReLU(修正线性单元)和Leaky ReLU等。前两种是饱和激活函数、后两种则是非饱和激活函数,它可以解决“梯度消失”的问题并加快收敛速度。

以一个隐藏层为例,神经网络的梯度下降法公式及其代码向量化如下:

使用逻辑回归构建分类器,可以看出其表现不佳,未对两种数据很好地分类。

浅层神经网络

建立只有一个隐藏层的神经网络模型。

def nn_model(X, Y, n_h, num_iterations=10000, print_cost=False):
    np.random.seed(3)
    # 给出输入层大小,隐藏层大小,输出层大小
    n_x, n_h, n_y = layer_sizes(X, Y)
    # 随机初始化参数
    parameters = initialize_parameters(n_x, n_h, n_y)
    # 分离各个W和b参数
    W1 = parameters['W1']
    b1 = parameters['b1']
    W2 = parameters['W2']
    b2 = parameters['b2']
    # 迭代进行梯度下降
    for i in range(0, num_iterations):
        # 前向传播,输出最终结果和中间计算数据
        A2, cache = forward_propagation(X, parameters)
        # 计算成本
        cost = compute_cost(A2, Y, parameters)
        # 反向传播,输出梯度
        grads = backward_propagation(parameters, cache, X, Y)
        # 更新梯度,输出各层的W和b参数,待下一次循环使用
        parameters = update_parameters(parameters, grads)
        # 打印成本
        if print_cost and i % 1000 == 0:
            print("Cost after iteration %i: %f" % (i, cost))
    return parameters

从下图的输出可以看出,神经网络的准确度要远高于逻辑回归,它能够学习高度非线性的决策边界。

深层神经网络

深层神经网络用来拟合复杂的函数模型,多层神经网络模型代码如下:

def L_layer_model(X, Y, layers_dims, learning_rate=0.0075, num_iterations=3000, print_cost=False):
    np.random.seed(1)
    costs = []
    # 参数初始化,初始化各层的W和b
    parameters = initialize_parameters_deep(layers_dims)
    # 梯度下降法迭代
    for i in range(0, num_iterations):
        # 前向传播: [LINEAR -> RELU]*(L-1) -> LINEAR -> SIGMOID.
        AL, caches = L_model_forward(X, parameters)
        # 计算成本
        cost = compute_cost(AL, Y)
        # 反向传播
        grads = L_model_backward(AL, Y, caches)
        # 更新参数(各层的W和b)
        parameters = update_parameters(parameters, grads, learning_rate)
        # 打印成本
        if print_cost and i % 100 == 0:
            print("Cost after iteration %i: %f" % (i, cost))
        if print_cost and i % 100 == 0:
            costs.append(cost)
    # 绘制成本变化图
    plt.plot(np.squeeze(costs))
    plt.ylabel('cost')
    plt.xlabel('iterations (per tens)')
    plt.title("Learning rate =" + str(learning_rate))
    plt.show()

    return parameters

首次输出的结果图像如上图所示,可以看出遇到了梯度消失的问题。查资料后得知,深层神经网络的模型初始化不能像浅层网络那样,需要对权重W的选取进行一定修改,一个解决方法是从区间均匀随机取值。

def initialize_parameters_deep(layer_dims):
    np.random.seed(3)
    parameters = {}
    L = len(layer_dims)
    for l in range(1, L):
        parameters['W' + str(l)] = np.random.randn(layer_dims[l], layer_dims[l-1]) / np.sqrt(layer_dims[l-1]) # 原语句:np.random.randn(layer_dims[l], layer_dims[l-1]) * 0.01
        parameters['b' + str(l)] = np.zeros((layer_dims[l], 1))
    return parameters

经过修改后可以看出,成本函数下降明显稳定了许多。

参考资料: 深度学习权重参数初始化要点