开发环境
- TensorFlow: 1.2.0
- Python: 3.6
- Python IDE: PyCharm 2017.2
- Android IDE: Android Studio 3.0
训练与评估
训练和评估部分主要目的是生成用于测试用的 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 函数, 核心代码如下:
测试
核心是使用 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 接口使用如下:
最终的测试效果为:
理论基础
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, 英文 Convolutional Neural Network, 中文全称卷积神经网络, 即所谓的卷积网 (ConvNets) 卷积 (Convolution) 可谓是现代深度学习中最最重要的概念了, 它是一种数学运算, 读者可以从下面链接理解卷积 Convolution 中卷积相关数学机理, 包括分别从傅里叶变换和狄拉克δ函数中推到卷积定义, 我们可以从字面上宏观粗鲁的理解成将因子翻转相乘卷起来卷积动画模型如下图所示:
神经网络: 一个由大量神经元 (neurons) 组成的系统, 如下图所示:
其中, x 表示输入向量, w 为权重, b 为偏值 bias,f 为激活函数
Activation Function 激活函数: 常用的非线性激活函数有 SigmoidtanhReLU 等等, 公式如下所示
Sigmoid 函数: 函数饱和使梯度消失 (神经元在值为 0 或 1 的时候接近饱和, 这些区域, 梯度几乎为 0) 同时, sigmoid 函数不是关于原点中心对称的(无 0 中心化)
tanh: 存在饱和问题, 但它的输出是零中心的, 因此实际中 tanh 比 sigmoid 更受欢迎
ReLU 函数: ReLU 对于 SGD 的收敛有巨大的加速作用, 只需要一个阈值就可以得到激活值, 而不用去算一大堆复杂的 (指数) 运算缺点是: 需要合理设置学习率(learning rate), 防止训练时 dead, 还可以使用 Leaky ReLU/PReLU/Maxout 等代替
Pooling 池化: 一般分为平均池化 mean pooling 和最大池化 max pooling, 如下图所示 [21] 为 max pooling, 除此之外, 还有重叠池化(OverlappingPooling)[24], 空金字塔池化(Spatial Pyramid
Pooling)
平均池化: 计算图像区域的平均值作为该区域池化后的值
最大池化: 选图像区域的最大值作为该区域池化后的值
CNN Architecture
三层神经网络: 分别为输入层(Input layer), 输出层(Output layer), 隐藏层(Hidden layer), 如下图所示
CNN 层级结构: 斯坦福 cs231n 中阐述了一种[INPUT-CONV-RELU-POOL-FC], 如上图右边图片所示, 分别为输入层, 卷积层, 激励层, 池化层, 全连接层
CNN 通用架构分为如下三层结构:
Convolutional layers 卷积层
Pooling layers 汇聚层
Dense (fully connected) layers 全连接层
用动画演示如下图:
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 的分类, 本例中用于判断每张图属于每个数字的概率
附录
[01]Mnist 官网
[02]Visualizing MNIST: An Exploration of Dimensionality Reduction
[03]TensorFlow Mnist 官方实例
- [04]Sample code for Tensorflow and deep learning, without a PhD
- [05]Convex functions
[06]斯坦福大学机器学习第七课 - 正则化 - regularization
[07]MachineLearning_Python
[08]Stanford Universitys Convolutional Neural Networks for Visual Recognition course materials 翻译
[09]July CNN 笔记: 通俗理解卷积神经网络
[10]理解卷积 Convolution
- [11]Imagenet classification with deep convolutional neural networks
- [12]Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition
- [13]Convolutional Neural Networks-Basics
- [14]A technical report on convolution arithmetic in the context of deep learning
[15]Google 官方 Demo
[16]Google 官方 Codelab
- [17]deep-learning-cnns-in-tensorflow Github
- [18]tensorflow-classifier-android
- [19]creating-custom-model-for-android-using-tensorflow
[20]TF-NN Mnist 实例
来源: http://blog.csdn.net/xiangzhihong8/article/details/79309080