Day 02:撰写第一个 Neural Network 程序 -- 阿拉伯数字辨识

入门

照理讲,我们应该先了解『神经网络』(Neural Network)概念,再谈如何写程式,但是,概念介绍内容有点硬,为了提高学习兴趣,避免一开始就搞一堆数学公式,造成读者跑光光,所以,还是柿子挑软的吃,先从简单的开始,与 Neural Network 先培养感情,如果您是条硬汉,可以等看完下一篇后,再回头看这一篇。

我们就先来写一个程序,目标是『辨识阿拉伯数字(0~9)』。

开发环境建置

首先是选择开发环境,一般而言,Python 及 R 都有很好的支援及大量的函数库(Library/Toolbox),而 Python 的框架较易于系统整合(Web、Mobile),因此我选择 Python,但支援 Python 的 Neural Network 框架(Framework)也很多,参见下图,要选择哪一个呢?


image.png

图. Machine Learning 框架(Framework)GitHub评比,资料来源:【AI关键技术】三大热门深度学习框架新进展
其中,TensorFlow 网路声量最高,因此,我们採用它作为程式开发的基础,Keras 则是支援TensorFlow的更高阶函数库(Meta Framework),可以用很简洁的程式码完成一个 Neural Network 模型,非常适合入门学习,因此我们就从 Keras 开始学起。

首先我们要建构开发环境,笔者以 Windows 环境为例,依序安装以下软体:

  1. 安装 Anaconda: 它包含 Python 及常用的套件(Packages),例如NumPy、Pandas等矩阵运算的套件,Python V2 与 V3 不相容,我们选 V3,除非你以前曾大量使用 V2。
  2. 安装 Tensorflow:可以选择CPU或GPU版,安装CPU版,直接在 DOS 下,输入 pip install tensorflow。
  3. 安装 Keras:在 DOS 下,输入 pip install keras。

就是这麽简单,当然,为了加速运算,你也可以安装支援GPU版本的Tensorflow,NVidia支援CUDA的显示卡请参考这裡 ,相关安装程序请参考tensorflow官网,如果要在 Linux 环境开发也行,安装内容不变, 请参考这裡

以我的电脑为例,配备如下图,GPU显示卡为NVIDIA GeForce GTX 750(1GB memory),实际安装 Tensorflow GPU 版本的程序如下:


image.png
  1. 下载 CUDA Toolkit 8.0,不能是 9.x,需先至nVidia官网建立帐号,再至 https://developer.nvidia.com/cuda-toolkit-archive 下载。
  2. 安装完 CUDA Toolkit 后,再下载 cuDNN v6.x ,并将压缩档解开,複製到 CUDA Toolkit 8.0 安装目录下同名子目录下。
  3. 将 CUDA Toolkit 8.0 安装目录下bin子目录 放到 环境变数 Path 中,在 DOS 中执行Tensorflow时,才找的到相关 Dll。
  4. 安装 Tensorflow GPU 版本,执行
    pip install --ignore-installed --upgrade tensorflow-gpu
  5. 在 DOS 中执行 python,接著输入下列程式,应该就会有相关讯息出现。
    import tensorflow as tf
    hello = tf.constant('Hello, TensorFlow!')
    sess = tf.Session()
    print(sess.run(hello))

实际测试简单的程式,确实快很多,但是记忆体太小,遇到複杂的程式,例如后续的CNN程式,需要储存大量矩阵时,就GG了,所以,奉劝各位,要学 Neural Network,还是要花钱买张新一点的显示卡,才能省去执行时去泡茶、喝咖啡的时间。

如果一切顺利完成,就可以开始写程式了。等一下,那 IDE 呢? 你可以用记事本、NodePad++、或者PyCharm,我则是使用 VS 2017 Community 版本,它也是一个很不错的选择喔,可以像 C# 一样的除错。另外,使用 Jupyter Notebook,可以让你像作笔记一样的写程式,总之,戏法人人会变,端看你熟悉甚麽样的环境与工具。

程式撰写

撰写 Keras 程式,我们需要了解简单的 Python 语法,建议快速浏览『Introducing Python』这本书的第二~四章就够了,它不只有中文版,也有免费的PDF电子书喔。

以下范例主要是利用 MNIST 资料集的训练资料,建立单一隐藏层(Hidden Layer)的 Neural Network 模型,以预测实际影像是哪一个阿拉伯数字,如下图:


image.png

图. 阿拉伯数字(0~9)辨识的流程

流程步骤如下:

  1. 先读入训练资料,本例为 60,000 笔资料,每笔资料是一个 28 * 28 的点矩阵图形。
  2. 图形的每一点都当成一个输入变数(X),乘以一个权重W(i,j),向隐藏层(Hidden Layer)传导,隐藏层的每一个节点会得到输入变数的加权总和(W * X)。
  3. 再如法炮製,向输出层传导,输出层的每一个节点会得到隐藏层的加权总和,将输出层的每一个节点化为机率,就得到一个预测模型了。
  4. 之后我们将新资料输入模型,就会得到 0~9 的机率,最大的机率对应的数字就是我们的预测值了。
  5. 权重(W)是唯一未知的变数,他们等于多少呢? 这就是 Neural Network 厉害的地方,它透过优化(Optimization)计算,就可以求出 W 的最佳解,构筑出模型公式了。

程式很简单,先看注解(#开头),即可了解整个流程:

  1. 导入(import)要使用的函式库,包括 NumPy(矩阵运算)、Keras、matplotlib(绘图)。
  2. 从网路载入 MNIST 资料集,请 Keras 自动分为『训练组』及『测试组』资料,MNIST 是由 AI 大师 Yann LeCun 所建立的手写阿拉伯数字资料集(Dataset)。
  3. 建立最简单的线性模型(Sequential),就是一层层往下执行,没有分叉(If),也没有迴圈(loop),这裡只设一层隐藏层(Dense)。
  4. 选择损失函数(crossentropy)及优化方法(adam)及成效衡量方式(accuracy),就可以开始训练。
  5. 执行模型评估,计算模型参数,即上图的W(i,j)及W(j,k),模型就算完成了。
  6. 接著就可以使用这个模型,预测新资料了。
# 导入函式库
import numpy as np  
from keras.models import Sequential
from keras.datasets import mnist
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.utils import np_utils  # 用来后续将 label 标籤转为 one-hot-encoding  
from matplotlib import pyplot as plt

# 载入 MNIST 资料库的训练资料,并自动分为『训练组』及『测试组』
(X_train, y_train), (X_test, y_test) = mnist.load_data()

# 建立简单的线性执行的模型
model = Sequential()
# Add Input layer, 隐藏层(hidden layer) 有 256个输出变数
model.add(Dense(units=256, input_dim=784, kernel_initializer='normal', activation='relu')) 
# Add output layer
model.add(Dense(units=10, kernel_initializer='normal', activation='softmax'))

# 编译: 选择损失函数、优化方法及成效衡量方式
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) 

# 将 training 的 label 进行 one-hot encoding,例如数字 7 经过 One-hot encoding 转换后是 0000001000,即第7个值为 1
y_TrainOneHot = np_utils.to_categorical(y_train) 
y_TestOneHot = np_utils.to_categorical(y_test) 

# 将 training 的 input 资料转为2维
X_train_2D = X_train.reshape(60000, 28*28).astype('float32')  
X_test_2D = X_test.reshape(10000, 28*28).astype('float32')  

x_Train_norm = X_train_2D/255
x_Test_norm = X_test_2D/255

# 进行训练, 训练过程会存在 train_history 变数中
train_history = model.fit(x=x_Train_norm, y=y_TrainOneHot, validation_split=0.2, epochs=10, batch_size=800, verbose=2)  

# 显示训练成果(分数)
scores = model.evaluate(x_Test_norm, y_TestOneHot)  
print()  
print("\t[Info] Accuracy of testing data = {:2.1f}%".format(scores[1]*100.0))  

# 预测(prediction)
X = x_Test_norm[0:10,:]
predictions = model.predict_classes(X)
# get prediction result
print(predictions)

执行方法很简单,在DOS执行Python,接著将以上程式一段段贴上即可,我们就可以观察每段程式的用途,要看变数内容,只要输入变数名称即可,全部执行完,可以看到准确率有 85%,够神奇吧,毕竟我们只写了10多行的程式(不含注解)。

要确认预测是否正确,可以再贴上下列程式,查看影像:

# 显示 第一笔训练资料的图形,确认是否正确
plt.imshow(X_test[0])
plt.show() 

image.png

如果我们要看优化的过程,可以输入以下程式,结果如下图:

plt.plot(train_history.history['loss'])  
plt.plot(train_history.history['val_loss'])  
plt.title('Train History')  
plt.ylabel('loss')  
plt.xlabel('Epoch')  
plt.legend(['loss', 'val_loss'], loc='upper left')  
plt.show() 

image.png

图. 优化过程的损失函数(Loss)的变化

进行到这裡,我们已经跨出了一小步,后续我们接著抽丝剥茧,好好研究它为什麽可以这麽厉害。
相关程式请至这裡 下载,本范例为0.py。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容