神经网络基本原理
系列博客,原文在笔者所维护的github上:https://aka.ms/beginnerAI,
点击star加星不要吝啬,星越多笔者越努力。
前言
For things I don’t know how to build, I don’t understand.
如果我不能亲手搭建起来一个东西,那么我就不能理解它。 – 美国物理学家理查德·费曼
在互联网发达的今天,很多知识都可以从网络上找到,但是网络上的博客、文章的质量参差不齐,或者重点不明确,或者直接把别人的博客抄袭过来。这种状况使得广大的初学者们学习起来很困难,甚至误入歧途,增加了学习曲线的陡峭程度。当然也有很多博主非常非常负责任,文章质量很高,只是连续度不够,正看得过瘾的时候,没有后续章节了,无法形成知识体系。
初学者也可以选择看一些教材或者理论书籍,但是,一个鸡生蛋蛋生鸡的问题出现了:如果你不懂,那么看完了理论你还是不会懂;如果你懂了,那么你就没必要看理论。这也是很多教材或者理论书籍的缺憾。
笔者也看过吴恩达老师的课,理论知识讲得由浅入深,还是非常清楚的,虽然代码示例基本没有,但仍然强烈建议大家去看。笔者的心得是:视频可以事先缓存在手机中,利用一些时间片段就可以学习了。
社会上还有一些网课,在线讲解深度学习的知识,笔者也参加了几个团购,老师和助教一般都很负责任,最后可以回看录像,下载PPT课件。这些课程一般偏重于工程项目,讲解深度学习框架和工具的使用,即教大家如何使用工具建模、训练等等,也是很有帮助的。但对于初学者来说,理解一个新概念可能需要前面很多个已有知识点的支撑,门槛过高,一下子就变得很沮丧。或者是知其然而不知其所以然,最后沦为调参工程师,职业发展受到了限制。
还是应了那句古话:授人以鱼不如授人以渔。经历了以上那些学习经历,程序员出身的笔者迫切感觉到应该有一种新的学习体验,在“做中学”,用写代码的方式把一些基础的理论复现一遍,可以深刻理解其内涵,并能扩充其外延,使读者得到举一反三的泛化能力。
笔者总结了自身的学习经历后,把深度学习的入门知识归纳成了9个步骤,简称为9步学习法:
- 基本概念
- 线性回归
- 线性分类
- 非线性回归
- 非线性分类
- 模型的推理与部署
- 深度神经网络
- 卷积神经网络
- 循环神经网络
笔者看到过的很多书籍是直接从第7步起步的,其基本假设是读者已经掌握了前面的知识。但是对于从零开始的初学者们,这种假设并不正确。
在后面的讲解中,我们一般会使用如下方式进行:
- 提出问题:先提出一个与现实相关的假想问题,为了由浅入深,这些问题并不复杂,是实际的工程问题的简化版本。
- 解决方案:用神经网络的知识解决这些问题,从最简单的模型开始,一步步到复杂的模型。
- 原理分析:使用基本的物理学概念或者数学工具,理解神经网络的工作方式。
- 可视化理解:可视化是学习新知识的重要手段,由于我们使用了简单案例,因此可以很方便地可视化。
原理分析和可视化理解也是本书的一个特点,试图让神经网络是可以解释的,而不是盲目地使用。
还有一个非常重要的地方,我们还有配套的Python代码,除了一些必要的科学计算库和绘图库,如NumPy和Matplotlib等,我们没有使用任何已有的深度学习框架,而是带领大家从零开始搭建自己的知识体系,从简单到复杂,一步步理解深度学习中的众多知识点。
对于没有Python经验的朋友来说,通过阅读示例代码,也可以起到帮助大家学习Python的作用,一举两得。随着问题的难度加深,代码也会增多,但是前后都有继承关系的,最后的代码会形成一个小的框架,笔者称之为Mini-Framework,可以用搭积木的方式调用其中的函数来搭建深度学习的组件。
这些代码都是由笔者亲自编写调试的,每章节都可以独立运行,得到相关章节内所描述的结果,包括打印输出和图形输出。
另外,为了便于理解,笔者绘制了大量的示意图,数量是同类书籍的10倍以上。一图顶万字,相信大家会通过这些示意图快速而深刻地理解笔者想要分享的知识点,使大家能够从真正的“零”开始,对神经网络、深度学习有基本的了解,并能动手实践。
对于读者的要求:
- 学过高等数学中的线性代数与微分
- 有编程基础,可以不会Python语言,因为可以从示例代码中学得
- 思考 + 动手的学习模式
可以帮助读者达到的水平:
- 可以判断哪些任务是机器学习可以实现的,哪些是科学幻想,不说外行话
- 深刻了解神经网络和深度学习的基本理论
- 培养举一反三的解决实际问题的能力
- 得到自学更复杂模型和更高级内容的能力
- 对于天资好的读者,可以培养研发新模型的能力
符号约定
符号 | 含义 |
---|---|
x x x | 训练用样本值 |
x 1 x_1 x1 | 第一个样本或样本的第一个特征值,在上下文中会有说明 |
x 12 , x 1 , 2 x_{12},x_{1,2} x12,x1,2 | 第1个样本的第2个特征值 |
X X X | 训练用多样本矩阵 |
y y y | 训练用样本标签值 |
y 1 y_1 y1 | 第一个样本的标签值 |
Y Y Y | 训练用多样本标签矩阵 |
z z z | 线性运算的结果值 |
Z Z Z | 线性运算的结果矩阵 |
Z 1 Z1 Z1 | 第一层网络的线性运算结果矩阵 |
σ \sigma σ | 激活函数 |
a a a | 激活函数结果值 |
A A A | 激活函数结果矩阵 |
A 1 A1 A1 | 第一层网络的激活函数结果矩阵 |
w w w | 权重参数值 |
w 12 , w 1 , 2 w_{12},w_{1,2} w12,w1,2 | 权重参数矩阵中的第1行第2列的权重值 |
w 1 12 , w 1 1 , 2 w1_{12},w1_{1,2} w112,w11,2 | 第一层网络的权重参数矩阵中的第1行第2列的权重值 |
W W W | 权重参数矩阵 |
W 1 W1 W1 | 第一层网络的权重参数矩阵 |
b b b | 偏移参数值 |
b 1 b_1 b1 | 偏移参数矩阵中的第1个偏移值 |
b 2 1 b2_1 b21 | 第二层网络的偏移参数矩阵中的第1个偏移值 |
B B B | 偏移参数矩阵(向量) |
B 1 B1 B1 | 第一层网络的偏移参数矩阵(向量) |
X T X^T XT | X的转置矩阵 |
X − 1 X^{-1} X−1 | X的逆矩阵 |
l o s s , l o s s ( w , b ) loss,loss(w,b) loss,loss(w,b) | 单样本误差函数 |
J , J ( w , b ) J, J(w,b) J,J(w,b) | 多样本损失函数 |
1.3 神经网络的基本工作原理简介
1.3.1 神经元细胞的数学模型
神经网络由基本的神经元组成,图1-13就是一个神经元的数学/计算模型,便于我们用程序来实现。
图1-13 神经元计算模型
输入 input
(x1,x2,x3) 是外界输入信号,一般是一个训练数据样本的多个属性,比如,我们要预测一套房子的价格,那么在房屋价格数据样本中,x1可能代表了面积,x2可能代表地理位置,x3可能朝向。另外一个例子是,假设(x1,x2,x3)分别代表了(红,绿,蓝)三种颜色,而此神经元用于识别输入的信号是暖色还是冷色。
权重 weights
(w1,w2,w3) 是每个输入信号的权重值,以上面的 (x1,x2,x3) 的例子来说,x1的权重可能是0.92,x2的权重可能是0.2,x3的权重可能是0.03。当然权重值相加之后可以不是1。
偏移 bias
还有个b是怎么来的?一般的书或者博客上会告诉你那是因为 y = w x + b y=wx+b y=wx+b,b是偏移值,使得直线能够沿Y轴上下移动。这是用结果来解释原因,并非b存在的真实原因。从生物学上解释,在脑神经细胞中,一定是输入信号的电平/电流大于某个临界值时,神经元细胞才会处于兴奋状态,这个b实际就是那个临界值。亦即当:
w 1 ⋅ x 1 + w 2 ⋅ x 2 + w 3 ⋅ x 3 > = t w_1 \cdot x_1 + w_2 \cdot x_2 + w_3 \cdot x_3 >= t w1⋅x1+w2⋅x2+w3⋅x3>=t
时,该神经元细胞才会兴奋。我们把t挪到等式左侧来,变成 ( − t ) (-t) (−t),然后把它写成b,变成了:
w 1 ⋅ x 1 + w 2 ⋅ x 2 + w 3 ⋅ x 3 + b > = 0 w_1 \cdot x_1 + w_2 \cdot x_2 + w_3 \cdot x_3 + b >= 0 w1⋅x1+w2⋅x