深入理解逻辑回归Logistic Regression后,能更好理解神经网络Neural Network,吴恩达的课程对神经网络的讲解相对清晰,原理性和推导都很好理解。
我一直认为好老师标准不在于拥有多深奥的知识,而在于能否良好的传授,不仅仅是知识,而是学习的思路。独孤九剑还需要好老师传授才能发扬广大~。
网易:http://study.163.com/course/courseMain.htm?courseId=1004570029
coursera原版:https://www.coursera.org/learn/machine-learning
笔记包括:
课程理论学习
延展分析
1. 算法学习
深度神经网络大爆发是在2012年AlexNet之后,所以这门神经网络课程,还是经典的多层感知机MLP,前向人工神经网络和反向传播模式。
人工神经网络算是深度学习中一种,神经网络的分支和演进算法很多种,从著名的卷积神经网络CNN,循环神经网络RNN,再到对抗神经网络GAN等等。多层感知机MLP已经out了,但是我认为深入学习和理解其原理,对于后续学习其他的深度学习算法有帮助。
下文“神经网络”默认指吴恩达老师课程中的多层感知机,全连接模式的人工神经网络。
1.1 概览
神经网络,源自于生物学对人脑的研究。人脑对现实的理解是从简单特征提取神经元(简单细胞)到逐渐复杂的特征提取神经元(复杂细胞)的层级连接结构。
神经元其实3个核心功能,接受外部传来的数据,经过处理后,输出给(别的神经元)。从程序上来说就是输入,输出和处理。
只能说是神经网络类似于人类的神经网络,人类的大脑神经元的工作原理还是一个谜,所以现在所谓的神经网络只是形似人类神经网络,实际工作机制就不见得是这样了,未来人类的生物科学更深入后,估计能解这个问题,不过到时估计已经能够有更强悍的算法了。
1.2 与逻辑回归Logistics Regression的关系
逻辑回归是构建一组权重参数θ,使得h(x)=θ'X预测函数尽可能的拟合测试数据(输入层),得到一个较准确的预测值(输出层)。
看下典型的神经网络图:Layer1是输入,Layer4是输出,而Layer2、Layer3是隐层,隐层可以有多个。假设只有Layer3和Layer4的时候,就是一个经典的逻辑回归问题,得到一组权重θ。那Layer1和Layer2之间,红色标注的就是一个逻辑回归,Layer1和Layer2是全连接的(每个都连接),所以就是3组θ。
所以损失函数(代价函数)也就是逻辑回归的变形,通过多个隐层的设计,能够更好的拟合测试数据。理论上当隐层越多,效果更好(实际上不是)。
激活函数和逻辑回归一样采用了sigmoid函数作为激活函数:
g(z)=1/(1+e^(-z))
除了sigmoid作为激活函数外,还有sigmoid变形tanh,以及ReLU:f(x)=max(0,x)等,后面有机会再展开聊。
1.3 公式推导
这里没有复杂的计算公式推导,只有大致理论上推导,适合小白(需懂逻辑回归)。从逻辑回归的公式:
z=θ'X %权重和输入的内积
a=g(z)=1/(1+e^(-z)) %激活函数sigmoid,也可使用tanh等
推导过程如下:
记录a(j)为对应j层的神经元,简书写不出来上坐标,只能凑合看了,具体的a(j)层对应的神经元是:
z(2)=θ'a(1)
a(1)=X
a(2)=g(z(2)) %加上激活函数后
以往的逻辑回归的θ,基本上是1x(n+1)维,现在由于全连接下,就变成了mx(n+1)维,如上图的θ(1)为第一层Layer1的权重,3x4的矩阵,第j层到下一层j+1的权重记录为θ(j),θ(j)的维度是s(j+1) x (s(j)+1) ,m=s(j+1),n=s(j)+1。
采用前向传播Forward Progagation(简称FP)算法(概念不重要),假设我们任意初始化θ,就可以推导出整个计算过程。
先计算中间值z(j+1)=θ'a(j), a(1)=x;之后经过激活函数g(z(j+1))后,就得出a(j+1)的值,最后a(3)就是h(x)=g(z(3))预测值。
代价函数就变成最后一层a(3)=g(z(3))与y值之间的对比差异了,使用逻辑函数的代价函数,如果有多个输出(多分类的方式),就需要加入总的k分类差异:
采用梯度下降法,求得J(θ)一阶导:
在求这个值的过程中,使用了反向传播BP(back propagation)的方法进行计算。反向传播的原理就是从最后一层开始,计算错误(偏差)值,最后一层的错误值δ(L):就是预测值-实际值的误差。
那么最后的J(θ)一阶导就等于(忽略正则化参数):
整个计算过程如下:
核心是计算出梯度下降的值Δ,通过计算错误δ,求得∂J(Θ)/∂(Θ)。
(1)初始化各层的梯度下降值Δ为0
(2)随机初始化Θ(含各层)
(3)初始化a(1)=x,通过FP前向传播方式,计算最后一层的输出值a(L)
(4)计算各层错误值δ(L),δ(L−1),δ(L−2),…,δ(2),通过算法:
δ(l)=((Θ(l))δ(l+1)) .∗ a(l) .∗ (1−a(l))
(5)得到每一层的Θ梯度下降值
Di,j(l):=1/m*(Δi,j(l)+λΘi,j(l)) If j≠0
Di,j(l):=1/m*Δi,j(l) if j=0
2. 延展分析
多层神经网络MLP是非常经典的神经网络算法,在推导公式过程中需要使用线性代数、向量微积分等理论推导。吴恩达老师的这个教材里面没有解释,在他的另外课程《深度学习工程师》-01神经网络和深度学习中- 《3.10 (选修)直观理解反向传播》中有详细的介绍。其实就是反向使用链式求导的方式。
课程地址:
原版:https://www.deeplearning.ai/
网易:http://mooc.study.163.com/smartSpec/detail/1001319001.htm
2.1 公式推导解析
下面通过链式求导的方式解析公式,如果激活函数g(z)是sigmoid的话有一下特性:
dg(z)/dz=a(1-a)
从最后一层a(l)看,我们要不断的计算Θ下降值,(忽略正则项)
dJ/dΘ(l)=dJ/da(l) x da(l)/dz(l) x dz(l)/Θ(l)
dJ/dz(l)=dJ/da(l) x da(l)/dz(l); % 代入J=-((y)log(a(l))+(1-y)log(1-a(l)), da(l)/dz(l)=dg(z)/dz=a(1-a)
dJ/dz(l)=(-y/a+ (1-y)/(1-a)) a(1-a)=a-y
dz(l)/Θ(l)= a(l-1)' a(l-1)转置
dJ/dΘ(l)=(a-y) a(l-1)' %如此反复推导得到dJ/dΘ(l-1),dJ/dΘ(l-2)...
有一位网友ooon做的剖析也很全面:
https://www.cnblogs.com/ooon/p/5577241.html
2.2 激活函数
有关激活函数问题:sigmoid和tanh,ReLU,Leak ReLU等,早期使用sigmoid比较多,也是课程所推荐的。最新课程,大部分使用了ReLU算法,只有最后一层输出逻辑回归2元预测时采用sigmoid,中间隐层大多使用ReLU算法。
1. Sigmoid能够把输入的连续实值“压缩”到0和1之间,非线性函数,使用时间很长,但存在缺点:当输入非常大或者非常小的时候,这些神经元的梯度是接近于0的,从图中可以看出梯度的趋势。所以,如果初始值很大的话,梯度接近0,信息会丢失,会导致网络变的很难学习。
2. 采用sigmoid算激活函数时(指数运算),计算量大,反向传播求误差梯度时,求导涉及除法,计算量相对大(tanh也是),而采用Relu激活函数,整个过程的计算量节省很多。
3. ReLU=max(0,z),还有在此基础上改进的Leaky ReLU=max(0.01z,z)。
经过激活函数ReLU处理的数据效果如下:
ReLU从单侧抑制了数据,从图左可以看出,输入信号时,输出都是0, 的情况下,输出等于输入。并且具有相对宽阔的兴奋边界,避免sigmoid的数值大梯度趋零问题。而且由于其简单性,在随机梯度下降SGD下,计算性能很高。
所以新课程中吴恩达老师推荐默认情况下使用ReLU激活函数,最后输出可以使用别的函数替换,如sigmoid或者tanh。
相比sigmoid/tanh,ReLU 缺点:训练的时候很容易就”die”。也就是说上文中learning rate 很大(上文中λ值),那么很有可能网络神经元会”dead”。 如果设置合适的较小learning rate,问题发生的可能性降低,吴恩达老师特意提出使用较小学习率,ReLU其他变种是为了避免die的问题。大部分情况下使用ReLU就够用了。
3. 小结
相比传统的经典机器学习算法,神经网络是我最为耗费心力学习的重要算法,对于数学已还给体育老师的我,不得不重新捡起高等数学、微积分、线性代数等数学课程。看来数学不好,搞人工智能是不现实的。
记得有人说过:吃不了学习的苦,就要吃生活的苦~ 共勉!