1. 程式人生 > >一步步提高手寫數字的識別率(3)

一步步提高手寫數字的識別率(3)

在前面的兩篇文章《一步步提高手寫數字的識別率(1)》和《一步步提高手寫數字的識別率(2)》中,我們分別介紹了使用Softmax迴歸和神經網路來實現手寫數字識別,其準確率分別在92和98%左右,這在機器學習領域是一個非常不錯的準確率,如果我們採用卷積神經網路,準確率還可以進一步提升。

在《一步步構建卷積模型》這篇文章中我們介紹瞭如何從頭構建卷積模型,如果我們使用TensorFlow框架,我們就不需要這麼麻煩,只需呼叫其中的卷積函式即可。不過在開始程式設計之前,還是簡單介紹一下卷積神經網路。

卷積神經網路簡介

卷積神經網路(Convolutional Neural Network, CNN)最初是為解決影象識別等問題設計的,其現在的應用不僅限於影象和視訊,也可用於時間序列訊號,比如音訊訊號、文字資料等。CNN作為一個深度學習框架被提出的最初訴求,是降低對影象資料預處理的要求,以及避免複雜的特徵工程。CNN可以直接使用影象的原始畫素作為輸入,減輕了使用傳統演算法必需做的大量重複、繁瑣的資料預處理工作。CNN的最大特點在於卷積的權值共享結構,可以大幅減少神經網路的引數量,防止過擬合的同時又降低了神經網路的複雜度。

在卷積神經網路中,第一個卷積層會直接接受影象畫素級的輸入,每個卷積操作只處理一小塊影象,進行卷積變化後再傳到後面的網路,每一層卷積(也稱作濾波器,filter)都會提取資料中最有效的特徵。

一般卷積神經網路由多個卷積層構成,每個卷積層中通常會進行如下幾個操作:

  1. 影象通過多個不同的卷積核的濾波,並加偏置(bias),提取區域性特徵,每個卷積核會映射出一個新的2D影象。
  2. 將卷積核的輸出結果,進行非線性的啟用函式(ReLU最常用)處理。
  3. 對啟用函式的結果再進行池化操作,即降取樣,一般採用最大池化方法,保留最顯著的特徵,並提升模型的畸變容錯能力。

這幾個步驟就構成了最常見的卷積層,我們還可以將多個卷積層拼在一起,構成卷積神經網路,比如下圖就表示包含兩個卷積層的卷積神經網路:

image

TensorFlow實現簡單的卷積神經網路

卷積神經網路可以有很多層,比如大名鼎鼎的LeNet5,有一百多個卷積層,具有相當的複雜度。對於手寫數字識別問題,我們當然不需要像LeNet5這樣複雜的卷積神經網路,這裡我們使用兩個卷積層加一個全連線層構建一個簡單但非常有代表性的卷積神經網路。

和前兩個的TensorFlow程式一樣,我們先載入MNIST資料集:

from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf

mnist = input_data.read_data_sets("MNIST_data/"
, one_hot=True) sess = tf.InteractiveSession()

接下來定義初始化函式初始化權重和偏置,我們需要給權重製造一些隨機的噪聲來打破對稱,而給偏置增加一些小的正值(0.1)來避免死亡節點(dead neurons)。

def weight_variable(shape):
    initial = tf.truncated_normal(shape, stddev=0.1)
    return tf.Variable(initial)


def bias_variable(shape):
    initial = tf.constant(0.1, shape=shape)
    return tf.Variable(initial)

接下來定義卷積層和池化層,TensorFlow中有二維卷積函式tf.nn.conv2d和池化函式tf.nn.max_pool,所以定義起來比較簡單:

def conv2d(x, W):
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')


def max_pool_2x2(x):
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

關於strides、padding等卷積運算的概念,請參考《一步步構建卷積模型》。

在正式設計卷積神經網路的結構之前,先定義輸入的placeholder,x是特徵,y_是真實的標籤。因為卷積神經網路會利用到空間結構資訊,因此需要將一維的輸入向量x轉化為2D的圖片結構,即從1x784轉化為原始的28x28的結構。

x = tf.placeholder(tf.float32, [None, 784])
y_ = tf.placeholder(tf.float32, [None, 10])
x_image = tf.reshape(x, [-1, 28, 28, 1])

接下來定義兩個卷積層和全連線層:

W_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)

W_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)

W_fc1 = weight_variable([7*7*64, 1024])
b_fc1 = bias_variable([1024])
h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)

為了減少過擬合,這裡也需要使用到Dropout,正如上一篇文章中所講到的,最後將Dropout層的輸出連線一個Softmax層,得到最後的輸出。

keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])
y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)

最後的步驟就是定義損失函式、選擇優化器、迭代訓練、評估結果,和前面兩篇文章的步驟一致,這裡就不再詳細討論了。

cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y_conv), reduction_indices=[1]))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

tf.global_variables_initializer().run()
for i in range(20000):
    batch = mnist.train.next_batch(50)
    if i % 100 == 0:
        train_accuracy = accuracy.eval(feed_dict={x:batch[0], y_: batch[1], keep_prob: 1.0})
        print("step %d, training accuracy %g" % (i, train_accuracy))
    train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})

batch = mnist.test.next_batch(2000)
print("test accuracy %g" % accuracy.eval(feed_dict={x: batch[0], y_: batch[1], keep_prob: 1.0}))

注意這裡沒有使用全部的測試資料集,因為在我的GTX 960顯示卡下,一次性喂入所有的測試資料集,會出現記憶體不足的問題,所以這裡只隨機選擇了2000個數據集。

總結

這個簡單的卷積神經網路模型的準確率大約為99.2%,基本可以滿足對手寫數字識別準確率的要求。相比之前的深度神經網路2%的錯誤率,CNN的錯誤率下降了60%。這其中主要的效能提升都來自更優秀的網路模型設計,充分說明卷積網路對影象特徵的提取和抽象能力。依靠卷積核的權值共享,CNN的引數數量並沒有爆炸,降低計算量的同時也減輕了過擬合,整個模型的效能有著較大的提升。

至此,一個比較實用的手寫數字識別程式就完成了,你也可以嘗試增加幾個卷積層,檢驗一下效果。這三篇文章中,我們先設計出了一個簡單的機器學習模型,然後逐步優化模型。在實際工作中,我們也通常遵循這樣一個流程。通過這一系列的文章,想必對TensorFlow的程式設計流程也有一定的掌握。

參考

  1. TensorFlow實戰,黃文堅、唐源著,電子工業出版社。

image

相關推薦

步步提高數字識別(3)

在前面的兩篇文章《一步步提高手寫數字的識別率(1)》和《一步步提高手寫數字的識別率(2)》中,我們分別介紹了使用Softmax迴歸和神經網路來實現手寫數字識別,其準確率分別在92和98%左右,這在機器學習領域是一個非常不錯的準確率,如果我們採用卷積神經網路,準確

TensorFlow程式碼實現()[MNIST數字識別]

最簡單的神經網路結構: 資料來源準備:資料在之前的文章中分析過了 在這裡我們就構造一層神經網路: 前提準備: 引數: train images:因為圖片是28*28的個數,換算成一維陣列就是784,因此我們定義x = tf.placeholder(tf

[TensorFlow深度學習入門]實戰十·用雙向BiRNN(LSTM)做數字識別準確率99%+

[TensorFlow深度學習入門]實戰十一·用雙向BiRNN(LSTM)做手寫數字識別準確率99%+ 此博文是我們在完成實戰五·用RNN(LSTM)做手寫數字識別的基礎上使用BiRNN(LSTM)結構,進一步提升模型的準確率,1000steps準確率達到99%。 首先我們先

pytorch 入門()數字識別

import torch from torch.autograd import * from torch import nn,optim from torch.utils.data import DataLoader from torchvision i

TensorFlow——Mnist數字識別並可視化 實戰教程(

要點: 該教程為深度學習tensorflow框架mnist手寫數字識別。 實戰教程分為(一)(二)(三)分別從tensorflow和MATLAB雙角度來實現。 筆者資訊:Next_Legend  Q

各種機器學習方法(線性迴歸、支援向量機、決策樹、樸素貝葉斯、KNN演算法、邏輯迴歸)實現數字識別並用準確率、召回、F1進行評估

本文轉自:http://blog.csdn.net/net_wolf_007/article/details/51794254 前面兩章對資料進行了簡單的特徵提取及線性迴歸分析。識別率已經達到了85%, 完成了數字識別的第一步:資料探測。 這一章要做的就各

數字識別

在學習識別手寫輸入數字時,初始化矩陣那裡,有點不理解。原始碼是這樣的:self.biases=[np.random.randn(y,1) for y in sizes[1:]] '''建立一個偏差向量''' self.weights=[np.random.ra

MNIST 數字識別

MNIST 手寫數字識別模型建立與優化 本篇的主要內容有: TensorFlow 處理MNIST資料集的基本操作 建立一個基礎的識別模型 介紹 SoftmaxSoftmaxSoftmax迴歸以及交叉熵等 MNIST是一個很有名的手寫數字識別資料集(基本可以算

DL之NN:NN演算法(本地資料集50000張訓練集圖片)進階優化之三種引數改進,進一步提高數字圖片識別的準確率

首先,改變之一:先在初始化權重的部分,採取一種更為好的隨機初始化方法,我們依舊保持正態分佈的均值不變,只對標準差進行改動,初始化權重改變前, def large_weight_initializer(self): self.biases = [np.ran

看就懂的K近鄰演算法(KNN),K-D樹,並實現數字識別

1. 什麼是KNN 1.1 KNN的通俗解釋 何謂K近鄰演算法,即K-Nearest Neighbor algorithm,簡稱KNN演算法,單從名字來猜想,可以簡單粗暴的認為是:K個最近的鄰居,當K=1時,演算法便成了最近鄰演算法,即尋找最近的那個鄰居。 用官方的話來說,所謂K近鄰演算法,即是給定一個訓練資

BP神經網絡(數字識別

根據 公式 輸入 廣泛 不可變 理想 變化 n) 放大 1實驗環境 實驗環境:CPU [email protected]/* */,內存8G,windows10 64位操作系統 實現語言:python 實驗數據:Mnist數據集 程序使用的數據庫是mni

keras入門實戰:數字識別

如果 turn wid 寬度 initial 作用 err examples 預測 近些年由於理論知識的硬件的快速發展,使得深度學習達到了空前的火熱。深度學習已經在很多方面都成功得到了應用,尤其是在圖像識別和分類領域,機器識別圖像的能力甚至超過了人類。 本文用深度學習Pyt

MFC基於對話框 數字識別 SVM+MNIST數據集

識別數字 做了 XML svm 簡單實用 清空 朋友 detail data 完整項目下載地址: http://download.csdn.net/detail/hi_dahaihai/9892004 本項目即拿MFC做了一個畫板,畫一個數字後可自行識別數字。此外還 有保存

【機器學習】數字識別算法

alt gdi 數字識別 -1 轉換 error: erro files turn 1.數據準備 樣本數據獲取忽略,實際上就是將32*32的圖片上數字格式化成一個向量,如下: 本demo所有樣本數據都是基於這種格式的 訓練數據:將圖片數據轉成1*1024的數組,作為一

Tensorflow - Tutorial (7) : 利用 RNN/LSTM 進行數字識別

ddc htm net sets 手寫 n-2 align csdn global 1. 經常使用類 class tf.contrib.rnn.BasicLSTMCell BasicLSTMCell 是最簡單的一個LSTM類。沒有實現clippi

Tensorflow實踐 mnist數字識別

model 損失函數 兩層 最簡 sin test http gif bat minst數據集      tensorflow的文檔中就自帶了mnist手寫數字識別的例子,是一個很經典也比較簡單

tensorflow 基礎學習五:MNIST數字識別

truncate averages val flow one die correct 表示 data MNIST數據集介紹: from tensorflow.examples.tutorials.mnist import input_data # 載入MNIST數據集,

第二節,TensorFlow 使用前饋神經網絡實現數字識別

com net config return pyplot dataset 運行 算法 但是 一 感知器 感知器學習筆記:https://blog.csdn.net/liyuanbhu/article/details/51622695 感知器(Percep

第三節,TensorFlow 使用CNN實現數字識別

啟用 out min 灰度 HA 打破 gre 大量 gray 上一節,我們已經講解了使用全連接網絡實現手寫數字識別,其正確率大概能達到98%,著一節我們使用卷積神經網絡來實現手寫數字識別, 其準確率可以超過99%,程序主要包括以下幾塊內容 [1]: 導入數據,即測試集和

Caffe的運行mnist數字識別

而不是 所在 結果 ack cif sting one efi 打開 老規矩,首先附上官方教程:http://caffe.berkeleyvision.org/gathered/examples/mnist.html 1、必要軟件   因為Caffe中使用的是Linux才能