深度神经网络初始化、正则化、梯度校验

初始化

深度神经网络模型中,以单个神经元为例,该层(l)的输入个数为n,其输出为:

z=w_1x_1+w_2x_2+\cdots+w_nx_n           

a=g(z)

这里忽略了常数项b。为了让z不会过大或者过小,思路是让w与n有关,且n越大,w应该越小才好。这样能够保证z不会过大。一种方法是在初始化w时,令其方差为\frac1n。激活函数是tanh,相应的python代码为:

parameters['W'] = np.random.randn(n[l], n[l - 1]) * np.sqrt(1 / n[l - 1])

 

激活函数是ReLU,权重w的初始化一般令其方差为\frac2n

正则化

L2正则化

J = -\frac{1}{m} \sum\limits_{i = 1}^{m} \large{(}\small y^{(i)}\log\left(a^{[L](i)}\right) + (1-y^{(i)})\log\left(1- a^{[L](i)}\right) \large{)}

也可以表示为:

J(w^{[1]},b^{[1]},\cdots,w^{[L]},b^{[L]})=\frac1m\sum_{i=1}^mL(\hat y^{(i)},y^{(i)})+\frac{\lambda}{2m}\sum_{l=1}^L||w^{[l]}||^2

||w^{[l]}||^2=\sum_{i=1}^{n^{[l]}}\sum_{j=1}^{n^{[l-1]}}(w_{ij}^{[l]})^2

||w^{[l]}||称为Frobenius范数,一个矩阵的Frobenius范数就是计算所有元素平方和再开方

python代码例子,在计算J成本函数时加上正则化成本,假设有w1,w2,w3:

L2_regularization_cost = lambd * (np.sum(np.square(W1)) + np.sum(np.square(W2)) + np.sum(np.square(W3))) / (2 * m)

在反向传播时,使用以下公式计算梯度

\frac{d}{dW} ( \frac{1}{2}\frac{\lambda}{m} W^2) = \frac{\lambda}{m} W

dw^{[l]}=dw^{[l]}_{before}+\frac{\lambda}{m}w^{[l]}

python代码:

dW3 = (1 / m) * np.dot(dZ3, A2.T) + ((lambd * W3) / m)

Dropout正则化

Dropout的原理就是每次迭代过程中随机将其中的一些节点失效。当我们关闭一些节点时,我们实际上修改了我们的模型。背后的想法是,在每次迭代时,我们都会训练一个只使用一部分神经元的不同模型。随着迭代次数的增加,我们的模型的节点会对其他特定节点的激活变得不那么敏感,因为其他节点可能在任何时候会失效。
正向传播python代码:

    D1 = np.random.rand(A1.shape[0], A1.shape[1])  # 步骤1:初始化矩阵D1 = np.random.rand(..., ...)
    D1 = D1 < keep_prob  # 步骤2:将D1的值转换为0或1(使​​用keep_prob作为阈值)
    A1 = A1 * D1  # 步骤3:舍弃A1的一些节点(将它的值变为0或False)
    A1 = A1 / keep_prob  # 步骤4:缩放未舍弃的节点(不为0)的值

除以 keep_prob。这样做的话我们通过缩放就在计算成本的时候仍然具有相同的期望值。

假设第l层有50个神经元,经过dropout后,有10个神经元停止工作,这样只有40神经元有作用。那么得到的al只相当于原来的80%。缩放后,能够尽可能保持al的期望值相比之前没有大的变化。

后向传播:

使用正向传播存储在缓存中的掩码D1,python代码

    dA1 = dA1 * D1  # 步骤1:使用正向传播期间相同的节点,舍弃那些关闭的节点(因为任何数乘以0或者False都为0或者False)
    dA1 = dA1 / keep_prob  # 步骤2:缩放未舍弃的节点(不为0)的值

梯度检查

\theta^{+} = \theta + \varepsilon

\theta^{-} = \theta - \varepsilon

J^{+} = J(\theta^{+})

J^{-} = J(\theta^{-})

gradapprox = \frac{J^{+} - J^{-}}{2 \varepsilon}

接下来,计算梯度的反向传播值,最后计算误差:

difference = \frac {\mid\mid grad - gradapprox \mid\mid_2}{\mid\mid grad \mid\mid_2 + \mid\mid gradapprox \mid\mid_2}

当difference小于10^{-7}时,我们通常认为我们计算的结果是正确的。

python代码

def gradient_check(x,theta,epsilon=1e-7):
    """
    参数:
        x  - 一个实值输入
        theta  - 参数,也是一个实数
        epsilon  - 使用公式(3)计算输入的微小偏移以计算近似梯度

    返回:
        近似梯度和后向传播梯度之间的差异
    """

    #使用公式的计算gradapprox。
    thetaplus = theta + epsilon                               
    thetaminus = theta - epsilon                              
    J_plus = forward_propagation(x, thetaplus)                
    J_minus = forward_propagation(x, thetaminus)              
    gradapprox = (J_plus - J_minus) / (2 * epsilon)           

    #检查gradapprox是否足够接近backward_propagation()的输出
    grad = backward_propagation(x, theta)

    numerator = np.linalg.norm(grad - gradapprox)                      
    denominator = np.linalg.norm(grad) + np.linalg.norm(gradapprox)    
    difference = numerator / denominator                               

    if difference < 1e-7:
        print("梯度检查:梯度正常!")
    else:
        print("梯度检查:梯度超出阈值!")

    return difference

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程泓哥

你的鼓励是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值