天天看點

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

因為有10個不同可能性的類别,是以我們預期的随機标記圖像的精度為10%。25-30%的結果已經比随機标記的結果好多了,但仍有很大的改進空間。在這篇文章中,作者wolfgang

beyer将介紹如何建構一個執行相同任務的神經網絡。看看可以提高預測精度到多少!雷鋒網(公衆号:雷鋒網)對全文進行編譯,未經許可不得轉載。

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

神經網絡是基于生物大腦的工作原理設計的,由許多人工神經元組成,每個神經元處理多個輸入信号并傳回單個輸出信号,然後輸出信号可以用作其他神經元的輸入信号。我們先來看看一個單獨的神經元,大概長這樣:

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

一個人工神經元:其輸出是其輸入權重和的relu函數值。

在單個神經元中發生的情況與在softmax分類器中發生的情況非常相似。一個神經元有一個輸入值的向量和一個權重值的向量,權重值是神經元的内部參數。輸入向量和權重值向量包含相同數量的值,是以可以使用它們來計算權重和。

weightedsum=input1×w1+input2×w2+...

到目前為止,我們正在做與softmax分類器完全相同的計算,現在開始,我們要進行一些不同的處理:隻要權重和的結果是正值,神經元的輸出是這個值;但是如果權重和是負值,就忽略該負值,神經元産的輸出為0。 此操作稱為整流線性單元(relu)。

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

由 f(x) = max(0, x)定義的整流線性單元

使用relu的原因是其具備非線性特點,因而現在神經元的輸出并不是嚴格的輸入線性組合(也就是權重和)。當我們不再從單個神經元而是從整個網絡來看時,會發現非線性很有用處。

人工神經網絡中的神經元通常不是彼此随機連接配接的,大多數時候是分層排列的:

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

人工神經網絡具有隐藏層和輸出層2個層。

輸入并不被當作一層,因為它隻是将資料(不轉換它)饋送到第一個合适的層。

<a href="https://commons.wikimedia.org/wiki/file:colored_neural_network.svg" target="_blank">wikimedia</a>

輸入圖像的像素值是第1層網絡中的神經元的輸入。第1層中的神經元的輸出是第2層網絡的神經元的輸入,後面的層之間以此類推。如果沒有每層的relu,我們隻是得到一個權重和的序列;并且堆積的權重和可以被合并成單個權重和,這樣一來,多個層并沒有比單層網絡有任何改進之處。這就是為什麼要具有非線性的重要原因。relu非線性解決了上述問題,它使每個附加層的确給網絡添加了一些改進。

我們所關注的是圖像類别的分數,它是網絡的最後一層的輸出。在這個網絡架構中,每個神經元連接配接到前一層的所有神經元,是以這種網絡被稱為完全連接配接的網絡。我們将會在本教程的第3部分中看到一些不同于此的其他情況。

對神經網絡理論的簡短介紹到此結束。 讓我們開始建立一個真正的神經網絡!

如果你已經通過我以前的部落格文章,你會看到神經網絡分類器的代碼非常類似于softmax分類器的代碼。 除了切換出定義模型的代碼部分之外,我還添加了一些小功能使tensorflow可以做以下一些事情:

正則化:這是一種非常常見的技術,用于防止模型過拟合。它的工作原理是在優化過程中施加反作用力,其目的是保持模型簡單

使用tensorboard可視化模型:tensorboard包含tensorflow,允許您根據模型和模型生成的資料生成表格和圖形。這有助于分析您的模型,并且對調試特别有用。

檢查點:此功能允許您儲存模型的目前狀态以供以後使用。訓練一個模型可能需要相當長的時間,是以它是必要的,當您想再次使用模型時不必從頭開始。

這次代碼被分成兩個檔案:定義模型two_layer_fc.py和運作模型run_fc_model.py(提示:'fc'代表完全連接配接的意思)。

讓我們先看看模型本身,然後進行一些運作和訓練處理。two_layer_fc.py包含以下函數:

inference(),使我們從輸入資料到類分數。

loss(),從類分數中計算損失值。

training(),執行單個訓練步驟。

evaluation(),計算網絡的精度。

inference()描述了通過網絡的正向傳遞。那麼,類分數是如何從輸入圖檔開始被計算的呢?

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

參數images是包含實際圖像資料的tensorflow占位符。接下來的三個參數描述網絡的形狀或大小。 image_pixels是每個輸入圖像的像素數,classes是不同輸出标簽的數量,hidden_units是網絡的第一個層或者隐藏層中的神經元數量。

每個神經元從上一層擷取所有值作為輸入,并生成單個輸出值。是以,隐藏層中的每個神經元都具有image_pixels輸入,并且該層作為整體生成hidden_units輸出。然後将這些輸入到輸出層的類神經元中,生成類輸出值,每個類一個分數。

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

由于神經網絡有2個相似的圖層,是以将為每個層定義一個單獨的範圍。 這允許我們在每個作用域中重複使用變量名。變量biases以我們熟悉的tf.variable()方式來定義。

此處會更多地涉及到weights變量的定義。tf.get_variable()允許我們添加正則化。weights是以hidden_units(輸入向量大小乘以輸出向量大小)為次元的image_pixels矩陣。initialier參數描述了weights變量的初始值。目前為止我們已經将weights變量初始化為0,但此處并不會起作用。關于單層中的神經元,它們都接收完全相同的輸入值,如果它們都具有相同的内部參數,則它們将進行相同的計算并且輸出相同的值。為了避免這種情況,需要随機化它們的初始權重。我們使用了一個通常可以很好運作的初始化方案,将weights初始化為正态分布值。丢棄與平均值相差超過2個标準偏差的值,并且将标準偏差設定為輸入像素數量的平方根的倒數。幸運的是tensorflow為我們處理了所有這些細節,我們隻需要指定調用truncated_normal_initializer便可完成上述工作。

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

第2層與第1層非常相似,其輸入值為hidden_units,輸出值為classes,是以weights矩陣的次元是是[hidden_units,classes]。

由于這是我們網絡的最後一層,是以不再需要relu。

通過将輸入(hidden)互乘以weights,再加上bias就可得到類分數(logits)。

總而言之,整個inference()函數接收輸入圖像并傳回類分數。這是一個訓練有素的分類器需要做的,但為了得到一個訓練有素的分類器,首先需要測量這些類分數表現有多好,這是損失函數要做的工作。

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

首先,我們計算logits(模型的輸出)和labels(來自訓練資料集的正确标簽)之間的交叉熵,這已經是我們對softmax分類器的全部損失函數,但是這次我們想要使用正則化,是以必須給損失添加另一個項。

讓我們先放一邊吧,先看看通過使用正則化能實作什麼。

當捕獲資料中随機噪聲的統計模型是被資料訓練出來的而不是真實的資料基礎關系時,就被稱為過拟合。

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

紅色和藍色圓圈表示兩個不同的類。綠線代表過拟合模型,而黑線代表具有良好拟合的模型。

<a href="https://en.wikipedia.org/wiki/file:overfitting.svg" target="_blank">wikipedia</a>

在上面的圖像中有兩個不同的類,分别由藍色和紅色圓圈表示。綠線是過度拟合的分類器。它完全遵循訓練資料,同時也嚴重依賴于訓練資料,并且可能在處理未知資料時比代表正則化模型的黑線表現更差。是以,我們的正則化目标是得到一個簡單的模型,不附帶任何不必要的複雜。我們選擇l2-正則化來實作這一點,l2正則化将網絡中所有權重的平方和加到損失函數。如果模型使用大權重,則對應重罰分,并且如果模型使用小權重,則小罰分。

這就是為什麼我們在定義權重時使用了regularizer參數,并為它配置設定了一個l2_regularizer。這告訴了tensorflow要跟蹤l2_regularizer這個變量的l2正則化項(并通過參數reg_constant對它們進行權重)。所有正則化項被添加到一個損失函數可以通路的集合——tf.graphkeys.regularization_losses。将所有正則化損失的總和與先前計算的交叉熵相加,以得到我們的模型的總損失。

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

global_step是跟蹤執行訓練疊代次數的标量變量。當在我們的訓練循環中重複運作模型時,我們已經知道這個值,它是循環的疊代變量。直接将這個值添加到tensorflow圖表的原因是想要能夠拍攝模型的快照,這些快照應包括有關已執行了多少訓練步驟的資訊。

梯度下降優化器的定義很簡單。我們提供學習速率并告訴優化器它應該最小化哪個變量。 此外,優化程式會在每次疊代時自動遞增global_step參數。

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

總結我們迄今為止做了什麼,已經定義了使用4個函數的2層人工神經網絡的行為:inference()構成通過網絡的正向傳遞并傳回類分數。loss()比較預測和真實的類分數并生成損失值。

training()執行訓練步驟,并優化模型的内部參數。evaluation()測量模型的性能。

現在神經網絡已經定義完畢,讓我們看看run_fc_model.py是如何運作、訓練和評估模型的。

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

在代碼開頭兩行中定義了指令行參數。每個标志的參數是标志的名稱(其預設值和一個簡短的描述)。 使用-h标志執行檔案将顯示這些描述。第二個代碼塊調用實際解析指令行參數的函數,然後将所有參數的值列印到螢幕上。

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

用常數定義每個圖像的像素數(32 x 32 x 3)和不同圖像類别的數量。

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

使用一個時鐘來記錄運作時間。

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

我們想記錄關于訓練過程的一些資訊,并使用tensorboard顯示該資訊。 tensorboard要求每次運作的日志都位于單獨的目錄中,是以我們将日期和時間資訊添加到日志目錄的名稱位址。

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

load_data()加載cifar-10資料,并傳回包含獨立訓練和測試資料集的字典。

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

定義tensorflow占位符。 當執行實際計算時,這些将被填充訓練和測試資料。

images_placeholder将每張圖檔批處理成一定尺寸乘以像素的大小。 批處理大小設定為“none”允許運作圖檔時可随時設定大小(用于訓練網絡的批處理大小可以通過指令行參數設定,但是對于測試,我們将整個測試集作為一個批處理) 。

labels_placeholder是一個包含每張圖檔的正确類标簽的整數值向量。

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

這裡引用了我們之前在two_layer_fc.py中描述的函數。

inference()使我們從輸入資料到類分數。

loss()從類分數中計算損失值。

training()執行單個訓練步驟。

evaluation()計算網絡的精度。

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨
機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨
機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

開始tensorflow會話并立即初始化所有變量。 然後我們建立一個彙總編輯器,使其定期将日志資訊儲存到磁盤。

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

這些行負責生成批輸入資料。讓我們假設我們有100個訓練圖像,批次大小為10.在softmax示例中,我們隻為每次疊代選擇了10個随機圖像。這意味着,在10次疊代之後,每個圖像将被平均選取一次。但事實上,一些圖像将被選擇多次,而一些圖像不會被添加到任何一個批次。但隻要重複的次數夠頻發,所有圖檔被随機分到不同批次的情況會有所改善。

這一次我們要改進抽樣過程。要做的是首先對訓練資料集的100個圖像随機混洗。混洗之後的資料的前10個圖像作為我們的第一個批次,接下來的10個圖像是我們的第二批,後面的批次以此類推。

10批後,在資料集的末尾,再重複混洗過程,和開始步驟一緻,依次取10張圖像作為一批次。這保證沒有任何圖像比任何其它圖像被更頻繁地拾取,同時仍然確定圖像被傳回的順序是随機的。

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨
機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨
機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

此行運作train_step操作(之前定義為調用two_layer_fc.training(),它包含用于優化變量的實際指令)。  

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

當訓練模型需要較長的時間,有一個簡單的方法來儲存你的進度的快照。

這允許您以後回來并恢複模型在完全相同的狀态。

所有你需要做的是建立一個tf.train.saver對象(我們之前做的),然後每次你想拍攝快照時調用它的save()方法。恢複模型也很簡單,隻需調用savever的restore()。

代碼示例請看github存儲庫中的restore_model.py檔案。

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

在訓練完成後,最終模型在測試集上進行評估(記住,測試集包含模型到目前為止還沒有看到的資料,使我們能夠判斷模型是否能推廣到新的資料)。

讓我們使用預設參數通過“python run_fc_model.py”運作模型。 我的輸出如下所示:

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨
機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

可以看到訓練的準确性開始于我們所期望到随機猜測水準(10級

- &gt; 10%的機會選擇到正确的)。 在第一次約1000次疊代中,精度增加到約50%,并且在接下來的1000次疊代中圍繞該值波動。

46%的測試精度不低于訓練精度。 這表明我們的模型沒有顯着過度拟合。 softmax分級器的性能約為30%,是以46%的改進約為50%。不錯!

tensorboard允許您從不同方面可視化tensorflow圖形,并且對于調試和改進網絡非常有用。 讓我們看看tensorboard相關的代碼。

在 two_layer_fc.py 我可以看到以下代碼:

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

這三行中的每一行都建立一個彙總操作。通過定義一個彙總操作告訴tensorflow收集某些張量(在本例中logits,loss和accuracy)的摘要資訊。彙總操作的其他參數就隻是一些想要添加到總結的标簽。

在 run_fc_model.py 是關于tensorboard 可視化的一些代碼:

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

tensorflow中的一個操作本身不運作,您需要直接調用它或調用依賴于它的另一個操作。由于我們不想在每次要收集摘要資訊時單獨調用每個摘要操作,是以使用tf.merge_all_summaries建立一個運作所有摘要的單個操作。

在tensorflow會話的初始化期間,建立一個摘要寫入器,摘要編入器負責将摘要資料實際寫入磁盤。在摘要寫入器的構造函數中,logdir是日志的寫入位址。可選的圖形參數告訴tensorboard渲染顯示整個tensorflow圖形。每100次疊代,我們執行合并的彙總操作,并将結果饋送到彙總寫入器,将它們寫入磁盤。要檢視結果,我們通過“tensorboard

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

tensorboard圖顯示模型在訓練中的損失和精度。

“graphs”頁籤顯示一個已經定義的可視化的tensorflow圖,您可以互動式地重新排列直到你滿意。我認為下面的圖檔顯示了我們的網絡結構非常好。

機器學習零基礎?手把手教你用TensorFlow搭建圖像識别系統(三)| 幹貨

tensorboard1以互動式可視化的方式顯示tensorboard圖像

也許你正在想訓練softmax分類器的計算時間比神經網絡少了很多。事實确實如此,但即使把訓練softmax分類器的時間增加到和神經網絡來訓練所用的時間一樣長,前者也不會達到和神經網絡相同的性能,前者訓練時間再長,額外的收益和一定程度的性能改進幾乎是微乎其微的。我們也已經在神經網絡中也驗證也這點,額外的訓練時間不會顯著提高準确性,但還有别的事情我們可以做。

已選的預設參數值表現是相當不錯的,但還有一些改進的餘地。通過改變參數,如隐藏層中的神經元的數目或學習率,應該能夠提高模型的準确性,模型的進一步優化使測試精度很可能大于50%。如果這個模型可以調整到65%或更多,我也會相當驚喜。但還有另一種類型的網絡結構能夠比較輕易實作這一點:卷積神經網絡,這是一類不完全連通的神經網絡,相反,它們嘗試在其輸入中了解局部特征,這對于分析圖像非常有用。它使得在解讀圖像擷取空間資訊的時候有非常直覺的意義。在本系列的下一部分中,我們将看到卷積神經網絡的工作原理,以及如何建構一個自己的神經網絡.。

本文作者:陳鳴鸠