diff --git a/recognize_digits/README.md b/recognize_digits/README.md index 237e56442fc45d2409db149979fcefbf399b09b2..d04e24e6ce71bcd287aeafe532b361fb67e56ec5 100644 --- a/recognize_digits/README.md +++ b/recognize_digits/README.md @@ -102,17 +102,21 @@ MNIST数据库作为一个简单的计算机视觉数据集,包含一系列如 ## 模型概览 ###问题说明: -基于MNIST数据,我们希望训练一个分类器 $f$,对于每张给定的图片数据 $x$ ,预测结果为 $f(x)$ ,应该尽可能准确的接近真实标签(label)。这是一个多分类问题,神经网络中通常使用 `softmax` 函数计算多分类问题中,每一类的概率。为了熟悉 `softmax` 函数,我们定义最简单的多分类网络:将输入层经过一个线性映射得到的特征,直接通过 `softmax` 函数进行多分类。 +基于MNIST数据,我们希望训练一个分类器 $f$,对于每张给定的图片数据 $X$ ,预测结果为 $ Y = f(x) $ ,应该尽可能准确的接近真实标签L。 ### Softmax回归(Softmax Regression) -MNIST数据库的图片为 $28X28$ 的二维图像,为了进行计算,我们一般将上将 $28X28$ 的二维图像转化为 $n(n=784)$ 维的向量,因此我们采用$x_i(i=0,1,2,...,n-1)$来表示输入的图片数据。同时,我们采用$y_i(i=0,1,2,..9)$来表示输出,其含义为: -比如说,如果图片的数字标签为3,则$y_i$组成的向量为[0,0,0,1,0,0,0,0,0,0]。输入层的数据x传到 `softmax` 层,在激活操作之前,会乘以相应的权重 $w$ ,并加上偏置变量 $b$ ,具体如下: +这是一个多分类问题,神经网络中通常使用 `softmax` 函数计算多分类问题中每一类的概率。为了熟悉 `softmax` 函数,我们定义最简单的多分类网络:将输入层经过一个线性映射得到的特征,直接通过 `softmax` 函数进行多分类。 + +MNIST数据库的图片为 $28X28$ 的二维图像,为了进行计算,我们一般将上将 $28X28$ 的二维图像转化为 $n(n=784)$ 维的向量,因此我们采用$x_i(i=0,1,2,...,n-1)$(向量表示为$X$)来表示输入的图片数据。同时,我们采用$ y_i (i=0,1,2,..9)$(向量表示为 $Y$来表示预测的输出,其含义为: + +比如说,$y_i$组成的向量$Y$为[0.2,0.3,0,1,0,0.1,0.1,0.1,0.1,0],每一维分别代表图像数字预测为0~9的概率。然后,我们用 $label_i$ (向量表示为$L$)来代表预测的输出。输入层的数据X传到 `softmax` 层,在激活操作之前,会乘以相应的权重 $W$ ,并加上偏置变量 $b$ ,具体如下: $$ net_i = \sum_j W_{i,j}x_j + b_i $$ -`net` 是激活前的值(仅仅进行了矩阵乘法),然后再用 `softmax` 函数进行激活: +`net` 是激活前的值(仅仅进行了矩阵乘法),然后再用 `softmax` 函数进行激活。 + 其中 `softmax` 函数的定义如下: $$ softmax(x_i) = \frac{e^{x_i}}{\sum_j e^{x_j}} $$ @@ -121,7 +125,7 @@ $$ softmax(x_i) = \frac{e^{x_i}}{\sum_j e^{x_j}} $$ $$ y_i = \frac{e^{net_i}}{\sum_j e^{net_j}} $$ -在神经网络中,多分类问题一般用 `softmax` 函数来作为输出。对于有 `N` 个类别的多分类问题,指定 `N` 个输出节点,`N` 维输入特征经过 `softmax` 将归一化为 `N` 个[0,1]范围内的实数值,分别表示该样本属于这N个类别的概率。此处的 $y_i$ 即对应该图片为数字 `i` 的概率。 +在神经网络中,多分类问题一般用 `softmax` 函数来作为输出。对于有 `N` 个类别的多分类问题,指定 `N` 个输出节点,`N` 维输入特征经过 `softmax` 将归一化为 `N` 个[0,1]范围内的实数值,分别表示该样本属于这N个类别的概率。此处的 $y_i$ 即对应该图片为数字 `i` 的预测概率。 以下为softmax回归的网络图:

@@ -132,28 +136,30 @@ $$ y_i = \frac{e^{net_i}}{\sum_j e^{net_j}} $$ 神经网络模型的构建包括网络配置在内,通常有以下几个步骤: -1. 网络结构配置 +1. 网络结构配置。 2. 初始化参数,其中包括训练参数权重W和偏置b,以及超参数训练速度 $\eta$、 `batchSize` 和训练轮次 `Pass` 等等,训练参数随着网络的迭代不断更新,而超参数一般是在网络初始化的时候给定好的。 3. 前向传播计算网络输出和代价损失函数。 4. 根据代价损失函数进行反向误差传播,更新训练参数。 5. 重复3~4步骤,直至网络训练误差达到规定的程度或训练轮次达到设定值。 -对于以上步骤4,神经网络的训练采用 `backpropagation` 的形式,其一般会定义一个损失函数(也称目标函数),训练的目的是为了减小目标函数的 -值。在分类问题中,我们一般采用交叉熵代价损失函数(cross entropy),其形式如下: +对于以上步骤4,神经网络的训练采用 `backpropagation` 的形式,其一般会定义一个损失函数(也称目标函数),训练的目的是为了减小目标函数的值。在分类问题中,我们一般采用交叉熵代价损失函数(cross entropy),其形式如下: + +$$ CE(label, y) = -\sum_i label_ilog(y_i) $$ + +注:上面公式为softmax输出层的交叉熵代价损失函数,CE为cross entropy的简称,y是预测每一类的概率,label是标签,为one-hot向量(事实上,由于label为one-hot向量,上面公式中只有一项不为0)。 ### 多层感知器(Multilayer Perceptron, MLP) -在softmax回归中,我们采用了最简单的两层神经网络,分别为输入的datalayer层和输出的 `softmax` 层,模型比较简单,意味着 -其拟合能力有限。因此,为了达到更好的识别效果,我们可以考虑在输入层和输出层中间加上若干个隐藏层。 +在softmax回归中,我们采用了最简单的两层神经网络,分别为输入的datalayer层和输出的 `softmax` 层,模型比较简单,意味着其拟合能力有限。因此,为了达到更好的识别效果,我们可以考虑在输入层和输出层中间加上若干个隐藏层。 -在该网络层中,我们有输入X($x_i(i=0,1,2,...,n-1)$),输出标签Y($y_i(i=0,1,2,..9)$),为了表示方便,以下我们都直接 -用向量计算来表示。经过第一层网络,我们可以得到: +在该网络层中,我们有输入X($x_i(i=0,1,2,...,n-1)$),输出标签Y($y_i(i=0,1,2,..9)$),为了表示方便,以下我们都直接用向量计算来表示。经过第一层网络,我们可以得到: $$ H_1 = activation(W_1X + b_1) $$ 上面,`activation` 代表激活函数,其常见的为 `sigmoid` ,`tanh` 或 `ReLU` 等函数。 + 经过第二层网络,可以得到: $$ H_2 = activation(W_2H_1 + b_2) $$ @@ -178,6 +184,16 @@ $$ Y = softmax(W_3H_2 + b_3) $$

卷积层是卷积神经网络的核心基石。该层的参数由一组可学习的过滤器(也叫作卷积核)组成。在前向过程中,每个卷积核在输入层进行横向和纵向的扫描,与输入层对应扫描位置进行卷积,得到的结果加上偏置并用相应的激活函数进行激活,结果能够得到一个二维的激活图(activation map)。每个特定的卷积核都能得到特定的激活图(activation map),如有的卷积核可能对识别边角,有的可能识别圆圈,那这些卷积核可能对于对应的特征响应要强。 +例如,假如我们有如上一个矩阵,用二维矩阵X(X的维度为$5\times5$)表示,然后我们用K组卷积核(filter)来扫描图片,卷积核(filter)的大小为 F = 3,扫描的Padding(P=0),扫描步长Stride(S=1)。则该次扫描会输出K个特征图(feature map),其中每个特征图的大小为 $ \frac{5-3}{1} + 1 = 3$,即为$3\times3$。设输出为Y,以其中一个卷积核为例,卷积核参数为$W_0$,偏置为$b_0$,则该卷积核扫描的输出结果如下: + +$$ Y_{0,0,0} = sum( X[:3, :3] * W0 ) + b0 $$ + +$$ Y_{1,0,0} = sum( X[1:4, :3] * W0 ) + b0 $$ + +$$ Y_{2,0,0} = sum( X[2:5, :3] * W0 ) + b0 $$ + +上图中计算的即为 $Y_{1,0,0}$的值,sum函数为对矩阵的所有元素求和。 + #### 池化层


@@ -187,6 +203,9 @@ $$ Y = softmax(W_3H_2 + b_3) $$ 池化包括最大池化、平均池化等等。 +例如,对于图上的矩阵,用二维矩阵X(X的维度为$4\times4$)表示,采用$F=2$的$2\times2$的过滤器(filter)进行最大池化,步长Stride设置为$S=2$,由于$F=S$,该池化为不重叠池化。 + + #### LeNet-5网络


@@ -194,6 +213,7 @@ $$ Y = softmax(W_3H_2 + b_3) $$

上面的网络是典型的LeNet结构,从中我们可以看出,从输入的二维图像,经过两次卷积->池化,然后再经过全连接,最后的输出层是 `softmax` 分类层。 +更详细的关于卷积神经网络的具体知识可以参考 [cs231n] ( http://cs231n.github.io/convolutional-networks/ ) ### 常见激活函数介绍 - sigmoid激活函数: @@ -225,29 +245,17 @@ $$ f(x) = max(0, x) $$ - 将下载下来的数据进行 `gzip` 解压,可以在文件夹 `data/raw_data` 中找到以下文件: -

- - - - - +
-
- - - +| 文件名称 | 说明 | +|----------------------|-------------------------| +|t10k-images-idx3-ubyte | 测试数据图片,10,000条数据 | +|t10k-labels-idx1-ubyte | 测试数据标签,10,000条数据 | +|train-images-idx3-ubyte| 训练数据图片,60,000条数据 | +|train-labels-idx1-ubyte| 训练数据标签,60,000条数据 | - - - - + - - - - -
t10k-images-idx3-ubyte 测试数据图片,10,000条数据
t10k-labels-idx1-ubyte 测试数据标签,10,000条数据
train-images-idx3-ubyte 训练数据图片,60,000条数据
train-labels-idx1-ubyte 训练数据标签,60,000条数据
-

- MNIST的每条数据可以分为两部分:手写字符图片和对应的标签。图片是28X28的像素矩阵,而标签则对应着0~9的10个数字,我们随机选取训练集中的10张图片进行绘制,并给出选取图片对应的标签,绘制脚本为 `./data/draw_data.py`。 @@ -262,6 +270,7 @@ label: [3, 4, 7, 0, 4, 1, 1, 4, 3, 1] ### 提供数据给PaddlePaddle 首先是用PaddlePaddle的 `PyDataProvider2` 来为模型导入数据,如 `mnist_provider.py` 中所示。 + 在下面代码中,`process` 函数读取MNIST数据,然后用 `yield` 函数返回数据的生成器,然后用 `@provider` 对返回的数据进行包装 (具体的过程见 `PaddlePaddle_root_path/python/paddle/trainer/PyDataProvider2.py`,从而方便以PaddlePaddle DataProvider对象的形式进行调用。 @@ -320,9 +329,7 @@ def process(settings, filename): # settings is not used currently. ### 算法配置 然后指定训练相关的参数,`batch` 大小( `batch_size` )表示神经网络每次训练使用的数据为128条,训练速度( `learning_rate` )是迭代 -的速度,影响着网络的训练收敛速度有关系,训练方法( `learning_method` )代表训练过程在更新权重时采用动量优化器 -( `MomentumOptimizer` ),其中参数0.9代表动量优化每次保持前一次速度的0.9倍,正则化( `regularization` )是防止网络过拟合的一 -种手段,此处采用L2正则化。 +的速度,影响着网络的训练收敛速度有关系,训练方法( `learning_method` )代表训练过程在更新权重时采用动量优化器( `MomentumOptimizer` ),其中参数0.9代表动量优化每次保持前一次速度的0.9倍,正则化( `regularization` )是防止网络过拟合的一种手段,此处采用L2正则化。 ```python ######################Algorithm Configuration ############# @@ -337,11 +344,7 @@ settings( #### Softmax回归 -定义好 `dataprovider` 之后,就可以通过 `data_layer` 调用来获取数据 `img`,然后通过一层简单的 `softmax` -全连接层,得到预测的结果,然后指定训练的损失函数为分类损失( `classification_cost` ),一般分类问题的损失函数为交叉熵 -损失函数( `cross_entropy` )。 -通过控制变量 `is_predict` ,该配置脚本也可以在预测时候使用,将 `is_predict` 置为 `True` ,则最后直接输出预测结果,而不会经过 -损失函数来进行训练过程。 +定义好 `dataprovider` 之后,就可以通过 `data_layer` 调用来获取数据 `img`,然后通过一层简单的 `softmax`全连接层,得到预测的结果,然后指定训练的损失函数为分类损失( `classification_cost` ),一般分类问题的损失函数为交叉熵损失函数( `cross_entropy` )。通过控制变量 `is_predict` ,该配置脚本也可以在预测时候使用,将 `is_predict` 置为 `True` ,则最后直接输出预测结果,而不会经过损失函数来进行训练过程。 ```python #######################Network Configuration ############# @@ -356,8 +359,7 @@ predict = fc_layer(input=img, size=10, act=SoftmaxActivation()) #### 多层感知器 -以下是一个简单的带有两个隐藏层的多层感知器,也就是全连接网络,两个隐藏层的激活函数均采用 `ReLU` 函数,最后的输出层用 -`softmax` 激活函数。 +以下是一个简单的带有两个隐藏层的多层感知器,也就是全连接网络,两个隐藏层的激活函数均采用 `ReLU` 函数,最后的输出层用`softmax` 激活函数。 ```python #######################Network Configuration ############# @@ -483,8 +485,7 @@ Best pass is 00047, error is 0.473053, which means predict get error as 0.343894 The classification accuracy is 89.49% ``` -从上面过程中可以看到,softmax回归模型分类效果最好的时候是pass-00047,分类准确率为89.49%,而最终的pass-00099的准确率为85.39%。 -从图中也可以看出,准确率最好的时候并以不定是最后一个pass的模型。 +从上面过程中可以看到,softmax回归模型分类效果最好的时候是pass-00047,分类准确率为89.49%,而最终的pass-00099的准确率为85.39%。从图中也可以看出,准确率最好的时候并以不定是最后一个pass的模型。 #### 多层感知器 @@ -498,9 +499,7 @@ Best pass is 00085, error is 0.164746, which means predict get error as 0.202945 The classification accuracy is 94.95% ``` -从训练日志中我们可以看出,最终训练的准确率为94.95%。这是多层感知器网络分类分类效果,可以 -看到其相对于softmax回归来说有了显著的分类效果的提升。但是,这还不是最好的分类效果,后面,我们可以看到卷积神经 -网络对于图像分类能够达到更为惊人的准确率。 +从训练日志中我们可以看出,最终训练的准确率为94.95%。这是多层感知器网络分类分类效果,可以看到其相对于softmax回归来说有了显著的分类效果的提升。但是,这还不是最好的分类效果,后面,我们可以看到卷积神经网络对于图像分类能够达到更为惊人的准确率。 #### 卷积神经网络 @@ -514,9 +513,7 @@ Best pass is 00076, error is 0.0244684, which means predict get error as 0.07821 The classification accuracy is 99.20% ``` -从训练日志中我们可以看出,最终训练的准确率为99.20%。由此可以看到,对于图像问题而言,卷积神经网络能够 -比一般全连接网络达到更好的识别效果,而这与卷积层的性质是分不开的。同时,我们可以看到,卷积神经网络在 -很早的时候就能达到好的效果,说明其训练收敛的速度很快。 +从训练日志中我们可以看出,最终训练的准确率为99.20%。由此可以看到,对于图像问题而言,卷积神经网络能够比一般全连接网络达到更好的识别效果,而这与卷积层的性质是分不开的。同时,我们可以看到,卷积神经网络在很早的时候就能达到好的效果,说明其训练收敛的速度很快。 ### 预测命令与结果 @@ -540,20 +537,17 @@ Input image_id [0~9999]: 3 0 0 ``` -上面,给出的向量是神经网络输出的十维向量,可以理解为分类为各个数字的概率,实际预测的类即为向量中 -值最大的一项。如上,代表该分类器接近100%的认为该图片上面的数字为0,而实际标签给出的类也确实如此。 +上面,给出的向量是神经网络输出的十维向量,可以理解为分类为各个数字的概率,实际预测的类即为向量中值最大的一项。如上,代表该分类器接近100%的认为该图片上面的数字为0,而实际标签给出的类也确实如此。 ## 总结 -从上面的过程中,我们了解到了softmax回归、多层感知器和卷积神经网络都是最基础的机器学习模型,而复杂的神经网络 -都是从这些衍生出来的,因此了解了这些基本的东西之后,对于我们之后的学习大有裨益。在这过程中,我们也观察到当我们将模型从简单的 -Softmax回归到稍微复杂的卷积神经网络的时候,识别准确率有了大幅度的提升,而这与卷积层的加入是密切联系的,这启发我们在之后遇到新的 -模型的时候,要认识到新模型相对于其他模型来说效果提升的关键之处。此外,在体验用PaddlePaddle搭建模型识别MNIST图片的同时 -我们了解了PaddlePaddle模型搭建的过程,从dataprovider的编写,到网络层的构建,到最后的训练和预测,是用PaddlePaddle实现自定义模型的一个 -基本流程。对这个流程熟悉以后,我们可以用自己的数据,定义自己的网络模型,来完成自己的训练和预测任务。 +从上面的过程中,我们了解到了softmax回归、多层感知器和卷积神经网络都是最基础的机器学习模型,而复杂的神经网络都是从这些衍生出来的,因此了解了这些基本的东西之后,对于我们之后的学习大有裨益。在这过程中,我们也观察到当我们将模型从简单的Softmax回归到稍微复杂的卷积神经网络的时候,识别准确率有了大幅度的提升,而这与卷积层的加入是密切联系的,这启发我们在之后遇到新的模型的时候,要认识到新模型相对于其他模型来说效果提升的关键之处。此外,在体验用PaddlePaddle搭建模型识别MNIST图片的同时我们了解了PaddlePaddle模型搭建的过程,从dataprovider的编写,到网络层的构建,到最后的训练和预测,是用PaddlePaddle实现自定义模型的一个基本流程。对这个流程熟悉以后,我们可以用自己的数据,定义自己的网络模型,来完成自己的训练和预测任务。 ## 参考文献 1. http://yann.lecun.com/exdb/mnist/ 2. LeCun, Yann, et al. "Gradient-based learning applied to document recognition." Proceedings of the IEEE 86.11 (1998): 2278-2324. 3. Simard, Patrice Y., David Steinkraus, and John C. Platt. "Best practices for convolutional neural networks applied to visual document analysis." ICDAR. Vol. 3. 2003. +4. Rosenblatt F. The perceptron: a probabilistic model for information storage and organization in the brain[J]. Psychological review, 1958, 65(6): 386. +5. Bishop C M. Pattern recognition[J]. Machine Learning, 2006, 128. +6. http://cs231n.github.io/convolutional-networks/