- 移動端AI與ML應用開發:基于iOS和Android
- (美)勞倫斯·莫羅尼
- 2595字
- 2023-07-24 18:05:23
2.1.4 編寫Fashion MNIST模型
前面描述的模型架構如下所示:

真的就是這么簡單!這里有一些新概念,讓我們來探索一下。
首先,我們可以看到我們正在使用Sequential。回想一下,這允許我們使用列表定義網絡中的層。該列表中的每個元素都定義了一個層類型(在這個例子中,一個Flatten后跟兩個Dense層),以及有關該層的詳細信息,例如神經元的數量和激活函數。
第一層是:

這展示了層的部分功能——你不僅可以使用它們定義模型架構,還可以將功能封裝在層中。所以在這里你的輸入形狀28×28被“展平”為你需要輸入神經網絡的784×1。
之后,你擁有我們在圖2-12中顯示的兩個層,即一個具有20個神經元的Dense層,以及一個具有10個神經元的Dense層。
但是,這里也有一些新東西——激活(activation)參數。這定義了一個激活函數,該函數在該層處理結束時于該層上執行。激活函數可以幫助網絡識別更復雜的模式,并在信息從一層到另一層流動時改變信息的行為,幫助網絡更好、更快地學習。
它們是可選的,但它們非常有用并且經常被推薦使用。
在這20個神經元的層上,激活函數是tf.nn.relu,其中relu代表rectified linear unit(修正線性單元)。這是一個非常新奇的術語,有效地等同于:如果該值小于零,則設置它歸零;否則,保持原樣。就像:

這有什么幫助呢?如果該層中的任何神經元返回負值,則可能會抵消另一個神經元的正值,從而有效地忽略了它學到的東西。因此,與其在每次迭代時對每個神經元進行大量檢查,我們不如在層上設置一個激活函數來為我們做這件事。
類似地,輸出層有一個稱為softmax的激活函數。這里的想法是我們的輸出層有10個神經元。理想情況下,它們都包含零,除了其中一個的值是1。那個就是我們要的類別。在現實中,這種情況很少發生,每個神經元都有一個值。最大的將是我們對輸入圖像進行分類的最佳候選值。然而,為了報告一個概率值,我們希望每個神經元的值加起來為1,并且它們的值能適當地縮放。我們可以簡單地將softmax激活函數應用于該層,而不是編寫代碼來處理這個問題,它會為我們做到這一點!
這只是模型架構。現在讓我們探索完整的代碼,包括獲取數據、編譯模型,然后執行訓練:

還記得之前我提到解析圖像內容的傳統編碼時,即使是像Fashion MNIST這樣簡單的圖像,也可能需要數千行代碼來處理它,而機器學習只需幾行代碼就可以完成嗎?現在讓我們來看一下。
首先是獲取數據。Fashion MNIST數據集內置于TensorFlow,因此我們可以像這樣輕松獲取它:

執行這行代碼后,training_images將有60000個訓練圖像,training_labels將有它們的關聯標簽。此外val_images和val_labels將有10000個圖像及其相關標簽。好在訓練時不使用它們,因此我們可以在探索神經網絡的效能時擁有一組神經網絡以前“沒有見過”的數據。
接下來是這些行:

使用Python中的NumPy的強大之處在于,如果將數組除以一個值,那么你會將該數組中的每個元素都除以該值。但是為什么我們要除以255?
這個過程稱為歸一化,這又是一個相當新奇的術語,意思是將一個值設置為0~1之間的某個值。我們的像素在0~255之間,因此通過除以255,我們將對其進行歸一化。為什么要歸一化?當值在0和1之間時,Dense中的數學運算效果最佳,當誤差較大時,它們不會大量增加。你可能還記得第1章中的y=2x-1示例,我們沒有進行歸一化。這是一個平凡示例,不需要這樣做,但在大多數情況下,你需要在將數據輸入神經網絡之前對其進行歸一化!
然后,在定義模型架構后,編譯模型,指定損失函數和優化器:

它們與你在第1章中使用的sgd和mean_squared_error不同。TensorFlow有一個包含這些函數的庫,你通常可以從中挑選出最適合你的模型的方法進行試驗。這里有一些限制,最明顯的是損失函數。鑒于該模型有多個輸出神經元,并且這些神經元為我們提供輸出的類別或類型,我們希望使用分類損失函數來有效地測量它們,為此我選擇了sparse_categorical_crossentropy。了解這些的工作方式超出了本書的范圍,但最好嘗試一下你可以在TensorFlow.org上找到的不同損失函數和優化器。對于優化器,我選擇了adam,它是sgd的增強版本,可以在內部進行自我調整以獲得更好的性能。
還請注意,我使用了另一個參數metrics=['accuracy'],它要求TensorFlow在訓練時報告準確度。當進行分類模型訓練時,我們希望分類器告訴我們它看到了什么,我們可以使用基本準確度,即其猜測“正確”的訓練圖像有多少,并報告損失值。通過在編譯時指定指標,TensorFlow會將此報告給我們。
最后,我們可以用訓練值擬合訓練數據:

通過將epochs設置為20,可執行整個訓練循環(進行猜測、評估和測量損失、優化、重復)20次,并要求它用訓練圖像擬合訓練標簽。
在訓練時,你會看到如下輸出:

注意準確度:僅經過三次循環,它在訓練集上的準確度就達到了94.5%!我使用Google Colab進行了訓練,可以看到,盡管處理了60000張圖像,但每次循環只用了兩秒鐘。最后,你會看到值1875/1875,你可能想知道它們是什么?訓練時你不必一次處理一張圖像,TensorFlow支持批處理以加快處理速度。Fashion MNIST默認每批次有32張圖像,因此它一次訓練一批圖像。這為你提供了1875批圖像來組成60000張圖像(即60000除以32可得1875)。
當你到達第20個輪次時,你會看到準確度現在超過97%:

因此,只需幾行代碼和不到一分鐘的訓練,你現在就擁有一個模型,可以以超過97%的準確度識別Fashion MNIST圖像。
還記得之前你保留了10000張圖像作為驗證數據集嗎?你現在可以將它們傳遞給模型來查看模型如何解析它們。請注意,它以前從未見過這些圖像,因此這是測試你的模型是否真正準確的好方法——它是否可以對以前從未見過的圖像進行高度準確的分類。你可以通過調用model.evaluate將圖像和標簽集傳遞給它來完成此操作:

由此可以看到,你的模型在之前從未見過的數據上的準確度為96%,這表明你有一個非常好的模型用以預測時尚數據。機器學習中稱為過擬合的概念是你在這里要避免的。當你的模型非常擅長理解其訓練數據,但卻不太擅長理解其他數據時,就會發生過擬合。這表明訓練準確度和驗證準確度之間存在巨大差異。把它想象成你在教一個聰明的人什么是鞋子,但只給他展示過高跟鞋。那么他會“認為”所有的鞋子都是高跟鞋,如果你隨后給它展示了一雙運動鞋,它便會過擬合到高跟鞋。你也想在神經網絡中避免這種做法,但可以看到我們在這里做得很好,在訓練和驗證準確度之間只有很小的差異!
這展示了如何創建一個簡單的模型來學習如何“查看”圖像的內容,但它依賴于非常簡單的單色圖像,其中數據是圖片中唯一的內容,并在圖像框內居中。識別真實世界圖像的模型要比這復雜得多,但可以使用卷積神經網絡來構建它們。深入了解它們的工作原理超出了本書的范圍,但請查看我在本章前面提到的其他書籍來獲得更深入的介紹。
不過,你可以做的一件事是遷移學習,無須深入研究模型架構類型,我們接下來將對此進行探討。