Neural networks and deep learning 学习笔记
文章目录
-
About
-
Chapter 1: Using neural nets to recognize handwritten digits \ 第一章:使用神经网络识别手写数字
-
- Perceptron \ 感知机
- Sigmoid neurons \ Sigmoid神经元
- The architecture of neural networks \ 神经网络的结构
- A simple network to classify handwritten digits \ 用简单的神经网络识别手写数字
- Learning with gradient descent \ 学习梯度下降
- Implementing our network to classify digits \ 实现分类数字的神经网络
- Toward deep learning \ 迈向深度学习
-
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 / 反向传播算法
-
- The code for backpropagation / 反向传播算法代码
- In what sense is backpropagation a fast algorithm? / 为什么说反向传播算法很高效?
- Backpropagation: the big picture
-
Chapter 3: Improving the way neural networks learn
-
- The cross-entropy cost function / 交叉熵代价函数
-
- What does the cross-entropy mean? Where does it come from?
\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)时点亮,否则熄灭
\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}
如此一来,多层(layer)感知机就可以处理复杂抽象的决策:

-
公式简化:
- 用向量点乘代替Σ求和公式:w\cdot x \equiv \sum w_j x_j
- 用偏置(bias)代替阈值:\text{b}=-\text{threshold}
- 最终化简为
\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}
偏置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函数:
\sigma (z)\equiv \frac{1}{1+e^{-z}}
则sigmoid 神经元的输出:
\text{output}=\sigma (w\cdot x+b)=\cfrac{1}{1+e^{-\sum w_j x_j-b}}
代数公式并不是我们要关注的重点,我们要注意的是它的图像:

相比于perceptron阶梯函数式的输出:

它在-\infin和+\infin时维持了perceptron的性质,而在中间部分的输出更平滑了。
而且,由
\Delta \text{output} \approx \sum \frac{\partial \text{output}}{\partial w_j}\Delta w_j + \frac{\partial \text{output}}{\partial b}\Delta b
可知,输出的微小改变是关于\Delta w_j和\Delta 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,使计算\sigma (w\cdot x +b)之前自变量足够小(至少得<0)。(或者重视和轻视的weight互为相反数,bias设为0也可)
其它三个神经元同理。
\space \\ \space \\
Learning with gradient descent \ 学习梯度下降
http://neuralnetworksanddeeplearning.com/chap1.html#learning_with_gradient_descent
我们的训练样本可以在MNIST上找到。
我们用 x 代表一个训练样本的输入,一个10维列向量y=y(x)代表我们希望的输出,如,某个图片x代表了6,那么 y(x)=(0,0,0,0,0,0,1,0,0)^T
我们想要的是一个算法来帮助我们找到特定的weights和biases,使得对于所有训练样本x,神经网络的输出都近似于y(x),为了度量这个近似度,也即我们神经网络的准确度,我们定义这样一个代价函数(cost function):
C(w,b)\equiv \frac{1}{2n}\sum _x \lVert y(x)-a \Vert ^2\tag 6
其中w代表所有的weight,b代表所有的bias,n代表所有训练样本的数量,a是某个x对应的输出结果列向量(为了简化,没有写成a(x,w,b)),\|v\|代表向量v的模。
这个代价函数中,单个样本的代价C_x=\frac{1}{2}\|y(x)-a\|^2=\frac{1}{2}\sum_{y_i\in y}(y_i-a_i)^2(注意y和a是向量)代表了神经网络对于单个样本的准确度,C_x越大(a与y相差越大),准确度越低。
C(w,b)是对于所有样本的代价取平均值,代表了神经网络对总体样本的准确度。
*这里的C(w,b)=\frac{1}{2n}\sum _x \lVert y(x)-a \Vert ^2形式的代价函数我们称为为二次代价函数(quadratic cost),也叫均方误差(mean squared error - MSE)
由于代价函数C(w,b)是一个光滑曲线,因此更容易找出如何对w和b做出微小的改变来缩小代价函数C(w,b)的值。
如果代价函数C(w,b)的值越小,就代表我们神经网络越准确。
由此,我们目前的目标是求什么样的w和b能使代价函数值最小。
要想求函数的最小值,我们最先想到的方法可能是解偏导=0,然后计算出极值点,最后得到最值点。但对于拥有庞大自变量的函数,这种方法几乎是不可能的。
我们可以换一种角度思考,想象一个二元函数C(v_1,v_2)的图像,把它当作一个山谷,随机找一点放一个小球,这个小球会沿着斜坡下滑,在极小值处停下,如果能算出小球下降的方向,根据小球下降的路径不就可以得到最小值(局部最小值,当然,如果是全局最小值更好)了吗。
把这个问题转化成数学语言:
若小球沿v_1方向移动微小量\Delta v_1,沿v_2方向移动微小量\Delta v_2,那么C的变化量近似为:
\Delta C \approx \frac{\partial C}{\partial v_1}\Delta v_1 + \frac{\partial C}{\partial v_2}\Delta v_2 \tag{7}
求\Delta v_1和\Delta v_2使得\Delta C为负(即使小球向下滚)。
我们记\Delta v \equiv(\Delta v_1,\Delta v_2),梯度\nabla C\equiv(\cfrac{\partial C}{\partial v_1}, \cfrac{\partial C}{\partial v_2}),那么公式(7)可以记作
\Delta C \approx \nabla C \cdot \Delta v \tag{9}
如果我们取\Delta v=-\eta \nabla C,其中\eta是比较小的正参数(也叫学习率 - learning rate),代入等式(9)得\Delta C\approx -\eta (\nabla C )^2 \le 0 ,可以保证C的值是减少的,因此,我们要移动小球的位置v为:
v \rarr v' =v-\eta\nabla C
然后不断利用这个方法移动小球,最终就可以使C达到(至少我们期望是)最小值。
总结一下,我们让小球不断沿-\nabla C的方向“滚下”山谷:
要想让梯度下降法正确地工作,我们要使学习率\eta足够小使等式(9)成立,否则的话,有可能导致\Delta C \gt0,与此同时,我们不能让学习率\eta过小导致梯度下降法过于缓慢。(现实中\eta可以不断地改变保证既不过小也不过大,稍后会讲解)
这种算法对多元函数同样成立:
\Delta v=(\Delta v_1,\dots,\Delta v_m),\Delta C \approx \nabla C \cdot \Delta v,其中\nabla C \equiv \bigg( \cfrac{\partial C}{\partial v_1},\dots,\cfrac{\partial C}{\partial v_m}\bigg),取\Delta v=-\eta\nabla C,不断更新v:
v \rarr v'=v-\eta\nabla C
*梯度下降法也是求函数小值的有效方法
把梯度下降算法应用在神经网络中,就是:
w_k\rarr w_k'=w_k-\eta\cfrac{\partial C}{\partial w_k}\\ b_l\rarr b_l'=b_l-\eta\cfrac{\partial C}{\partial b_l}
但目前有一个问题,因为 C(w,b)\equiv \frac{1}{2n}\sum _x \lVert y(x)-a \Vert ^2 是分别计算单个样本的代价C_x=\frac{1}{2}\|y(x)-a\|^2=\frac{1}{2}\sum_{y_i\in y}(y_i-a_i)^2
最后求和取平均值,因此要想计算梯度\nabla C我们也要分别计算单个样本的梯度\nabla C_x并求和取平均值,\nabla C=\frac{1}{n}\sum_x\nabla C_x。
问题是,因为遍历一次所有样本得到的\nabla C只能令小球向下走一步,要想走到山谷需要不断地遍历所有样本,而在样本量巨大的情况下,学习速度会大大减慢。
为了提高学习速度,我们引入了随机梯度下降算法(stochastic gradient descent - SGD)。
这个算法的主要思想是:在计算训练样本中随机抽取一小部分,计算这些样本的梯度\nabla C_x来代替所有样本的梯度\nabla C。通过计算这小部分的样本的梯度平均值代替真正的梯度\nabla C,可以大大提高算法效率,因而提高学习速率,而且估计值和准确值相差不大。
具体来说,SGD随机在训练样本中挑出少量的m个,我们记为X_1,X_2,\dots,X_m,称作一个 mini-batch 。如果m的值足够大,我们可以认为这一个 mini-batch 的梯度\nabla C_{X_j}的平均值(左式)约等于所有样本的梯度\nabla C_x的平均值(右式):
\begin{aligned} &\cfrac{\sum^m_{j=1}\nabla C_{X_j}}{m}\approx\cfrac{\sum_x\nabla C_x}{n}=\nabla C \\ \\ \Rarr&\nabla C\approx\frac{1}{m}\sum^m_{j=1}\nabla C_{X_j} \end{aligned}
由此可以估计出\nabla C的真实值。
对于神经网络模型来说,SGD通过随机抽取训练样本组成 mini-batch ,通过这些 mini-batch 训练:
\tag{20}w_k\rarr w_k'=w_k-\frac\eta m\sum_j\cfrac{\partial C_{X_j}}{\partial w_k}
\tag{21}b_l\rarr b_l'=b_l-\frac\eta m\sum_j\cfrac{\partial C_{X_j}}{\partial b_l}
其中求和是对于当前 mini-batch 中的样本X_j求和。然后我们继续随机抽取下一个 mini-batch 再进行训练,直到所有的训练样本都被用过一次,我们称为完成了一轮(epoch)训练,然后我们再重新进行新的一轮训练。
要注意的是,在等式(6)中,我们对所有样本的代价和进行了\frac 1 n的缩放。别人有时会省略这个\frac 1n,直接计算所有样本代价的和,尤其适用于对于样本数不确定(比如会实时产生测试数据)的时候。这种情况下,对应等式(20)和等式(21)中的\frac 1 m也会省略。理论上来讲,这种变化影响不大,因为等价于改变了学习率\eta,但在做详细的比较时需要格外关注。
*SGD是神经网络学习中常用且强大的技巧,也是本书中大部分使用的学习方法的基础。
这里有别人对高维空间的直观解释(表示我什么也看不懂)
Implementing our network to classify digits \ 实现分类数字的神经网络
http://neuralnetworksanddeeplearning.com/chap1.html#implementing_our_network_to_classify_digits
在这下载代码和数据
MNIST的数据由60,000个训练图像和10,000个测试图像构成。但我们会把60,000个训练图像再分成50,000个训练图像集和10,000个图像的测试集(validation set),后面会讲到测试集有助于设置神经网络中的超参数(hyper-parameter)如学习率,我们暂时不使用。并且以后提到的“训练数据”指的是这50,000个图像集。
同时我们需要Numpy这个Python库。
首先是建立神经网络的一个类:
class Network(object):
def __init__(self, sizes):
self.num_layers = len(sizes)
self.sizes = sizes
self.biases = [np.random.randn(y, 1) for y in sizes[1:]]
self.weights = [np.random.randn(y, x)
for x, y in zip(sizes[:-1], sizes[1:])]
其中sizes列表包含的是每一层神经元的数量,比如想建立一个第一层有2个神经元,第二层有3个神经元,第三层有1个神经元的网络,只需
net = Network([2, 3, 1])
randn可以生成标准正态分布(均值为0,标准差为1)的随机数,接受的参数表示对应维度的长度。
注意weight和bias的建立方式。我们用w^{(L)}_{jk}表示第L层第j个神经元和第L-1层第k个神经元之间的联系。(如第二层第2个神经元与第三层第1个神经元之间的权重用w^{(3)}_{12}表示)
这样记录的原因是符合矩阵计算的习惯,如要想计算第三层a'的激活值,用向量表示为:
a'=\sigma(wa+b)
(a表示第二层的激活值)
矩阵表示为(以2-3-1神经网络
为例):
\begin{bmatrix} a^{(3)}_1 \end{bmatrix}=\sigma \Big( \begin{bmatrix} w^{(3)}_{11}, w^{(3)}_{12}, w^{(3)}_{13} \end{bmatrix} \cdot \begin{bmatrix} a^{(2)}_1\\ a^{(2)}_2\\ a^{(2)}_3\\ \end{bmatrix} + \begin{bmatrix} b^{(3)}_1\end{bmatrix} \Big)
\begin{bmatrix} a^{(2)}_1 \\ a^{(2)}_2 \\ a^{(2)}_3 \end{bmatrix}=\sigma \Bigg( \begin{bmatrix} w^{(2)}_{11}, w^{(2)}_{12}\\ w^{(2)}_{21}, w^{(2)}_{22}\\ w^{(2)}_{31}, w^{(2)}_{32}\\ \end{bmatrix}+99 \cdot \begin{bmatrix} a^{(1)}_1\\ a^{(1)}_2 \end{bmatrix} + \begin{bmatrix} b^{(2)}_1\\ b^{(2)}_2\\ b^{(2)}_3 \end{bmatrix} \Bigg)
接下来是完整的实现代码,传送门,具体反向传播的数学公式可以参考这里,代码里用的是矩阵计算方法,会在下一章讲到。
*如果是Python3,在mnist_load.py中要把cPickle改成picke;load最后的(f)改成(f,encoding='bytes');SGD中开头加上training_data=list(training_data) test_data=list(test_data)
debug神经网络比较困难,因为不知道问题出在哪。可能是学习率过高?或过低?可能是默认的weight和bias不够好?可能是训练数据不够?可能是训练轮数不够?亦或者是神经元的结构设计不对?后面会详细讲如何选择这些参数。
练习
epoches=30, mini_batch_size=10, eta=3.0
- 784-30-10: 95%
- 784-10-10-10-10: 91%
- 784-10: 75%
又讲了跟SVM(support vector machine)算法的比较
*复杂的算法 \le 简单的算法+好的训练数据
Toward deep learning \ 迈向深度学习
http://neuralnetworksanddeeplearning.com/chap1.html#toward_deep_learning
有两层以上隐含层的网络叫深度神经网络(deep neural networks)
讲了直观上神经网络是如何分层解决问题的,把大问题化成小问题。而且有5到10层隐含层的深度神经网络表现比浅层神经网络好很多。但同时单纯的SGD算法在深度神经网络的表现并不好,他们在此基础上对算法进行了优化。
Chapter 2: How the backpropagation algorithm works / 反向传播算法是如何工作的
http://neuralnetworksanddeeplearning.com/chap2.html
反向传播(backpropagation)的具体算法
Warm up: a fast matrix-based approach to computing the output from a neural network / 热身:一个基于矩阵的快速计算神经网络输出的方法
neuron-by-neuron:
a^l_j=\sigma\Bigg(\sum_kw^l_{jk}a^{l-1}_k+b^l_j\Bigg)
layer-by-layer:
a^l=\sigma(w^la^{l-1}+b^l)=\sigma(z^l)
where
z^l\equiv w^la^{l-1}+b^l
and
\sigma\Bigg(\begin{bmatrix}z_1\\ z_2\end{bmatrix} \Bigg)=\begin{bmatrix}\sigma(z_1)\\ \sigma(z_2)\end{bmatrix}
z也叫加权输入(weighted input)
\,\\ \,\\
The two assumptions we need about the cost function / 关于代价函数的两个假设
C=\frac{1}{2n}\sum _x \lVert y(x)-a^L(x) \Vert ^2
where: n is the total number of training examples; the sum is over individual training examples, x; y=y(x) is the corresponding desired output; L denotes the number of layers in the network; and a^L=a^L(x) is the vector of activations output from the network when x is input.
1st assumption:
C=\frac 1n\sum_xC_x
where C_x is cost of a single input.
as in:
C_x=\frac 12\|y-a^L\|^2
2nd assumption: C=C(a^L) since:
C_x=\frac 12\|y-a^L\|^2=\frac 12\sum_{j=1}^{n_{FL}}(y_j-a^L_j)^2
因此C可以看作以a^L为变量的函数
\,\\ \,\\
The Hadamard product, s⊙t / 哈达玛积,s⊙t
http://neuralnetworksanddeeplearning.com/chap2.html#the_hadamard_product_s_\odot_t
s\odot t=c\quad where \;\; c_{ij}=s_{ij}* t_{ij}
\begin{matrix} \left[\begin{array}{c} 1 \\ 2 \end{array}\right] \odot \left[\begin{array}{c} 3 \\ 4\end{array} \right] = \left[ \begin{array}{c} 1 * 3 \\ 2 * 4 \end{array} \right] = \left[ \begin{array}{c} 3 \\ 8 \end{array} \right]. \tag{28}\end{matrix}
称作 Hadamard product 或 Schur product
\,\\ \,\\
The four fundamental equations behind backpropagation / 反向传播背后的四个基本等式
我们记错误量(error)为\delta ^l
\delta^l_j=\frac{\partial C}{\partial z^l_j}
输出层的错误量 \delta^L 等式:
它的分量为:
\delta^L_j=\frac{\partial C}{\partial a^L_j}\sigma'(z^L_j)\tag{BP1}
矩阵形式可以写成:
\begin{aligned} \delta^L&=\nabla_aC\odot\sigma'(z^L)\\ \\ &=(a^L-y)\odot\sigma'(z^L) \end{aligned}\tag{BP1}
由下一层 \delta^{l+1}计算错误量\delta^l 的等式:
\delta^l = ((w^{l+1})^T \delta^{l+1}) \odot \sigma'(z^l)\tag{BP2}
通过对下一层的错误量\delta^{l+1}左乘对应权重矩阵的转置(w^{l+1})^T,我们可以理解成把错误量 回退 到了上一层,再算哈达玛积\odot \sigma'(z^l)又退去了激活函数,就得到了l层的对应加权输入(weighted input)的错误量\delta^l
由等式{BP1}和{BP2}我们就可以算出任意一层的错误量了。
代价函数相对于偏置的等式 :
\frac{\partial C}{\partial b^l_j}=\delta^l_j\tag{BP3}
写成矩阵形式就是:
\frac{\partial C}{\partial b} = \delta\tag{BP3}
代价函数相对于权重的等式 :
\frac{\partial C}{\partial w^l_{jk}} = a^{l-1}_k \delta^l_j
可以简洁表达成:
\frac{\partial C}{\partial w} = a_{\rm in} \delta_{\rm out}
当a_{\rm in}很小,a_{\rm in}\approx0时,梯度中对应的\partial C/\partial w也会比较小,我们会说学习得慢,因为这个weight在梯度下降时改变的不多。
所以,由等式(BP4)得到的结论是:激活值低的神经元输出的权重学习得很慢。
其他结论:
根据(BP1),当\sigma(z^L_j)\approx 0或1 时,根据sigmoid函数图像,对应的\sigma'(z^L_j)\approx0。因此结论是:如果输出层神经元的激活值过低(\approx0)或过高(\approx1)时,对应的最后一层的权重学习得慢。这时可以说这个输出神经元已经“饱和(saturated)”了,结果就是,权重不再学习了(或者学得很慢)
对偏置的影响类似。
对其他层来说也类似。对于等式(BP2)来说,如果神经元接近饱和,\delta^l_j就会很小。同样也说明输入给饱和神经元的权重学习得很慢。
总结一下就是,一个权重,如果它的输入神经元激活值低,或者它的输出神经元饱和(激活值要么高要么低),那么这个权重学习得慢。
这四个等式对任意的激活函数——不只是\sigma——都适用。我们可以利用这些等式设计特定性质的激活函数,比如可以找一个(非sigmoid)函数\sigma,保证\sigma'一直是正的,而且永不接近0,这样就可以防止sigmoid神经元饱和时会发生的学习慢的问题。
记住这四个等式有助于我们理解为什么要对激活函数做出特定的调整,以及它们产生的影响。

\,\\ \,\\
Proof of the four fundamental equations (optional) / 四个基本方程的证明(自选章节)
利用导数的链式法则证明。细节不写。
\,\\ \,\\
The backpropagation algorithm / 反向传播算法
http://neuralnetworksanddeeplearning.com/chap2.html#the_backpropagation_algorithm
使用SGD算法,有mini_batch时,对应的算法修改为:

The code for backpropagation / 反向传播算法代码
http://neuralnetworksanddeeplearning.com/chap2.html#the_code_for_backpropagation
Problem:
把单个样本的计算整合成整个矩阵进行计算
In what sense is backpropagation a fast algorithm? / 为什么说反向传播算法很高效?
与显而易见的微积分求偏导方法相比,极大地减少了时间消耗
Backpropagation: the big picture
http://neuralnetworksanddeeplearning.com/chap2.html#backpropagation_the_big_picture
Chapter 3: Improving the way neural networks learn
http://neuralnetworksanddeeplearning.com/chap3.html
- cross-entropy cost function - 交叉熵代价函数
- four so-called “regularization” methods (L1 and L2 regularization, dropout, and artificial expansion of the training data), which make our networks better at generalizing beyond the training data - 四种正则化方法
- a better method for initializing the weights in the network
- a set of heuristics to help choose good hyper-parameters for the network
The cross-entropy cost function / 交叉熵代价函数
http://neuralnetworksanddeeplearning.com/chap3.html#the_cross-entropy_cost_function
根据原文动画的两个例子,我们可以发现,当输出接近0或1时,\sigma'(z)会变得非常小,导致 \partial C/\partial w 和 \partial C/\partial b 变得小,进而导致梯度下降得慢(学习得慢)
对于一个神经元:
我们定义交叉熵代价函数 如下:
C = -\frac{1}{n} \sum_x \left[y \ln a + (1-y ) \ln (1-a) \right]
分析一下这个式子就会发现,
- C>0(因为y=0\; or\; 1,\quad a\in(0,1))
- 输出接近期望值时,代价\approx 0,即
\begin{aligned} &y=0,\,a\approx 0\, 时,C=\ln(1-a)\approx 0 \\ 或 \\ &y=1,\,a\approx 1\, 时,C=\ln(a)\approx 0 \end{aligned}
这两点与原来的二次代价函数性质一致。那么这个函数的好处是什么呢,经过计算并把 a=\sigma(z),\sigma'(z)=\sigma(z)(1-\sigma(z)) 代入后会发现,影响二次代价函数学习速率的 \sigma'(z) 项被约掉了:
\begin{aligned} \frac{\partial C}{\partial w_j} & = -\frac{1}{n} \sum_x \left( \frac{y }{a} -\frac{(1-y)}{1-a} \right) \frac{\partial a}{\partial z} \frac{\partial z}{\partial w_j} \\ & = -\frac{1}{n} \sum_x \left( \frac{y}{\sigma(z)} -\frac{(1-y)}{1-\sigma(z)} \right)\sigma'(z) x_j\\ & = \frac{1}{n} \sum_x \frac{\sigma'(z) x_j}{\sigma(z) (1-\sigma(z))} (\sigma(z)-y)\\ &=\frac{1}{n} \sum_x x_j(\sigma(z)-y) \end{aligned}
同理算出
\frac{\partial C}{\partial b} = \frac{1}{n} \sum_x (\sigma(z)-y)
概括到一般情况下,交叉熵代价函数就写作:
C = -\frac{1}{n} \sum_x \sum_j \left[y_j \ln a^L_j + (1-y_j) \ln (1-a^L_j) \right]
*一般情况下,如果使用sigmoid神经元,那么交叉熵代价函数总比二次代价函数要好。
*当神经元是线性神经元(即a=z)时,使用二次代价函数不会造成学习速率慢的问题。
What does the cross-entropy mean? Where does it come from?
1,讲了交叉熵代价函数的来源:
有没有办法去掉\sigma'(z)项,使得偏导数更符合“错的越厉害学的越快”的直觉呢?(同时也能干掉学习速度慢的问题)
然后通过想要的结果和当前的结果进行计算,最终能得到交叉熵公式
2,“交叉熵”的直观理解是啥
*[sigmoid函数:]: 也叫logistic function,对应的神经元也叫logistic neuron

