zoukankan      html  css  js  c++  java
  • 神经网络详解及技巧

    前言

    笔者一直在ipad上做手写笔记,最近突然想把笔记搬到博客上来,也就有了下面这些。因为本是给自己看的笔记,所以内容很简陋,只是提了一些要点。随缘更新。

    正文

    step1 建立一个神经网络模型

    一个常见的神经网络——完全连接前馈神经网络
    • 全连接:layer和layer之间两两连接
    • 前馈传递方向由后向前,任意两层之间没有反馈
    • 深度:许多隐含层

    (sigma(egin{bmatrix}1&-2 \-1&1end{bmatrix}egin{bmatrix}1 \-1end{bmatrix}+egin{bmatrix}1 \0end{bmatrix})=egin{bmatrix}0.98 \0.12end{bmatrix}) 如此一层一层传递下去。

    最普通的激活函数(sigma(z))为sigmoid函数

    [f(z)=frac{1}{1+e^{-z}} ]

    其图像为:

    当然,现在已经很少使用sigmoid函数做激活函数了。

    本质

    通过隐含层来代替原来的特征工程,这样最后一个隐含层输出的就是一组新的特征,然后通过一个多分类器(可以是(solfmax)函数)得到最后的输出(y)

    举例:手写识别

    step2 模型评估

    对于神经网络,我们采用交叉熵来对 (y)(hat y) 的损失进行计算。(后期我将在生成模型和判别模型中对他进行详细的描述)

    step3 最佳模型——梯度下降

    (backpropation)(反向传播,也就是所谓的(BP))在神经网络中是一种有效的方式计算(frac{partial{L}}{partial w})的方式,我们可以利用很多框架进行计算,如:TensorFlow,Pytorch。

    反向传播((BP))

    (L( heta))是总体损失函数,(l^n( heta))是单个样本产生的误差。

    计算(L( heta)= sum_{n=0}^{N}l^n( heta)),只需要计算(frac{partial L( heta)}{partial w}=sum_{n=1}^{N}frac{partial L( heta)}{partial w})

    我们取出一个神经元进行分析

    易得:

    [frac{partial l}{partial w}=frac{partial z}{partial w}frac{partial l}{partial z} ]

    Forward Pass (frac{partial z}{partial w}):

    这里我可以很轻松看出(frac{partial z}{partial w})为上一隐含层输出的值。

    Backward Pass (frac{partial l}{partial z}):

    [frac{partial l}{partial z}=frac{partial a}{partial z}frac{partial l}{partial a} = frac{partial a}{partial z}[frac{partial z'}{partial a}frac{partial l}{partial z}+frac{partial z''}{partial a}frac{partial l}{partial z''}] = sigma'(z)[w_3 frac{partial l}{partial z'} + w_4 frac{partial l}{partial z''}] ]

    这时候我们会觉得每计算一次梯度相当麻烦,每个参数的梯度都需要层层往后计算,计算量大到无法想象。实际上进行Backward Pass和向前传播的计算量差不多,我们只需将我们的思维逆转一下,从最后一层往前计算,也能计算出所有参数的梯度,这时的计算量是线性的,这就是 (BP) 的思想(个人为很类似于算法中的动态规划)。

    利用keras建立神经网络

    建立神经网络的过程,别人以为你在搞什么特别深奥高大上的东西,其实你只是在搭积木一样一层一层叠隐含层而已=。=

    import keras
    from keras.models import Sequential
    from keras.layers import Dense
    
    model = Sequential()    # 建立一个模型
    # 搭建网络
    '''@param
        Dense: Fully connect layer
        input_dim: 输入层
        units: 神经元
        activation: 激活函数
    '''
    model.add(Dense(input_dim=10, units=500, activation='sigmoid'))   # 建立一个神经网络
    # 再加一个隐含层
    model.add(Dense(units=500, activation='sigmoid'))
    # 输出层
    model.add(Dense(units=10, activation='softmax'))    # 输出向量长度为10,激活函数为softmax
    # loss function
    model.compile(loss='categotial_crossentropy',  # 损失函数:交叉熵
                  optimizer='adam',  # 优化器(都是梯度下降)
                  metrics=['accuracy']  # 指标
                  )
    # batch_size: 将训练集随机分为分为几个batch,每次计算随机的一个
    # 所有batch都计算一次,一个epoch结束
    model.fit(x_train, y_train, batch_size=100, epochs=20)
    
    # case1: 测试集正确率
    score = model.evaluate(x_test, y_test)
    print('Total loss on Test Set:', score[0])
    print('Accuracy of Testing Set:', score[1])
    # case 2:模型预测
    result = model.predict(x_test)
    

    深度学习的技巧

    在test上如何改进:

    新的激活函数

    sigmoid缺点——梯度消失:

    有时神经网络层数越深,结果越差,原因可能是梯度消失,比较靠近input的几层梯度很小,靠近output的几层梯度较大,在前几层还未怎么更新参数时,后几层已经收敛。因为每经过一个sigmoid,(Delta w)的影响就会被消弱。

    ReLU:
    • 当 input > 0 时,output = input
    • 当 input < 0 时,output = 0

    在input < 0 时,相当于该节点被移除,整个网络就是 a thinner linear network,如果时线性的话,梯度不会递减。
    你可能会说这个线性模型如何处理那些复杂的非线性模型,毕竟不是所有问题都和线性一样美好,你要注意了我们这是deep learning,关键在于这个“deep”,这是一个有着数层几千个神经元的网络,它们叠加的效果就是一个非线性的模型,是一个很复杂的function。对于ReLU activation function的神经网络,只是在小范围内是线性的,在总体上还是非线性的。

    好处:

    1. 比sigmoid处理起来快
    2. 无穷多的sigmoid叠加起来的结果(不同的bias)
    3. 可以处理梯度消失

    变种:

    • Leaky ReLU

    • Parametric ReLU

    Maxout —— 让network自动学习的激活函数

    方法:

    1. 先将输入分组,如2个一组或3个一组
    2. 再从每一组中选择最大的一个

    下图为一个简单的示例

    原理:
    其实上面介绍的ReLU为一个特殊的Maxout,理论上Maxout可以拟合任何激活函数
    比如下面这个ReLU可以由如此的Maxout得到

    选择不同的(w)(b)可以做到

    你可能会问这样不就有的节点训练不到了吗?因为有些节点的权值为0等于从网络中去除了。其实只是部分数据上此节点为0,但是我们有大量数据,总有数据可以训练到这个节点。所以 (Maxout) 需要比 (ReLU) 更大的数据量才能训练好这个网络。

    更新学习速率

    RMSProp

    属于之前在线性模型中提到的(Adagrad)算法的变形

    [w^1 longleftarrow w^0 - frac{eta}{sigma^0}g^0 qquad sigma^0=g^0 ]

    [w^2 longleftarrow w^1 - frac{eta}{sigma^1}g^1 qquad sigma^1=sqrt{alpha(sigma^0)^2+(1-alpha)(g^1)^2} ]

    [w^3 longleftarrow w^2 - frac{eta}{sigma^2}g^2 qquad sigma^2=sqrt{alpha(sigma^1)^2+(1-alpha)(g^2)^2} ]

    [...... ]

    [w^{t+1} longleftarrow w^t - frac{eta}{sigma^t}g^t qquad sigma^t=sqrt{alpha(sigma^{t-1})^2+(1-alpha)(g^t)^2} ]

    一个固定的learning rate除以一个(sigma)(在第一个时间点,(sigma)就是第一个算出来GD的值),在第二个时间点,你算出来一个(g^1)(sigma^2)(你可以去手动调一个(alpha)值,把(alpha)值调整的小一点,说明你倾向于相信新的gradient告诉你的这个error surface的平滑或者陡峭的程度)。

    Momentum

    参考了物理世界惯性的概念,遇到一个小山坡时可以通过惯性翻过,从而越过局部最优点。

    在算法中只参考上一次的速度,因为上一次的速度已经包含了之前所有的速度。
    步骤:

    1. 选择一个初始位置 ( heta^0) 和初始速度 (v^0=0)
    2. 计算在 ( heta^0) 处的梯度(Delta L( heta^0))
    3. (v^1=lambda v^0-etaDelta L( heta^0))
    4. ( heta^0= heta^1+v^1)
    5. 如此往复
    Adam

    (RMSProp)(Momentum)的结合。有兴趣的朋友直接看图吧。

    在这里插入图片描述

    在train上改进(过拟合)

    Early Stopping

    我们需要的是测试集错误最小,而不是训练集,如果测试集的Loss上升,则需要立刻停止训练,但是如果将测试集加入训练则会导致测试结果不客观。这时我们可以引入验证集来解决。当训练时验证集Loss上升则停止训练。

    Regularization

    和线性模型一样,我们需要在原来的(loss function)加入正则化,让得到的结果更加平滑。
    常见的有(L_1-norm)(一次式)和(L_2-norm)(二次式)

    Dropout
    如何训练

    在训练时的时候,每一次参数更新之前,对network里面的每个神经元(包括输入层),做采样(sampling)。 每个神经元会有p%的可能性会被丢掉,跟着的 (w) 也会被丢掉。

    解释

    你在训练时,加上dropout,你会看到在训练集上结果会变得有点差(因为某些神经元不见了),但是dropout真正做的事就是让你测试集越做越好。

    假设有(m)个神经元,就可以训练 (2^m) 个神经网络结构,每个网络的偏差虽然很大,但是最后平均下来还是很准的(这个又要回到我们在线性模型中说的 (varience)(bias) 问题)。

    dropout其实是用了模型融合(model essemble)的思想,训练了很多模型最后加权得到最终的结果。

    在testing上注意两件事情:
    • 第一件事情就是在testing上不做dropout。
    • 在dropout的时候,假设dropout rate在training是p%,all weights都要乘以((1-p\%))

    关于为什么要乘((1-p\%)),举一个简单的例子:

    总结

    到此神经网络已经介绍得差不多了,你可能会说,就这,就这?其实神经网络也不是什么深奥的东西,本质上就是一个有着数千个参数的模型,和最简单的线性模型一样,也是通过最常规的方法——梯度下降求解。当然,其中也涉及了一些挺玄学(只可意会,不可言传,当然也是我的数学功底不够,无法准确描述)的方法。

    上一篇:机器学习笔记(1)——线性回归
    下一篇:可能会讲一讲CNN或者神经网络中神经元的来源——logistic回归(未开始写=。=)

    (如果觉得有用请点个赞吧)

  • 相关阅读:
    c# 三层结构的简单理解
    浅析C#鼠标右键如何添加
    三层结构开发的理解
    Windows快捷键大全
    command 中 ExecuteScalar() ExecuteNonQuery ()和ExecuteReader()的用法
    很拽的JSON
    FCKeditor的全局API
    WebForm_DoPostBackWithOptions 丢失的解决
    闭包的错误例子
    XPath学习笔记 XPath数据模型
  • 原文地址:https://www.cnblogs.com/ghost222/p/12631190.html
Copyright © 2011-2022 走看看