文章目录
- About
- Chapter 1: Using neural nets to recognize handwritten digits \ 第一章:使用神经网络识别手写数字
- Chapter 2: How the backpropagation algorithm works / 反向传播算法是如何工作的
-
- Warm up: a fast matrix-based approach to computing the output from a neural network / 热身:一个基于矩阵的快速计算神经网络输出的方法
- The two assumptions we need about the cost function / 关于代价函数的两个假设
- The Hadamard product, s⊙t / 哈达玛积,s⊙t
- The four fundamental equations behind backpropagation / 反向传播背后的四个基本等式
- Proof of the four fundamental equations (optional) / 四个基本方程的证明(自选章节)
- The backpropagation algorithm / 反向传播算法
- Chapter 3: Improving the way neural networks learn
\space \\ \space \\
About
http://neuralnetworksanddeeplearning.com/about.html
- 本书主要讲解机器学习内部的原理,如果你只想学习函数库应该自己去别处寻找对应的教程和文档。
- 第二章会涉及一些难的数学知识(多元微积分,线性代数)。
- 学习的过程中,尝试做书中的exercise,不应该专注于解决书中的problems,因为problems往往更有挑战性,但如果你能耐心解决problems,会使你更好地理解机器学习。
- 更好的是你可以尝试把problems换成自己的项目,如把你的音乐收藏分类、或者预测股票价格,这样自己更有动力。因为
Emotional commitment is a key to achieving mastery.
\space \\ \space \\
Chapter 1: Using neural nets to recognize handwritten digits \ 第一章:使用神经网络识别手写数字
http://neuralnetworksanddeeplearning.com/chap1.html
Perceptron \ 感知机
http://neuralnetworksanddeeplearning.com/chap1.html#perceptrons
- 这个感知机接受二进制输入,输出二进制,通过权重(weight)表示各个变量对输出的重要程度,大于阈值(threshold)时点亮,否则熄灭
output = { 0 if ∑ w j x j ≤ threshold 1 if ∑ w j x j > threshold \text{output}= \begin{cases} 0\quad \text{if}~ \sum w_j x_j \le \text{threshold}\\ 1\quad \text{if}~ \sum w_j x_j \gt \text{threshold} \end{cases} output={ 0if ∑wjxj≤threshold1if ∑wjxj>threshold
如此一来,多层(layer)感知机就可以处理复杂抽象的决策:
- 公式简化:
- 用向量点乘代替Σ求和公式: w ⋅ x ≡ ∑ w j x j w\cdot x \equiv \sum w_j x_j w⋅x≡∑wjxj
- 用偏置(bias)代替阈值: b = − threshold \text{b}=-\text{threshold} b=−threshold
- 最终化简为
output = { 0 if w ⋅ x + b ≤ 0 1 if w ⋅ x + b > 0 \text{output}= \begin{cases} 0\quad \text{if}~ w \cdot x +b \le 0\\ 1\quad \text{if}~ w \cdot x +b \gt 0 \end{cases} output={ 0if w⋅x+b≤01if w⋅x+b>0
偏置b可以理解成一个神经元点亮的难易度,b越大越容易点亮,否则不容易点亮
- 我们可以使用感知机来计算初等逻辑函数,如这个与非门
- 与非门可以表示一切计算,因此感知机也可以,比如实现这个二进制加法:(weight=-2, b=3)
简化:把最下面的神经元两个相同的输入变为一个,weight改成-4
最左边的输入可以简记为输入层:
输入感知机的记法:
应将其看作能输出想要的值的单元
\space \\ \space \\
Sigmoid neurons \ Sigmoid神经元
http://neuralnetworksanddeeplearning.com/chap1.html#sigmoid_neurons
使用perceptron网络时,一个perceptron的weight和bias的微小改变可能会使整个网络的输出发生翻天覆地的改变(因为一个perceptron的输出直接从0变成了1)
由此我们推出了接受实数输入,输出更平滑的sigmoid neuron。
sigmoid函数:
σ ( z ) ≡ 1 1 + e − z \sigma (z)\equiv \frac{1}{1+e^{-z}} σ(z)≡1+e−z1
则sigmoid 神经元的输出:
output = σ ( w ⋅ x + b ) = 1 1 + e − ∑ w j x j − b \text{output}=\sigma (w\cdot x+b)=\cfrac{1}{1+e^{-\sum w_j x_j-b}} output=σ(w⋅x+b)=1+e−∑wjxj−b1
代数公式并不是我们要关注的重点,我们要注意的是它的图像:
相比于perceptron阶梯函数式的输出:
它在 − ∞ -\infin −∞和 + ∞ +\infin +∞时维持了perceptron的性质,而在中间部分的输出更平滑了。
而且,由
Δ output ≈ ∑ ∂ output ∂ w j Δ w j + ∂ output ∂ b Δ b \Delta \text{output} \approx \sum \frac{\partial \text{output}}{\partial w_j}\Delta w_j + \frac{\partial \text{output}}{\partial b}\Delta b Δoutput≈∑∂wj∂outputΔwj+∂b∂outputΔb
可知,输出的微小改变是关于 Δ w j \Delta w_j Δwj和 Δ b \Delta b Δb的线性函数,因此可以方便的通过weight和bias的微小改变控制输出的微小改变。
因此,sigmoid neuron不仅性质上与perceptron类似,同时也更容易控制改变weight和bias带来的输出的改变。
练习
\space \\ \space \\
The architecture of neural networks \ 神经网络的结构
http://neuralnetworksanddeeplearning.com/chap1.html#the_architecture_of_neural_networks
名词术语:
这种模型是前馈神经网络(feedforward neural networks),信息只向前传播,不存在环。存在环路的神经网络模型叫递归神经网络(recurrent neural networks)。
虽然多层网络(multiple layer networks)由sigmoid neuron组成,但也被称作多层感知机(MLP - multilayer perceptrons)。
\space \\ \space \\
A simple network to classify handwritten digits \ 用简单的神经网络识别手写数字
http://neuralnetworksanddeeplearning.com/chap1.html#a_simple_network_to_classify_handwritten_digits
我们首先需要把一串数字分成单个数字,这并不难,重点是如何分辨各个数字。
我们设计这样的神经网络模型:
把单个数字图片(分辨率为28x28)的每个像素的灰度值(0.0为纯白,1.0为纯黑)作为一个输入,输入层总共有28x28=784个输入神经元,隐含层我们暂定有n=15个神经元,输出层定为10个神经元(分别表示0~9)。
当输出层的某一个神经元(如6号神经元)的激活值(activation value)最大时,我们认为输入的数字是6。
接下来是一种对识别过程的形象理解:
我们可以假设隐含层中第一个神经元识别输入中有没有类似这样的笔画:
可以通过重视输入中这些像素点(权重更大)而忽视其他像素点(权重小),类似的,假设第二、三、四个神经元识别输入中有没有:
如果第一、二、三、四个神经元被激活那么我们可以推断出这个数字是0:
注意,这种思路只是给你一个启发性的理解,并不代表机器真的是这么工作的。
练习:
在上述的三层神经网络中额外加一层就可以实现按位表示数字(2进制),如下图所示。假如旧输出层正确的输出不低于0.99,错误输出不高于0.01,请为新输出层寻找一组合适的weight和bias。
解:
思路:如果用new output layer中第i个神经元代表输出结果的二进制表达中的第i位的话,根据
Oct | Bin |
---|---|
0 | 0000 |
1 | 0001 |
2 | 0010 |
3 | 0011 |
4 | 0100 |
5 | 0101 |
6 | 0110 |
7 | 0111 |
8 | 1000 |
9 | 1001 |
对于new的第一个神经元,我们需要这个神经元更看重old中第8、9号的输入,轻视其他输入,由此设计出它的weight为[0, 0, 0, 0, 0, 0, 0, 10, 10],bias为-5,使计算 σ ( w ⋅ x + b ) \sigma (w\cdot x +b) σ(w⋅x+b)之前自变量足够小(至少得<0)。(或者重视和轻视的weight互为相反数,bias设为0也可)
其它三个神经元同理。
\space \\ \space \\
Learning with gradient descent \ 学习梯度下降
http://neuralnetworksanddeeplearning.com/chap1.html#learning_with_gradient_descent
我们的训练样本可以在MNIST上找到。
我们用 x x x 代表一个训练样本的输入,一个10维列向量 y = y ( x ) y=y(x) y=y(x)代表我们希望的输出,如,某个图片 x x x代表了6,那么 y ( x ) = ( 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 ) T y(x)=(0,0,0,0,0,0,1,0,0)^T y(x)=(0,0,0,0,0,0,1,0,0)T
我们想要的是一个算法来帮助我们找到特定的weights和biases,使得对于所有训练样本 x x x,神经网络的输出都近似于 y ( x ) y(x) y(x),为了度量这个近似度,也即我们神经网络的准确度,我们定义这样一个代价函数(cost function):
(6) C ( w , b ) ≡ 1 2 n ∑ x ∥ y ( x ) − a ∥ 2 C(w,b)\equiv \frac{1}{2n}\sum _x \lVert y(x)-a \Vert ^2\tag 6 C(w,b)≡2n1x∑∥y(x)−a∥2(6)
其中 w w w代表所有的weight, b b b代表所有的bias, n n n代表所有训练样本的数量, a a a是某个x对应的输出结果列向量(为了简化,没有写成 a ( x , w , b ) a(x,w,b) a(x,w,b)), ∥ v ∥ \|v\| ∥v∥代表向量 v v v的模。
这个代价函数中,单个样本的代价 C x = 1 2 ∥ y ( x ) − a ∥ 2 = 1 2 ∑ y i ∈ y ( y i − a i ) 2 C_x=\frac{1}{2}\|y(x)-a\|^2=\frac{1}{2}\sum_{y_i\in y}(y_i-a_i)^2 Cx=21∥y(x)−a∥2=21yi∈y∑(yi−ai)2(注意y和a是向量)代表了神经网络对于单个样本的准确度, C x C_x Cx越大( a a a与 y y y相差越大),准确度越低。
C ( w , b ) C(w,b) C(w,b)是对于所有样本的代价取平均值,代表了神经网络对总体样本的准确度。
*这里的 C ( w , b ) = 1 2 n ∑ x ∥ y ( x ) − a ∥ 2 C(w,b)=\frac{1}{2n}\sum _x \lVert y(x)-a \Vert ^2 C(w,b)=2n1∑x∥y(x)−a∥2形式的代价函数我们称为为二次代价函数(quadratic cost),也叫均方误差(mean squared error - MSE)
由于代价函数 C ( w , b ) C(w,b) C(w,b)是一个光滑曲线,因此更容易找出如何对 w w w和 b b b做出微小的改变来缩小代价函数 C ( w , b ) C(w,b) C(w,b)的值。
如果代价函数 C ( w , b ) C(w,b) C(w,b)的值越小,就代表我们神经网络越准确。
由此,我们目前的目标是求什么样的 w w w和 b b b能使代价函数值最小。
要想求函数的最小值,我们最先想到的方法可能是解偏导=0,然后计算出极值点,最后得到最值点。但对于拥有庞大自变量的函数,这种方法几乎是不可能的。
我们可以换一种角度思考,想象一个二元函数 C ( v 1 , v 2 ) C(v_1,v_2) C(v1,v2)的图像,把它当作一个山谷,随机找一点放一个小球,这个小球会沿着斜坡下滑,在极小值处停下,如果能算出小球下降的方向,根据小球下降的路径不就可以得到最小值(局部最小值,当然,如果是全局最小值更好)了吗。
把这个问题转化成数学语言:
若小球沿 v 1 v_1 v1方向移动微小量 Δ v 1 \Delta v_1 Δv1,沿 v 2 v_2 v2方向移动微小量 Δ v 2 \Delta v_2 Δv2,那么 C C C的变化量近似为:
(7) Δ C ≈ ∂ C ∂ v 1 Δ v 1 + ∂ C ∂ v 2 Δ v 2 \Delta C \approx \frac{\partial C}{\partial v_1}\Delta v_1 + \frac{\partial C}{\partial v_2}\Delta v_2 \tag{7} ΔC≈∂v1∂CΔv1+∂v2∂CΔv2(7)
求 Δ v 1 \Delta v_1 Δv1和 Δ v 2 \Delta v_2 Δv2使得 Δ C \Delta C ΔC为负(即使小球向下滚)。
我们记 Δ v ≡ ( Δ v 1 , Δ v 2 ) \Delta v \equiv(\Delta v_1,\Delta v_2) Δv≡(Δv