如同全部語言的hello world同樣,手寫體識別就至關於深度學習裏的hello world。python
TensorFlow是當前最流行的機器學習框架,有了它,開發人工智能程序就像Java編程同樣簡單。web
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表明黑色,小數表明某種程度的灰色。函數
如今,對於MNIST數據集中的圖片來講,咱們只要把它當成長度爲784的向量就能夠了(忽略它的二維結構,28×28=784)。咱們的任務就是讓這個向量通過一個函數後輸出一個類別。就是下邊這個函數,稱爲Softmax分類器。
這個式子裏的圖片向量的長度只有3,用x表示。乘上一個係數矩陣W,再加上一個列向量b,而後輸入softmax函數,輸出就是分類結果y。W是一個權重矩陣,W的每一行與整個圖片像素相乘的結果是一個分數score,分數越高表示圖片越接近該行表明的類別。所以,W x + b 的結果實際上是一個列向量,每一行表明圖片屬於該類的評分。一般分類的結果並不是評分,而是機率,表示有多大的機率屬於此類別。所以,Softmax函數的做用就是把評分轉換成機率,並使總的機率爲1。
卷積神經網絡(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方面的比賽。