文章目录
  1. 1. 思路的开始
  2. 2. 损失函数 和 最优解 概念
  3. 3. 神经网络
    1. 3.1. 感知器
    2. 3.2. 进一步了解感知机原理
    3. 3.3. 前馈网络
    4. 3.4. Sigmoid 神经元
  4. 4. 损失函数
  5. 5. 梯度下降
  6. 6. 反向传播
  7. 7. 不负责任尾声
  8. 8. 参考

写这个 article 帮助自己消化 免费网络书 http://neuralnetworksanddeeplearning.com/ 前面俩个 chapter。尽量通俗易懂地解释神经网络和深度学习的思路。
这篇文章有几个重要知识点会接触到的领域: 统计学、最优解、人工神经网络、逻辑学、偏微分。其中有大部分高中都已经接触过了,而篇幅会在阐述人工神经网络的一些概念和实现的思路,而不在具体如何实现的技术问题上。若想要付与行动实现,或更入清楚了解哪强烈建议去看回原作

思路的开始

有果必有因,假设这个因果关系只有上帝能解释清楚,但我们可以透过经验知道什么因导致什么果,然后汲取经验猜因果关系,由因预测果。
我们都是懒虫,想把这个工作交给电脑做。 要把这个过程变成数学工具能处理的东西,以下是很蠢的例子:

而我不知道小花为什么会生气,只有上帝知道。

经验:

  • 给小花巧克力 - 小花很快乐
  • 给小花巧克力,再跟小花讲数学 - 小花生气

因:

  • 给小花巧克力
  • 跟小花讲数学

学习 - 经验猜出来的因果关系:

  • 给小花一块巧克力 是 $+1$
  • 跟小花讲一次数学 是 $-2$
  • $\sum$因 $\leq 2$ 是 小花生气
  • $\sum$因 $> 2$ 是 小花快乐

预测 - 用猜出来的因果关系来预测果:

  • 给小花俩三块巧克力,再跟小花讲一次数学 - 小花很快乐

损失函数 和 最优解 概念

这个部分我们的高一数学已经接触过了它的核心概念,只是针对要解决的问题而方法不同。
独中 高级数学 高一下册 1995年5月第一版

比如 -

  • $y(x)$ 是上帝才能解释清楚的函数
  • $f(x)$ 是我们猜出来的函数

在机械学习中,我们需要:

  • 知道我们错得有多离谱
    设计一个能对比 $y(x)$ 和 $f(x)$ ,表示他们之间的差别 来知道我们错得有多离谱的 损失函数(lost function)
  • 减少这个离谱程度。
    调整 $f(x)$ 使 损失函数 最小。进而得出 $f(x)$ 最优解(optimal solution)
    如果对这个减少离谱程度的过程还没有概念的话可以再看看高三学的牛顿法。

值得一提的是,所有机械学习都需要 最优化,而最优化的对象就是损失函数。

如何设计 损失函数 和得到 最优解我们在后面会谈到,这里先明白有这种操作方便后面理清思路。

神经网络

如果世界有一个部分是大脑的基础逻辑所不能建构的,哪我们的世界就不会有这一个部分。 ——国成乱掰
p/s: 后来还发现 量子力学 里面好像就有一个 shutup and calculate 说法。

感知器

重点的问题来了,我们该如何设计 $f(x)$ ?
参考奇妙的大脑来设计 $f(x)$,设计人工神经网络。这个概念和其中的模型是1943年心理学家 Warren McCulloch 和数理逻辑学家 Walter Pitts 一起在论文发表的 。这里介绍一种名叫 感知器(perceptron) 的人工神经网络,是神经学家 Frank Rosenblatt 提出,1957年才成功仿真 [link]
好像神经元,感知器可以接受多方的“刺激(输入)”,若刺激达到阈值就会产生“神经冲动(输出)”:

如图,我们的感知器接受了 $x_1,x_2,x_3$ 的刺激,感知机对每个刺激赋予 权重(weight) $w_1,w_2,w_3$,表示该刺激的重要性(或产生的影响力);若刺激达到了 阈值(threshold) 则产生冲动,输出1;反之则输出0。

$$
\text{output} = \begin{cases}
0& \text{ if } \sum_iw_ix_i \leq \text{threshold} \\
1& \text{ if } \sum_iw_ix_i > \text{threshold}
\end{cases}
$$

这个函数是以二分法为基础,我们可以用之前 小花的例子 来一窥这个 感知器 的函数:

学习 - 经验猜出来的因果关系:

  • 给小花一块巧克力 是 $+1$
  • 跟小花讲一次数学 是 $-2$
  • $\sum$因 $\leq 2$ 是 小花生气
  • $\sum$因 $> 2$ 是 小花快乐

把这段意思翻译给 感知器:

  • $x_1 $ 为给小花的巧克力, $w_1$ 表示小花有多喜欢巧克力 (即其值为 1)
  • $x_2 $ 为跟小花讲数学的次数,$w_2$ 表示小花有多喜欢数学 (即其值为 -2)
  • 阈值 threshold 为 2

给小花三块巧克力 $x_1=3$,
再跟小花讲一次数学 $x_2=1$

$
\sum_iw_ix_i\ \\
= w_1x_1 + w_2x_2 \\
= 1(3) + -2(1) > \text{threshold} \\$
$\therefore$ 小花终于甘心听讲数学了。

为了方便我们处理,让 $b \equiv -\text{threshold}$,感知器函数重写为

$$
\text{output} = \begin{cases}
0& \text{ if } \sum_iw_ix_i + b\leq 0 \\
1& \text{ if } \sum_iw_ix_i + b > 0
\end{cases}
$$
理工班的同学应该会管这个 $b$ 叫 偏压(bias),说不定还发现 感知器 能组合成为 逻辑闸(logic gate) 呢!
重要的一点是,我们只要调整这些 权重 和 偏压 到适合的值,我们的神经网络就可以给做比较正确预测了!

进一步了解感知机原理

刚刚那个高一课本 那一页下面给的例子启发,
独中 高级数学 高一下册 1995年5月第一版

我们用同样的原理,设z变量来观察全局。
以小花的例子:

  • $x_1$ 对应 $y$ 轴;
  • $x_2$ 对应 $x$ 轴;
  • 令 $z = w_1x_1 + w_2x_2 + b$

得出以下的函数图,直线为 $z$。把函数图区分成俩边,A区 和 B区。

可以发现到,我们调整 权重 和 偏压 其实是调整z线的 斜率 和 截距。维基百科有个更直观的例子来阐述二分法的性质(图):

这些函数关系可视化例子都是 1维、2维 的,但实际的操作中我们可能会遇到 n 个需要处理的 $x_i$,也就是说有 n 个维度,但方法都是不变的,只是我们要用向量的数学工具来处理这些问题。

前馈网络

新的问题产生了,这种感知机只能用一条直线做二分法。面对 线性不可分 的情况,它几乎是束手无策阿。

但是多层感知机机可以,多个组合成为正意义上的人工神经网络。照书给的模型叫 前馈网络(feed forward network), 这种人工神经网络可以分为三层: 输入层(input layer)、隐藏层(hidden layer)、输出层(output layer)

用 $f_{li}(x)$ 表示神经网络中第 $l$ 层 地 $i$ 个感知机, $x_1,x_2$ 为输入的值。
哪整个神经网络可以勉强这样用函数表示:

$$
f_{31}\begin{pmatrix}
f_{21}
\begin{pmatrix}
f_{11}(x_{1}),\\
f_{12}(x_{2})\:\\
\end{pmatrix},\\
f_{22}
\begin{pmatrix}
f_{11}(x_{1}),\\
f_{12}(x_{2})\:\\
\end{pmatrix},\\
f_{23}
\begin{pmatrix}
f_{11}(x_{1}),\\
f_{12}(x_{2})\:\\
\end{pmatrix}\:\\
\end{pmatrix}
$$

如果感觉混乱的话可以看看这个每层只有一个 感知器 的简化版:
$$
f_3(f_2(f_1(x_1,x_2)))
$$

这个设计下,我们的 神经网络 需要调整的变量有

  • 神经网络有几层
  • 各层有几个感知机
  • 每个感知机的 权重 和 偏压

我们的模型中,需要训练的变量是 每个感知机的 权重 和 偏压。而前俩者我也说不清,大概就是依靠自己的数学直觉来设定吧。
到目前位置应该算是掌握了最早的人工神经网络原型,设计出了第一个 $f(x)$,下一步应该要为 $f(x)$ 来定制 损失函数。

Sigmoid 神经元

可是我们发现到 感知器函数 是不连续的,对于我们要使用 牛顿法、梯度下降 这类依赖导数的最优化手段,要怎么设计它可导的 损失函数 呢?我 google、阅读了别人的 article 一个下午还算是看懂了,因为不是平常我们接触的类型,我不想+懒惰解释。

想跟我一样去折腾这个的同学请:
https://www.leiphone.com/news/201706/QFydbeV7FXQtRIOl.html | https://zh.wikipedia.org/wiki/感知器#结构

这里把 感知器 替换为另一个在 感知器 的基础上 改进的 Sigmoid 神经元(sigmoid neurons)
$$\sigma(z) \equiv \frac{1}{1+e^{-z}}$$
其中 $z=\sum_i w_ix_i-b$
我们来对比 感知器函数 和 Sigmoid函数:

Sigmoid 的函数连续方便求导外,最重要的一个是 权重 或 偏压 小小的变化不至于像 感知器 一样导致下一层的神经元乃至整个神经网络输出彻底地改变。二分法方面,我们还可以得到不仅仅是 是与非 的结果,还有其概率(多靠近 1 或 多靠近 0)。

损失函数

想知道我猜的函数像不像“上帝函数”,在机械学习的情况下牵涉到大量对比 $y(x)$ 和 $f(x)$ 的样本,因此我们设计 损失函数 时需要用到 统计学。
遵循着我读的书,作者给的 损失函数 是:
$$
C = \frac{1}{2n} \sum_i || y(x_i) - f(x_i) || ^2
$$
它的名字叫 均方误差(Mean squared error),其中的 n 是数据的总数(经验)。 好好学习不缺课的同学可能会发现这个跟 方差(variance) $\frac{1}{n}\sum (x_{i} - \bar{x})^2$ 很像。
但其中最大的不同的是:

  • 均方误差 —— 预测数据真实数据 的“误差”。
  • 方差 —— 数据 和其 平均数 的“误差”,或者离中的趋势。

但是我不明白为什么书里给的 均方误差 公式还有乘以 $\frac{1}{2}$ 的系数,一个区区的常数其实不影响我们对 损失函数 求最优解。我只知道后来对它求偏导数可以让式子看起来比较简洁(因为 $\frac{1}{2}$ 的系数被约了)。

梯度下降

本来觉得用我们熟悉的 牛顿法 会容易解释,可是在多维度下之前说的所谓 “向量的数学工具” 其实是一个专门的学科叫 线性代数,在牛顿法求最优解里需要用到 海森矩阵(Hessian Matrix)。老实说这个超过我目前的范围了,我们还是用书里比较容易的 梯度下降(Gradient Descent) 例子,顺便省掉解释 一些线性代数处理的功夫吧。

想象有一个简单的损失函数 $C(v_1,v_2)$ 构成的三维函数图像,好像现实世界一样球因为重力而产生往谷底方向的加速度使球滚下去:

随机把球放在一个位置,移动球$\Delta C$ 来达到谷底(最优解)。我们要找球在这个位子上的 梯度 (通俗的了解就是函数对应各个方向的斜率)。$(\frac{\partial C}{\partial v_1}, \frac{\partial C}{\partial v_2})$ 的值 进而找到 $\Delta C$。以下我们以 $C(v_1,v_2)$ 在 $v_1$ 方向上的 变化率 为 $\Delta C_{v_1}$,
$$
\Delta C_{v_1} \approx \frac{\partial C}{\partial v_1} \Delta v_1 \\
\Delta v_1 = -\eta\frac{\partial C}{\partial v_1}
$$
$\Delta v_1$ 一项中,$\eta$ 是一个常数,叫 学习率(learning rate),他的大小可以影响 $\Delta C$ 大小。俩式合并,我们可以看到 $\Delta v_1$ 的设计是为了确保 $\Delta C_{v_1}$ 是一直往谷底的方向去的 :
$$
\Delta C_{v_1} \approx -\eta{\frac{\partial C}{\partial v_1}}^2
$$
因为 ${\frac{\partial C}{\partial v_1}}^2 \geq 0$,再乘以常数 $-\eta$ 能确保 $\Delta C_{v_1}$ 总是为负数(向下)。多维度下,用线性代数的符号表示:
$$
\nabla C \equiv
\begin{pmatrix}
\frac{\partial C}{\partial v_1}, \frac{\partial C}{\partial v_2}
\end{pmatrix}^T\\
\Delta v = -\eta \nabla C \\
\Delta C \approx \nabla C\cdot \Delta v = -\eta||\nabla C||^2
$$
我们根据 梯度 来调整 $\Delta x$ 来移动 “球”$\Delta C$, 再使 $C’ = C - \Delta C$, 并且不停地迭代下去,直到靠近谷底 $C \to 0$ ,或者 $\nabla C \to 0$。当然如果 损失函数 有俩个或以上 谷 的情况,我们只能到达其中一个 谷 (希望它是最低的)。

我们把这个概念引用在真正我们要解决的用于学习的 损失函数,找到相应的 $w,b$,这个实现神经网络深度学习的思路算是告一段落了。

反向传播

如果在上世纪 50 年代你想到用梯度下降法来实现机械学习,你可能是人工智能领域里第一个有这个想法先锋。可是要实现 梯度下降 需要 损失函数 的梯度。也就是说我们要对各个 $w,b$ 来求导才能实现梯度下降。当然数学不好的朋友可以用比较简单粗暴的做法,直接自行设定 $\Delta x$ 代入 $\frac{C(x+\Delta x) - c(x)}{\Delta x}$ 来得到近似的梯度。
当然高中毕业的同学就应该要优雅地把学来的那套微积分应用出来阿!这里应用微积分求导得到 梯度 的方法就叫做 反向传播(backpropagation),从 输出层 开始用 链导法(chain rule) 一层一层求导,往前得到某层特定 w,b 的偏导。它的本质就是简单的 链导法。首先我们来整理 Sigmoid神经元 组成网络的函数,如果不用 线性函数 的那套,看上去应该像这样:

$$
\sigma_{31}\begin{pmatrix}
\sigma_{21}
\begin{pmatrix}
\sigma_{11}(x_{1}),\\
\sigma_{12}(x_{2})\:\\
\end{pmatrix},\\
\sigma_{22}
\begin{pmatrix}
\sigma_{11}(x_{1}),\\
\sigma_{12}(x_{2})\:\\
\end{pmatrix},\\
\sigma_{23}
\begin{pmatrix}
\sigma_{11}(x_{1}),\\
\sigma_{12}(x_{2})\:\\
\end{pmatrix}\:\\
\end{pmatrix}
$$
用 $\sigma_{li}(z_{li})$ 表示神经网络中第 l 层 地 i 个 Sigmoid神经元, $x1,x2$ 为输入的值。

我们知道$z=\sum_i w_ix_i-b$,哪
$$\sigma_{li} = \sigma(\sum_i w_{li}\sigma_{l-1,i} - b_{li})$$
在这里 $\sigma_{21}(z)$ 做例子, $z$ 就是:
$$
w_{21}\sigma_{11}(x_{1}) + w_{22}\sigma_{12}(x_{2}) + b_{21}
$$
再提醒一次,当中的 $x$ 是样本,而我们需要调整 $w$ 和 $b$ 达到适合的值以做比较正确的预测。
另外在每一层网络中有多个 Sigmoid神经元,也就是说“讯息”可以通过不同的 Sigmoid神经元,不同路径的事实上对应的维度也不同,$C$ 对各种 $w,b$ 得的偏导自然不同也不一样。以下不考虑路径以简化表示……
调整一个 $\Delta w$ 来移动 “球” $\Delta C$:
$$\Delta C \approx \frac{\partial C}{\partial w_{l}} \Delta w_{l}$$

如果想找到 $\frac{\partial C}{\partial w_{l}}$ 经过各层 Sigmoid神经元 到$l$层的偏导数,运用导链法,以下是简单可是繁琐的推导(以 $L$ 表示最外层的输出层):
$$
\frac{\partial C}{\partial w_{l}}
\\
=
[
\frac{\partial C}{\partial \sigma_{L}}
]\cdot
[
\frac{\partial \sigma_{L}}{\partial \sigma_{L-1}}\cdot
\frac{\partial \sigma_{L-1}}{\partial w_{L-2}}
\ldots
\frac{\partial \sigma_{2+l}}{\partial \sigma_{1+l}}\cdot
\frac{\partial \sigma_{1+l}}{\partial \sigma_{l}}
]\cdot
[\frac{\partial \sigma_{l}}{\partial w_{l}}]
$$
把这个链分成三个部分:

  • 输入层的部分 $\frac{\partial C}{\partial \sigma_{L}}$
  • 隐藏层中反向传播 $\frac{\partial \sigma_{l}}{\partial \sigma_{l-1}}$
  • 目标层的 $w$ 偏导 $\frac{\partial \sigma_{l}}{\partial w_{l}}$

$\sigma_{L}$ 就是 神经网络 中的 输出层的 Sigmoid神经元,负责输出结果。也就是 损失函数 $\frac{1}{2n} \sum_i || y(x_i) - f(x_i) || ^2$ 中的 $f_i$ 的输出。
因为这个 损失函数 是许多样本的统计,如何求导呢?我的理解是可以看作 $C_{average} = \frac{1}{n} \sum_i C_i$ ,而 $C_i \equiv \frac{|| y(x_i) - f(x_i) || ^2}{2}$,然后大胆假设 “标准损失函数”为 $C = \frac{|| y(x) - f(x) || ^2}{2} = C_{average} $。哪第一部分:
$$\frac{\partial C}{\partial \sigma_{L}} = y(x)-f(x)$$

接着我们来求 隐藏层 中俩个相连的 Sigmoid神经元 ($\sigma_l,\sigma_{l-1}$)之间的偏导:
$$
\frac{\partial \sigma_{l}}{\partial \sigma_{l-1}} = \frac{\sigma_l}{z_l} \cdot \frac{z_l}{\sigma_{l-1}}
\\
= \frac{\partial}{\partial z_l}(\frac{1}{1+e^{-z_l}}) \cdot \frac{\partial }{\partial \sigma_{l-1}}(\sum_i w_lz_{l-1} +b_{l-1})
\\
= [\sigma_l(z_l)(1-\sigma_l(z_l))] \cdot [w_l]
$$
还有链的最后一个部分:
$$
\frac{\partial \sigma_l}{\partial w_l}
\\
= \frac{\partial }{\partial w_{l}}(\sum_i w_lz_{l-1} + b_{l-1})
\\
= \sigma_{l-1}
$$

同样的思路去求 $\frac{\partial C}{\partial bl}$。

不负责任尾声

“Talk is cheap. Show me the code.” ― Linus Torvalds.

对不起,我只会说……show 不出 code,又想好好结尾,所以假假写一些屁话来尾声:

算法优化、以及如何真正实现请去读 这本网络书,里面教从无到有建造人工神经网络,总有6章(这篇文章仅仅只是其中的头两章)。比起套个 API 来学习数据跟大家讲说“我会做AI”,还远比不过自己动手建立神经网络来的有趣和实质呢。
另外不能否认的是所谓的 “AI” 是个趋势,能而且深入到更多的行业。这可以是工业革命以来的另一波同样具有影响力的革命,而且冲击着、改变着我们的社会秩序。

参考

http://neuralnetworksanddeeplearning.com/chap1.html
http://neuralnetworksanddeeplearning.com/chap2.html
https:/zh.wikipedia.org/wiki/感知器
https://www.leiphone.com/news/201706/QFydbeV7FXQtRIOl.html
https://en.wikipedia.org/wiki/Multilayer_perceptron

文章目录
  1. 1. 思路的开始
  2. 2. 损失函数 和 最优解 概念
  3. 3. 神经网络
    1. 3.1. 感知器
    2. 3.2. 进一步了解感知机原理
    3. 3.3. 前馈网络
    4. 3.4. Sigmoid 神经元
  4. 4. 损失函数
  5. 5. 梯度下降
  6. 6. 反向传播
  7. 7. 不负责任尾声
  8. 8. 参考