深度卷積網路通俗介紹(PyTorch) | 翻譯徵文 | 雷鋒字幕組
本文為雷鋒字幕組「觸摸世界前沿科技 | 翻譯徵文 」活動收錄稿件
Deep Convolutional Neural Networks 入門指南
這篇文章是 medium 上《Deep Learning 入門指南》系列中的一部分。我打算逐步去完善這個系列的內容。目標受眾是有基本編程能力的新手,當然最好是會 Python。
前提
這篇文章假設您已對 Deep Neural Networks(也稱為前饋神經網路)有基本的了解。上一篇文章《Deep Neural Networks 入門指南》中已經詳細介紹了此內容。強烈建議您閱讀上一篇文章,以更好地理解本文的內容。
序幕
隨著深度學習的到來,作為一個領域,「電腦視覺」已發展到了新的高度。幫助機器以更直觀的方式理解影像細節的能力(而非從孤立的像素值出發或者藉助於少量手工設計的特徵),帶來了該領域的研究範式的轉變。如今,我們的日常生活、商業和企業、以及工業技術產品中都使用了各種尖端的電腦視覺應用程式。我們在日常生活中已經從電腦視覺領域中深度學習最新進展中獲得了巨大的好處。您可能並沒有意識到在某些產品中電腦視覺領域的應用程式的細節。有幾個值得注意的例子:特斯拉的自動駕駛模式(auto-pilot),iPhone 的面部識別解鎖(face-id)、Animoji 和高級相機功能,您智慧手機相機的背景模糊效果(bokeh effect 或者 portrait mode),Snapchat 和 Facebook Messenger 的濾鏡等等。
電腦視覺領域的基本想法始於一個非常簡單的問題,即確定影像中存在什麼東西。事實證明,儘管,我們人類處理這一點非常容易,但該問題是一項極為艱巨的任務。
我們可以使用像素值組成的三維矩陣這樣的數字形式來表示影像(長 ×寬,並包含 R、G、B 三個通道)。從這個三維矩陣中提取資訊並不是那麼簡單。
讓我們簡單回顧下歷史
傳統的電腦視覺解決方案
在早些時候,當使用機器學習的時候,電腦視覺問題取得了相當大的成功。 這些問題主要通過使用手工設計的特徵和傳統的機器學習演算法(例如 SVM,即支援向量機)解決。「手工設計的特徵」是使用其他各種演算法得出的影像屬性。 這類特徵的一個常見示例是邊和角的存在情況。基礎的邊緣檢測器演算法是通過尋找影像強度突然變化的區域(即與附近像素值存在巨大差異)來工作。一些演算法的組合可以得到幾個這樣的基本屬性和一些更複雜的特徵,然後結果被送到一個有監督的機器學習演算法(a supervised ML algorithm)中。
這種方法雖然有效,結果卻不是很令人鼓舞。首先,手工設計的特徵所需的工作量是壓倒性的;此外,它需要大量的領域知識,並且是非常特定於用例的。例如,為檢測 X 射線影像中的骨折所創建的手工設計特徵,可能無法用於識別寫在快遞包裹上的名字。
圖 1——使用機器學習的傳統電腦視覺解決方案示意圖
為了減少手工設計特徵的工作量,如果我們考慮以表格形式表示影像,即將每個像素值轉換為一個特徵,結果將非常令人失望。網路/機器學習演算法幾乎沒有捕獲到有關影像的任何資訊,因此導致性能不佳。
圖 2——將影像為機器學習解決方案展平為表格數據示意圖
從以上的問題空間( problem-space)中,我們可以推斷出一個重要的細節——影像特徵提取是不可避免的,但很難解決。
以下是一些示例,可以幫助您了解為什麼電腦視覺任務難以解決。為了簡單起見,讓我們假設從影像中預測貓的問題是一個二值問題。
請參考下面展示的兩個影像。根據像素值,這兩張影像在數字格式上將具有完全不同的表示形式。由於像素值僅表示每個像素應輸出的顏色,因此基本表示(underlying representation)的語義含義將不會有任何直觀的意義。
Picture Credits — Alexander London //unsplash.com/photos/mJaD10XeD7w
同樣的,在圖片中,貓也可能和背景差異很小。看看下面的圖片。傳統的特徵大多會產生沒有意義的結果。因此,手工設計的特徵在這裡將不會太有效。
Picture Credits — MIKHAIL VASILYEV, KiVEN Zhao,Hannah Troupe @ Unsplash.com
此外,人們可能會以完全不同的方式為一隻貓咪拍照,這使得識別的過程更加困難。貓這些不同的姿勢也只是其中的一些。
Picture Credits —Marko Bla ž evi ć, Timo Volz, Willian Justen de Vasconcellos @ Unsplash.com
當將這些問題外推到代表更一般的用例時,比如在影像中檢測多個對象,就會成倍地增加複雜性。
顯然,像素的表格表示,或者開發檢測特定特徵的手工設計的特徵,亦或者將兩者結合起來,並不是解決電腦視覺問題的最佳方法。
那麼,解決電腦視覺問題的更好方法是什麼呢?
從歷史上看,我們發現手工設計的功能雖然費勁,但確實可以在一定程度上解決問題。 但是此過程將非常昂貴,並且需要大量領域知識來解決特定問題。
如果我們可以自動進行特徵提取怎麼辦?
幸運的是,這是有可能的,它最終使我們討論的話題「卷積神經網路」(CNN)引起了人們的關注。CNN 通過使用通用、可擴展且可持續的方式提供了一種解決電腦視覺問題的高級方法,該方法可以在沒有域先驗知識的情況下跨域應用。有了足夠的訓練和數據,網路將學會自我提取強大的特徵,因此不再需要手工設計特徵了。
深度卷積神經網路的想法最初由 Hinton,Krizevsky,Sutskever 發布的,並在當時用於 ImageNet 分類挑戰,實現了最先進的性能。然後,這項研究徹底改變了電腦視覺領域。您可以從原始論文中了解更多內容。
深入了解深度卷積神經網路
CNN 的通用架構如下所示。目前細節可能有點抽象,但是稍等片刻,我們很快就會分別了解每個組件的細節。該架構中的特徵提取組件將是「卷積 + 池化」的組合。您可能已經注意到該組件是重複使用的,並且在大多數現代架構中,您將看到該組件在一層中重複多次。這些特徵提取器,首先提取低級特徵(例如邊緣,線條),然後是中級特徵(例如形狀)或者是多個低級特徵的組合,並且最後會獲得高級特徵(例如在檢測貓的例子中,可能會是耳朵、鼻子、眼睛等等)。最後,這些層(的特徵)被展平並且連接到輸出層。輸出層使用了激活操作(類似於前饋神經網路)。
圖 3——卷積神經網路示意圖
首先,讓我們從基礎開始
我們先花一點時間來了解人腦通常如何通過視覺識別物體。我們的大腦從視網膜接收有關從外部世界感知到的視覺的訊號,這一步驟非常簡單。首先,大腦對邊緣進行檢測,然後通過檢測到的邊緣來進一步檢測曲線、以及更複雜的圖案如形狀。從邊緣到線條、曲線、複雜形狀甚至更複雜形狀的神經活動的層次編排,最終有助於識別特定對象。當然,這只是人腦對視覺進行處理以及同時進行更複雜的操作的一個高度簡化的過程,
類似地,在卷積神經網路中,我們在淺層進行特徵學習時學到了非常基本的特徵。 「深度卷積神經網路」中的「深度」是指網路中的層數。常規卷積神經網路中通常有 5–10 個甚至更多的特徵學習層。前沿應用中使用的現代體系結構的網路深度超過 50-100 層。 卷積神經網路的工作與人腦在通過視覺皮層識別視覺組件方面的簡化後的工作非常相似。
讓我們來了解一下 CNN 組件的具體細節
我們首先要了解什麼是卷積。
「卷積」是訊號處理領域中的一種操作; 在深度學習領域,它基本上是通過在影像(一個矩陣)上沿著寬和高滑動內核或過濾器(一個較小的矩陣),對原圖中滑動到的像素和內核執行矩陣乘法。 下面的動畫演示了將[3×3]過濾器/內核在[5×5]影像上進行卷積的給 u 歐城。 卷積運算的結果是尺寸為[3×3]的較小影像。
Source — //giphy.com/gifs/blog-daniel-keypoints-i4NjAwytgIRDW
本質上,這種矩陣乘法是特徵提取的基礎。 在內核的值正確時,我們可以從影像中提取顯著的特徵。 下面說明在實際影像上執行此操作的示例。 我們可以看到,使用單位矩陣作為內核時,原始影像保持不變。 但是,當我們使用不同的內核時,可以看到與使用其他邊緣檢測器/平滑/銳化/等其他影像處理技術類似的效果。
來源—維基百科
這就完成了第一步,同一組件中的下一部分是池化。 池化層有助於減小影像表示的空間大小,從而減少網路中參數的數量和計算量。 通過對定義的內核尺寸使用求最大值來執行此操作。 下圖是一個簡單的池化操作示例。 對大小為[20 x 20]的卷積(另一個矩陣)輸出,選定內核尺寸為[10 x 10]、執行池化操作。 最終輸出結果是[2 x 2]矩陣。
我們使用卷積層和池化層(通常是最大池化)的組合,創建了 CNN 的基本構件。執行卷積和池化操作可以減少原始輸入的大小,具體減小的程度取決於卷積核和池化大小。當我們對輸入的影像使用 1 個內核進行卷積時,就會得到一個特徵圖。在 CNN 中,通常在一個卷積單元中使用多個卷積核。下圖突出了卷積過程中從 n 個卷積核中提取的特徵圖的過程。
圖 4—CNN 架構的說明
多次重複這個過程,我們可以得到更深的卷積神經網路。每一層都從上一層提取特徵。這些層的分層組織有助於逐步學習特徵,如從小的邊緣到由低級特徵創建的更複雜的特徵,再到高級特徵,這些特徵將捕獲足夠的資訊,從而使網路能夠準確地預測。
最後一個卷積層連接到一個全連接層,該層用於應用相關的激活函數來預測結果;對於二元結果,我們使用 sigmoid 和或 softmax 激活函數來預測非二元結果。
所討論的整個架構可以簡化為下圖——
圖 5—簡化的 CNN 架構的說明
到目前為止,我們忽略了複雜的 CNN 架構中的幾個重要方面。但這是為了讓事情簡單化,來幫助你了解 CNN 中基本構件的基本概念。
另外幾個重要的關鍵概念是:
-
步長–簡單來說, 步長可以定義為過濾器的移動量。當我們討論過濾器在輸入影像上滑動時,我們假設運動只是在預定方向上移動 1 個單位。不過,我們可以來控制滑動運動的步長(不過常見的是用 1)。根據用例的需要,我們可以選擇一個比較合適的步長。較大的步長往往有助於減少計算量,對特徵的泛化學習等。
-
填充–我們還看到,與輸入影像的大小相比,應用卷積降低了特徵圖的大小。零填充是應用大於 1×1 的濾波器後控制尺寸收縮的通用方法,避免邊界的資訊損失。
1.填充時沒有任何步長(輸入藍色,輸出綠色)
Source and Credits –//github.com/vdumoulin/conv_arithmetic
2.零填充但是有步長(輸入藍色,輸出綠色)
Source and Credits — //github.com/vdumoulin/conv_arithmetic
其他幾個我們到現在還沒有接觸到的重要內容是 Batch-Normalization 層和 Dropout 層。兩者都是 CNN 中相關的重要內容。如進,我們大多會把卷積單元定義為(卷積 + 最大池化 + 批歸一化)的組合,而不僅僅只有前兩者。批歸一化是一種技術,通過對每個批的輸入進行標準化,幫助輕鬆訓練非常深的神經網路。標準化的輸入有助於穩定學習過程,從而大幅減少訓練深度網路所需的訓練紀元數。
Dropout 則是一種正則化技術,對減少過擬合和泛化幫助最大。
連接點
現在我們已經對卷積神經網路內的基本構件有了大致的理解,我想你關於細枝末節可能還有一些問題。貫穿你的大腦的最重要的問題可能是 “我們如何決定使用什麼過濾器”,”使用多少過濾器?”等等。
我們來逐一解決這些問題。
我們如何決定使用什麼過濾器?
這個問題的答案很簡單。我們設置的過濾器的隨機值是從正態分布或其他分布中抽取的。這個方法可能有點混亂,難以解釋,但效果很好。在訓練網路的過程中,會逐漸學到有助於提取準確預測標籤所需的最多資訊的最優過濾器。這就是神奇的地方,在技術上我們消除了手工特徵的過程。在給定足夠的訓練輪數和數據的情況下,網路負責製作合適的過濾器,來提取最佳特徵。
我們在每個卷積單元中使用多少個濾波器?
不存在一個標準的數量。過濾器的大小和數量是可以調整的超參數。一般的經驗法則是使用尺寸為奇數的過濾器,比如 3×3、5×5 或 7×7。另外,與大過濾器相比,大多首選小過濾器,但這也有一個權衡,可以通過經驗驗證來解決。
網路是如何學習的?
學習過程類似於我們在之前的部落格中研究的前饋神經網路。我們利用網路的反向傳播技術來更新過濾器中的權重,從而學習影像中的底層特徵。學習過程幫助網路發現最優的過濾器,它能最好地從輸入影像中提取最多的資訊。
上面的圖片是簡單的 2D,大部分圖片都是 3D 的,對於 3D 的圖片,網路是怎麼操作的呢?
為了簡潔,插圖使用了二維圖片。我們使用的大多數影像是三維的(RGB)顏色通道。在這種情況下,除了卷積核的尺寸,一切都保持不變。卷積核將會是一個三維內核,其中第三維為通道數。比如說,輸入影像中包含 3 個顏色通道(紅、綠、藍),則卷積核尺寸為 5x5x3。
卷積神經網路和深度卷積神經網路的區別是什麼?
它們都是一樣的,這裡的深度是指網路架構的層數。現代大多數 CNN 架構的深度為 30-100 層。
我們是否需要一個 GPU 來訓練 CNN?
雖然沒有規定,但是我們建議使用 GPU。利用 GPU 幾乎可以使訓練神經網路的速度提高 50 倍。另外,Kaggle 和 Google Colab 平台還免費提供了一個基於 GPU 的環境(每周有使用上限。
好了,基本內容已經結束;我們看一個實際的例子
讓我們舉一個實際的例子,演示如何使用 PyTorch 構建 ConvNet。
我們將根據上面的內容回顧我們接觸了的所有主題。
首先,讓我們導入所有必要的包。我們將導入必要的實用工具、神經網路核心模組以及少量來自於 Scikit-learn 的額外模組,以評估網路性能。
接下來,讓我們將數據集載入到記憶體中。對於這個例子,我使用 Kaggle 上的 MNIST CSV 數據集。您可以在這裡找到完整的數據集。
圖 6——上面程式碼片段的輸出
現在,我們已經載入了數據集,讓我們將其轉換為 PyTorch 適用的抽象。
#Covert Train Images from pandas/numpy to tensor and normalize the values train_images_tensor = torch.tensor(train_images)/255.0 train_images_tensor = train_images_tensor.view(-1,1,28,28) train_labels_tensor = torch.tensor(train_labels) #Create a train TensorDataset train_tensor = TensorDataset(train_images_tensor, train_labels_tensor) #Covert Validation Images from pandas/numpy to tensor and normalize the values val_images_tensor = torch.tensor(val_images)/255.0 val_images_tensor = val_images_tensor.view(-1,1,28,28) val_labels_tensor = torch.tensor(val_labels) #Create a Validation TensorDataset val_tensor = TensorDataset(val_images_tensor, val_labels_tensor) print("Train Labels Shape:",train_labels_tensor.shape) print("Train Images Shape:",train_images_tensor.shape) print("Validation Labels Shape:",val_labels_tensor.shape) print("Validation Images Shape:",val_images_tensor.shape) #Load Train and Validation TensorDatasets into the data generator for Training iterations train_loader = DataLoader(train_tensor, batch_size=64, num_workers=2, shuffle=True) val_loader = DataLoader(val_tensor, batch_size=64, num_workers=2, shuffle=True)
圖 7——以上程式碼片段的輸出
現在,我們將定義 CNN 的結構,並定義其他函數。這些函數將有助於我們評估和生成預測。
圖 8——以上程式碼片段的輸出
最後,讓我們訓練模型。
圖 9——上面程式碼片段的輸出
我們現在有了一個訓練了 5 個周期的簡單模型。對於大多數情況,您需要超過 30 個周期才能具有出色的性能。現在,讓我們在驗證數據集上計算準確率並繪製混淆矩陣。
#Make Predictions on Validation Dataset actual, predicted = make_predictions(val_loader) actual,predicted = np.array(actual).reshape(-1,1),np.array(predicted).reshape(-1,1) print("Validation Accuracy-",round(accuracy_score(actual,predicted),4)*100) print("\n Confusion Matrix\n",confusion_matrix(actual,predicted))
圖 10——上面程式碼片段的輸出
至此,對這個沉重主題的簡短介紹就結束了。希望你喜歡。另外,我建議使用這個神奇的工具來理解每層如何為不同的輸入影像生成濾波器和特徵圖。
Tool – Visualize CNN in action
您可以從我的 Git 倉庫中訪問和下載整個 notebook 文件——PyTorchExamples
總結思考
這篇文章的目的是用一種非常簡單的語言讓初學者輕鬆了解這一主題。保持數學的抽象化,並將重點從純粹的函數方法轉移到在現代企業項目中利用深度卷積神經網路上。
在下一篇文章中,我將介紹「遞歸神經網路入門指南」,示例也將使用 PyTorch 展示。
原文鏈接://www.yanxishe.com/TextTranslation/2579
選題由雷鋒字幕組提供本文為雷鋒字幕組「觸摸世界前沿科技 | 翻譯徵文 」活動收錄稿件