在接触深度学习的时候有很多新的名词,例如正向传递、反向传递、激活函数等等。深度学习中运用了很多导数计算,很多人已经把导数忘得一干二净,也有很多人对导数的了解只是皮毛,这就是为什么会让人觉得学习这门技能门槛高。我很感谢吴恩达教授开设了这么课,让我重新拾起了对数学的理解,也同时让我明白网上很多教程讲的是什么。我大概整理了一下内容,希望能给自己有更深刻的理解,同时也希望能帮助到别人。
导数
我从吴老师的课中重新认识了导数,回想读了这么多年书,书是学得很多,但却很少让人对学的这个东西有什么作用,应该怎么去用,在课堂上很乏味的带过。在之前看了一个台湾教授在讲解深度学习的时候,通过解析当下学生最热门的《pokemon go》,以抓到的宠物以进化后的性价比为课题来讲解。我在想如果当今教育能更加有趣一点。我相信会更加多的人为我们创造更好的未来。
导数其实讲的是该函数在某个点的斜率。
导数反应的变化率:一个函数在某一点的导数描述了这个函数在这一点附近的变化率。导数的本质是通过极限的概念对函数进行局部的线性逼近。
吴老师也在视频中讲到移动0.001只是为了更直观的发现数值移动一小步尝试的变化。可能是0.0000000001甚至更小。
在函数 y = kx + b 中呈现的是一条直线,直线上的任何一个点的斜率都为k
在曲线函数中 y = x^2 中,斜率就相对复杂了起来
直线 f(a) = 3a
当a = 2 f(a)= 6
当a = 2.001 f(a)= 6.003
当a移动0.001 ,f(a)移动0.003 代表斜率(导数) 在a=2时,斜率(导数)为3
曲线 f(a) = a^2
a = 2 ==> 4
a = 2.001 ==> 4.004
a = 5 ==> 25
a = 5.001 ==> 25.010
当a在2移动0.001 ,f(a)移动0.004 代表斜率(导数) 在a=2时,斜率(导数)为4
当a在5移动0.001 ,f(a)移动0.010 代表斜率(导数) 在a=5时,斜率(导数)为10
当我们拿出教科书中的公式代入后发现是成立的
3a ==> 3
a^2 ==> ( d / da )* a^2 = 2a
a^3 ==> ( d / da )* a^3 = 3a^2
为什么深度学习需要导数呢
这个其实就要抛出深度学习的两个很重要的思想 ——正向传播 反向传播
在整个模型训练过程中先是正向传播 接着再 反向传播步骤 (从左到右计算J函数的的值,从右到左计算计算导数)
正向传播
J(a,b,c) = 3(a+b*c)
1. u = b * c
2. v = a + u
3. J = 3v
a ( a ) ==> (v = a+u) ==> 3v
b ==> (u = b*c) ==>
c ==>
a =5 ( 5 ) ==> (v = 5+6) ==> (3v = 3*11)
b =3 ==> (u = 2*3) ==>
c =2 ==>
函数J = 3(a+b*c) 中先乘除后加减分解为 123步, 通过b与c得到u,在通过u与a 得到v,以此类推算出J 这是我们正常的计算逻辑。
反向传播
反向传播(从右到左,计算J函数导数)
dJ/ dv ==> J对v的导数
J = 3v
v = 11 ==> 11.001
J = 33 ==> 33.003 J对v的导数是3
dJ/ da ==> J对a的导数
a = 5 ==> 5.001
v = 11 ==> 11.001
J = 33 ==> 33.003 J对a的导数是3
...
...
...
dJ/dv = 3 斜率=3
dJ/du = 3 斜率=3
dJ/da = 3 斜率=3 当a的值变大1时 J比原来变大3倍
dJ/db = 6 斜率=6 当b的值变大1时 J比原来变大6倍
dJ/dc = 9 斜率=9 当c的值变大1时 J比原来变大9倍
你是否刚开始也跟我一样,为什么要求斜率呢,斜率有什么作用呢,这个时候抛出一个想法。
我们人类经过了不停的学习,一只猫一只狗站在我们面前,我们如何去分辨是猫是狗呢,有两个眼睛,叫声不同。。。但是真的能很好的去描述出来吗,描述出来就一定是对的吗。深度学习通过根据不同的特征及目标值不断的去训练,无需告诉计算机计算公式,也无需告诉计算机计算步骤,让计算机自己去学习,自己去判别,我们只需要收集大量的数据交给计算机就可以了。
如上面的反向传播例子。计算机只要计算出a,b,c的导数就可以去预测目标值。
刚开始,a,b,c的导数可能是与实际相差很远。通过大量的数据去训练 不停的去更新
深度学习
不必太过担心自己对导数的计算去烦恼,计算机会去帮我们处理这些问题,不然还需要计算机干什么呢,我们只需要了解为什么导数能解决深度学习去训练的方式,在以后不停的实践后再慢慢的去探索总结,不断的提升,相信这些都不是什么事。
在训练模型的时候除了上面提到的通过正向传递、反向传递的传播过程,还抛出了激活函数,损失函数,梯度下降这三个,通过这三个来完成深度学习的正向传递、反向传递传播。
激活函数
在定义层(函数)的时候,在每一层计算后都会加上一个激活函数,激活函数可以让你的神经网络计算出有去的函数,如果没有激活函数,该网络只能够表现出线性映射,就算有再多的隐藏层,整个网络与单层网络是等价的。
sigmoid 0 到 1 之间 用于二元分类 输出层(0 - 1)
tanh -1 到 1 之间 激活函数的平均值就更接近于0 使用tanh而不是sigmoid函数也有类似数据中心化的效果,使数据的平均值更接近0 让下一层学习更加方便
*sigmoid 和 tanh 都有一个缺点 如果Z非常大或非常小 那么导数的梯度 或者说这个函数的斜率可能就很小,函数的斜率很接近0 这样就会拖慢梯度下降算法
ReLU 0 到 无穷大 当z为负数的时候,导数等于0
*如果你的输出值是0和1那么sigmoid函数很适合做为输出层的激活函数,然后其他所有单元都用ReLU(修正线性单元)
损失函数
损失函数(loss function)是用来估量你模型的预测值f(x)与真实值Y的不一致程度,它是一个非负实值函数,通常使用L(Y, f(x))来表示,损失函数越小,模型的准确性就越好。损失函数是经验风险函数的核心部分,也是结构风险函数重要组成部分。
常用的损失函数有 平均差 ,交叉熵
梯度下降
梯度下降法是一个算法,通常也称为最速下降法。最速下降法是求解无约束优化问题最简单和最古老的方法之用负梯度方向为搜索方向的,最速下降法越接近目标值,步长越小,前进越慢。
/*
logistic : 二分类
sigmoid : 让数值在 0 到 1 之间
*/
//****************** 激活函数 ********************//
//y^ = w * x + b
//y^有可能比1大得多,或者甚至为负数,在二分类中我们希望介于0到1之间
//所以在logistic回归中,我们的输出变成
// Z = w * x + b //计算预测值Z
// y^ = sigmoid( Z ) //通过非线性函数让 Z 值,符合我们的要求
//* 当Z值在0时,垂直轴相交0.5处 Z值越大越接近1 Z值越小越接近0
//****************** 成本函数 ********************//
//成本函数用于衡量算法运行情况
// Loss = 平均交叉熵