您好,登錄后才能下訂單哦!
這篇文章給大家介紹Tensorflow中CNN入門的手寫數字識別是怎樣的,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
深度學習最令人興奮的領域之一就是計算機視覺。通過卷積神經網絡,我們已經能夠創建自動駕駛汽車系統、面部檢測系統和自動醫學圖像分析等等。我將向你展示卷積神經網絡的基本原理以及如何自己創建一個對手寫數字進行分類的系統。
cdn.com/f6b247650f1d689504cfca4e25034dcb51025592.jpeg">
卷積神經網絡的功能似乎是人類大腦中生物功能的復制,早在1959年,David Hubel和Torsten Wiesel對貓和猴進行了研究,這些研究揭示了動物視覺皮層的功能。他們發現的是,許多神經元具有小的局部接受性,即僅對整個視野的一小塊有限區域起反應。他們發現某些神經元會對某些特定模式做出反應,例如水平線、垂直線和其他圓形。他們還發現其他神經元具有更大的感受野并且被更復雜的模式刺激,這些模式是由較低水平神經元收集的信息組合。這些發現奠定了我們現在稱之為卷積神經網絡的基礎。接下來,我們逐一介紹卷積神經網絡的組成。
1、卷積層
卷積神經網絡中每層卷積層由若干卷積單元組成,每個卷積單元的參數都是通過反向傳播算法最佳化得到的。卷積運算的目的是提取輸入的不同特征,第一層卷積層可能只能提取一些低級的特征如邊緣、線條和角等層級,更多層的網路能從低級特征中迭代提取更復雜的特征。你可以將每個過濾器描繪成一個窗口,該窗口在圖像的尺寸上滑動并檢測屬性。濾鏡在圖像上滑動的像素數量稱為步幅。步幅為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.池化層
池化層的目標是通過聚合卷積層收集的值或所謂的子采樣來進一步降低維度。除了為模型提供一些正則化的方案以避免過度擬合之外,這還將減少計算量。它們遵循與卷積層相同的滑動窗口思想,但不是計算所有值,而是選擇其輸入的最大值或平均值。這分別稱為最大池化和平均池化。
這兩個組件是卷積層的關鍵構建塊。然后,你通常會重復此方法,進一步減少特征圖的尺寸,但會增加其深度。每個特征圖將專門識別它自己獨特的形狀。在卷積結束時,會放置一個完全連接的圖層,其具有激活功能,例如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填充。這將輸出一個6*6*16維矩陣。你可以看到我們正在縮小特征圖的維度空間,但要更深入。接下來,我們使用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產生的預測。
關于Tensorflow中CNN入門的手寫數字識別是怎樣的就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。