神经网络:人工神经网络(Artificial Neural Networks,简写为ANNs)也简称为神经网络(NNs)或称作连接模型(Connection Model),它是一种模仿动物神经网络行为特征,进行分布式并行信息处理的算法数学模型。这种网络依靠系统的复杂程度,通过调整内部大量节点之间相互连接的关系,从而达到处理信息的目的。
上述图片中即为简单的前馈神经网络,主要有隐藏层,输入三个特征,输出一个特征。也就是说换句通俗的话来讲。对于这张图的释义就是输入X1,X2,X3 输出一个Y
其中,每一个节点类似于一个逻辑回归节点,换句话来说,可以认为一系列的逻辑回归节点就构成了ANN网络。
其中左侧input layer为输入数据层 右侧为输出层,真正起作用的就是中间的w权重和偏置b的不断地迭代更新,进而实现不断寻优,真正的找到,适合训练目标数据的w和b。对于神经网络,我个人的理解就是若干个人坐在一个教室里学习,中国的社会要发展,需要引进各个方向的人才,比如计算机科学,或者土建设计等等,但是在一间教室里的学生生性不同,对于有的同学或许把时间荒废了,跑到网吧里打游戏,有的同学做一些与学习知识无关的事情,等到经历三年过后,按照这个学校的规章制度认真听讲的同学们都顺利的考上了高中,而另一些同学,则就不在校园里读书了,去寻找更适合他们发展的方向。对于整个教育体制中,认真读书的那一部分同学成功考上了相关专业,满足了国家社会的大方向发展,而另一部分学生,在教育体制内就是失败的,就是被淘汰的对象。考上大学的同学,或许他高中并没有努力,考的结果并不是让他们感觉很理想,他们在大学的校园里优化高中的学习方法,化身为卷王,最终考上了一个理想大学的研究生,而到大学就不喜欢读书,自暴自弃的荒废时间就会在学习的这条路上越走越远,也就是权重的偏离,然后被淘汰掉。考上研究生的这一步同学会继续读书,继续淘汰,一直重复下去,这就是典型的人工神经网络,一直向前推进,不断地寻优,不断地更新权重,反反复复。直到找到一个合适的无限接近于完美的“科学家”。
相反的而时间倒流,让考上大学的他们重新读一次高中,会有一部分同学意识到了之前学习的问题所在,开始努力学习,考更高的分数,然后继续淘汰,反反复复,直到选择出无限接近于满分的同学,作为最优值。其中学生们经历了时间倒流,形象的说这就是反向传播,更新权重w和偏置b的过程就是找学习方法的过程。
好的,我们如今已经基本理解神经网络这个概念了。
那我们接下来具体探索神经元的工作原理
神经网络之所以这么强大,是因为他是一个非线性的方程,而线性方程的缺点就是输出结果过于单一。
神经网络的过程就是不断调整y=wx+b 不断调整w权重和b偏置,来尽可能的使输出的y无限接近于真实的y
输入层 --w1– 隐层1 -w2- 隐层2 -w3- 输出层
输出out= w3 (w2 * (w1x1+b1)+b2) + b3
其中需要注意的是,加入输入的x1是[1000,3]的矩阵,其中 w1给定的维度行数目必须等于输入的x1的特征数,列的话无所谓,b的行数无所谓,列必须和w的列一直即可,注意的是,在初始化过程中,w一般都是随机的,或者按照高斯分布来进行的,这样在反向传播过程中,每次的w都不一样,这样会增大他的迭代特性,而不至于它向一个方向发展,而有了w后就可以对其进行梯度下降,每次的w更新都是一个梯度下降后找到的最优解,而其中改变w的过程,就是梯度下降。
激活函数:将特征映射进去的一个函数,被称为激活函数。如图所示。
其中,激活函数一般表示为。
这个就是典型的激活函数,但是在之前也许他是比较合适的,但是他面临一个问题,他的最大值就是1,因为当它最大时,导数就趋于0,没有办法继续梯度下降更新w因此使用这种函数容易使神经网络在反向传播过程中陷入到局部最优的陷阱中。这是我们不想看到的结果。
所以我们如今一般都引用Relu激活函数用来机会神经元,relu的计算公式为。
Relu这个公式就不会陷入僵局,因为他的线段是直线,网络上有很多激活函数,其实就我个人来讲,都可以吧,这个东西或许影响的意义并不大,真正对他影响大的函数loss函数和梯度下降后函数,这两个函数直接影响w的变化,而我认为,最大意义的函数梯度下降函数,这个才是核心中的核心。
这就是整个网络正向传播的过程,其中最后一次输出,需要引入损失函数这一重要特征。
损失函数,也就是目标函数,顾名思义在输出时衡量输出预测值和真实值对比的一个重要函数,他返回的是一个标量用这个标量L-真实的y就等于误差。
当然,这里面的w1和w2 w1是初始化随机的w1 w2是经历一次w1X+b后然后经过激活函数后更新的w2
如果找到一个损失值为0的W,我们应该使用吗?
其实我们并关心函数在训练数据集上拟合的怎么样,我们更关心在测试数据集上的表现。如果告诉分类器你唯一的目标就是去拟合训练数据集,分类器去尽力拟合训练的数据,甚至达到很完美的地步,这其实是很糟糕的情况。因为此时如果加入一些新的数据进来,那么这个拟合曲线就很难拟合这些新的点。因此我们更加希望,分类器是那个绿色的线而非蓝色的完全拟合所有训练数据的线,蓝色的线段明显是过拟合的线。
添加正则项R(W),鼓励模型以某种方式选择更简单的W,这里的简约取决于任务的规模和模型的种类。体现了奥卡姆剃刀理论:如果你有多个可以解释你观察结果的假设,一般来讲,你应该选择最简约的,因为这样可以在未来将其用于解释新的观察结果。正则化里面最常用的就是L2正则化。
举个例子
当然,引入正则化奖惩机制会使参数寻优更好,这个类似于施工在多次对砂性土地质结构和特性进行多次勘探后,对于此处修公路其中的公路沉降系数经验公式。
好的,那这样的话完整的损失函数输出公式为
我自认为某种意义上来说,损失函数和目标函数没什么区别,简单来说吧,这里的话其实不影响的。直接调torch的包就可以了。
好的,这样我们把前向传播就都理清楚了。那么我们开始考虑反向传播及其原理所在,首先,在数据层面上无论看哪里的论文,哪位学者写的文章,相同的是他们都要进行首先得数据预处理将数据归一化,这样会提高数据的泛化能力。讲到这里不得不提一下,神经网络主要就是权重w,而偏置b的话无所谓,但是我们也要考虑一下b,不过b的话影响没有w大。
在讲反向传播之前,我们引入一个学习率这个新的参数概念。
学习率:顾名思义,即为学习能力,用正常人常理思维考虑,小步慢跑,这样的话会学的更平稳,更扎实。学的也越好。所以学习率这个参数小点设置比较好。
那么我们继续说反向传播,我们都学过高等数学,都有数学基础,那么我们想一下,真实的y–预测的y=误差,误差的话越小越好,误差是零最好,换句话来说就是没有误差,所以,那就转化为一个数学问题,就是求极值的问题,这样才能找到一个使误差值最小。那么就转为一个求偏导数的问题,多元函数叫偏导,一元函数叫导数,所以导数的意义是什么,导数的意义是研究函数的上升和下降的趋势,导数为零则取极值,取极大值或取极小值。反向传播单一神经元的过程。
这个神经元看起来好像不是那么特别清晰,解释一下,这里面输入特征x和特征y经过一次[(w1x+b1)+(w1y+b1)]后并把它作为激活函数的自变量后得到z,然后对于这个z我如何判断x和y对z的影响力度。
我举一个例子就可以很好地理解了这样一个问题,比如欧洲一个小国塞尔维亚要进行总统大选,世界很多个国家都想干预这个国家,例如:发达国家–法国,德国,俄罗斯,美国, 发展中区域性中国家—印度,印度尼西亚,沙特等 ,最不发达国家—缅甸,阿富汗等,对于塞尔维亚要大选,不出所料,美国首先要干预,而且对其影响力相当大,其次俄罗斯也要干预,影响力也较大,但是比如阿富汗缅甸等国家,即使想要干预,也有心无力,影响力很小。
这样的话就很容易的说清了反向传播的输入变量的意义。很明显的问题,求出来影响力,就会进而求得各个特征值对特征结果的影响,也就是相关性,可以这样理解,好的了解了这张图后那我们继续理解一下过程,如图所示。
这个就是单个神经元单体的简化过程。
举个例子
对于这张图首先了解一下,x+y=3 然后 3再和z相乘=3-4=-12 好,最终输出就是-12 那么我如何知道x&y&z对结果的影响力呢,答案是求导 首先 f先对z求偏导 结果=1 。所以,z对f的影响就1
然后f对x求导,x中间有一个与y相加的环节。那么假设中间变量为q,f先对q求偏导结果=z=-4 所以,q对f的影响就是-4 那么q对x求偏导=1 q对y求偏导也是1。在神经网络反向传播中,遵循链式求导法则,也就是说对于各个环节计算出的偏导值进行累乘。
所以推出x对于f的影响力为 -41 = -4
y对于f的影响力为 -41 = -4
z对于f的影响力为 1
如果w增大之后导致Loss输出增大,那就应该把w调小
如果w增大之后导致Loss输出减小,那就应该把w调大
注意:BP神经网络的反向传播是一步一步的。
那么问题就来了,如果计算单元更多怎么办,像图中这样的计算还不是特别大。如果更复杂的网络结构每一步都这么计算,比如残差网络是152层,那计算成本和耗时则很麻烦。
那就把他们全都放在一起再进行激活。这里用的是sigmoid激活函数,这个激活函数在前文提到过。
梯度下降,比如说我们在山顶,要以最快的速度下山,我们可以每一次都沿着最陡峭的方向走一步,这样一直走到山底。在数学中,我们可以用梯度这个概念来表示最陡的方向,梯度指向函数增加最快的方向,负梯度就是函数减小最快的方向。
举一个例子,就刚刚那个登山的人,他有无数种走的方法,走到山底是目标。那么需要慢慢走,然后有指南针不断地指导,再加上地图,这样就可以实现找到最低点。BP神经网络最经典的就是梯度下降法。计算公式为
但是这里我们考虑一个问题,如果每个数据输入进去都要进行更新,那么问题来了,如果这个数据是采集错误,或者是一些其他的问题导致这个数据的准确率很差,那么当传进去的时候,这个数据的误差会带给接下来的所有参数,这样使我们不想看到的现象,目标函数的选择固然重要,这样我们可以有效地避免不好的数据,但是我们解决这个问题的办法就是batchsize是每一次在数据里面取得的,然后每一个epoch进行训练和迭代。并不是每一次输入数据就进行更新。提高容错性。Y = y - α* df/dx 这个就是梯度更新表达式,其中α为学习率,应该合理设置,小点比较好吧。
随机梯度下降(SGD)的意思就是:在实际训练中,根据batch多次遍历所有训练样本,即训练不止一个epoch,对于每一个epoch,我们需要随机打乱样本次序,来增大随机性和避免巧合性。
如果单纯的正向传播不考虑反向传播,在梯度下降算法中,首先我们初始化W为随机值,当为真时,我们计算损失和梯度,然后向着梯度相反的方向更新权重W值。每次更新的步长是一个超参数,又叫学习率,就相当于每次选择最陡峭的方向走一步,这一步走多长。其实在每次走一步时,会有很多种比较高级一点更新的法则,其本质就是梯度下降,每一步都试着朝着下坡走。–这种就是人工神经网络工作原理。
这就是梯度下降优化w和b的调整权重函数。理一下逻辑,既然我们都拿到了对于输入值对输出值的影响力。何不换种更好的方式优化呢?
Softmax也称为交叉熵函数,广泛应用于分类问题,这里不过多解释,其实对于无论是分类还是回归的问题,本质上都是相同的,分类问题无非就是训练后的模型经过测试使各个类别的概率,对于离散型数据来说,输出一个概率评分最高的类别。回归问题,就是对于连续型数据进行拟合,本质上来说都是wx+b的操作
Svm也称为支持向量机,最开始被提出的时候是为了解决分类问题,对于神经网络还没出现时,svm曾紅极一时,直到现在也依然备受追捧,它本质上就是找各个类别中临近值最大的区域,越大越好。
再或者用深度学习优化方法。
总之优化算法有很多,关键是在于针对不同的优化问题,数据是连续还是离散,目标函数和约束条件的复杂程度(线性还是非线性)等,应用不同的算法。对于连续型和线性选择梯度下降法或者遗传算法,蚁群算法,模拟退火、禁忌搜索、粒子群算法等等。
注意事项:DROP-out
降低复杂度,减少过拟合风险,降低单次训练时间,增加迭代次数,使神经网络更优。
写在最后的建议
BP神经网络搭建及训练过程和若干参数设置:
-
随机梯度下降SGD
-
激活函数选择
-
训练数据初始化
-
权重w及偏置b
-
Batch Normalization
-
目标函数(损失函数)的选择
-
参数更新策略
-
随机梯度下降SGD强调一下,随机梯度下降的优点就是不用每输入一个样本就去变换参数,而是输入一批样本(叫做一个batch或者mini-batch),求出这些样本的梯度平均值后,根据这个平均值改变参数。在神经网络训练中,batch的样本数根据情况而定。
-
激活函数的选择
Sigmoid函数求导非常简单,激励性也更强,适合小样本,但容易陷入到局部最优,因为只要中间有一个环节的导数为0就没办法继续更新w
而工程实例中业内目前来说更推荐ReLU来进行激活 -
训练数据初始化
一般都是均值和方差归一化。但是总而言之吧,无论是什么数据,都直接调整为归一化之后最好。公式及表达方式如图所示。
np.mean()这个函数的意思是求平均
np.std() 这个函数的意思是求方差
axis=0这个的意思是按照行来进行计算 axis=1的话就是列
那最终表达的话就应该是
avgx= np.mean(train_x,axis=0)
sigma = np.std(train_x,axis=0)
train_x = (trian_x – avgx)/sigma
4. 权重w和偏置b在初始化中,如果激活函数选择sigmoid或tanh的时候,容易产生梯度消失现象,如果wx+b一开始很小或者很大,那么梯度将趋于0,反向传播后前面与之相关的梯度也趋于0,导致训练缓慢,因此我们要使wx一开始在0附近。这个是一个不错的选择办法。
在线性上和非线性上维持平衡,方差为5的话就有数据的95%个点 -
Batch Normalization
既然我们希望每一层获得的值都在0附近,从而避免梯度消失的现象,那么我们为什么不直接把每一层的值做基于均值和方差的归一化呢?那这样的话大多数的点都落在0 1的附近
输入和输出详细公式
完事之后在引入γ和β进行放缩,减少模型最终训练后过于线性的风险。 -
目标函数的选择
和前文提到的一样。正则项的话因项目而异。可加可不加 -
参数更新的策略
问题所在: -
常规更新随机梯度下降
for i in range(len(y)):
##计算w的偏导和b的偏导
dw= np.dot(inputs[i].T,deltas[i])
db= np.sum(deltas[i],axis=0,keepdims=True)
y[i][‘w’] = y[i][‘w’] - alphadw
y[i][‘b’] = y[i][‘b’] - alphadb
常规的随机梯度下降(SGD)更新的每一个分量获得的梯度绝对值有大有小,一些情况下将会迫使优化路径变成z字形状。 -
SGD求梯度的策略过于随机,由于上一次和下一次用的是完全不同的batch数据,将会出现优化的方向随机的情况。
Adagrad算法,RMSPro算法,SGD+Momentum算法,Adam算法
参数设置及训练建议: -
通过x经过目标函数y=1/2*(y_pre - y_test)² 得到标量E,标量E的平均值不断减小,但是如果增大则有两种情况,第一是模型不够复杂,以至于不能在训练集上完全拟合,第二是已经训练很好了,再训练下去过拟合风险很大。
-
分出一些验证集,训练的本质目标是在验证集上获取最大准确率的模型,因此在训练一段时间后,必须在验证集上测试准确率,并保存准确率高的模型参数作为最后结果。(过拟合风险增加)尽信书则不如无书。
-
注意调整学习率,如果刚训练几步标量E就增加,一般来说,学习率太高了,如果每次训练的E变化很小,说明学习率太低。
-
Batch normalization还是比较好用的,用了这个后,对学习率,参数更新不敏感,如果用Batch normalization 更新策略用最简单的SGD即可,用别的反而不好
-
由于梯度累积效应,Adagrad算法,RMSPro算法,Adam算法更新策略到训练后期会很慢,可以采用提高学习率的策略来补偿这一效应。
我自认为的BP神经网络的改进思路(个人开发经验,如有错误别信就完了):
- 通过引入优化算法给定多个初始值,训练无数个BP神经网络,直到训练出最优的结果
- 通过优化算法优化整个网络参数,直接优化人工神经网络,不引入BP的反向传播
- 通过优化算法优化全部网络,包括前向和反向,缺点是过拟合风险极大。
- 随机指定初始值,走完一轮,第一轮用传统的梯度下降,第二轮通过优化算法优化引入的初始值,然后用优化算法在正向传播里优化出比较好的初始参量,再用反向传播优化权重和偏置。再或者直接简单粗暴一点,全部用优化算法,不用传统的梯度下降了。
我自认为第四点是最好的因为有了w就要考虑梯度下降,以及优化问题了,第一次网络走完正向传播反向传播后,第二轮开始,可以改变引入数据的初始值,然后用优化方法优化出比较好的初始值,然后在反向传播中优化权重w和偏置b。这种我觉得也是最合理的。
手推过程:
参考资料
https://zhuanlan.zhihu.com/p/91322308
https://www.codenong.com/cs105189439/
https://blog.csdn.net/gdxdekx/article/details/125639667
浙江大学胡浩基老师机器学习课程
https://www.icourse163.org/course/ZJU-1206573810
附录:如需BP神经网络回归预测的代码,可以与我联系,本人只会python和C++像MATLAB本人不精通,可以给我发邮箱探讨基础问题需要代码的话直接给我发邮箱即可,备注好要问的问题,可以讲解,我的邮箱是 deyuliang0228@163.com