小白也能懂的手寫體識別

手寫體識別與Tensorflow

如同全部語言的hello world同樣,手寫體識別就至關於深度學習裏的hello world。python

TensorFlow是當前最流行的機器學習框架,有了它,開發人工智能程序就像Java編程同樣簡單。web

MNIST

MNIST 數據集已是一個被」嚼爛」了的數據集, 不少教程都會對它」下手」, 幾乎成爲一個 「典範」. 不過有些人可能對它還不是很瞭解, 下面來介紹一下.算法

MNIST 數據集可在 http://yann.lecun.com/exdb/mnist/ 獲取, 它包含了四個部分:編程

   Training set images: train-images-idx3-ubyte.gz (9.9 MB, 解壓後 47 MB, 包含 60,000 個樣本) 
       Training set labels: train-labels-idx1-ubyte.gz (29 KB, 解壓後 60 KB, 包含 60,000 個標籤)
        Test set images: t10k-images-idx3-ubyte.gz (1.6 MB, 解壓後 7.8 MB, 包含 10,000 個樣本)
        Test set labels: t10k-labels-idx1-ubyte.gz (5KB, 解壓後 10 KB, 包含 10,000 個標籤)微信

MNIST 數據集來自美國國家標準與技術研究所, National Institute of Standards and Technology (NIST). 訓練集 (training set) 由來自 250 個不一樣人手寫的數字構成, 其中 50% 是高中學生, 50% 來自人口普查局 (the Census Bureau) 的工做人員. 測試集(test set) 也是一樣比例的手寫數字數據.網絡

tensorflow提供一個input_data.py文件,專門用於下載mnist數據,咱們直接調用就能夠了,代碼以下:框架

import tensorflow.examples.tutorials.mnist.input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

執行完成後,會在當前目錄下新建一個文件夾MNIST_datadom

input_data文件會調用一個maybe_download函數,確保數據下載成功。這個函數還會判斷數據是否已經下載,若是已經下載好了,就再也不重複下載。機器學習

思路

把圖片當成一枚枚像素來看,下圖爲手寫體數字1的圖片,它在計算機中的存儲實際上是一個二維矩陣,每一個元素都是0~1之間的數字,0表明白色,1表明黑色,小數表明某種程度的灰色。函數

image

如今,對於MNIST數據集中的圖片來講,咱們只要把它當成長度爲784的向量就能夠了(忽略它的二維結構,28×28=784)。咱們的任務就是讓這個向量通過一個函數後輸出一個類別。就是下邊這個函數,稱爲Softmax分類器。

image

這個式子裏的圖片向量的長度只有3,用x表示。乘上一個係數矩陣W,再加上一個列向量b,而後輸入softmax函數,輸出就是分類結果y。W是一個權重矩陣,W的每一行與整個圖片像素相乘的結果是一個分數score,分數越高表示圖片越接近該行表明的類別。所以,W x + b 的結果實際上是一個列向量,每一行表明圖片屬於該類的評分。一般分類的結果並不是評分,而是機率,表示有多大的機率屬於此類別。所以,Softmax函數的做用就是把評分轉換成機率,並使總的機率爲1。

CNN

卷積神經網絡(Convolutional Neural Networks / CNNs / ConvNets)與普通神經網絡很是類似,它們都由具備可學習的權重和偏置常量(biases)的神經元組成。每一個神經元都接收一些輸入,並作一些點積計算,輸出是每一個分類的分數,普通神經網絡裏的一些計算技巧到這裏依舊適用。

卷積神經網絡利用輸入是圖片的特色,把神經元設計成三個維度 : width, height, depth(注意這個depth不是神經網絡的深度,而是用來描述神經元的) 。好比輸入的圖片大小是 32 × 32 × 3 (rgb),那麼輸入神經元就也具備 32×32×3 的維度。下面是圖解:

這裏寫圖片描述

一個卷積神經網絡由不少層組成,它們的輸入是三維的,輸出也是三維的,有的層有參數,有的層不須要參數。

卷積神經網絡一般包含如下幾種層:  

數據輸入層:

該層要作的處理主要是對原始圖像數據進行預處理,其中包括:
• 去均值:把輸入數據各個維度都中心化爲0,以下圖所示,其目的就是把樣本的中心拉回到座標系原點上。
• 歸一化:幅度歸一化到一樣的範圍,以下所示,即減小各維度數據取值範圍的差別而帶來的干擾,好比,咱們有兩個維度的特徵A和B,A範圍是0到10,而B範圍是0到10000,若是直接使用這兩個特徵是有問題的,好的作法就是歸一化,即A和B的數據都變爲0到1的範圍。
• PCA/白化:用PCA降維;白化是對數據各個特徵軸上的幅度歸一化

卷積層

卷積神經網路中每層卷積層由若干卷積單元組成,每一個卷積單元的參數都是經過反向傳播算法優化獲得的。卷積運算的目的是提取輸入的不一樣特徵,第一層卷積層可能只能提取一些低級的特徵如邊緣、線條和角等層級,更多層的網絡能從低級特徵中迭代提取更復雜的特徵。 

下面的動態圖形象地展現了卷積層的計算過程:


    線性整流層(Rectified Linear Units layer, ReLU layer),這一層神經的活性化函數(Activation function)使用線性整流(Rectified Linear Units, ReLU)f(x)=max(0,x)

把卷積層輸出結果作非線性映射。


     池化層(Pooling layer),一般在卷積層以後會獲得維度很大的特徵,將特徵切成幾個區域,取其最大值或平均值,獲得新的、維度較小的特徵。

池化層的具體做用。

1.特徵不變性,也就是咱們在圖像處理中常常提到的特徵的尺度不變性,池化操做就是圖像的resize,平時一張狗的圖像被縮小了一倍咱們還能認出這是一張狗的照片,這說明這張圖像中仍保留着狗最重要的特徵,咱們一看就能判斷圖像中畫的是一隻狗,圖像壓縮時去掉的信息只是一些可有可無的信息,而留下的信息則是具備尺度不變性的特徵,是最能表達圖像的特徵。

2.特徵降維,咱們知道一幅圖像含有的信息是很大的,特徵也不少,可是有些信息對於咱們作圖像任務時沒有太多用途或者有重複,咱們能夠把這類冗餘信息去除,把最重要的特徵抽取出來,這也是池化操做的一大做用。

3.在必定程度上防止過擬合,更方便優化。


    池化層用的方法有Max pooling 和 average pooling,而實際用的較多的是Max pooling。
     全鏈接層( Fully-Connected layer), 把全部局部特徵結合變成全局特徵,用來計算最後每一類的得分。

CNN的經常使用框架

Caffe
• 源於Berkeley的主流CV工具包,支持C++,python,matlab
• Model Zoo中有大量預訓練好的模型供使用
    Torch
• Facebook用的卷積神經網絡工具包
• 經過時域卷積的本地接口,使用很是直觀
• 定義新網絡層簡單
    TensorFlow
• Google的深度學習框架
• TensorBoard可視化很方便
• 數據和模型並行化好,速度快

實現代碼

代碼以下:

# -*- coding: utf-8 -*-
"""
Spyder Editor

This is a temporary script file.
"""
# -*- coding:utf-8 -*-  
import tensorflow as tf  
from tensorflow.examples.tutorials.mnist import input_data  
#number from 0 to 9:  
mnist=input_data.read_data_sets('MNIST_data/',one_hot=True)  
  
def add_layer(inputs,in_size,out_size,activation_function=None):  
    Weights=tf.Variable(tf.random_normal([in_size,out_size]))  
    bises=tf.Variable(tf.zeros([1,out_size])+0.1)  
    Wx_plus_b=tf.matmul(inputs,Weights)+bises  
  
    if activation_function is None:  
        outputs=Wx_plus_b  
    else:  
        outputs=activation_function(Wx_plus_b)  
  
    return outputs  
  
#計算準確度  
def compute_accuracy(x,y):  
    global prediction  
    y_pre=sess.run(prediction,feed_dict={xs:x})  
    correct_prediction=tf.equal(tf.argmax(y_pre,1),tf.argmax(y,1))  
    accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))  
    result=sess.run(accuracy,feed_dict={xs:x,ys:y})  
    return result  
  
#def placeholder for inputs  
xs=tf.placeholder(tf.float32,[None,784])  #28*28  
ys=tf.placeholder(tf.float32,[None,10])  #10個輸出  
  
#add output layer  
prediction=add_layer(xs,784,10,tf.nn.softmax)  #softmax經常使用於分類  
  
cross_entropy=tf.reduce_mean(-tf.reduce_sum(ys*tf.log(prediction),reduction_indices=[1]))  
train=tf.train.GradientDescentOptimizer(0.3).minimize(cross_entropy)  
  
sess=tf.Session()  
sess.run(tf.initialize_all_variables())  
  
for i in range(2000):  
    batch_xs,batch_ys=mnist.train.next_batch(100)  
    sess.run(train,feed_dict={xs:batch_xs,ys:batch_ys})  
    if i%100==0:  
        print(compute_accuracy(mnist.test.images,mnist.test.labels))

執行看輸出,準確度爲:

Extracting MNIST_data/train-images-idx3-ubyte.gz
Extracting MNIST_data/train-labels-idx1-ubyte.gz
Extracting MNIST_data/t10k-images-idx3-ubyte.gz
Extracting MNIST_data/t10k-labels-idx1-ubyte.gz
0.1007
0.6668
0.7603
0.7946
0.8198
0.8324
0.8416
0.8473
0.8544
0.8565
0.8634
0.8661
0.8654
0.8692
0.8725
0.8727
0.8748
0.8753
0.8771
0.8781

準確率爲87%。

總結

上面的例子使用的是TensorFlow提供的數據集,咱們能夠本身手寫一個數字,而後經過opencv對數字進行剪裁,而後輸入模型看識別的結果。

深度學習和nlp的能夠加微信羣交流,目前,咱們正在參加nlp方面的比賽。

webwxgetmsgimg

相關文章
相關標籤/搜索