10分鐘搭建你的第一個影像識別模型 | 附完整程式碼
- 2019 年 10 月 11 日
- 筆記

(圖片由AI科技大本營付費下載自視覺中國)
作者 | Pulkit Sharma
譯者 | 王威力
來源 | 數據派THU(ID:DatapiTHU)
【導讀】本文介紹了影像識別的深度學習模型的建立過程,通過陳述實際比賽的問題、介紹模型框架和展示解決方案程式碼,為初學者提供了解決影像識別問題的基礎框架。
序言
「幾分鐘就可以建立一個深度學習模型?訓練就要花幾個小時好嗎!我甚至沒有一台足夠好的機器。」我聽過無數次有抱負的數據科學家這樣說,他們害怕在自己的機器上構建深度學習模型。
其實,你不必在Google或其他大型科技公司工作,就可以訓練深度學習數據集。你完全可以用幾分鐘的時間從頭搭建起你自己的神經網路,而不需要租Google的伺服器。Fast.ai的學生花了18分鐘設計出了用於ImageNet數據集的一個模型,接下來我將在本文中展示類似的方法。
深度學習是一個廣泛的領域,所以我們會縮小我們的關注點在影像分類問題上。而且,我們將使用一個非常簡單的深度學習架構來達到一個很好的準確率。
你可以將本文中的Python程式碼作為構建影像分類模型的基礎,一旦你對這些概念有了很好的理解,可以繼續編程,參加比賽、登上排行榜。
如果你剛開始深入學習,並且對電腦視覺領域著迷(誰不是呢?!)一定要看一看Computer Vision using Deep Learning的課程,它對這個酷炫的領域進行了全面的介紹,將為你未來進入這個巨大的就業市場奠定基礎。
課程鏈接: https://trainings.analyticsvidhya.com/courses/course-v1:AnalyticsVidhya+CVDL101+CVDL101_T1/about?utm_source=imageclassarticle&utm_ medium=blog
目錄
01 什麼是影像分類以及它的應用案例
02 設置影像數據結構
03 分解模型建立過程
04 設置問題定義並認識數據
05 建立影像分類模型的步驟
06 其他挑戰
01 什麼是影像分類以及它的應用案例
觀察以下圖片:

你應該可以馬上就認出它——是一倆豪華車。退一步來分析一下你是如何得到這個結論的——你被展示了一張圖片,然後你將它劃分為「車」這個類別(在這個例子中)。簡單來說,這個過程就是影像分類。
很多時候,影像會有許多個類別。手動檢查並分類影像是一個非常繁瑣的過程。尤其當問題變為對10000張甚至1000000張圖片的時候,這個任務幾乎不可能完成。所以如果我們可以將這個過程自動化的實現並快速的標記影像類別,這該有多大的用處啊。
自動駕駛汽車是一個影像分類在現實世界應用的很好的例子。為了實現自動駕駛,我們可以建立一個影像分類模型來識別道路上的各種物體,如車輛、人、移動物體等。我們將在接下來的部分中看到更多的應用,甚至在我們的身邊就有許多的應用。
既然我們已經掌握了主題,那麼讓我們來深入研究一下如何構建影像分類模型,它的先決條件是什麼,以及如何在Python中實現它。
02 設置影像數據結構
我們的數據集需要特殊的結構來解決影像分類問題。我們將在幾個部分中看到這一點,但在往下走之前,請記住這些建議。
你應該建立兩個文件夾,一個放訓練集,另一個放測試集。訓練集的文件夾里放一個csv文件和一個影像文件夾:
- csv文件存儲所有訓練圖片的圖片名和它們對應的真實標籤
- 影像文件夾存儲所有的訓練圖片
測試集文件夾中的csv文件和訓練集文件夾中的csv文件不同,測試集文件夾中的csv文件只包含測試影像的圖片名,不包括它們的真實標籤。因為我們要通過訓練訓練集中的圖片來對測試集中的圖片進行預測。
如果你的數據集不是這樣的格式,你需要進行轉換,否則的話預測結果可能有錯誤。

03 分解模型搭建的過程
在我們研究Python程式碼之前,讓我們先理解影像分類模型通常是如何設計的。可以將過程分為4個部分。每個步驟需要一定時間來執行:
- 第1步:載入和預處理數據——30%時間
- 第2步:定義模型架構——10%時間
- 第3步:訓練模型——50%時間
- 第4步:評價模型表現——10%時間
接下來我會更詳細地解釋一下上面的每一個步驟。這一部分非常重要,因為並非所有模型都是在第一步構建的。你需要在每次迭代之後返回,對步驟進行微調,然後再次運行它。對基礎概念有一個紮實的理解,對於加速整個過程將有很大的幫助。
1. 載入和預處理數據,所需時間:大約2-3分鐘
就深度學習模型而言,數據非常關鍵。如果訓練集中有大量的影像,你的影像分類模型也會有更大的可能實現更好的分類效果。此外,根據所用的框架不同,數據的維度不同,效果也不一樣。
因此,對於關鍵的數據預處理這一步,我推薦大家瀏覽下面這篇文章,來對影像數據的預處理有一個更好的理解:
Basics of Image Processing in Python https://www.analyticsvidhya.com/blog/2014/12/image-processing-python-basics/
但我們還沒完全到數據預處理這一步,為了了解我們的數據在新的之前沒見過的數據集中的表現(在預測測試集之前),我們需要先從訓練集中劃分出一部分為驗證集。
簡而言之,我們在訓練集上訓練模型然後在驗證集上進行驗證。如果我們對在驗證集上的結果滿意,就可以用來預測測試集的數據。
2. 建立模型框架,所需時間:大約1分鐘定義這個框架
這是深度學習模型建立過程中的另一個重要的步驟。在這個過程中,需要思考這樣幾個問題:
- 需要多少個卷積層?
- 每一層的激活函數是什麼?
- 每一層有多少隱藏單元?
還有其他一些問題。但這些基本上是模型的超參數,它們對預測結果起著重要作用。
如何確定這些超參的值?好問題!一個方法是根據現有的研究選擇這些值。另一個想法是不斷嘗試這些值,直到找到最好的,但這可能是一個非常耗時的過程。
3. 訓練模型,所需時間:大概5分鐘,來進行模型的結構的學習
對模型訓練,我們需要:
- 訓練影像和它們的真實標籤。
- 驗證集影像和其真實標籤。(我們只用驗證集的標籤進行模型評估,不用於訓練)
我們還需要定義迭代次數(epoch)。開始階段,我們訓練10次(你可以再更改)。
4. 評估模型表現,所需時間:1分鐘
最後,我們載入測試數據(影像)並完成預處理步驟。然後我們使用訓練模型預測這些影像的類別。

04 設置問題定義並認識數據
我們將嘗試一個非常酷的挑戰來理解影像分類。我們需要建立一個模型,可以對給定的影像進行分類(襯衫、褲子、鞋子、襪子等)。這實際上是許多電子商務零售商面臨的一個問題,這使得它成為一個更有趣的電腦視覺問題。
這個挑戰被稱為「識別服裝」,是我們在數據黑客平台上遇到的實踐問題之一。你必須註冊並從上面的鏈接下載數據集。
「識別服裝」比賽鏈接: https://datahack.analyticsvidhya.com/contest/practice-problem-identify-the-apparels/ 數據黑客平台: https://datahack.analyticsvidhya.com/

一共有70000影像(28×28維),其中60000來自訓練集,10000來自測試集。訓練影像已經預先被打上了衣服類別的標籤,一共10個類別。測試集沒有標籤。這個比賽是對測試集的影像進行識別。
我們將在Google Colab搭建模型,因為它提供免費的GPU。
Google Colab: https://colab.research.google.com/
05 建立影像分類模型的步驟
接下來是時候展示你的Python技巧啦,最終我們到了執行階段!
主要步驟如下:
- 第1步:設置Google Colab
- 第2步:導入庫
- 第3步:導入數據預處理數據(3分鐘)
- 第4步:設置驗證集
- 第5步:定義模型結構(1分鐘)
- 第6步:訓練模型(5分鐘)
- 第7步:預測(1分鐘)
下面詳細介紹以上步驟。
1. 設置Google Colab
因為我們將從Google Drive link導入數據,我們需要在Google Colab notebook上增加幾條程式碼。新建Python3 notebook,寫下下面的程式碼:
!pip install PyDrive
這一步是安裝PyDrive。下面導入需要的庫:
import os from pydrive.auth import GoogleAuth from pydrive.drive import GoogleDrive from google.colab import auth from oauth2client.client import GoogleCredentials
下面創建drive變數訪問Google Drive:
auth.authenticate_user() gauth = GoogleAuth() gauth.credentials = GoogleCredentials.get_application_default() drive = GoogleDrive(gauth)
需要用Google Drive上傳文件的ID來下載數據集:
download = drive.CreateFile({'id': '1BZOv422XJvxFUnGh-0xVeSvgFgqVY45q'})
把id的部分替換為你的文件夾的ID。接下來將下載文件夾並解壓。
download.GetContentFile('train_LbELtWX.zip') !unzip train_LbELtWX.zip
每次啟動notebook都需要運行以上程式碼。
2. 導入模型所需的庫
import keras from keras.models import Sequential from keras.layers import Dense, Dropout, Flatten from keras.layers import Conv2D, MaxPooling2D from keras.utils import to_categorical from keras.preprocessing import image import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.model_selection import train_test_split from keras.utils import to_categorical from tqdm import tqdm
3. 接下來是數據導入和數據預處理
train = pd.read_csv('train.csv')
接下來,我們將讀入訓練集,存儲為list,最終轉換為numpy array。
# We have grayscale images, so while loading the images we will keep grayscale=True, if you have RGB images, you should set grayscale as False train_image = [] for i in tqdm(range(train.shape[0])): img = image.load_img('train/'+train['id'][i].astype('str')+'.png', target_size=(28,28,1), grayscale=True) img = image.img_to_array(img) img = img/255 train_image.append(img) X = np.array(train_image)
這是一個多分類問題(10個類別),需要對標籤變數進行one-hot編碼。
y=train['label'].values y = to_categorical(y)
4. 從訓練集中劃分驗證集
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42, test_size=0.2)
5. 定義模型結構
我們將建立一個簡單的結構,有2個卷積層,一個隱藏層一個輸出層。
model = Sequential() model.add(Conv2D(32, kernel_size=(3, 3),activation='relu',input_shape=(28,28,1))) model.add(Conv2D(64, (3, 3), activation='relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.25)) model.add(Flatten()) model.add(Dense(128, activation='relu')) model.add(Dropout(0.5)) model.add(Dense(10, activation='softmax'))
接下來編譯模型。
model.compile(loss='categorical_crossentropy',optimizer='Adam',metrics=['accuracy'])
6. 訓練模型
在這一步,我們將訓練訓練集的數據,在驗證集上進行驗證。
model.fit(X_train, y_train, epochs=10, validation_data=(X_test, y_test))
7. 預測
我們將首先遵循處理訓練數據集時執行的步驟。載入測試影像並預測分類結果,用model.predict_classes()函數預測它們的類。
download = drive.CreateFile({'id': '1KuyWGFEpj7Fr2DgBsW8qsWvjqEzfoJBY'}) download.GetContentFile('test_ScVgIM0.zip') !unzip test_ScVgIM0.zip
首先導入測試集:
test = pd.read_csv('test.csv')
接下來,讀於數據並存儲測試集:
test_image = [] for i in tqdm(range(test.shape[0])): img = image.load_img('test/'+test['id'][i].astype('str')+'.png', target_size=(28,28,1), grayscale=True) img = image.img_to_array(img) img = img/255 test_image.append(img) test = np.array(test_image)
# making predictions prediction = model.predict_classes(test)
還需要新建一個提交文件夾,用來上傳DataHack平台。
download = drive.CreateFile({'id': '1z4QXy7WravpSj-S4Cs9Fk8ZNaX-qh5HF'}) download.GetContentFile('sample_submission_I5njJSF.csv')
# creating submission file sample = pd.read_csv('sample_submission_I5njJSF.csv') sample['label'] = prediction sample.to_csv('sample_cnn.csv', header=True, index=False)
下載sample_cnn.csv文件並上傳到比賽的頁面,生成你的排名。這提供了一個幫助你開始解決影像分類問題的基礎方案。
你可以嘗試調整超參數和正則化來提高模型效果。也可以通過閱讀下面這篇文章來理解調參的細節。
A Comprehensive Tutorial to learn Convolutional Neural Networks from Scratch https://www.analyticsvidhya.com/blog/2018/12/guide-convolutional-neural-network-cnn/
06 開啟一個新的挑戰

讓我們嘗試在其他的數據集進行測試。這部分,我們將解決Identify the Digits上的這個問題。
Identify the Digits比賽鏈接: https://datahack.analyticsvidhya.com/contest/practice-problem-identify-the-digits/
在你往下看之前,請嘗試自己來解決這個挑戰。你已經收穫了解決問題的工具,只需要使用它們。當你遇到困難的時候可以再回來檢查你的過程和結果。
在這個挑戰中,我們需要識別給定影像中的數字。一共有70000張圖片,49000張訓練影像有標籤,剩下的21000張為測試圖片無標籤。
準備好了嗎?好!打開新的Python3 notebook,運行下面的程式碼:
# Setting up Colab !pip install PyDrive import os from pydrive.auth import GoogleAuth from pydrive.drive import GoogleDrive from google.colab import auth from oauth2client.client import GoogleCredentials auth.authenticate_user() gauth = GoogleAuth() gauth.credentials = GoogleCredentials.get_application_default() drive = GoogleDrive(gauth) # Replace the id and filename in the below codes download = drive.CreateFile({'id': '1ZCzHDAfwgLdQke_GNnHp_4OheRRtNPs-'}) download.GetContentFile('Train_UQcUa52.zip') !unzip Train_UQcUa52.zip # Importing libraries import keras from keras.models import Sequential from keras.layers import Dense, Dropout, Flatten from keras.layers import Conv2D, MaxPooling2D from keras.utils import to_categorical from keras.preprocessing import image import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.model_selection import train_test_split from keras.utils import to_categorical from tqdm import tqdm train = pd.read_csv('train.csv') # Reading the training images train_image = [] for i in tqdm(range(train.shape[0])): img = image.load_img('Images/train/'+train['filename'][i], target_size=(28,28,1), grayscale=True) img = image.img_to_array(img) img = img/255 train_image.append(img) X = np.array(train_image) # Creating the target variable y=train['label'].values y = to_categorical(y) # Creating validation set X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42, test_size=0.2) # Define the model structure model = Sequential() model.add(Conv2D(32, kernel_size=(3, 3),activation='relu',input_shape=(28,28,1))) model.add(Conv2D(64, (3, 3), activation='relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.25)) model.add(Flatten()) model.add(Dense(128, activation='relu')) model.add(Dropout(0.5)) model.add(Dense(10, activation='softmax')) # Compile the model model.compile(loss='categorical_crossentropy',optimizer='Adam',metrics=['accuracy']) # Training the model model.fit(X_train, y_train, epochs=10, validation_data=(X_test, y_test)) download = drive.CreateFile({'id': '1zHJR6yiI06ao-UAh_LXZQRIOzBO3sNDq'}) download.GetContentFile('Test_fCbTej3.csv') test_image = [] for i in tqdm(range(test_file.shape[0])): img = image.load_img('Images/test/'+test_file['filename'][i], target_size=(28,28,1), grayscale=True) img = image.img_to_array(img) img = img/255 test_image.append(img) test = np.array(test_image) prediction = model.predict_classes(test) download = drive.CreateFile({'id': '1nRz5bD7ReGrdinpdFcHVIEyjqtPGPyHx'}) download.GetContentFile('Sample_Submission_lxuyBuB.csv') sample = pd.read_csv('Sample_Submission_lxuyBuB.csv') sample['filename'] = test_file['filename'] sample['label'] = prediction sample.to_csv('sample.csv', header=True, index=False)
在練習題頁面上提交這個文件,你會得到一個相當不錯的準確率。這是一個好的開端,但總有改進的餘地。繼續肝,看看你是否可以改進我們的基本模型。