使用卷積神經網絡識別手寫數字(理論篇一)

「識別手寫數字」 在幾天以前對我來講仍是以爲很厲害的一件事,或許這須要很高深的機器學習的算法?可是這幾天看了一些關於神經網絡的文章,才發現識別數字實際上是一個很簡單的事情(固然這裏指的是最基本的識別單個數字),甚至能夠算是 計算機視覺(Computer Vison)的 「Hello World」。html

而在計算機視覺領域,卷積神經網絡(Convolution Neural Networks)的出現引領了一場技術革命,它在圖像識別方面能夠說是大顯身手。本文就基於卷積神經網絡,對單個數字進行識別。git

概覽

本質上來說,識別手寫數字要作的事情是圖像識別,無論圖裏面是數字也好,小貓小狗也好,實質上是同樣的。咱們的輸入是一張圖片,輸出是一個識別結果。github

與人類天生擁有的識別能力不一樣,計算機只能讀取一串串二進制數字。爲何程序可以識別圖片?這裏並無什麼浪漫色彩,不是由於計算機產生了智慧,而僅僅只是一系列數學公式起了做用。算法

設想咱們是如何分別一張照片是否有人臉的,雖然是一眼就能看出,但想象你纔剛出生,爲何你能知道照片裏那個東西是我的臉,而不是別的東西?網絡

實際上,咱們也是通過一步步訓練而具有這種能力的。咱們首先會辨別,這裏有沒有一個頭?頭的左上角、右上角有沒有一隻眼睛?中間有沒有一隻鼻子?最後這些答案大部分都是 「有」 的狀況下,咱們會得出結論:哦,這是一張臉。機器學習

而計算機也是同樣的道理,它也能夠經過判斷一張臉的組成是否都存在來判斷是不是一張臉。ide

因此它先辨別有沒有一隻眼睛,但它怎麼知道這是否是眼睛?那由於眼睛由眼珠、眼白組成,他能夠先辨別有沒有眼珠。但它怎麼知道這是否是眼珠?……函數

你可能已經明白了,這個問題能夠一直細分下去,計算機最後能識別的是一個一個像素點。根據像素點的組成,計算機能夠判斷是不是一個眼睛,同理往上識別一張人臉。這實際上也就是卷積層劃分的本質,咱們接下來會談到。post

因此,識別其實也沒有什麼神奇的地方,能夠說是數理統計的結果。不過,設計算法並無這麼簡單,一張圖由數千數萬的像素點組成,如何進行訓練也是一個關鍵的問題。這就引出了卷積神經網絡,咱們會先對圖片進行掃描,而後進行壓縮,最後才進行計算:學習

不要被上面的圖嚇到了,咱們識別手寫數字也是同樣的思路,但看完本文,你會發現它所作的事情其實並不複雜。

神經網絡基礎

提到卷積神經網絡,就不得不先說一下 神經網絡(Neural Networks)。我想即便沒有研究過機器學習,大部分人對神經網絡這個概念也不陌生,它借鑑了生物學上大腦的神經結構,抽象出了計算機領域的神經網絡的模型。

一個簡單的神經網絡能夠表示以下:

神經網絡分爲三個部分:輸入層(Input Layer)、隱藏層(Hidden Layer)和 輸出層(Output Layer)。層的個數和每層中節點的個數不是固定的,好比在上圖的神經網絡中只有一個隱藏層,而在實踐中,根據場景不一樣,隱藏層的數量也不盡相同。

每一層由若干個 感知器(perceptrons)組成,也就是圖中的節點。感知器接收一些輸入,而後產生一個輸出。另外,輸入層的感知器沒有輸入,他們分別做爲了隱藏層的輸入,在隱藏層中,每一個感知器進行計算,產出的輸出分別做爲了輸出層的輸入,最後經由輸出層計算,產出最終結果。

顯然,咱們能夠把感知器看做一個函數:

output = f(x_1, x_2, x_3)

很幸運,這裏的 f 很是簡單,是一個線性函數。這裏有三個輸入,因此咱們再定義三個 權重(weight)w一、w二、w3 和一個 誤差(bias)b,上式就能夠表示爲:

output = w_1 * x_1 + w_2 * x_2 + w_3 * x_3 + b

因此,能夠簡單理解上面提到的神經網絡實際上就是進行以下的計算(這裏省略了 Sigmoid 函數,以後再提到):

h1 = w_1 * x_1 + w_2 * x_2 + b_1 \\
h2 = w_3 * x_1 + w_4 * x_2 + b_2 \\
o1 = w_5 * h_1 + w_6 * h_2 + b_3

對於這個神經網絡而言,訓練集包含的是 x一、x2 對應的 o1 值,而咱們須要肯定的是 w1 到 w6 和 b1 到 b3 一共 9 個變量的值。由於肯定這 9 個值後,咱們就能根據任意的 x一、x2 來預測對應的 o1 了。

一開始,能夠對這 9 個值進行隨機賦值,而後直接開始訓練。從輸入到輸出,這是一個 前向(forward)的過程,不過這樣只是生成預測值。而根據預測值,咱們能夠判斷神經網絡的預測值和真實值相差多少,而後利用 梯度降低 (Gradient Descent)、反向傳播(Backward Propagation)從後往前來改變節點的權重和誤差,這樣實現一個 「學習」 的過程。

舉一個簡單的例子,咱們對吉他調音的時候,咱們首先彈一個音,調音器說 「音高了!」,因而咱們將旋鈕順時針扭一下而後再彈,調音器仍是說 「音高了!」,因而咱們再將旋鈕順時針扭一下,這時調音器說 「音低了!」,咱們再逆時針扭 …… 如此反覆,最後獲得旋鈕的最佳位置。

這裏調整的過程就是 梯度降低 的過程,能夠參考 以前翻譯的一篇文章

神經網絡的入門推薦閱讀 Machine Learning for Beginners: An Introduction to Neural Networks

卷積神經網絡基礎

簡單講,卷積神經網絡是在神經網絡上加入了 卷積層(Convolutional layers),卷積層由一些 濾波器(filter)組成,它對原始圖像進行掃描,在掃描窗口內,與原始圖像作內積(逐個元素相乘再求和)。這個操做就是所謂的 「卷積」 操做,也是卷積神經網絡的名字來源。

卷積層

咱們的卷積神經網絡的第一層就是卷積層,如上所述,它使用濾波器對圖片進行掃描。

舉個例子,假設圖片是 4 * 4 尺寸,濾波器爲 3 * 3,那麼濾波器將掃描 4 次,產出一個 2 * 2 的矩陣。

原始圖片和濾波器:

掃描過程以下:

想想這是在幹什麼?咱們說過圖像識別實際上作的事情就是判斷原始圖像中是否存在目標物體的組成部分。這個濾波器實際上就是在作這件事情。

再假設濾波器的像素組成爲:

那麼當原始圖像的窗口內有濾波器的圖像時,卷積結果就會很大,反之就越小。實際上使用這個圖片能夠判斷原始圖片是否有一個老鼠的組成部分:

你也能想到,由於一隻老鼠有不少特徵,一個濾波器固然是不夠的,因此在卷積層裏,會有多個濾波器。每個濾波器掃描完生成一個圖層,那麼一共就有濾波器數量個圖層。

咱們要識別的手寫數字圖片是 28 * 28 像素的,本文中將使用 8 個濾波器。因此卷積層的輸入爲 28 * 28 = 784 個,經由卷積層處理後,輸出爲 26 * 26 * 8 個節點。(3 * 3 的濾波器會使尺寸縮小一圈)

池化層

卷積神經網絡的第二層稱爲 池化層(Pooling Layer),它用來下降卷積層輸出的特徵向量,同時改善結果(不易出現過擬合)。

常見的池化操做有 平均池化(Mean Pooling)和 最大池化(Max Pooling)。本文將使用最大池化。它實際上就是將上層的輸入再經過 2 * 2 的濾波器掃描取最大值:

由於像素點之間的值其實是很是近的,咱們沒有必要保留全部相鄰的像素點,使用池化層處理後,像素點能顯著減小,它的輸出節點變爲 13 * 13 * 8 個。

Softmax 層

Softmax 層是本文中的最後一層,它將神經網絡的輸出變成了一個機率分佈。

這也是咱們在神經網絡基礎一節提到的實際使用公式計算的位置,Softmax 層輸入的節點個數爲 13 * 13 * 8 = 1352 個,輸出節點個數爲 10 個,因此咱們會有 1352 * 10 個權重,10 個誤差,對十種可能性進行計算。它們分別表示原始圖片是 0 - 9 的機率大小,其中的最大值所在位置就是神經網絡預測的數字值:

p_0 = w_{(1,1)} * x_1 + w_{(1,2)} * x_2 + ... + w_{(1,1352)} * x_1352 + b_1 \\
p_1 = w_{(2,1)} * x_1 + w_{(2,2)} * x_2 + ... + w_{(2,1352)} * x_{1352} + b_2 \\
... \\
p_9 = w_{(10,1)} * x_1 + w_{(10,2)} * x_2 + ... + w_{(10,1352)} * x_{1352} + b_{10} \\

以上就是整個前向反饋的過程,通過這些實現後,神經網絡就能夠對一個圖片進行預測,但如今只是瞎猜(由於沒有任何學習的過程)。接下來須要使用反向傳播對權重和誤差進行調整,咱們下篇繼續。

參考

相關文章
相關標籤/搜索