机器学习系列课程-深度学习导论
目录
正文
Advanced machine learning specialization 机器学习专业化进阶
一、线性模型
线性模型一般用于回归和分类
1.1 回归

如图所示,回归主要是完成对数据的拟合。



1.2 分类

如上图所示,用直线进行分类。

先通过似然函数,了解二项逻辑回归函数的来由。





1.3 梯度
对于单个样例\((x,y)\),其代价函数为:
\[J(W,b;x,y) = \frac{1}{2}||h_{W,b}(x)-y||^2\]给定一个包含m个样例的数据集,整体代价函数为:
\[J(W,b) = [\frac{1}{m}\sum_{i=1}^{m}J(W,b; x^{(i)}, y^{(i)})] + \frac{\lambda}{2}\sum_{l=1}^{n_l-1}\sum_{i=1}^{s_l}\sum_{j=1}^{s_l+1}(W_{ji}^{(l)})^2\]目标是针对参数W和b来求其函数 \(J(W,b)\) 的最小值。
为了求解神经网络,需要将每一个参数 \(W^{(l)}_{ij}\) 和 \(b^{(l)}_{i}\) 初始化为一个很小的、接近零的随机值。
比如使用正态分布 \(Normal(0, \sigmoid^2)\) 生成的随机值, \(\sigmoid = 0.01\),这里注意:要将参数进行随机初始化,而不是全部置为0.
如果所有参数都用相同的值作为初始值,那么所有隐藏层但愿最终会得到与输入值有关的、相同的函数。即(对于所有的i,\(W^{(1)}_{ij}\)都会取相同的值,那么对于任何输入x,都会有\(a^{(2)}_{1}=a^{(2)}_{2}=a^{(2)}_{3}=...\)。 随机初始化的目的是使对称失效。
之后对目标函数使用诸如批量梯度下降法的最优化算法。
有时候 \(J(W,b)\) 是一个非凸函数,梯度下降法很可能会收敛到局部最优解。
但是在实际应用中,梯度下降法通常能得到令人满意的结果。
梯度下降法中每一次迭代都按照如下公式对参数 \(W\) 和 \(b\) 进行更新:
\[W^{(l)}_{ij} = W^{(l)}_{ij} - \alpha \frac{\partial}{\partial{W_{ij}^{(l)}}} J(W,b)\] \[b^{(l)}_i = b^{(l)}_i - \alpha \frac{\partial}{\partial{b_{i}^{(l)}}} J(W,b)\]其中 \(\alpha\) 是学习速率。关键步骤是计算偏导数。
反向传播算法是计算偏导数的一种有效方法。
反向传播算法的思路如下:
1、给定一个样例(x,y),首先进行“向前传导”运算,计算出网络中所有的激活值,包括\(h_{W,b}(x)\)的书持之。
2、之后,针对第l层的每一个节点i,计算出其“残差” \(\sigma^{(l)}_i\),该残差表明了该节点对最终输出值的残差产生了多少影响
3、对于最终的输出节点,我们可以直接算出网络产生的激活值与实际值之间的差距,将其定义为 \(\sigma^{(n_l)}_i\)
计算过程如下:
1、进行前馈传导计算,利用前向传导公式,得到 \(L_2, L_3 ...\) 直到输出层 \(L_{n_l}\) 的激活值
2、对于第\(n_l\)层(输出层)的每个输出单元i,我们根据以下公式计算残差:
\[\sigma^{(n_l)_i = \frac{\partial}{\partial{z^{(n_l}_i}}J(W,b;x,y) = \frac{\partial}{\partial{z^{(n_l}_i}}\frac{1}{2}||y - h_{W,b}(x)||^2 = \frac{\partial}{\partial{z^{(n_l}_i}}\frac{1}{2}\sum_{j=1}^{S_{n_l}}(y_j - a_j^{(n_l)})^2 = \frac{\partial}{\partial{z^{(n_l}_i}}\frac{1}{2}\sum_{j=1}^{S_{n_l}}(y_j - f(z_j^{(n_l)}))^2 = -(y_i - f(z_i^{(n_l)}))·f^{'}(z_i^{(n_l)}) = -(y_i - a^{(n_l)})·f^{'}(z_i^{(n_l)})\]3、对 $$ l = n_l-1,n_l-2, n_l-3, …, 2的各个层,第l层的第i个节点的残差计算方法如下:
\(\sigma^{(n_l-1)}_i\) \(= \frac{\partial}{\partial{z_i^{(n_l-1)}}}J(W,b;x,y)\)
\[= \frac{\partial}{\partial{z_i^{(n_l-1)}}}\frac{1}{2}||y-h_{W,b}(x)||^2\] \[= \frac{\partial}{\partial{z_i^{(n_l-1)}}}\frac{1}{2}\sum_{j=1}^{S_{n_l}}(y_j - a_j^{(n_l)})^2\] \[= \frac{1}{2}\sum_{j=1}^{S_{n_l}}\frac{\partial}{\partial{z_i^{(n_l-1)}}}(y_j - a_j^{(n_l)})^2\] \[= \frac{1}{2}\sum_{j=1}^{S_{n_l}}\frac{\partial}{\partial{z_i^{(n_l-1)}}}(y_j - f(z_j^{(n_l)}))^2\] \[= \sum_{j=1}^{S_{n_l}}-(y_j-f(z_j^{(n_l)})·\frac{\partial}{\partial{z_i^{(n_l-1)}}}f(z_j^{(n_l)})\] \[= \sum_{j=1}^{S_{n_l}}-(y_j-f(z_j^{(n_l)})·f^'(z_j^{(n_l)})·\frac{\partial{z_j^{(n_l)}}{\partial{z_i^{(n_l-1)}}}\] \[= \sum_{j=1}^{S_{n_l}}\sigma^{(n_l)}_j·\frac{\partial{z_j^{(n_l)}}{\partial{z_i^{(n_l-1)}}}\] \[= \sum_{j=1}^{S_{n_l}}(\sigma^{(n_l)}_j·\frac{\partial{\partial{z_i^{(n_l-1)}}}\sum_{j=1}^{S_{n_l-1}}f(z_k^{(n_l-1)})·W_{jk}^{(n_l-1)})\] \[= \sum_{j=1}^{S_{n_l}}\sigma^{(n_l)}_j·f(z_i^{(n_l-1)})·W_{ji}^{(n_l-1)}\] \[= (\sum_{j=1}^{S_{n_l}}W_{ji}^{(n_l-1)}\sigma^{(n_l)}_j))·f^'(z_i^{(n_l-1)})\]将上式中的\(n_l-1\)与\(n_l\)的关系,就可以得到:
从这个公式,明显看到是逐次从后向前求导的过程,也称为反向传导
\[\delta^{(l)}_i = (\sum_{j=1}^{S_{n_l}}W_{ji}^{l}\delta^{(l+1}_j))f^'(z_i^{l})\]4、计算需要的偏导数,计算方法如下:
\[\frac{\partial}{\partial{W^{(l)}_{ij}}}J(W,b;x,y)=a^{(l)}_j\delta^{(l+1)}_i\] \[\frac{\partial}{\partial{b^{(l)}_{i}}}J(W,b;x,y)=\delta^{(l+1)}_i\]写成矩阵的形式,反向传播算法可表示为以下几个步骤:
1、进行前馈传导计算,利用前向传导公式,得到\(L_2\),\(L_3\),…直到输出层\(L_{n_l}\)的激活值
2、对输出层(第\(n_l\)层),计算:
\[\delra^{(n_l)} = -(y-a^{(n_l)}·f^'(z^{(n_l)})\]3、对于\(l=n_l-1, n_l-2, n_l-3,...,2\)的各层,计算:
\[\delta^{(l)}=((W^{(l)})^T\delta^{(l+1)}·f^'(z^{(l)}))\]4、计算最终需要的偏导数值:
\[\nabla_{W^{(l)}}J(W,b;x,y)=\delta^{(l+1)}(a^{(l)})^T\] \[\nabla_{b^{(l)}}J(W,b;x,y)=\delta^{(l+1)}\]下面,实现批量梯度下降法中的一次迭代:
1、对于所有\(l\),令\(\Delta_W^{(l)}:=0\),\(\Delta_b^{(l)}:=0\) (设置为全零矩阵或全零向量,不应该是正态随机数吗)
2、对于\(i=1\)到\(m\),
a. 使用反向传播算法计算 $$\nabla_W^{(l)}J(W,b;x,y)$$和$$\nabla_b^{(l)}J(W,b;x,y)$$
b. 计算$$\Delta W^{(l)}:=\Delta W^{(l)}+\nable_W^{(l)}J(W,b;x,y)$$
c. 计算$$\Delat b^{(1)}:=\Delat b^{(l)}+\nabla_b^{(l)}J(W,b;x,y)$$
3、更新权重参数
\[W^{(l)}=W^{(l)}-\alpha[(\frac{1}{m}\Delta W^{(l)})+\lambda W^{(l)}]\] \[b^{(l)}=b^{(l)}-\alpha[\frac{1}{m}\Delta b^{(l)}]\]接下来就可以重复梯度下降法的迭代步骤来减少代价函数 \(J(W,b)\)的值,进而求解神经网络。
梯度检验与高级优化
众所周知,反向传播算法很难调试得到正确结果,尤其是当实现程序存在很多难以发现的bug时。
举例来说,索引的缺位错误(off-by-one error)会导致只有部分层的权重得到训练,再比如忘记计算偏置项。
这些错误会使你得到一个看似十分合理的结果(但实际上比正确代码的而结果要差)
因此,单从计算结果上来看,我们很难发现代码中有什么东西遗漏了。
这里将介绍一种对求导结果进行数值检验的方法。该方法可以验证求导代码是否正确。
也可以帮助提升写正确代码的信心。
缺位错误(off-by-one error)举例说明:
比如for循环中循环m次,正确应该是:
i = 1
while i <= m:
print(i)
i += 1
结果一时疏忽,写成了
i = 1
while i < m:
print(i)
i += 1
在一维的情况下
假设我们想要最小化 以\(\theta\)为自变量的目标函数\(J(\theta)\)。
假设\(J:R->R\),则\(\theta \in R\)
一次迭代的梯度下降公式是:
\[\theta := \theta - \alpha \frac{d}{d\theta}J(\theta)\]这个过程,如果检测求导是否正确呢?
回忆导数的数学定义:
\[\frac{d}{d\theta}J(\theta)=\lim_{\epsilon\rightarrow+0}\frac{J(\theta + \epsilon) - J(\theta - \epsilon)}{2\epsilon}\]那么对于任意\(\theta\)值,我们都可以对等式左边的导数用:
\[\frac{J(\theta + \epsilon) - J(\theta - \epsilon)}{2\epsilon}\]来近似。
通过计算近似结果和直接求导结果,来检验函数是否正确。
上述两种结构的接近程度取决于\(J\)的具体形式。
但是假定\(\epsilon=10^{-4}\)的情况下,你通常会发现上述两个结果至少有4位有效数字是一样的。(通常会更多)
多维情况下
\(\theta \in R^n\)是一个向量而非一个实数(那么就有n个参数要学习得到)
那么此时,\(J:R^n \rightarrow R\)
这时要针对每个参数,计算对应的梯度值\(g_i(\theta)\),\(\frac{\partial}{\partial{\theta_i}}J(\theta)\)
想要检验\(g_i\)是否输出正确的求导结果。
定义:\(\theta^{(i+)}=\theta + \epsilon × \vec{e_i}\),其中
\[\vec{e_i} = \left[ \begin{matrix} 0 \\ 0 \\ \vdots \\ 0 \\ 1 \\ 0 \\ \vdots \\ 0 \\ \end{matrix} \right ] \tag{3}\]是第\(i\)个基向量(维度和\(\theta\)相同,在第i行是1,而其他行是0)
所以,\(\theta^{(i+)}\) 和 \(\theta\) 几乎相同, 除了第\(i\) 行元素增加了\(\epsilon\)。
类似地,\(\theta^{(i-)} = \theta - \epsilon \times \vec{e}_i\) 得到的第\(i\) 行减小了 \(\epsilon\)。
然后我们可以对每个\(i\) 检查下式是否成立,进而验证 \(g_i(\theta)\) 的正确性
\[\begin{align} g_i(\theta) \approx \frac{J(\theta^{(i+)}) - J(\theta^{(i-)})}{2 \times \epsilon}. \end{align}\]当用反射传播算法求解神经网络时,正确算法实现会得到:
\[\begin{align} \nabla_{W^{(l)}} J(W,b) &= \left( \frac{1}{m} \Delta W^{(l)} \right) + \lambda W^{(l)} \\ \nabla_{b^{(l)}} J(W,b) &= \frac{1}{m} \Delta b^{(l)}. \end{align}\]以上结果与反向传播算法中的最后一段伪代码一致,都是计算梯度下降。
为了验证梯度下降代码的正确性,使用上述数值检验方法计算 \(J(W,b)\) 的导数,
然后验证 \(\left(\frac{1}{m}\Delta W^{(l)} \right) + \lambda W\) 与 \(\frac{1}{m}\Delta b^{(l)}\) 是否能够给出正确的求导结果。
迄今为止,我们的讨论都集中在使用梯度下降法来最小化 \(J(\theta)\)。
如果你已经实现了一个计算 \(J(\theta)\) 和 \(\nabla_\theta J(\theta)\) 的函数,
那么其实还有更精妙的算法来最小化\(J(\theta)\)。
举例来说,可以想象这样一个算法:它使用梯度下降,并能够自动调整学习速率\(\alpha\),
以得到合适的步长值,最终使 \(\theta\) 能够快速收敛到一个局部最优解。
还有更妙的算法:比如可以寻找一个Hessian矩阵的近似,得到最佳步长值,
使用该步长值能够更快地收敛到局部最优(和牛顿法类似)。
此类算法的详细讨论已超出了这份讲义的范围,
但是L-BFGS算法我们以后会有论述(另一个例子是共轭梯度算法)。
你将在编程练习里使用这些算法中的一个。
使用这些高级优化算法时,你需要提供关键的函数:即对于任一个 \(\theta\),
需要你计算出\(J(\theta)\)和 \(\nabla_\theta J(\theta)\)。
之后,这些优化算法会自动调整学习速率/步长值\(\alpha\) 的大小(并计算Hessian近似矩阵等等)
来自动寻找 \(J(\theta)\) 最小化时\(\theta\) 的值。
诸如L-BFGS和共轭梯度算法通常比梯度下降法快很多。
对偶梯度上升
对偶梯度下降是一个优化带约束目标函数的常用方法。在强化学习中,该方法可以帮助我们做出更好的决策。
\[min_x f(x) s.t. C(x)=0\]该方法的核心思想是把目标函数转换为可以迭代优化拉格朗日对偶函数。其中拉格朗日函数 𝓛 和拉格朗日对偶函数 g 定义为:
\[L(x, \lambda) = f(x) + \lambda C(x)\] \[g(\lambda) = L(x^*(\lambda), \lambda) where x^* = arg min_x L(x, \lambda)\]其中标量 λ 被称为拉格朗日乘子。
对偶函数 g 是原始优化问题的下限,实际上,若 f 是凸函数,g和f保持强对偶关系,即g函数的最大值等价于优化问题的最小。只要找到使得g最大的 λ ,我们就解决了原始优化问题。
所以,我们随机指定 λ 为初始值,使用优化方法解决这个无约束的g(λ)。
\[x^* = arg min_x L(x, \lambda)\]接下来,我们将应用梯度上升来更新 λ 以便最大化g。 g的梯度是:
\[\frac{dg}{d\lambda} = \frac{dL}{dx^*} \frac{x^*}{\lambda} + \frac{L}{\lambda} if x^* = arg min_x L(x, \lambda), then \frac{L}{x^*} = 0!\]即为
\[\frac{dg}{d\lambda} = \frac{dL}{d\lambda}\]在下面的步骤1中,我们根据当前的 λ 值找到最小x,然后我们对g进行梯度上升(步骤2和3)。
\[1. Find x^* <- arg min_x L(x, \lambda) 2. compute \frac{dg}{d\lambda} = \frac{dL}{d\lambda}(x^*, \lambda) 3. \lambda <- \lambda + \alpha \frac{dg}{d\lambda}\]先最小化带有原始x变量的拉格朗日𝓛,再用梯度法更新拉格朗日乘子 λ ,不断交替着进行这两种计算。通过这样重复迭代,λ、x将收敛。
可视化
让我们想象一下这个算法是如何工作的。

Modified from source
设 y = g(x), z = f(x)。y 和 z 在来自于空间 G ,我们画出了与y对应的z。我们的解是上面的橙色的点: 空间 G上的最小f同时满足g(x)= 0。下面的橙色线是拉格朗日函数。它的斜率等于λ,它接触G的边界 。

然后我们使用梯度上升来调整 λ(斜率),以获得与 g(x)= 0 接触G的最大值 f(x) 。

Modified from source
这就是对偶梯度上升法的工作原理。(PPT)
例子:

对偶梯度下降可以使用任何优化方法来最小化具有λ值的拉格朗日函数。
在轨迹优化问题中,我们一般使用的优化方法为iLQR。然后我们应用梯度上升来调整λ。通过重复迭代可以找到最优解。

了解各种梯度类型:
① Gradient Descent https://www.baidu.com/link?url=AF4VebES3jKrlDbJscpAwpt1EVGE3k4vlIFz1xgbvn37233GnQ_VPlpYEktcVTawOEl4tjCF5FMq4E-1SuiXo_N6cGqsFCBWfnIsmYaHtVa&wd=&eqid=c1ff1c2e00027620000000065c624453
\(w^0\) : 初始化
while True:
$$ w^t = w^{t-1} - \eta_t \delta L(w^{t-1}) $$ if || $w^t - w^{t-1}$||< $\epsilon$ then break
但是这种梯度下降法,每次都需要计算全部的样本,文件太大,会占用过多的内存,(也不适用于分布式训练?)因此使用下一种方法去改善:
② Stochastic gradient descent
\(w^0\) : 初始化
while True:
$$ w^t = w^{t-1} - \eta_t \delta L(w^{t-1}, x_i; y_i) $$ if || $w^t - w^{t-1}$||< $\epsilon$ then break
这里每次只随机选择一个样本,而不是使用全部样本,解决了上一个的问题,但是随机选择一个样本,带来的噪声和波动非常大。因此使用下一种方法去改善:
③ Mini-batch gradient descent
\(w^0\) : 初始化
while True:
$ i_1,..., i_m $: random indices between 1 and n $$ w^t = w^{t-1} - \eta_t 1\m \sum_{j=1}^{m} \delta L(w^{t-1}, x_ij; y_ij) $$ if || $w^t - w^{t-1}$||< $\epsilon$ then break
这里每次只随机选择一个样本,而不是使用全部样本,解决了上一个的问题,但是随机选择一个样本,带来的噪声和波动非常大。因此使用下一种方法去改善:
了解各种梯度类型:

一般来说,梯度要计算所有样本的梯度值,因为损失函数就是各个样本的总和。 ==> gradient descent
但是在样本量很大的情况下,很难做到,这时候就采取近似梯度值的方法。
==> stochastic gradient descent ,好处是只需要一个样本,但是会产生很多噪声,但是迭代的次数足够多,可以收敛到一个最小点。而且可以应用到线上训练过程中,数据流不断产生新的数据,就用新的数据继续训练即可。
针对difficult function问题,采取 momentum 方法去改进梯度。
上图的4,作用是。一般梯度收敛是,如果是方向相同,即符号相同的时候,很快就会收敛到最小值。但是如果符号来回变动,就会一直徘徊,而4的改进方法是,如果前面一步和这一步的方向相同,那么会增加步幅,如果前面一步和这一步方向相反,则相互抵消,使得步幅几乎为0。
因此,ht消除了导致梯度震荡的一些坐标,使得实现更好更快的收敛。
对 momentum 方法改进的是 Nesterov momentum,这个算法里,我们计算现在这个点w_{t-1}的梯度值,我们从it走一梯度步gt,然后就得到了momentum
因为很显然,实际上就在沿着momentum的方向前进,因此更聪明的做法是,首先沿着ht的方向前进,然后在新点w_{t-1}上计算梯度,得到w_{t-1}+ht消除了导致梯度震荡的一些坐标,使得实现更好更快的收敛。
在这种情况下,我们可以得到在下一步上更好的估计。
但是上面的都是要求自己确定学习速率 eta_t,而 eta_t又会对结果产生很大的影响。
所以现在对学习速率进行改进,可以自动选择学习速率。
AdaGrad 分母加上epsilon只是为了不会除以0,这样把速率设置一个常数即可,后面就不用管了。 而且它对每个样本都选择自己的学习速率。 比如在文本分析中,每个字对应着一个特征,有的字经常出现,那么迭代的次数就会多一些,有的字不经常出现,那么迭代的次数就会少一些 缺点是G是积累,有时候会非常大,这样速率就变得很小,更新几乎就不动了。
所以改进上述的问题,就:
RMSprop加了权重,Adam对G进行了增强,转而使用V,之所以V分母增加了1-beta_2,是为了正则化,以抵消偏差(bias)的影响。在第一步,正则化(normalization还很大) 当t较大时,正则化就趋近于1。
但是momentum这个方法也有缺点。
线性方程的迭代解法


共轭梯度法:


神经网络框架介绍








x,y
回归和分类。均方误差,损失函数
在分类中的应用,y=-1,1
y = 1,2,…,k 多类
判断效果好坏:accuracy loss, Iverson bracket。其实就是看预测结果正确所占的比重。
但是这个指标有两个缺点:在优化过程中一般使用梯度去计算损失函数,而这个损失函数没有梯度,其次是无法计算置信度。
可以用损失函数替代
a(x) = sign(w^Tx)
交叉熵(cross entropy)
二元/多元
梯度:
终止条件,既可以判断wt-1和wt之间的差是不是足够小,也可以判断损失函数的值的变化是不是变小,还有就是看梯度向量的模是不是接近于0.
有很多问题值得探讨,比如怎么去初始化w0,如何选择步幅eta_t,什么时候停止,如何去估计梯度。
什么情况下,线性模型的analytical solution和MSE loss有效:
训练集和测试集。
交叉训练(cross-validation)训练多次,但像深度神经网络在多个GPU上仍可能训练很多周,训练很多次是不太可行的,一般就选一个测试集。在数据量比较大的情况下,还是具有代表性的。
使用惩罚项的原因是:
在没有过度拟合的情况下,系数的数值一般会小一些。
因此把这个特点看做是特征,认为过度拟合的模型会有较大的权重,而好的模型没有较大的权重。
因此为了解决过度拟合问题,对大的权重进行惩罚。
这样总觉得不对,会不会导致前后结果差别很大? 比如可能8次方的系数原先很大,然后惩罚以后8次方就被毙了,这种情况怎么说
这里主要是集中在在众多的特征中选择重要的特征。要和另外一种情况做区分:就是所有的特征都有用,想做的是合成少量的新特征。
随机梯度下降(stochastic gradient descent)可以用在在线学习上(online learning),而且步幅(学习率)对随机梯度下降法影响更大,需要谨慎选择。
如果在一个非常大的样本上训练模型,内存不够存,怎么做。使用随机梯度下降,把样本存在硬盘上,每次读一个例子。
为了克服随机梯度下降的缺点,可以使用mini-batch gradient descent(选择m个随机样本)
一、深度学习介绍(deep learning)
参考文献: https://mp.weixin.qq.com/s/FAVLapdlLNvhnQ2yLGJ41Q