- Catalogue
- 1. Overview
- 2. Practice
- 2.1. Environment
- 2.2. Train & Evaluate(Python+TensorFlow)
- 2.3. Test(Android+TensorFlow)
- 3. Theory
- 3.1. MNIST
- 3.2. CNN(Convolutional Neural Network)
- 3.2.1. CNN Keys
- 3.2.2. CNN Architecture
- 3.3. Regression + Softmax
- 3.3.1. Linear Regression
- 3.3.2. Softmax Regression
- 4. References & Recommends
- Overview
本文系 SkySeraph AI 实践到理论系列第一篇, 咱以 AI 界的 HelloWord 经典 MNIST 数据集为基础, 在 Android 平台, 基于 TensorFlow, 实现 CNN 的手写数字识别
- Code~
- Practice
- Environment
- TensorFlow: 1.2.0
- Python: 3.6
- Python IDE: PyCharm 2017.2
- Android IDE: Android Studio 3.0
- Train & Evaluate(Python+TensorFlow)
训练和评估部分主要目的是生成用于测试用的 pb 文件, 其保存了利用 TensorFlow python API 构建训练后的网络拓扑结构和参数信息, 实现方式有很多种, 除了 cnn 外还可以使用 rnn,fcnn 等
其中基于 cnn 的函数也有两套, 分别为 tf.layers.conv2d 和 tf.nn.conv2d, tf.layers.conv2d 使用 tf.nn.conv2d 作为后端处理, 参数上 filters 是整数, filter 是 4 维张量原型如下:
convolutional.py 文件
- def conv2d(inputs, filters, kernel_size, strides=(1, 1), padding=valid, data_format=channels_last,
- dilation_rate=(1, 1), activation=None, use_bias=True, kernel_initializer=None,
- bias_initializer=init_ops.zeros_initializer(), kernel_regularizer=None, bias_regularizer=None,
- activity_regularizer=None, kernel_constraint=None, bias_constraint=None, trainable=True, name=None,
- reuse=None)
gen_nn_ops.py 文件
def conv2d(input, filter, strides, padding, use_cudnn_on_gpu = True, data_format = "NHWC", name = None)
官方 Demo 实例中使用的是 layers module, 结构如下:
- Convolutional Layer #1:32 个 5×5 的 filter, 使用 ReLU 激活函数
- Pooling Layer #1:2×2 的 filter 做 max pooling, 步长为 2
- Convolutional Layer #2:64 个 5×5 的 filter, 使用 ReLU 激活函数
- Pooling Layer #2:2×2 的 filter 做 max pooling, 步长为 2
- Dense Layer #1:1024 个神经元, 使用 ReLU 激活函数, dropout 率 0.4 (为了避免过拟合, 在训练的时候, 40% 的神经元会被随机去掉)
- Dense Layer #2 (Logits Layer):10 个神经元, 每个神经元对应一个类别(0-9)
核心代码在 cnn_model_fn(features, labels, mode)函数中, 完成卷积结构的完整定义, 核心代码如下.
也可以采用传统的 tf.nn.conv2d 函数, 核心代码如下
Test(Android+TensorFlow)
核心是使用 API 接口: TensorFlowInferenceInterface.java
配置 gradle 或者 自编译 TensorFlow 源码导入 jar 和 so
compile org.tensorflow:tensorflow-android:1.2.0
导入 pb 文件. pb 文件放 assets 目录, 然后读取
- String actualFilename = labelFilename.split(file:///android_asset/)[1];
- Log.i(TAG, Reading labels from: + actualFilename);
- BufferedReader br = null;
- br = new BufferedReader(new InputStreamReader(assetManager.open(actualFilename)));
- String line;
- while ((line = br.readLine()) != null) {
- c.labels.add(line);
- }
- br.close();
TensorFlow 接口使用
最终效果:
Theory
MNIST
MNIST, 最经典的机器学习模型之一, 包含 0~9 的数字, 28*28 大小的单色灰度手写数字图片数据库, 其中共 60,000 training examples 和 10,000 test examples
文件目录如下, 主要包括 4 个二进制文件, 分别为训练和测试图片及 Label
如下为训练图片的二进制结构, 在真实数据前(pixel), 有部分描述字段(魔数, 图片个数, 图片行数和列数), 真实数据的存储采用大端规则
(大端规则, 就是数据的高字节保存在低内存地址中, 低字节保存在高内存地址中)
在具体实验使用, 需要提取真实数据, 可采用专门用于处理字节的库 struct 中的 unpack_from 方法, 核心方法如下:
struct.unpack_from(self._fourBytes2, buf, index)
MNIST 作为 AI 的 Hello World 入门实例数据, TensorFlow 封装对其封装好了函数, 可直接使用
- mnist = input_data.read_data_sets(MNIST, one_hot=True)
- CNN(Convolutional Neural Network)
- CNN Keys
CNN,Convolutional Neural Network, 中文全称卷积神经网络, 即所谓的卷积网(ConvNets)
卷积 (Convolution) 可谓是现代深度学习中最最重要的概念了, 它是一种数学运算, 读者可以从下面链接 [23] 中卷积相关数学机理, 包括分别从傅里叶变换和狄拉克δ函数中推到卷积定义, 我们可以从字面上宏观粗鲁的理解成将因子翻转相乘卷起来
卷积动画演示如下图[26], 更多动画演示可参考[27]
神经网络一个由大量神经元 (neurons) 组成的系统, 如下图所示[21]
其中 x 表示输入向量, w 为权重, b 为偏值 bias,f 为激活函数
Activation Function 激活函数: 常用的非线性激活函数有 SigmoidtanhReLU 等等, 公式如下如所示
Sigmoid 缺点
函数饱和使梯度消失(神经元在值为 0 或 1 的时候接近饱和, 这些区域, 梯度几乎为 0)
sigmoid 函数不是关于原点中心对称的(无 0 中心化)
tanh: 存在饱和问题, 但它的输出是零中心的, 因此实际中 tanh 比 sigmoid 更受欢迎
ReLU
优点 1:ReLU 对于 SGD 的收敛有巨大的加速作用
优点 2: 只需要一个阈值就可以得到激活值, 而不用去算一大堆复杂的 (指数) 运算
缺点: 需要合理设置学习率(learning rate), 防止训练时 dead, 还可以使用 Leaky ReLU/PReLU/Maxout 等代替
Pooling 池化一般分为平均池化 mean pooling 和最大池化 max pooling, 如下图所示 [21] 为 max pooling, 除此之外, 还有重叠池化(OverlappingPooling)[24], 空金字塔池化(Spatial Pyramid Pooling)[25]
平均池化: 计算图像区域的平均值作为该区域池化后的值
最大池化: 选图像区域的最大值作为该区域池化后的值
CNN Architecture
三层神经网络分别为输入层(Input layer), 输出层(Output layer), 隐藏层(Hidden layer), 如下图所示[21]
CNN 层级结构 斯坦福 cs231n 中阐述了一种[INPUT-CONV-RELU-POOL-FC], 如下图所示[21], 分别为输入层, 卷积层, 激励层, 池化层, 全连接层
CNN 通用架构分为如下三层结构:
Convolutional layers 卷积层
Pooling layers 汇聚层
Dense (fully connected) layers 全连接层
动画演示参考[22]
Regression + Softmax
机器学习有监督学习 (supervised learning) 中两大算法分别是分类算法和回归算法, 分类算法用于离散型分布预测, 回归算法用于连续型分布预测
回归的目的就是建立一个回归方程用来预测目标值, 回归的求解就是求这个回归方程的回归系数
其中回归 (Regression) 算法包括 Linear Regression,Logistic Regression 等, Softmax Regression 是其中一种用于解决多分类 (multi-class classification) 问题的 Logistic 回归算法的推广, 经典实例就是在 MNIST 手写数字分类上的应用
Linear Regression
Linear Regression 是机器学习中最基础的模型, 其目标是用预测结果尽可能地拟合目标 label
多元线性回归模型定义
多元线性回归求解
Mean Square Error (MSE)
Gradient Descent(梯度下降法)
Normal Equation(普通最小二乘法)
局部加权线性回归(LocallyWeightedLinearRegression, LWLR ): 针对线性回归中模型欠拟合现象, 在估计中引入一些偏差以便降低预测的均方误差
岭回归 (ridge regression) 和缩减方法
选择: Normal Equation 相比 Gradient Descent, 计算量大(需计算 X 的转置与逆矩阵), 只适用于特征个数小于 100000 时使用; 当特征数量大于 100000 时使用梯度法当 X 不可逆时可替代方法为岭回归算法 LWLR 方法增加了计算量, 因为它对每个点做预测时都必须使用整个数据集, 而不是计算出回归系数得到回归方程后代入计算即可, 一般不选择
调优: 平衡预测偏差和模型方差(高偏差就是欠拟合, 高方差就是过拟合)
获取更多的训练样本 - 解决高方差
尝试使用更少的特征的集合 - 解决高方差
尝试获得其他特征 - 解决高偏差
尝试添加多项组合特征 - 解决高偏差
尝试减小 λ - 解决高偏差
尝试增加 λ - 解决高方差
Softmax Regression
Softmax Regression 估值函数(hypothesis)
Softmax Regression 代价函数(cost function)
理解:
Softmax Regression & Logistic Regression:
多分类 & 二分类 Logistic Regression 为 K=2 时的 Softmax Regression
针对 K 类问题, 当类别之间互斥时可采用 Softmax Regression, 当非斥时, 可采用 K 个独立的 Logistic Regression
总结: Softmax Regression 适用于类别数量大于 2 的分类, 本例中用于判断每张图属于每个数字的概率
- References & Recommends
- MNIST
[01]Mnist 官网
[02]Visualizing MNIST: An Exploration of Dimensionality Reduction
[03]TensorFlow Mnist 官方实例
- [04] Sample code
- for Tensorflow and deep learning,
- without a PhD Softmax[11] Convex functions
[12]斯坦福大学机器学习第七课 - 正则化 - regularization
- [13]MachineLearning_Python
- CNN
[21]Stanford Universitys Convolutional Neural Networks for Visual Recognition course materials 翻译
[22]July CNN 笔记: 通俗理解卷积神经网络
[23]理解卷积 Convolution
- [24]Imagenet classification with deep convolutional neural networks
- [25]Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition
- [26]Convolutional Neural Networks-Basics
- [27]A technical report on convolution arithmetic in the context of deep learning
- TensorFlow+CNN / TensorFlow+Android
[31]Google 官方 Demo
[32]Google 官方 Codelab
- [33]deep-learning-cnns-in-tensorflow Github
- [34]tensorflow-classifier-android
- [35]creating-custom-model-for-android-using-tensorflow
[36]TF-NN Mnist 实例
- By SkySeraph-2018
- SkySeraph cnBlogs
- SkySeraph CSDN
本文首发于 skyseraph.com:Android+TensorFlow+CNN+MNIST 手写数字识别实现
来源: http://skyseraph.com/2018/01/10/AI/AIHandwritingAndroid/