• 机器学习入门(七)神经网络--代价函数、前向反向传播算法及问题


    目录

    一、代价函数

    1.1 问题介绍

    1.2 代价函数介绍

    二、前向传播与反向传播 

    2.1 我们要做的事情

    2.2 理解前向传播        

    2.3 理解反向传播

    2.4 利用前向传播与反向传播实现神经网络 

    2.5 举例 

    三、梯度检验 

    3.0 什么是梯度检测

    3.1 方法:用数值逼近导数(数值上求近似导数)

    3.2 结论 

    四、随机初始化 

    4.1 为什么需要随机初始化

    4.2 随机初始化要做什么 

    五、本章在做什么呢? 


    一、代价函数

    1.1 问题介绍

            对于一元分类问题,比如我们上节判断两个数是不是异或关系。

            又如多元分类,我们正如上节说的,我们输出这是个鸡鸭鹅或者是什么,我们不能输出1,2,3。我们输出一个R4" role="presentation" style="position: relative;">R4向量(0/1),比如第一维是1就是鸡......。

            然后我们上次得到的θ" role="presentation" style="position: relative;">θ值都不是经过训练过的,因此我们要训练θ" role="presentation" style="position: relative;">θ值,也要获得获得训练出θ" role="presentation" style="position: relative;">θ值的好坏因此我们要获得代价函数。那么就让我们看看都怎么做吧!

    1.2 代价函数介绍

    逻辑回归的代价函数如下:

    ȷ(θ)=1m[i=1m(y(i)log(hθ(x(i)))+(1y(i))log(1hθ(x(i)))]+λ2mj=1nθj2" role="presentation" style="position: relative;">ȷ(θ)=1m[i=1m(y(i)log(hθ(x(i)))+(1y(i))log(1hθ(x(i)))]+λ2mj=1nθj2

    仿照逻辑回归的代价函数,我们仿写出逻辑回归的代价函数:

    ȷ(Θ)=1m[i=1mk=1Kyk(i)log(hΘ(x(i)))k+(1yk(i))log(1(hΘ(x(i)))k)]+λ2ml=1L1i=1slj=1sl+1(Θji(l))2" role="presentation" style="position: relative;">ȷ(Θ)=1m[i=1mk=1Kyk(i)log(hΘ(x(i)))k+(1yk(i))log(1(hΘ(x(i)))k)]+λ2ml=1L1i=1slj=1sl+1(Θji(l))2

    其中:hΘ(x)Rk    (hΘ(x))i=ith Output" role="presentation" style="position: relative;">hΘ(x)Rk    (hΘ(x))i=ith Output

            解释:

    二、前向传播与反向传播 

    2.1 我们要做的事情

            我们得到了神经网络的代价函数:(后文有解释这是怎么推出来的)

            这里K" role="presentation" style="position: relative;">K是输出的分类结果,m" role="presentation" style="position: relative;">m是样本个数,L" role="presentation" style="position: relative;">L是神经网络层数,sl" role="presentation" style="position: relative;">sl为在l" role="presentation" style="position: relative;">l层的单元。

    ȷ(Θ)=1m[i=1mk=1Kyk(i)log(hΘ(x(i)))k+(1yk(i))log(1(hΘ(x(i)))k)]+λ2ml=1L1i=1slj=1sl+1(Θji(l))2" role="presentation" style="position: relative;">ȷ(Θ)=1m[i=1mk=1Kyk(i)log(hΘ(x(i)))k+(1yk(i))log(1(hΘ(x(i)))k)]+λ2ml=1L1i=1slj=1sl+1(Θji(l))2

            我们要求的是θ" role="presentation" style="position: relative;">θ使得minΘȷ(Θ)" role="presentation" style="position: relative;">minΘȷ(Θ)

            因此要编码去求ȷ(Θ)" role="presentation" style="position: relative;">ȷ(Θ)Θij(l)" role="presentation" style="position: relative;">Θij(l)。 

    2.2 理解前向传播        

             我们给定一个数据(x,y)" role="presentation" style="position: relative;">(x,y),神经网络系统在做如下的事情。

            为了方便标记,我们把输入x" role="presentation" style="position: relative;">x作为第一层的激活项,即a(1)=x" role="presentation" style="position: relative;">a(1)=x,然后前向传播,计算第二层的激活项即a(2)=g(z(2)),z(2)=Θ(1)a(1)=(θ0,θ1)(1,x)T" role="presentation" style="position: relative;">a(2)=g(z(2)),z(2)=Θ(1)a(1)=(θ0,θ1)(1,x)T 。然后最终得到输出a(4)" role="presentation" style="position: relative;">a(4)也就是y" role="presentation" style="position: relative;">y

            在这一步中,我们得到了每一层的输出值。

    2.3 理解反向传播

            反向传播是用于计算代价函数的,如下图所示:

            我们定义误差项δj(l)" role="presentation" style="position: relative;">δj(l)为在l" role="presentation" style="position: relative;">l层第j" role="presentation" style="position: relative;">j个节点的误差。

            对于第四层,我们假设只有一个输出节点δj(4)=aj(4)yj" role="presentation" style="position: relative;">δj(4)=aj(4)yj,误差为第四层的输出值-真值y。

            对于第三层的误差,我们只给出最终结果(推导较难)δj(3)=(Θ(3))Tδ(4).g(z(3))" role="presentation" style="position: relative;">δj(3)=(Θ(3))Tδ(4).g(z(3))

            对于第二层的误差,我们只给出最终结果(推导较难)δj(2)=(Θ(2))Tδ(3).g(z(2))" role="presentation" style="position: relative;">δj(2)=(Θ(2))Tδ(3).g(z(2))

            δj(i)" role="presentation" style="position: relative;">δj(i)为第i" role="presentation" style="position: relative;">i层的所有节点的误差,即每一个节点的误差为该层下一层可学习参数的向量与反向穿播得到的误差进行点乘,再点乘激活函数的导数。

    2.4 利用前向传播与反向传播实现神经网络 

            我们有m" role="presentation" style="position: relative;">m个训练集。先将可叠加误差项ij(l)" role="presentation" style="position: relative;">ij(l)初始化为0,它被用来计算偏导项Θij(L)ȷ(Θ)" role="presentation" style="position: relative;">Θij(L)ȷ(Θ),意思为对第L" role="presentation" style="position: relative;">L层的第j" role="presentation" style="position: relative;">j个参数Θ(Θij)" role="presentation" style="position: relative;">Θ(Θij)求偏导,如下图:

            至此,我们来总结一下这个算法到底在做什么:对于每一个数据,我们先利用前向传播计算出每一个节点的激活项。我们用反向传播计算出最后一层的误差δ(L)" role="presentation" style="position: relative;">δ(L),我们用这个误差值乘以训练参数再计算出前一层的误差向量δ(L1)" role="presentation" style="position: relative;">δ(L1) ,我们按照这样算出所有层的误差向量,将每一个样本的误差aj(l)δi(l+1)" role="presentation" style="position: relative;">aj(l)δi(l+1)(第i个样本的第l层第j列节点的误差)  累计得到ij(l)" role="presentation" style="position: relative;">ij(l),最终除以样本数量得到对于每个节点的累计误差,我们也就得到了对每个学习参数的偏导。从而我们也就能通过梯度下降法来寻找最优解完成学习任务。

    2.5 举例 

            正向传播:以z1(3)" role="presentation" style="position: relative;">z1(3)的获得为例子:z1(3)=+1Θ02(2)+a1(2)Θ12(2)+a2(2)Θ22(2)" role="presentation" style="position: relative;">z1(3)=+1Θ02(2)+a1(2)Θ12(2)+a2(2)Θ22(2),再根据激活函数a13=g(z1(3))" role="presentation" style="position: relative;">a13=g(z1(3))得到下一层的输入,经过这些步骤,我们前向计算得到了每一个节点的激活值和最终的分类输出结果。

            我们再前面得出:δj(l)" role="presentation" style="position: relative;">δj(l)aj(l)" role="presentation" style="position: relative;">aj(l)的误差项(第l" role="presentation" style="position: relative;">l层的第j" role="presentation" style="position: relative;">j个节点),学过高等数学的同学可能指导,我们所算的δj(l)" role="presentation" style="position: relative;">δj(l)其实就是代价函数关于zj(l)" role="presentation" style="position: relative;">zj(l)的偏导数

            反向传播:以δ1(4),δ2(2)" role="presentation" style="position: relative;">δ1(4),δ2(2)的获得为例子:δ1(4)=y(i)a1(4)" role="presentation" style="position: relative;">δ1(4)=y(i)a1(4)这个很好理解,最终节点的误差就是我们的神经网络输出值与实际值的插值。δ2(2)=Θ12(2)δ1(3)+Θ22(2)δ2(3)" role="presentation" style="position: relative;">δ2(2)=Θ12(2)δ1(3)+Θ22(2)δ2(3),这个也很好理解,我们把误差反向传播,和前向传播相似。

    三、梯度检验 

    3.0 什么是梯度检测

            在神经网络或其他复杂的模型下使用前向传播,反向传播时,如果使用梯度下降来寻找参数,那么使用梯度检测会100%地消除梯度下降过程中产生的bug。

    3.1 方法:用数值逼近导数(数值上求近似导数)

            有一个代价函数J(Θ)" role="presentation" style="position: relative;">J(Θ),在横轴上取一点θ(θR)" role="presentation" style="position: relative;">θ(θR),则这一点的导数对应于图像上在该点的切线斜率,如下图:   

            计算该点切线的斜率,可以做一个近似,即:

            在θ" role="presentation" style="position: relative;">θ附近分别取点θ+ε" role="presentation" style="position: relative;">θ+εθε" role="presentation" style="position: relative;">θε(易知ε" role="presentation" style="position: relative;">ε为很小的值),两点在曲线上表现为 (θ+ε,J(θ+ε))" role="presentation" style="position: relative;">(θ+ε,J(θ+ε))(θε,J(θε))" role="presentation" style="position: relative;">(θε,J(θε)),两点的割线斜率即可近似为θ" role="presentation" style="position: relative;">θ点在曲线上的切线斜率。即双侧差分:

    J(θ+ε)J(θε)2ε" role="presentation" style="position: relative;">J(θ+ε)J(θε)2ε

             考虑更普遍的情况,参数θ" role="presentation" style="position: relative;">θ为向量参数的时候也很好理解,如下图:

            其实如果加上limε0" role="presentation" style="position: relative;">limε0就是偏导数定义了。 

    3.2 结论 

            之后,检查这个得到的θ" role="presentation" style="position: relative;">θ向量导数值(gradApprox)和通过反向传播计算出的偏导项进行比较,如果相等或在数值上近似等于,那么就可以确定反向传播的实现(或使用其他高级算法计算出来的偏导数)是正确的。(等于的阈值是多少,那就交给调参侠了啊哈哈哈)

            那么总的来说,梯度检测的步骤如下:

            ①反向传播得到各个节点的误差项

            ②利用梯度检测算出偏导数

            ③看看误差和偏导数差的大不大

            ④梯度检测消耗资源很大,记得确认在反向传播代码无问题的时候关闭接口。

    四、随机初始化 

    4.1 为什么需要随机初始化

            对于一个模型来说,当执行梯度下降法或者高级算法时,我们需要对初始化参数Θ" role="presentation" style="position: relative;">Θ初始一个值,对于梯度下降法也是如此,给予梯度下降法初始参数后,就能一步步通过梯度下降来最小化代价函数J(Θ)" role="presentation" style="position: relative;">J(Θ),但怎样初始化就成了一个难题。

    4.2 随机初始化要做什么 

            我们先考虑一个问题:如果将参数都初始化设置为0会有什么问题呢?首先进行正向传播,第一层的激活项经过计算都是相同的且都是0,经过反向传播,误差项也相等,偏导数也相等.....因此经过每次更新以后,这两个隐藏单元的每个参数输入都相等的。即使利用梯度下降进行了一次迭代,这两个隐藏单元依然以相同的函数输入作为计算。他们会一直相等下去.....

            解决方法是我们要进行随机初始化。如上图所示。

            因此,为了训练神经网络,首先要将权重随机初始化为一个接近0的范围在(ε,+ε)" role="presentation" style="position: relative;">(ε,+ε)中的数,然后进行反向传播、梯度检验,最后使用梯度下降来最小化我们的代价函数。 

    五、本章在做什么呢? 

            当训练一个神经网络时,我们第一步做的就是选择一种网络架构(神经元之间的连接方式):一般来说,我们只设置一个隐藏层,若设置多个隐藏层,每一层神经元的数量应该相等,如下图所示:

            第二步:构建一个神经网络并初始化权重(随机法)

            第三步:执行前向传播算法

            第四步:计算出代价函数JΘ" role="presentation" style="position: relative;">JΘ

            第五步:执行反向传播算法计算偏导数们

            第六步:梯度检查

            第七步:用梯度下降或是其他优化方法最小化代价函数

  • 相关阅读:
    hive-on-spark
    对象映射 - Mapping.Mapster
    Xilinx FPGA 编程技巧之常用时序约束
    python和go相互调用的两种方法
    线程是如何实现的?
    【DataEase】“宇宙最强” 零代码数据可视化分析工具的安装部署保姆级教程
    8月一次阿里云的Java面试凉经(止步三面)
    计算机网络复习——第六章网络层
    【Java成王之路】EE初阶第二十三篇: HTTP协议和Tomcat
    C. Bouncing Ball(从后往前的前缀和)
  • 原文地址:https://blog.csdn.net/qq_41694024/article/details/127733302