第六章一文搞懂神经网络的学习算法——原理+numpy代码详解

本专栏是书《深度学习入门》的阅读笔记一共八章:

第一章深度学习中的Python基础。主要讲解了深度学习将要用到的python的基础知识以及简单介绍了numpy库和matpoltlib库,本书编写深度学习神经网络代码仅使用Python和numpy库,不使用目前流行的各种深度学习框架,适合入门新手学习理论知识。

第二章感知机。主要介绍了神经网络和深度学习的基本单元感知机。感知机接收多个输入,产生一个输出,单层感知器可以实现与门,或门以及与非门,但是不能实现异或门,异或门的实现需要借助多层感知机,这也就是说,单层感知机只能表示线性空间,而非线性空间的表示需要借助多层感知机。

第三章神经网络——基于numpy的代码详解。主要讲解了神经网络的构成,神经网络中的激活函数,神经网络中层与层的矩阵乘法,3层神经网络的代码,输出层的设计和批处理。

第四章神经网络的学习算法——随机梯度下降numpy代码详解。主要讲解了神经网络中的学习算法,介绍了损失函数,通过微分求导的方法求梯度,随机梯度下降算法的原理以及基于numpy的代码详解。

第五章误差反向传播算法——基于numpy的代码详解。这一章主要介绍了,实现误差反向传播的一种工具,计算图,从最简单的加法节点乘法节点的计算图开始,介绍了加法节点乘法节点的反向传播,一步步深入,到加法层,乘法层,激活函数层等层的反向传播,最终把各种层的反向传播拼接在一起,就形成了整个网络的反向传播。

第六章与学习相关的技巧

        本章将主要介绍除了随机梯度下降以外的更新参数的方法,权重的初始值设定,解决过拟合的正则化办法,以及超参数的设置经验。

6.1更新参数的其他方法

6.1.1随机梯度下降(stochastic gradient descend SGD)的缺点

        神经网络学习的目的是确定参数使得损失函数的值最小,属于参数最优化(optimization)问题,我们之前学过的更新参数的方法是随机梯度下降算法(SGD),让我们再来回顾一下SGD算法的核心思想:

                                                                           w=w-\eta \frac{\partial L}{\partial w}

        代码实现为:

class SGD:

    def __init__(self,lr):
        self.lr=lr

    def update(self,params,grads):

        for key in params.keys():
            params[key]-=self.lr*grads[key]

        下面我们针对一个二元函数最优化问题说明SGD算法的缺点,求函数f(x,y)=\frac{1}{20}x^2+y^2的最小值。

        函数的图像为:

        梯度的图像为:

        利用SGD算法进行优化,参数的变化图像为:

        可以看到,当函数形状非均向,比如延伸状,利用SGD算法进行搜索的效率就会很低,SGD低效的根本原因是梯度指向的方向不是最小值方向。

6.1.2Momentum

        Momentum在物理学中翻译为动量,使用Momentum方法更新参数的直观理解是,把更新参数想象成小球从山顶下落的过程,v表示速度,\alpha v表示原有的摩擦力,参数的梯度表示新的受力,公式如下:

                                                                                             v=\alpha v-\eta \frac{\partial L}{\partial W}

                                                                                               W=W+v

        代码实现为:

class Momentum:

    def __init__(self,lr,momentum):

        self.lr=lr
        self.momentum=momentum
        self.v=None

    def update(self,params,grads):

        if self.v is None:
            self.v={}
            for key,val in params.items():#items返回(键,值)
                self.v[key]=np.zeros_like(val)
        for key in params.keys():
            
            self.v[key]=self.momentum*self.v[key]-self.lr*grads[key]
            params[key]+=self.v[key]

        让我们再来看一下,用此方法解决上面函数求极值问题的参数更新路径:

6.1.3AdaGrad

        在学习率设置的技巧中,有一种技巧被称作是学习率衰减,即随着学习的进行,学习率的值逐渐减小。而AdaGrad的思想进一步改善了这种思想,AdaGrad为每一个参数量身定制了一个学习率的衰减规则,让我们一起来看一下它的公式:

                                                                       h=h+\frac{\partial L}{\partial W}\odot \frac{\partial L}{\partial W}

                                                                       W=W-\eta \frac{1}{\sqrt{h}}\frac{\partial L}{\partial W}

        实现代码为:

class AdaGrad:

    def __init__(self,lr):
        
        self.lr=lr
        self.h=None

    def update(self,params,grads):

        if self,h is None:
            self.h={}
            for key,val in params.items():
                self.h[key]=np.zeros_like(val)

        for key in params.keys():
            self.h[key]+=grads[key]*grads[key]
            params[key]-=self.lr*grads[key]/(np.sqrt(self.h)+1e-7)
#加一个极小值避免出现h为0的情况                                
   

        用此方法解决以上函数求极值问题,参数的更新路径如下:

6.1.4Adam

        Adam方法的原理比较复杂,这里只给出它的直观解释,Adam的方法就是结合了Momentum和AdaGrad两种方法,将两种方法结合就是Adam方法,用这种方法更新参数的路径图为:

6.2权重的初始值

        当激活函数为sigmoid或者tanh时,使用“Xavier初始值”,具体方法为,如果前一层的神经元数量为n,那么本层神经元的权重初始化为标准差为\sqrt{\frac{1}{n}}的高斯分布,实现代码如下:

import numpy as np
#node_num表示隐藏层神经元个数
W=np.random.randn(node_num,node_num)*np.sqrt(node_num)

        当激活函数为ReLU时,一般采用“He初始值”,具体方法为,如果前一层的神经元数量为n,那么本层神经元的权重初始化为标准差为\sqrt{\frac{2}{n}}的高斯分布。

6.3Batch Normalization 

        上一节我们看到,使用适当的初始化权重的方法,会使各层的激活值有适当的广度,从而可以顺利的进行学习。Batch Normalization的思想就是这样,以进行学习的mini-batch为单位,对每一层神经元的输入数据进行正规化处理,即使数据具有均值为0,方差为1的正规化。公式参考如下:

                                                                                \mu_B=\frac{1}{m}\sum_{i=1}^{m}x_i

                                                                           \sigma^2_B=\frac{1}{m}\sum_{i=1}^{m}(x_i-\mu_B)^2

                                                                                 \hat{x}_i=\frac{x_i-\mu_B}{\sigma_B}

        这里对具有m个数据的mini-batch集合B=\left \{ x_1,x_2,x_3......,x_m \right \}}求均值\mu_B和方差\sigma^2_B,进行均值为0方差为1的正规化。接着对数据进行进行缩放和平移处理,公式如下:

                                                                                 y_i=\gamma x_i+\beta

        \gamma\beta是超参数,初始值设为1和0,然后通过神经网络进行学习确定合适的参数。Batch Normalization的计算图如下:

        使用Batch Normalization处理的好处有:

        1.加快学习

        2.不那么依赖参数的初始值,对初始值不是那么敏感

        3.抑制过拟合

6.4正则化

6.4.1过拟合

        过拟合是指,神经网络对于训练数据过于拟合,导致对测试数据拟合效果很差。见百度百科的图片:

        过拟合产生的原因主要有两个:

        1.模型拥有大量参数,表现力强。

        2.训练数据少。

6.4.2权重衰减

        权重衰减是一种抑制过拟合的有效手段,权重衰减的核心思想就是通过在学习的过程中对大的权重值进行惩罚,来达到抑制过拟合的目的。具体方法是,因为神经网络的学习目的是尽可能的减小损失函数的值,我们可以通过在损失函数中加入权重的惩罚项来达到对大的权重进行惩罚的目的,具体的惩罚措施有,L1范数,L2范数,L∞范数,实际上,我们可以从中挑选一个作为惩罚项,加入到损失函数中,这样因为神经网络会不断地减小损失函数的值,因此就会对大的权重进行抑制。

        常用的是L2范数,L2范数实际上就是求平方和再开方,例如权重W=\left \{ w_1,w_2,w_3......w_n \right \},那么其L2范数为\sqrt{w_1^2+w_2^2+w_3^2+......+w_n^2},L1范数实际上是绝对值求和,即其L1范数为|w_1|+|w_2|+|w_3|+......+|w_n|,而L∞范数实际上是求最大值,相当于各个元素中最大的一个,其L∞范数为w_{max}

6.4.3Dropout

        Dropout是另一种常用的抑制过拟合的方法,更多用于隐藏层比较多,网络结构比较复杂的网络中。Dropout通过在每次训练时,随机“删除”一部分隐藏神经元,被“删除”的神经元在本次训练中不参与数据传递。但是在测试时,每一个神经元都参数与数据传递,并且各个神经元的输出要乘以训练时删除神经元的比例。这种思想有点类似于机器学习中的集成学习,就是让多个模型单独进行学习,测试时取这几个模型输出的平均值。如图所示:

        实现代码为:

class Dropout:

    def __init__(self,dropout_ratio):#删除神经元的比例

        self.dropout_ratio=dropout_ratio
        self.mask=None


    def forward(self,x,train_flag=True):

        if train_flag:
            self.mask=np.random.rand(*x.shape)>self.dropout_ratio
            return x*self.mask
        else:
            return x*(1.0-self.dropout_ratio)

    def backward(self,dout):

        return dout*self.mask

6.5超参数(hyper-parameter)的选择

        这里所指的超参数是,比如隐藏层神经元的个数,学习率,权重衰减系数等需要人工进行设置的参数,这些参数对于神经网络的学习很重要,如果能够确定合适的超参数则会使得学习过程事半功倍但是如果超参数设置的不合适,则会让学习过程变得艰难甚至无法学习。

        超参数最优化的步骤:

        步骤0:设定超参数的范围

        步骤1:从设定的超参数范围中随机采样

        步骤2:使用步骤1中采样得到的超参数进行学习,通过验证数据进行评估

        步骤3:重复步骤1和步骤2缩小超参数的选择范围

 

        例如,我们设定学习率的范围是10^{-6}10^{-2},权重衰减系数的范围为10^{-8}10^{-4},随机采样的代码实现为:

weight_decay=10**np.random.uniform(-8,-4)
lr=10**np.random.uniform(-6,-2)

 

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
神经网络在自动驾驶中扮演着重要角色,它可以帮助车辆感知环境、做决策和控制行为。以下是一个简单的自动驾驶神经网络算法代码详解: ```python import numpy as np # 定义神经网络类 class NeuralNetwork: def __init__(self, input_size, hidden_size, output_size): # 初始化权重和偏置 self.W1 = np.random.randn(input_size, hidden_size) self.b1 = np.zeros((1, hidden_size)) self.W2 = np.random.randn(hidden_size, output_size) self.b2 = np.zeros((1, output_size)) def forward(self, X): # 前向传播计算输出 self.z1 = np.dot(X, self.W1) + self.b1 self.a1 = np.tanh(self.z1) self.z2 = np.dot(self.a1, self.W2) + self.b2 self.a2 = self.sigmoid(self.z2) return self.a2 def backward(self, X, y, learning_rate): # 反向传播更新权重和偏置 m = X.shape[0] delta2 = self.a2 - y dW2 = (1/m) * np.dot(self.a1.T, delta2) db2 = (1/m) * np.sum(delta2, axis=0) delta1 = np.dot(delta2, self.W2.T) * (1 - np.power(self.a1, 2)) dW1 = (1/m) * np.dot(X.T, delta1) db1 = (1/m) * np.sum(delta1, axis=0) self.W2 -= learning_rate * dW2 self.b2 -= learning_rate * db2 self.W1 -= learning_rate * dW1 self.b1 -= learning_rate * db1 def sigmoid(self, x): # sigmoid激活函数 return 1 / (1 + np.exp(-x)) # 样本输入和输出 X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]]) y = np.array([[0], [1], [1], [0]]) # 创建神经网络对象 nn = NeuralNetwork(2, 3, 1) # 训练神经网络 for i in range(10000): output = nn.forward(X) nn.backward(X, y, learning_rate=0.1) # 测试神经网络 test_input = np.array([[0, 0], [0, 1], [1, 0], [1, 1]]) predictions = nn.forward(test_input) print(predictions) ``` 这段代码实现了一个简单的多层感知器神经网络,用于解决XOR逻辑门问题。其中`NeuralNetwork`类定义了神经网络的结构和操作,`forward`方法用于前向传播计算输出,`backward`方法用于反向传播更新权重和偏置。最后通过训练和测试数据来验证神经网络的准确性。该代码可以作为自动驾驶神经网络算法的基础,根据具体问题进行进一步扩展和优化。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值