影象分類 | 深度學習PK傳統機器學習
影象分類,顧名思義,是一個輸入影象,輸出對該影象內容分類的描述的問題。它是計算機視覺的核心,實際應用廣泛。
影象分類的傳統方法是特徵描述及檢測,這類傳統方法可能對於一些簡單的影象分類是有效的,但由於實際情況非常複雜,傳統的分類方法不堪重負。現在,我們不再試圖用程式碼來描述每一個影象類別,決定轉而使用機器學習的方法處理影象分類問題。
目前,許多研究者使用CNN等深度學習模型進行影象分類;另外,經典的KNN和SVM演算法也取得不錯的結果。然而,我們似乎無法斷言,哪種方法對於影象分來問題效果最佳。
本專案中,我們做了一些有意思的事情:
- 將業內普遍用於影象分類的CNN和遷移學習演算法與KNN,SVM,BP神經網路進行比較。
- 獲取深度學習經驗。
- 探索谷歌機器學習框架TensorFlow。
下面是具體實施細節。
系統設計
在本專案中,用於實驗的5種演算法為KNN、SVM、BP神經網路、CNN以及遷移學習。我們採用如下三種方式進行實驗
- KNN、SVM、BP神經網路是我們在學校能夠學到的。功能強大而且易部署。所以第一步,我們主要使用sklearn實現KNN,SVM,和BP神經網路。
- 由於傳統的多層感知機模型在影象識別方面效果甚佳,但由於其節點間的全連線模式對於其延展性造成了阻礙,因此對於高解析度的影象,識別率不是很理想。所以這一步,我們用Google TensorFlow框架構建CNN。
- 對於已經預訓練過的深度神經網路Inception V3進行重訓練。Inception V3由TensorFlow提供,使用ImageNet自2012年以來的資料進行訓練。ImageNet是計算機視覺領域一個經典挑戰,參賽者試圖用模型將全部影象放至1000個分類中。為了要重新訓練已經預訓練好的模型,我們必須保證我們自己的資料集沒有被預訓練過。
實施
第一種方法:使用sklearn預處理資料以及實現KNN,SVM和BP神經網路。
- 步驟1,使用openCV包,定義2個預處理函式,分別是影象特徵向量(用來調整影象大小並將影象扁平化成一系列行畫素)和提取顏色直方圖(使用cv2.normalize從HSV色域中提取一個3D顏色直方圖並做平滑處理)。
- 步驟2,構造引數。由於我們試圖在整個資料集以及具有不同類別數目的子資料集上進行效能測試,所以我們把各個資料集看作為引數,以便進行實驗分析。另外,我們還設定了KNN中的鄰居數目作為引數。
- 步驟3,提取影象特徵並寫入陣列。我們使用cv2.imread函式讀取影象,根據規範化的影象名稱進行分類。然後執行第步驟1中提到的2個函式,分別得到2種影象特徵並寫入陣列。
- 步驟4,使用函式train_test_split分割資料集。85%的資料作為訓練集,15%的資料作為測試集。
- 步驟5,使用KNN,SVM和BP神經網路方法去評估資料。對於KNN,使用KNeighborsClassifier,對於SVM,使用SVC,對於BP神經網路,使用MLPClassifier。
第二種方法:基於TensorFlow構建CNN。使用TensorFlow得到計算圖並在C++中實現,比Python更高效。
TensorFlow中使用到的的幾個概念:佔位符,變數,數學公式,成本計量,最優方法,CNN體系結構。
- 步驟1,第一層放置影象。
- 步驟2,構建3層卷積層(3 Convolutional layers),2X2的max-pooling和ReLU。輸入是4維張量:【影象編號,Y座標,X座標,通道】。輸出是另一個經處理得到的4維張量:【影象編號(不變),Y座標,X座標,通道】。
- 步驟3,構建2層全連線層(2 Fully-Connected Layers)。輸入是2維張量:【影象編號,輸入編號】。輸出是2維張量【影象編號,輸出編號】。使用
- 步驟4,使用合併層(Flatten Layer)連結卷積層和全連線層。
- 步驟5,使用softmax layer標準化輸出。
- 步驟6,優化訓練結果。我們使用交叉熵(cross entropy)作為成本計量函式,取其均值。最優方法使用tf.train.AdamOptimizer()。
第三種方法:Retrain Inception V3。使用Retrain Inception V3 ,並利用遷移學習減少工作量。
我們得到pre-trained模型,移除原有頂層,訓練新模型。然後分析在磁碟上的所有影象並計算它們的bottleneck值。指令碼會執行4000次。每次執行都會從訓練集中隨機選取10個影象,找到它們的bottleneck值並注入最後一層得到預測結果。然後在反向傳播過程中,根據預測結果和實際標籤的比較結果去更新每層的權重。
實驗
實驗中使用到的資料集是Oxford-IIIT Pet 資料集。其中有犬類25類,貓類12類。每類有200個影象。我們使用到該資料集中的10個類別的貓的資料,分別是[‘Sphynx’,’Siamese’,’Ragdoll’,’Persian’,’Maine-Coon’,’British-shorthair’,’Bombay’,’Birman’,’Bengal’,’Abyssinian’]。即,共有2000個影象,由於影象大小不一,我們調整大小統一為固定尺寸64X64或128X128。
本專案中,我們主要使用OpenCV預處理影象。一般通過變形、剪裁或亮化隨機處理訓練集。github
賦值
第一種方法:KNN,SVM,和BP神經網路
第一部分:使用sklearn預處理資料以及實現KNN,SVM和BP神經網路。在image_to_feature_vector函式中,我們設定尺寸128X128。經試驗表明,影象尺寸越大,結果越精確,執行負擔越大。最終我們決定使用128X128的尺寸。在extract_color_histogram函式中,設定每個通道的容器數量為32,32,32。對於資料集,使用3種資料集。第一個是具有400個影象,2個標籤的子資料集。第二個是具有1000個影象,5個標籤的子資料集。第三個是整個資料集,1997個影象,10個標籤。
- 在KNeighborsClassifier中,我們只改變鄰居數量且儲存結果作為每個資料集的最佳K值,其他引數預設。
- 在MLPClassifier中,我們設定每層有50個神經元。
- 在SVC中,最大迭代次數是1000,類權重是“balanced”。
依據資料集,2個標籤到10個標籤不同,執行時間大約為3到5分鐘不等。
第二種方法:基於TensorFlow構建CNN
由於在整個資料集中執行時間過長,我們在每個迭代中分批次處理。每批次一般有32個或64個影象。資料集分為1600個影象的訓練集,400個影象的驗證集,300個影象的測試集。
本方法中有大量的引數可調整。學習速率設定為1x10^-4;影象大小設定為64x64和128x128;然後是層和形狀,然而有太多的引數可調整,我們依據經驗並進行實驗去得到最佳結果。
為了得到最佳的layers,我們進行實驗。首先,引數如下:
# Convolutional Layer 1. filter_size1 = 5 num_filters1 = 64
# Convolutional Layer 2. filter_size2 = 5 num_filters2 = 64
# Convolutional Layer 3. filter_size3 = 5 num_filters3 = 128
# Fully-connected layer 1. fc1_size = 256
# Fully-connected layer 2. fc1_size = 256
我們使用了3個卷積層和2個全連線層,然而悲劇的是過度擬合。經過研究發現,對於該構造,我們的資料集過小,網路過於複雜。
最終,我們使用如下引數:
# Convolutional Layer 1. filter_size1 = 5 num_filters1 = 64
# Convolutional Layer 2. filter_size2 = 3 num_filters2 = 64
# Fully-connected layer 1. fc1_size = 128
# Number of neurons in fully-connected layer.
# Fully-connected layer 2. fc2_size = 128
# Number of neurons in fully-connected layer.
# Number of color channels for the images: 1 channel for gray-scale. num_channels = 3
我們只使用了2個卷積層和2個全連線層。依然不盡人意,經過4000次迭代,結果仍舊過擬合,不過好在測試結果10%優於前者。最終,經過5000次迭代,我們得到43%的精確度,執行時間是半小時以上。
PS:我們使用另一個數據集CIFAR-10進行了實驗。
該資料集包含60000個32x32的彩色影象,分為10個類別,每個類別6000個影象。訓練集50000個影象,測試集10000個影象。使用同樣的網路結構,經過10個小時的訓練,最終得到78%的精確度。
第三種方法:Retrain Inception V3
與以上方法相似,訓練次數為4000,依據結果進行調整。學習速率依據每批次的影象數量進行調整。80%的資料用來訓練,10%用來驗證,10%用來測試。
實驗結果
第一種方法:KNN,SVM,和BP神經網路
在KNN中,Knn_raw_pixel和Knn_histo的精確度的值比較接近。在5類標籤情況下,前者比後者要低,整體來說,原始畫素表現更好。
在MLP分類器中,原始畫素精確地要低於柱狀圖精確度。對於整個資料集(10個標籤)來講,原始畫素精確度竟然低於隨機猜想的精確度。
上面兩種sklearn方法都沒有得到非常好的效能。對於整個資料集,只有24%的精確度。實驗結果證明,sklearn方法不能夠有效進行影象分類。為了有效進行影象分類並且提高精確度,有必要使用深度學習的方法。
第二種方法:基於TensorFlow構建CNN
由於過擬合,我們無法得到好的實驗結果。執行時間一般為半個小時,由於過擬合,我們認為,執行時間無法預估。通過與方法1比較,可以得出:即使CNN過擬合訓練集,實驗結果依舊優於方法1。
第三種方法:Retrain Inception V3
整個訓練過程不超過10分鐘,且我們得到了非常好的結果。事實證明,深度學習和遷移學習十分強大。
Demo:
結論
基於以上實驗比較,我們得出:
- KNN,SVM,和BP神經網路在影象分類中不夠有效。
- 即使在CNN中過擬合,CNN的實驗結果依舊比傳統分類演算法好。
- 遷移學習在影象分類問題上非常有效。執行時間短且結果精準,能夠良好地解決過擬合和資料集過小的問題。
通過本次專案,我們得到了許多寶貴的經驗,如下所示:
- 調整影象使其更小。
- 對於訓練的每次迭代,隨機選取小批次資料。
- 隨機選取小批次資料作為驗證集進行驗證,並且在訓練期間反饋驗證評分。
- 利用Image Augmentation把輸入影象集轉變為可調整的更大的新資料集。
- 影象資料集要大於200x10。
- 複雜網路結構需要更多的訓練集。
- 小心過擬合。
參考文獻
1. CS231n Convolutional Neural Networks for Visual Recognition
2. TensorFlow Convolutional Neural Networks
3. How to Retrain Inception’s Final Layer for New Categories
4. k-NN classifier for image classification
5. Image Augmentation for Deep Learning With Keras
6. Convolutional Neural Network TensorFlow TutorialNote: The first method is performed by Ji Tong
https://github.com/JI-tong
Originally published at gist.github.com.