美文网首页
Feedforward Neural Network

Feedforward Neural Network

作者: 孟哲凡 | 来源:发表于2018-11-28 17:19 被阅读0次

    前言

    前馈神经网络的目标是近似某个函数 f^* 。后面在围绕解释的也就是这个话题。

    从XOR问题说起

    xor(异或)运算应该都不陌生,两个二进制值 x_{1}x_{2} 的运算,当恰好有一个值为1时,结果就是1,其余是0。我们把这个规则(运算)当成我们要学习的函数 y = f^*(x),我们的模型给出一个函数 y = f(x;\theta) ,我们希望能够不断调整 \thetaf 能够 接近 f^*

    在这个例子中。x \in X = \{[0,0]^T,[0,1]^T,[0,0]^T,[1,1]^T\}, y \in \{1,0\}
    我们可以把这个问题当作回归问题(当然当作分类也是可以的),并使用均方误差作为损失函数,那么损失函数就可以表示为
    J(\theta)= \frac{1}{4}\sum_{x\in X}(f^*(x)-f(x;\theta))^2
    然后我们确定 f(x;\theta) 的具体模型,假设是一个线性模型(简单一点),那么 \theta 就包含 \omegab 两个参数,模型也就是
    f(x;\omega,b)=x^T\omega +b
    然后通过求解最小化的 J(\theta) 来得出 \omegab 的值。

    %matplotlib inline
    import matplotlib.pyplot as plt
    import numpy as np
    
    def plot_data(data, labels):
        
        one = data[labels == 1, :]
        zero = data[labels == 0, :]
        plt.scatter(one[:, 0], one[:, 1], 
                           color='red', marker='+', s=200)
        plt.scatter(zero[:, 0], zero[:, 1], 
                           color='blue', marker='.',s=200)
    
    one = np.array([[1, 0], [0, 1]])
    zero = np.array([[0, 0], [1, 1]])
    
    data = np.concatenate([one, zero])
    labels = np.array([1, 1, 0, 0])
    plot_data(data, labels)
    
    image.png

    上面用代码构造了这个数据并简单展示一下。然后我们用sklearn里的线性模型来进行求解

    from sklearn import linear_model
    clf = linear_model.LinearRegression()
    clf.fit(data, labels)
    print(clf.coef_)
    print(clf.intercept_)
    out:
    [0. 0.]
    0.5
    

    发现 \omega 的值 是0(向量),b 的值是0.5,也就是说不论输入数据是什么,输出都是0.5。怎么形象的理解这个问题呢,简单说就是一个线性模型根本无法区分开这个数据(有人说,不对啊,svm就可以,我试过了,svm确实在构造一个超平面,但是它可以使用核函数把数据维度提高成线性可分的去解决非线性问题。单纯的线性模型是不可以的。)我们观察上图发现,当 x_{1}=0 时,模型输出必须随着 x_{2} 的增大而增大。当 x_{1}=1 时,模型必须随着 x_{2} 的增大而减小。线性模型不能使用 x_{1} 的值来改变 x_{2} 的值

    那么如何解决这个问题呢。传统机器学习那些处理非线性的思路是可行的,还有一种方法就是使用一个模型来学习一个不同的特征空间,然后在这个空间上使用线性模型可以表示这个解。

    具体来说,到这里就可以引入简单的前馈神经网络了。(如下图)它有一个隐藏层并且隐藏层中包含两个单元。这个前馈神经网络通过函数 f^{(1)}(x;W,c) 计算隐藏单元的向量 h
    h=f^{(1)}(x;W,c)
    这些隐藏单元的值随后被用作第二层的输入。第二层就是这个网络的输出层。输出层仍然是一个线性回归模型,只不过变量是 h 而非 x。那么现在就可以用
    f(x;W,c,\omega ,b)=f^{(2)}(f^{(1)}(x))
    来表示网络

    g1.gv.png

    还有种简单的表示方法,如下

    g2.gv.png

    现在要考虑的问题是 f^{(1)} 用什么样的模型表示,假设它依旧是线性回归模型那么 f^{(1)}=W^Tx + c,如果不考虑 c截距的话,f 将表示成 f=\omega ^TW^Tx,这仍旧是一个线性函数,我们前面讨论到问题的所在就是线性所致,所以需要一个非线性的变换,在神经网络的通常做法加入一个激活函数(关于激活函数会在后面详细介绍)来使之前的仿射变换变成非线性的,也就是
    f^{(1)}=g(W^Tx+c)
    这个用一个比较通用的激活函数ReLU(rectified linear unit)。g(z)=max\{0,z\},那么现在我们的网络就可以表示成
    f(x;W,c,\omega ,b)=\omega^Tmax\{0,W^Tx+c\}+b

    现在继续讨论xor问题,我们确定解的参数(至于参数为什么会是这个,也在后续说明,这里只是解释这个问题)
    W=\begin{bmatrix} 1 & 1 \\ 1 & 1 \end{bmatrix}
    c=\begin{bmatrix} 0 \\ -1 \end{bmatrix}
    \omega=\begin{bmatrix} 1 \\ -2 \end{bmatrix}
    b=0

    用X作为输入矩阵,当经过ReLU后,数据变成
    \begin{bmatrix} 0 & 0 \\ 1 & 0 \\ 1 & 0 \\ 2 & 1 \end{bmatrix}
    我们用上面的分析,绘制下图

    new_data = np.array([[1,0],[1,0],[0,0],[2,1]])
    plot_data(new_data, labels)
    
    image.png

    我们发现数据集变成线性可分的了,继续用线性回归模型去计算现在的数据,也得到了结果。

    clf.fit(new_data, labels)
    print(clf.coef_)
    print(clf.intercept_)
    out:
    [ 1. -2.]
    6.661338147750939e-16
    

    回顾这个过程,不论是损失函数的选择,模型的选择,或者是激活函数,再到后面的给定的参数,都有点“假”,这也是我们后面要详细说的东西。

    [这是一个正在更新的东西,因为课比较多,人比较懒,也懂的少,所以比较慢]

    相关文章

      网友评论

          本文标题:Feedforward Neural Network

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