神经网络(二)

继续发公式。有兴趣阅读能正常显示公式的版本请移步 http://blog.kamidox.com/neural-networks-2.html

成本函数

与线性回归或逻辑回归类似,要使用神经网络对训练数据进行拟合时,需要有成本函数。这样只要针对训练数据,求解成本函数的最小值即可得出神经网络模型参数。

针对 K 类分类问题的神经网络的输出层

$$
h_\Theta(x) \in R^K; \left( h_\Theta(x) \right)_k = k^{th} output
$$

其中 K 是输出层的的单元个数,K >= 3。因为如果 K < 3 则可以直接用一个单元表示。其成本函数是:

$$
J(\Theta) = - \frac{1}{m} \left[ \sum_{i=1}^m \sum_{k=1}^K y_k^{(i)} log(h_k^{(i)}) + (1 - y_k^{(i)}) log(1 - h_k^{(i)}) \right] + \frac{\lambda}{2m} \sum_{l=1}^{L-1} \sum_{i=1}^{s_l} \sum_{j=1}^{s_{l+1}} (\Theta_{ji}{(l)})2
$$

其中 $h_k^{(i)} = {h_\Theta(x^{(i)})}_k$ 是输出层的第 $k^{th}$ 个输出值。$L$ 是神经网络的层数,$s_l$ 是指第 $l$ 层的单元个数。公式的前半部分是未正则化的成本函数,后半部分是正则项,加起来就是正则化的成本公式。注意正则项部分求和时是从 $i=1$ 开始的,即我们不把偏置变量正则化。

!!! warnning "MathJax 的缺陷"
这个公式我写了 20 分钟。它已经复杂到我不得不把 $h_k^{(i)}$ 独立写出来了,如果全部写一个公式里,公式将无法正确显示。不服的人可以试看看。

怎么理解神经网络的成本公式

实际上不需要记住这么复杂的公式,但可以结合逻辑回归算法的成本公式来理解神经网络的成本公式。我们知道,神经网络中间层和输出层的每个神经元,都和其前面一层的神经网络的神经元构成逻辑回归关系。这个是神经网络的定义。而逻辑回归算法的成本函数是:

$$
J(\theta) = -\frac{1}{m} \left[ \sum_{i=1}^m y^{(i)} log(h_\theta(x^{(i)})) + (1 - y^{(i)}) log(1 - h_\theta(x^{(i)})) \right]
$$

跟神经网络成本函数对比,你会发现神经网络输出层有 K 个神经元。所以计算成本函数时,需要把输出层 K 个神经元的逻辑回归成本累加起来。

怎么理解正则项呢?

正则项有三个累加器,最前面那个是层累加器,典型地,对 3 层神经网络模型 $L=3$ ,正则项简化为:

$$
reg = \frac{\lambda}{2m} \left( \sum_{i=1}^{s_1} \sum_{j=1}^{s_2} \left( \Theta_{ji}^{(1)} \right)^2 + \sum_{i=1}^{s_2} \sum_{j=1}^{s_3} \left( \Theta_{ji}^{(2)} \right)^2 \right)
$$

向后传播算法

我们把 $\delta_j^{(l)}$ ( $\delta$ 读作 delta ) 记作神经网络中第 $l$ 层,第 $j$ 个节点的误差。针对输出层,我们有

$$
\delta_j^{(L)} = a_j^{(L)} - y_j
$$

按照向量化写法,我们得到

$$
\delta^{(L)} = a^{(L)} - y
$$

此由可见,$\delta^{(L)}$ 是和 $y$ 一样维度的向量。针对第 $L-1$ 层,我们把误差定义为

$$
\delta^{(L-1)} = (\Theta{(L-1)})T \delta^{(L)} .* g'(z^{(L-1)})
$$

这个公式的前半部分 $ (\Theta{(L-1)})T \delta^{(L)}$ 样式很熟悉吧,就是线性回归算法的预测函数的样式。中间的 $.*$ 读作点乘,就是逐个元素相乘。$z{(L-1)}=\Theta{(L-2)} a^{(L-2)}$,$g'(z)$ 是 Sigmoid 函数的偏微分。

可以从数学上证明 $g'(z^{(L-1)}) = a^{(L-1)} .* (1 - a^{(L-1)})$ 成立。证明过程可以参阅 常用的微分运算法则 里关于 Sigmoid Function 偏微分的推导过程。这样我们算出输出层的误差,然后一层层往前推导,算出各层的误差,就是我们向后传播算法名字的由来。需要注意的是,不存在 $\delta^{(1)}$,因为神经网络的第 1 层是我们的输入项,不存在误差问题。

从数学上可以证明,如果忽略正则项,即 $\lambda = 0$时

$$
\frac{\partial}{\partial \Theta_{ij}^{(l)}} J(\Theta) = a_j^{(l)} \delta_i^{(l+1)}
$$

注意

  1. 计算微分项时,只需要计算 1, 2, ..., l+1 层的微分项
  2. 微分项 $\frac{\partial}{\partial \Theta_{ij}^{(l)}} J(\Theta)$ 是个和 $\Theta^{(l)}$ 尺寸相同的矩阵

针对训练样本 ${ (x^{(1)}, y^{(1)}), (x^{(2)}, y^{(2)}), ... (x^{(m)}, y^{(m)}),}$,我们可以把向后传播算法用伪代码描述如下:

  • 初始化误差累加值 set $\Delta_{ij}^{(l)} = 0$, for all $l, i, j$
  • 遍历所有的训练样本 for i = 1 to m
    • 设置输入层的激励为第 $i$ 个训练样本的输入值 set $a^{(1)} = x^{(i)}$
    • 使用向前传播算法 $a^{(l+1)} = g\left( a^{(l)} * \left( \Theta^{(l)} \right)^T \right)$,算出所有层的激励 $a^{(l)}$ for $l = 2, 3, ... , L$
    • 使用输出层的激励,计算输出层的误差 $\delta^{(L)} = a^{(L)} - y^{(i)}$
    • 使用反向扩散的方法 $\delta^{(L-1)} = (\Theta{(L-1)})T \delta^{(L)} .* g'(z^{(L-1)})$ 计算每一层的误差 $\delta^{(L-1)}, \delta^{(L-2)}, ..., \delta^{(2)}$。
    • 累加 $(x^{(i)}, y^{(i)})$ 训练样本的误差 $\Delta_{ij}^{(l)} = \Delta_{ij}^{(l)} + a_j^{(l)} \delta_i^{(l+1)}$。
  • endfor
  • 累加的值除以 m 即得到无正则化的微分项 $\frac{\Delta_{ij}^{(l)}}{m}$

最后一项可以用向量化的写法:

$$
\Delta^{(l)} = \Delta^{(l)} + \delta^{(l+1)} \left( a^{(l)} \right)^T
$$

注意:
计算过程中,需要注意偏置单元。根据惯例,累加时不计算偏置单元。针对反向扩散公式 $\delta^{(L-1)} = (\Theta{(L-1)})T \delta^{(L)} . g'(z^{(L-1)})$,需要特别注意矩阵运算时的维度需要匹配。*

加入正则项后,我们有

$$
D_{ij}^{(l)} = \frac{1}{m} \Delta_{ij}^{(l)} + \frac{\lambda}{m} \Theta_{ij}^{(l)}, if j \ne 0
$$
$$
D_{ij}^{(l)} = \frac{1}{m} \Delta_{ij}^{(l)}, if j = 0
$$

从数学上可以证明

$$
\frac{\partial}{\partial \Theta_{ij}^{(l)}} J(\Theta) = D_{ij}^{(l)}
$$

这样我们就算出来了神经网络模型的成本函数微分项。有了成本函数和成本函数微分项,我们就可以使用线性回归或其他高级算法来计算神经网络成本函数的最小值,从而求解神经网络中各层激励的参数。

在具体实现的时候,使用向量化的实现可以大幅提高算法效率。具体可以参考 Neural Network Vectorization

实践中的向后传播算法

参数折叠

在线性回归或逻辑回归算法里,我们的参数是向量,我们使用的 fminunc 等函数也只接受向量作为参数。而神经网络算法里,参数是个向量,$\Theta^{(l)} \in R^{s_{l+1} \times s_l + 1}$。所以,在训练神经网络算法时,需要对参数进行折叠,即把矩阵转换为向量,而在使用时,可以再从向量里恢复矩阵数据。

假设 Theta1 是 10x11 的矩阵,它是第一层的参数; Theta2 是 10x11 的矩阵,它是第二层的参数。可以使用下面的 matlab/octave 来转换:

ThetaVec = [Theta1(:); Theta2(:)];

在成本函数函数里,我们需要转换为矩阵进行计算:

Theta1 = reshape(ThetaVec(1:110), 10, 11);
Theta2 = reshape(ThetaVec(111:220), 10, 11);

同理,针对成本函数的微分项,$D^{(1)} \in R^{10x11}, D^{(2)} \in R^{10x11}$,我们的成本函数返回这个微分项时,也需要把矩阵转换为向量:

DVec = [D1(:); D2(:)]

微分项检验

神经网络的微分项特别复杂,有时候一些小的错误可能不会导致算法失败,这样就很难发现问题。这里介绍一个方法来验证微分项算法是否正确。我们使用的是微分的数值估算方法。

$$
\frac{d}{d\theta} J(\theta) \approx \frac{J(\theta + \varepsilon) + J(\theta - \varepsilon)}{2 \varepsilon}
$$

这里只要 $\varepsilon$ 足够小,则可以近似地计算出微分项的值。实际计算时,我们一般取 $\varepsilon = 0.0001$ 。这样算出来的值和微分项算出来的值应该非常近似,用这个方法我们可以验证微分项计算是否准确。需要特别注意的是,在验证完微分项计算的正确性后,数值近似计算必须关闭掉。否则会使算法效率严重降低。因为数值计算的成本是很高的。

编程时需要注意

微分项检查实际上是一种纯数学的做法。主要是检查我们使用向后传播算法 (backpropagation) 方法算出来的微分和用数值计算算出来的微分是否相同。它适用于其他算法,如线性回归或逻辑回归算法。有几点需要特别注意。

  • 由于计算很费时间,实际检查时,$\theta$ 可以选小一点的矩阵,比如 3 x 5,而不需要使用真正的机器学习时的 theta。因为 $\theta$ 太大不但费时间,还不利于观察。
  • 实际计算时,$\theta$ 往往是个列向量。这个时候我们需要让 $\varepsilon$ 也是一个和 $\theta$ 维度相同的向量,当检查 $\theta(i)$ 元素的偏微分项时,让 $\varepsilon$ 的的第 i 项的值为 0.0001,其他项都为 0 。这样进行矩阵来进行数值微分计算。

用随机数初始化参数

在进行线性回归和逻辑回归计算时,我们把参数全部初始化为零。但这个做法在神经网络里是不可行的,如果我们把参数全部初始化为零,那么隐藏层的神经单元的激励 $a_i^{(l)}$ 将是相同的,其误差 $\delta_i^{(l)}$ 也将是相同的,即我们计算的全部是相同的特征,这样神经网络就失去了其特征的覆盖度和丰富性。

所以,我们需要把神经网络的每个参数 $\Theta_{ij}^{(l)}$ 初始化为 $[-\varepsilon, \varepsilon]$ 之间的一个随机数。例如:

Theta1 = rand(10, 11) .* (2 .* INIT_VAREPSILON) - INIT_VAREPSILON;
Theta2 = rand(10, 11) .* (2 .* INIT_VAREPSILON) - INIT_VAREPSILON;
Theta3 = rand(1, 11) .* (2 .* INIT_VAREPSILON) - INIT_VAREPSILON;

$\varepsilon$ 应该选择小一点,这样神经网络的学习最有效率。一个经验做法是

$$
\varepsilon^{(l)} = \frac{\sqrt{6}}{\sqrt{s_l} + \sqrt{s_{l+1}}}
$$

$s_l, s_{l+1}$ 分别表示 $l$ 层和 $l+1$ 层的神经单元个数。即每层的参数范围根据这层的神经单元个数及下一层的神经单元个数。

总结

使用神经网络解决问题时,需要经过两个步骤。一是设计神经网络的架构;二是训练出对应的神经网络参数。

神经网络架构

在进行神经网络计算时,需要先进行神经网络的架构设计。架构设计时需要考虑以下三个事情:

  1. 输入层的特征数量 (number of input unit)
  2. 输出层的单元个数 (number of output unit) ,针对多类别的分类问题,可以把输出层设计成一个向量
  3. 隐藏层的个数以及每个隐藏层的单元数目。一般来讲,隐藏层的个数越多越好,但会增加计算的工作量。另外,多个隐藏层的单元数目一般是相同的。

训练神经网络

训练神经网络总共有六个步骤

  • 按照随机数对初始权重 (参数) 进行初始化
  • 实现向前传播算法,以便针对任何的输入 $x^{(i)}$ 都能算出相应的 $h_\Theta(x^{(i)})$
  • 实现神经网络成本函数 $J(\Theta)$ 来计算成本
  • 实现向后传播算法,计算成本函数针对每个参数的偏微分 $\frac{\partial}{\partial \Theta_{ij}^{(l)}} J(\Theta)$
    • 需要遍历每个训练样本,即有个从 1 到 m 的循环
    • 针对每个训练样本 $(x^{(i)}, y^{(i)})$ 执行向前传播算法和向后传播算法,以便算出 $l$ 层的激励 (Activations) $a^{(l)}$ 和误差 $\delta^{(l)}$
    • 需要针对神经网络的每层算出*的值,这些层是 2, 3, ... , L
    • 最后,在循环外,算出成本函数的偏微分
  • 使用数值估计算法来验证神经网络成本函数的偏微分是否正确。验证通过后,关闭数值估计算法。
  • 使用梯度下降或其他优化过的高级算法来对成本函数 $J(\Theta)$ 进行最小化运算
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容