(Tensorflow)手把手CNN入門:手寫數字識別

摘要: 手把手帶你實戰——《CNN入門:手寫數字識別》!

深度學習最使人興奮的領域之一就是計算機視覺。經過卷積神經網絡,咱們已經可以建立自動駕駛汽車系統、面部檢測系統和自動醫學圖像分析等等。在本文中,我將向你展現卷積神經網絡的基本原理以及如何本身建立一個對手寫數字進行分類的系統。git

卷積神經網絡的功能彷佛是人類大腦中生物功能的複製,早在1959年,David Hubel和Torsten Wiesel對貓和猴進行了研究,這些研究揭示了動物視覺皮層的功能。他們發現的是,許多神經元具備小的局部接受性,即僅對整個視野的一小塊有限區域起反應。他們發現某些神經元會對某些特定模式作出反應,例如水平線、垂直線和其餘圓形。他們還發現其餘神經元具備更大的感覺野而且被更復雜的模式刺激,這些模式是由較低水平神經元收集的信息組合。這些發現奠基了咱們如今稱之爲卷積神經網絡的基礎。接下來,咱們逐一介紹卷積神經網絡的組成。算法

一、卷積層服務器

卷積神經網絡中每層卷積層由若干卷積單元組成,每一個卷積單元的參數都是經過反向傳播算法最佳化獲得的。卷積運算的目的是提取輸入的不一樣特徵,第一層卷積層可能只能提取一些低級的特徵如邊緣、線條和角等層級,更多層的網路能從低級特徵中迭代提取更復雜的特徵。你能夠將每一個過濾器描繪成一個窗口,該窗口在圖像的尺寸上滑動並檢測屬性。濾鏡在圖像上滑動的像素數量稱爲步幅。步幅爲1意味着濾波器一次移動一個像素,其中2的步幅將向前跳過2個像素。網絡

在上面的例子中,咱們能夠看到一個垂直線檢測器。原始圖像爲6x6,它使用3x3濾鏡進行掃描,步長爲1,從而產生4x4尺寸輸出。而過濾器僅對其視野左右列中的部分感興趣。經過對圖像的輸入求和並乘以3×3濾波器的配置,咱們獲得3+1+2-1-7-5=-7。而後濾波器向右移動一步,而後計算1+0+3-2-3-1=-2。-2而後進入-7右側的位置。此過程將持續到4x4網格完成爲止。以後,下一個特徵圖將使用它本身的惟一過濾器/內核矩陣計算本身的值。架構

2.池化層機器學習

池化層的目標是經過聚合卷積層收集的值或所謂的子採樣來進一步下降維度。除了爲模型提供一些正則化的方案以免過分擬合以外,這還將減小計算量。它們遵循與卷積層相同的滑動窗口思想,但不是計算全部值,而是選擇其輸入的最大值或平均值。這分別稱爲最大池化和平均池化。ide

這兩個組件是卷積層的關鍵構建塊。而後,你一般會重複此方法,進一步減小特徵圖的尺寸,但會增長其深度。每一個特徵圖將專門識別它本身獨特的形狀。在卷積結束時,會放置一個徹底鏈接的圖層,其具備激活功能,例如Relu或Selu,用於將尺寸從新整形爲適合的尺寸送入分類器。例如,若是你的最終轉換層爲3x3x128矩陣,但你只預測10個不一樣的類,則須要將其從新整形爲1x1152向量,並在輸入分類器以前逐漸減少其大小。徹底鏈接的層也將學習它們本身的特徵,如在典型的深度神經網絡中。函數

如今讓咱們看看在MNIST手寫數字數據集上的Tensorflow中的實現。首先,咱們將加載咱們的庫。使用sklearn中的fetch_mldata,咱們加載mnist數據集並將圖像和標籤分配給x和y變量。而後咱們將建立咱們的訓練/測試裝置。最後,咱們將舉幾個例子來了解任務。性能

接下來,咱們將進行一些數據加強,這是提升模型性能的可靠方法。經過建立訓練圖像的輕微變化,能夠爲模型建立正則化。咱們將使用Scipy的ndimage模塊將圖像向右、向左、向上和向下移動1個像素。這不只提供了更多種類的例子,並且還會大大增長咱們訓練集的大小。學習

我將向你展現的最後一種數據加強的方式:使用cv2庫建立圖像的水平翻轉。咱們還須要爲這些翻轉圖像建立新標籤,這與複製原始標籤同樣簡單。

設置「flipCode = 0」將產生垂直翻轉

接下來,咱們將建立一個輔助函數,用於將隨機微型批次提供給咱們的神經網絡輸入。因爲卷積層的性質,它們在前向和後向傳播步驟期間須要大量的存儲器。考慮具備4x4濾鏡的圖層,輸出128步幅爲1的特徵圖和具備尺寸299x299的RGB圖像輸入的SAME填充。參數的數量將相等(4x4x3+1)x128 = 6272.如今考慮這128個特徵圖中的每個都計算299x299個神經元,而且這些神經元中的每個都計算4x4x3輸入的加權和。這意味着咱們須要4x4x3x299x299x150=643,687,200次計算,這只是一個訓練的例子。

如今咱們開始建立咱們的網絡架構。首先,咱們爲咱們的培訓數據/特徵建立佔位符。咱們須要將它們從新整形爲(-1,28,28,1)矩陣,由於tensorflow conv2d層須要4維輸入。咱們將第一個維度設置爲「null」,以容許將任意批量大小提供給佔位符。

接着咱們設計咱們的卷積層,我是從Le-NET5(由Yann LeCun開創)網絡架構中獲取靈感,該架構因其在手寫數字分類方面成功而聞名。我建議你研究Le-NET5以及其餘通過驗證的模型,這樣就能夠了解哪一種卷積網絡適用於不一樣的任務。連接:http://yann.lecun.com/exdb/publis/pdf/lecun-01a.pdf

咱們模型卷積層的第一層由12個特徵圖組成,使用3x3過濾器,步幅爲1。咱們選擇了SAME填充,經過在輸入周圍添加一個零填充來保持圖像的尺寸。而後,咱們設置最大池化層使用3x3過濾器,步幅爲1,這將輸出13x13x12矩陣。因此咱們從一個28x28x1的圖像開始,而後咱們將這個矩陣傳遞給第二個轉換層,第二個轉換層具備3x3過濾器的深度,stride=1和SAME填充。這將輸出一個6616維矩陣。你能夠看到咱們正在縮小特徵圖的維度空間,但要更深刻。接下來,咱們使用Selu函數激活兩個密集層來減小每層輸入的數量大約一半,直到最終將它們輸入咱們的logits。

接着咱們建立咱們的損失函數,在這種狀況下,它將是softmax交叉熵,它將輸出多類機率。你能夠將交叉熵視爲各類數據點之間距離的度量。咱們選擇AdamOptimizer(自適應矩估計),當梯度降低時自動調整它的學習率。最後,咱們建立了一種評估結果的方法。Tensorflow的in_top_k函數將計算咱們的logits並選擇最高分。而後咱們使用咱們的準確度變量輸出0-1%之間的百分比。

如今咱們已經爲訓練階段作好了準備,讓咱們看看咱們的模型表現得如何。

在第19epoch,咱們的正確率在0.9907。這已經比任何機器學習算法的結果更好,所以卷積已經取得了領先。如今讓咱們嘗試使用咱們的移位功能/翻轉功能,併爲咱們的網絡添加兩個新元素:dropout和批量標準化。

咱們使用placeholder_with_default節點修改現有佔位符,這些節點將保存批量標準化和dropout層生成的值。在訓練期間,咱們將這些值設置爲True,在測試期間,咱們將經過設置爲False將其關閉。

批量標準化只是簡單地對每批次的數據進行標準化。咱們指定了0.9的動量。而dropout和正則化指定動量爲1才能在訓練期間徹底隨機地關閉節點。這致使其他節點必須鬆弛,從而提升其有效性。想象一下,一家公司決定每週隨機選擇50名員工留在家裏。其他的工做人員將不得不有效地處理額外的工做,提升他們在其餘領域的技能。

接着咱們建立咱們的損失函數,訓練步驟和評估步驟,而後對咱們的執行階段進行一些修改。經過批量標準化執行的計算在每次迭代期間保存爲更新操做。爲了訪問這些,咱們分配一個變量extra_update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)。在咱們的訓練操做期間,咱們將其做爲列表項與training_op一塊兒提供給sess.run。最後,在執行驗證/測試預測時,咱們經過feed_dict爲佔位符分配False值。咱們不但願在預測階段有任何隨機化。爲了得到輸出,咱們使用咱們的測試集運行logits操做。讓咱們看看這個模型添加正則化/標準化而且正在使用加強數據的方法後表現得如何。

在29epoch,咱們在10,000個數字的測試集上達到了99.5%的準確率。正如你所看到的那樣,第二個epoch時模型精確度達到了99%,而以前的模型只有16%。雖然0.05%可能不是不少,但在處理大量數據時這是一個重大改進。最後,我將向你展現如何在logits輸出上使用np.argmax產生的預測。

雲服務器99元拼團購!拉新還可贏現金紅包!300萬等你瓜分!
立刻一鍵開團贏紅包: http://click.aliyun.com/m/100...



本文做者:【方向】

閱讀原文

本文爲雲棲社區原創內容,未經容許不得轉載。

相關文章
相關標籤/搜索