美文网首页
Deep Learning笔记: Course 1, Week

Deep Learning笔记: Course 1, Week

作者: 帆_2065 | 来源:发表于2017-11-27 01:31 被阅读0次

    Shallow Neural Network

    本周课程涉及到的知识点:

    • Shallow neural network 的基本结构
    • Activation function 的选择和计算
    • Gradient descent 和 Backward propagation

    Shallow neural network 的基本结构

    Shallow neural network 可以看做是前一节课介绍的 logistic regression 的拓展,也即是只有一层的神经网络。 它的结构如下所示:

    Shallow Neural Network结构

    最左边的是输入层,最右边的是输出层,中间部分是隐藏层。可以看到和 logistic regression 不同的是在隐藏层我们定义了多个 neuron, 每个都会执行 Z[1] = W[1] * X + b[1] 以及 a[1] = g(Z[1]) 的操作,这里的 g(*) 被称为 activation function,我们下面会讨论这个 function 的选择。最后我们对 a[1] 进行类似的线性变换然后通过sigmoid function得到最后的输出。 可以看到 Shallow Neural Network 的计算套路和 logistic regression 是基本一样的:

    1. 定义神经网络的结构 ( 例如 隐藏层 neuron 的个数).
    2. 定义模型参数,注意我们有 W1, W2, b1, b2 四个参数
    3. 循环:
      - Forward propagation 计算输出
      - 计算Loss 和 cost function的值
      - Backward propagation 计算梯度
      - Gradient descent 优化参数

    假定现在我们要构建一个shallow neural network. 输入层大小(neuron 个数)是 n_x, 中间层大小是 n_h, 输出层大小是 n_y, 下面我们来走一遍整个流程。

    定义模型参数

    我们需要如下定义模型参数:

    -  W1 = np.random.randn (n_h, n_x) * 0.01
    -  W2 = np.random.randn (n_y, n_h) * 0.01
    -  b1= np.zeros ((n_h, 1)) 
    -  b2= np.zeros ((n_y, 1)) 
    

    关于这个定义,两点需要注意:

    • 为什么我们不直接把 W1W2 定义为全0矩阵?
    • 为什么要把 W1W2 乘以0.01 ?

    关于第一点,课上的讲解是如果 W1W2 是全0的话,那么隐藏层的每个neuron都会给出同样的计算结果(fail to break symmetric),这样导致神经网络跟只有一个neuron没什么区别。然而经过我的计算发现后果其实更加严重 - 如果 W1W2 被初始化为 0, 经过一轮 forward propagation 和 backward propagation 以后 W1W2 依然是 0, 也就是完全没有更新参数。

    补充说明:对于logistic regression, 把初始 W 设置为全 0 向量则不会有问题。这是因为经过计算可以发现一轮 forward propagation 和 backward propagation 以后 W 已经被更新成非 0 向量了。

    关于第二点,反过来想,如果 W1W2 很大,那么会造成计算得到的 Z 很大,这样会导致经过激活函数计算出来的 a 值非常接近于1或者0。 这样会有可能导致最后的结果 log(a) 以后趋向于无穷大 - 这样会显著的拖慢收敛速度。因此一般来说我们会把 W1W2 的初始值设置的小一点。

    Activation function 的选择

    一般来说在隐藏层我们会选择 tanh 或者 ReLU (或者 Leaky ReLU) 函数, 在输出层则会选择 sigmoid 函数。 这是一个典型的nobody knows why it just works的例子。虽然有理论说 tanh 的均值为0,因此效果较好,然而这无法解释为何 ReLU 激活函数的性能也非常不错(均值显然不为0)。

    这4种函数的图形如下所示(左下为ReLu, 右下为 Leaky ReLu):

    Activation Function

    值得考虑的是,为何我们需要这样一个激活函数?

    答案很显然,如果去掉activation function, 那么可以发现输出 Y 就完全是输入 X 的线性变换了, 这样我们就无法完成一些非线性划分的复杂工作了。

    最后我们列一下四种不同激活函数的导数,这个在计算反向传播的时候会用到。

    Activation Function Form Derivatives
    sigmoid g(z) = 1 / (1 + exp(-z)) g'(z) = g(z) (1 - g(z))
    tanh g(z) = exp(z) - exp(-z) / (exp(z) + exp(-z)) g'(z) = (1 - g(z))^2
    ReLU max (0, z) 0 if z < 0, 1 if z >= 1
    Leaky ReLU max(0.01z, 1) 0.01 if z < 0, 1 if z >= 1

    Forward propagation 计算输出

    假设我们隐藏层激活函数采用tanh function, 直接给出公式

    [图片上传失败...(image-9c7983-1511717394092)]

    [图片上传失败...(image-91df7e-1511717394092)])

    [图片上传失败...(image-bb4ea8-1511717394092)]

    [图片上传失败...(image-64301a-1511717394092)])

    看似很复杂,其实很简单。对每层依次计算线性变换结果 Z[L] 和 激活函数后的结果 a[L] 即可。 需要注意的只是各个矩阵向量的维度。设输入 X 共有 m 个training data, 每层的neuron个数为 n(L), 那么各个矩阵向量的维度为:

    • X: n_x * m
    • W[L]: n(L) * n(L-1)
    • b[L]: n(L) * 1
    • Z[L], A[L]: n(L-1) * m

    Backward propagation 计算梯度

    同样直接给出公式(递推一下其实也不难):

    Backward propagation

    需要注意的是在计算反向传播梯度的时候,我们用到了当前层(以及前一层)的输出。例如在计算 dZ[2] 的时候我们需要用到 A[2], 而在计算 dW[2] 的时候直接用到了 A[1] 并且间接用到了 A[2]。因此通常的做法是把每一层的输出放到cache里,以方便计算梯度的时候直接调用。

    Gradient descent 优化参数

    没有什么可说的,根据计算出来的梯度挨个更新每个参数即可。

    总结

    这一课基本是个从logistic regression 到 deep neural network的过渡。重点:

    • 随机化初始参数的重要性
    • 非线性activation function的重要性
    • 如何计算正向传播和反向梯度(大概记住原理即可)

    相关文章

      网友评论

          本文标题:Deep Learning笔记: Course 1, Week

          本文链接:https://www.haomeiwen.com/subject/arfemxtx.html