代价函数
现在来讨论神经网络模型的代价函数. 首先有如下定义:
L: 网络中的层数
$ s_l $: 第 l 层中的单元数(不包括偏差单元)
K: 输出单元个数
我们记 $ h_Θ(x)_k $ 表示第 k 个输出单元. 回顾在逻辑回归中, 我们使用如下代价函数:
$$ J(θ) = - \frac{1}{m} \displaystyle \sum_{i=1}^m [y^{(i)}\log (h_θ (x^{(i)})) + (1 - y^{(i)})\log (1 - h_θ(x^{(i)}))] + \fracλ{2m}\sum_{j=1}^nθ_j^2 $$
对于神经网络, 看起来有些复杂:
$$ J(θ) = - \frac{1}{m} \displaystyle \sum_{i=1}^m\sum_{k=1}^K [y^{(i)}_k\log ((h_θ (x^{(i)}))_k) + (1 - y^{(i)}_k)\log (1 - (h_θ(x^{(i)}))_k)] + \fracλ{2m}\sum_{l=1}^{L-1}\sum_{i=1}^{s_l}\sum_{j=1}^{sl+1}(Θ_{j,i}^{(l)})^2 $$
公式使用了一个嵌套的求和来计算输出单元的平均偏差. 正则项部分, 我们需要将 L-1 个Θ矩阵全部求和, 同时每个矩阵是 $ s_{j+1} × (s_j + 1) $ 维的.
总之:
双重嵌套求和试图将全部样本的每个分类输出值求和.
三重嵌套求和试图整个网络的每个Θ求和.
三重嵌套循环中的 i, 跟第 i 个训练样本无关, 不是一个概念.
反向传播 (BP) 算法
如果梯度下降是一个最小化回归模型的方法, 那么术语
反向传播(Backpropagation)
用于最小化神经网络模型. 我们的目标依旧是 $ min_ΘJ(Θ) $, 这表示我们试图找到最优的参数 $ Θ $ 来最小化代价函数 $ J(Θ) $. 本节介绍如何通过 Backpropagation 计算 $ J(Θ) $ 的偏导数:
$$ \frac{Θ^{(l)}_{i,j}}J(Θ) $$
首先给出 BP 算法的实现步骤:
假设训练数据集如下
$$ \lbrace (x^{(1)}, y^{(1)}) \cdots (x^{(m)}, y^{(m)})\rbrace $$
设 $ Δ^{(l)}_{ij} $ 为全 0 矩阵.
for t=1 to m
设 $ a^{(1)} := x^{(t)} $
通过正向计算, 分别算得 $ a^{(l)}\space l=2,3...L $
根据实际结果 $ y^{(t)} $, 计算 $ \delta^{(L)} = a^{(L)} - y^{(t)} $. 由于 L 是总的层数, 所以 $ a^{(L)} $ 其实是是通过模型得到的输出向量. 所以第 L 层的偏差可以直接通过训练集的实际结果向量 y 得到. 其他层的偏差则是从右往左的顺序依次计算:
$ \delta^{(L-1)} $,$ \delta^{(L-2)} $,...$ \delta^{2} $, 公式为:$ \delta^{(l)} = ((Θ^{(l)})^T)\delta^{(l+1)} .* a^{(l)} .* ( 1 - a^{(l)}) $ 要计算第 l 层的偏差, 首先将第 l 层的Θ矩阵与下一层的偏差向量相乘. 放大项 $ a^{(l)} .* ( 1 - a^{(l)}) $ 实际是激励函数 g 的导数:$ g'(z^{(l)} = a^{(l)} .* ( 1 - a^{(l)}) $
$ Δ^{(l)} := Δ^{(l)} + \delta^{(l+1)}(a^{(l)})^T $
最后, 计算
$$ \frac{Θ^{(l)}_{i,j}}J(Θ) = D^{(l)}_{i,j} $$
- $$ D^{(l)}_{i,j} := \frac{1}{m}\left(\Delta^{(l)}_{i,j} + \lambda\Theta^{(l)}_{i,j}\right)\space\space ,j0 $$
- $$ D^{(l)}_{i,j} := \frac{1}{m}\left(\Delta^{(l)}_{i,j} \right)\space\space ,j=0 $$
上述算法就是 BP 算法, 确实是个比较难理解的算法, 有兴趣的可以参阅如何直观地解释 back propagation 算法? https://www.zhihu.com/question/27239198 , 帮助理解.
得到了 J(Θ)的偏导数, 意味着得到了梯度, 模型就可以训练出Θ.
梯度检查
BP 算法有很多细节, 这些细节可能导致错误的算法实现. 我们可以用梯度检查的方法, 验证算法是否准确. 这种方法也称为
数值梯度检查(Numerical Gradient Checking)
:
如上图, 当前我们希望求解 J(Θ)在Θ处的导数 (即梯度) 时, 我们可以选取一个很小的 $ \epsilon $, 分别计算 $ J(\Theta + \epsilon) $ 和 $ J(\Theta - \epsilon) $, 这两个点的连线应近似等于Θ处的切线方向, 只要 $ \epsilon $ 越接近于 0, 就越准确. 因此可以得到如下公式计算导数:
$$ \frac{\partial}{\partial\Theta}J(\Theta) \approx \frac{J(\Theta + \epsilon) - J(\Theta - \epsilon)}{2\epsilon} $$
$ \epsilon $ 通常取值为 $ 10^{-4} $. 当Θ是一个多值矩阵时, 用如下公式分别计算每个 $ Θ_j $ 的梯度:
$$ \frac{\partial}{\partial\Theta_j}J(\Theta) \approx \frac{J(\Theta_1, \dots, \Theta_j + \epsilon, \dots, \Theta_n) - J(\Theta_1, \dots, \Theta_j - \epsilon, \dots, \Theta_n)}{2\epsilon} $$
一旦验证 BP 算法正确, 应该停止使用梯度检查, 因为这通常很耗时间, 这也是为什么不用数值梯度算法来计算梯度, BP 是相对更高效的算法.
随机初始化
当使用梯度下降法时, 需要设置Θ初始值. 在逻辑回归中, 我们可以把初始的Θ设置为 0. 但在神经网络中, 这么做可能会导致同一层单元, 其激励值与误差δ相同. 进而每次更新, 参数对应的每个输入到隐藏层的值是相同的.
通俗的说, 当某一层的 $ Θ^{(j)} $ 表示的权重相同的话, 会导致下一层的单元计算结果全部相同, 这意味着, 特征在传递到下层时, 全部压缩为一个特征了.
我们把这种现象称为对称性(Symmetry), 可以通过类似如下方法
打破对称性(Symmetry Breaking)
, 使初始化θ在 [-ε, ε] 的区间内:
If the dimensions of Theta1 is 10x11, Theta2 is 10x11 and Theta3 is 1x11.
- Theta1 = rand(10,11) * (2 * INIT_EPSILON) - INIT_EPSILON;
- Theta2 = rand(10,11) * (2 * INIT_EPSILON) - INIT_EPSILON;
- Theta3 = rand(1,11) * (2 * INIT_EPSILON) - INIT_EPSILON;
训练神经网络
首先, 选择一个神经网络架构, 有多少层, 每层有多少个单元:
输入单元数: 特征 $ x^{(i)} $ 的维度
输出单元数: 分类数量
每个隐藏层的单元数: 通常多多益善, 但要平衡计算成本. 默认使用 1 个隐藏层, 如果多于 1 个隐藏层, 推荐每层的单元数保持相同.
接下来:
随机初始化权重Θ
对每一个 $ x^{(i)} $ 使用前向传导计算 $ h_θ(x^{(i)}) $
实现代价函数 J(Θ)
实现反向传导计算偏导数
使用梯度检查, 确保反向传播算法正确. 然后关闭梯度检查
使用梯度下降或其他优化函数最小化代价函数
理想情况下,$ h_\Theta(x^{(i)}) \approx y^{(i)} $, 但由于 J(Θ)可能是 non-convex 的, 所以, 你可能会得到局部最优解.
来源: https://segmentfault.com/a/1190000014476396