zoukankan      html  css  js  c++  java
  • 深度学习入门(一)介绍神经网络、logistic回归和梯度下降

      学习自吴恩达,深度学习课程。

    什么是神经网络(Neural Network)?

       假设需要进行房屋价格预测,给了六个数据<size of the house, price of the house>,为了方便观察他们之间的联系----找到一个合适的函数,将其放在一个二维坐标系中。

      很自然可以看出用一条直线可以拟合(线性回归),当然根据常识,价格不可能为负,所以要改为折线让其归为 0 ,这个拟合函数可以看成是最简单的神经网络了。通常这种开始为0,之后是一条直线的函数称为ReLU函数----修正线性单元(Stands for  Rectified Linear Unit),这里修正就是取不为0的值。

      输入size记为x,经过神经元(中间圆圈,也就是刚刚找到的拟合函数)处理后,输出price记为y。这就是一个单神经网络,简单地说,把多个神经元像搭积木一样堆叠起来就会形成一个神经网络。

      如果现在不仅知道房屋的面积,我们还知道其他信息,例如邮编 zip code可以推测地区富裕程度以及距离工作地点远近,周围居民财富状况wealth可以来推测学校质量,我们就可以更精确地预测房屋价格。

      将这些神经元组合起来,就得到了一个简单的预测器。神经网络的一个强大之处就是输入一个庞大的数据,可以不管中间的处理过程,最终都会主动获得输出结果。如图,左侧是输入层,中间是神经网络,其间被蓝色箭头指向的节点被称为预测神经元,右侧是输出层。

     用神经网络进行监督学习 Supervised Learning

      在例如广告推送方面,一般使用标准神经网络(Standerd NN),在图像方面使用卷积神经网络(CNN),在音频和文字方面使用循环神经网络(RNN),在更复杂的例如自动驾驶方面使用混合神经网络。

       通常我们输入的数据分为结构化数据(Structured Data)和非结构化数据(Unstructured Data),结构化数据是数据的数据库形式,而非结构数据可能是图片、音频、文字,亦或者是其他信号。一般来说人类擅长处理非结构化的数据,计算机擅长处理结构化数据。

    二分分类 Binary Classification

      假设我们输入这样一张图片,我们想要识别图中是否有猫,输出 1 代表有猫,0 表示没有猫。

       图片在计算机中是用红绿蓝三原色矩阵来存储表示的,如下图,假设这张猫猫图由三个64*64的矩阵表示,为了将这些矩阵放进一个特征向量里,我们用 x 来表示这个特征向量,我们把三个矩阵的所有值都取出来放入向量 x 中,那么向量 x 的维度就是 nx = 64*64* = 12288,为了方便将 nx 简记为 n 来代表向量维度。

      在二分类问题中,目标是训练处一个分类器,它以图片的特征向量 x 作为输入,预测输出的结果的标签 y 是 1 还是 0. 为了方便后面说明,这里声明一下符号的含义:

    •  (x, y)代表一个独立的样本, x 是 nx维的特征向量,x ∈ Rnx , 标签 y 值为 0 或 1,y ∈ {0, 1}
    • 训练集由 m 个训练样本构成,(x(1), y(1))代表样本一的输入和输出,训练集为 {(x(1), y(1)),  ……, (x(m), y(m))}, m 代表训练样本的个数,有时候为了更精确说明,用 mtrain 来代表训练集样本的个数,用 mtest 来代表测试集样本的个数
    • X 表示输入矩阵,如下图所示,在神经网络计算时,约定使用列堆叠的方式,这会让构建过程简单很多。在 Python 里 X.shape 会输出矩阵的维度 (nx, m)
    • 表示输出矩阵, Y.shape = (1, m)

    Logistic 回归

      logistic 回归是一个用在监督学习问题中的学习算法,当其输出 y ∈ {0, 1}时就属于二分分类。

      接着上面猫猫图片的问题,现在我们输入一个 x, 我们想要获得预测值 y-hat =  P(y = 1 | x) ,我们通常想得到一个概率,自然 0 ≤ y-hat ≤ 1。 

    • x ∈ Rnx 
    • 已知 logistic 回归参数 w ∈ Rnx ,也是一个向量,b ∈ R, b 是一个实数

      已知这些后我们可以假设一个线性函数 y hat =  wT x + b ,当然这明显不符合我们的要求,我们期望获得的 y-hat 是一个概率,y hat 的取值范围应该在 0 到 1 之间,所以我们引入 sigmoid 函数。

      sigmoid 函数 : σ (z) = 1 / ( 1 + exp(-z) )

      而这里我们令 z = wT x + b, 则 y hat = σ (z)  = σ (wT x + b) 。参考下图。

    Logistic 回归损失函数和代价函数

      现在给了一组训练样本 X ,在上面的logistic函数计算下获得一组预测值 Y-hat,并且想要 Y-hat 尽可能接近训练集中的 Y,为了衡量算法的运行情况,我们对单个样本设置一个损失函数L,函数值越高代表算法运行情况越差。通常我们期望损失函数是凸函数,这样可以方便找得最小值----最优解。 像平方损失函数就不适合,提出一个样例:

      Loss function:L ( y-hat, y ) = - [ y log y-hat + (1 - y) log ( 1 - y-hat ) ]

      代价函数则是衡量函数在全体训练样本上的表现。

      Cost function: J (  w, b ) = 1/m *  ∑ L( y- hat(i) ,  y(i)

      因此在训练logistic回归模型中,我们要找到合适的参数 w 和 b,来使代价函数 J 尽可能的小。


      这里解释下损失函数和代价函数是怎么来的。

      首先约定:

    • 这里 y 只取 0, 1两种情况,二分类问题
    • y-hat = p( y=1 | x ),即算法的输出 y-hat 是在给定训练样本 x 的条件下 y = 1 的概率

      也就是说:

      我们将这两个式子合并成一个: p ( y | x) = y-hat y (1 - y-hat) (1 - y)

      由于 log 函数是严格单调递增函数,那么 最大化 log p (y | x) 就等于最大化 p (y | x),那计算 log p (y | x) 就可化简为 y log y-hat + (1 - y) log ( 1 - y-hat ) 

      损失函数前有个负号是因为log中我们计算的是最大化,而logistic回归中我们需要的是最小化损失函数 L ( y-hat, y )。

      对于代价函数,假设所有样本都是独立同分布的,那么这些样本的联合概率就是每个样本概率的乘积,P = ∏ p(yi | xi),如果想要做极大似然估计,寻找到一组参数,使得给定样本的观测值概率最大,这个概率最大化就等价于令其对数最大化,也就是log P = log ∏ p(yi | xi)= ∑ p(yi | xi)= ∑ L ( y-hat, y ),为了方便计算,还会对其进行适当放缩 1 / m。

     梯度下降法 Gradient Descent

       为了求得最优解的 w 和 b ,我们使用梯度下降法,在凸函数中,我们给w, b一个初始值,并让w 和 b 每次都沿着最陡或者下降最快的方向更新,这样在多次更新后总会取到最优解。 

       为了方便理解,我们暂时只考虑参数w,并且 w 是一维的。那么有这样的更新操作  w =  w - ∝ ( dJ(w) / dw)

    • ∝ 为学习率,用来控制每次更新下降的步长,后面会详细介绍 (这个符号不这么写,但是找不到对于符号,只能先将就一下,可以看图)
    •  dJ(w) / dw 为更新量,实际上就上该点的斜率

      在多元函数中则是偏微分。

      实际上  w = w - ∝( ∂J(w, b) / ∂w), b = b - ∝( ∂J(w, b) / ∂b)

      接下来利用链式求导来计算dw 和 db,一般都把 log 视为 ln。

    • z = wx + b
    • a = y-hat = σ (z) =  1 / ( 1 + exp(-z) )
    • L =   - [ y log a + (1 - y) log a ]

      根据计算我们得到:

    • dL / da  = (1 - y) / (1 - a) - y / a
    • da / dz = exp(-z) / (1 + exp(-z))2 = a(1 - a)
    • dz = (a - y) dL
    • dw = xdz
    • db = dz

      由此我们可以编写代码如下,前提给了m个样本,输入两个特征w1,w2, b,n代表特征w数量:

      

    L = 0;
    dw1 = 0;
    dw2 = 0;
    db = 0;
    For j = 1 to n:
      For i = 1 to m:
          z[i] = wT x[i] + b;
        a[i] = σ (z[i]);
        L =  - [ y[i] log a[i] + (1 - y[i])) log a[i] ];
        dz[i] = a[i] - y[i];
        dw1 += x1[i] dz[i];
        dw2 += x2[i] dz[i];
        db += dz[i];
      L /= m;
      dw1 /= m;
      dw2 /= m;
      db /= m;
    

       但是这种在代码里显式使用 for 循环在深度学习(数据量大)里会使算法很低效,由此引入向量化。

    向量化

       之前我们说显示的 for 循环性能不如向量化后的结果,下图展示了二者的差距。

      我们已经知道:

    • zi = wi xi + b
    • ai = σ (zi)

      那么有,这里约定加粗字母的代表向量,字母右上角标号代表记号,不是指数

                     向量                                维度

    •  = [ z1,……,zm ]               (1, m)
    •  = [x1, ……,,xnx]                 (nx, 1)
    •  = [x1, ……,xm]                 (nx,m)
    • = [w1, ……,wnx]                      (nx, 1)
    •  = [b, ……,b]                            (1, m)
    •  = [a1, ……,am]                  (1, m)

    Z = wTX + b

    A = σ (Z)

       在numpy里,z = np.dot(w.t, x) + b    这里的 b 是个实数,python会自动给向量每个的值都加上 b,这种操作称之为广播(Broadcasting).

       同理在计算梯度下降时,就可以

    • dZ  = [dz1, ……, dzm]
    •  = [y1, ……, ym]

    dZ = A - Y

    dw = 1/m * X dZT

    db = 1/m  * ∑im dzi = 1/m * np.sum(dZ)

       这样我们就利用向量化把两次显示循环取代了,新的代码过程如下图右侧,当然还有一个for循环来控制下降次数,这个就没有办法向量化。

      人生不如意的时候,是上帝给的长假,这个时候应该好好享受假期。
      突然有一天假期结束,时来运转,人生才是真正开始了。
  • 相关阅读:
    算法竞赛入门经典习题2-3 韩信点兵
    ios入门之c语言篇——基本函数——5——素数判断
    ios入门之c语言篇——基本函数——4——数值交换函数
    144. Binary Tree Preorder Traversal
    143. Reorder List
    142. Linked List Cycle II
    139. Word Break
    138. Copy List with Random Pointer
    137. Single Number II
    135. Candy
  • 原文地址:https://www.cnblogs.com/astonc/p/15466735.html
Copyright © 2011-2022 走看看