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循环来控制下降次数,这个就没有办法向量化。

      人生不如意的时候,是上帝给的长假,这个时候应该好好享受假期。
      突然有一天假期结束,时来运转,人生才是真正开始了。
  • 相关阅读:
    heapq of python
    array of python
    Unittest of Python
    事件驱动型工作流 vs 引擎型工作流
    airflow
    WPF 调试触发器
    WPF 使用Popup和TreeView实现树状下拉框
    Oracle : ORA 00933: SQL command not properly ended
    PostgreSQL && PostGIS
    基于ArcGIS开发3D立方体空间关系判断
  • 原文地址:https://www.cnblogs.com/astonc/p/15466735.html
Copyright © 2011-2022 走看看