手把手教你用Python構建你的第一個多標籤圖像分類模型(附案例)

本文明確了多標籤圖像分類的概念,並講解了如何構建多標籤圖像分類模型。html

介紹

你正在處理圖像數據嗎?咱們可使用計算機視覺算法來作不少事情:算法

  • 對象檢測
  • 圖像分割
  • 圖像翻譯
  • 對象跟蹤(實時),還有更多……

這讓我思考——若是一個圖像中有多個對象類別,咱們該怎麼辦?製做一個圖像分類模型是一個很好的開始,但我想擴展個人視野以承擔一個更具挑戰性的任務—構建一個多標籤圖像分類模型!編程

製做一個圖像分類模型數組

www.analyticsvidhya.com/blog/2019/0…架構

我不想使用簡單玩具數據集來構建個人模型—這太普通了。而後,它打動了我—包含各類各樣的人的電影/電視劇海報。我能夠僅經過看海報就能來構建我本身的多標籤圖像分類模型來預測不一樣的流派嗎?app

image.png

答案很簡單——是的!在本文中,我解釋了多標籤圖像分類背後的思想。咱們將使用電影海報構建咱們本身的模型。你將會對咱們的模型產生的使人印象深入的結果感到驚訝。若是你是《復仇者聯盟》或《權力的遊戲》的粉絲,那麼在實現部分會有一個很棒的驚喜(無劇透的)給你。dom

激動嗎?很好,咱們開始吧!機器學習

目錄

  1. 什麼是多標籤圖像分類?
  2. 多標籤圖像分類與多類圖像分類有何不一樣?
  3. 瞭解多標籤圖像分類模型體系結構;
  4. 構建多標籤圖像分類模型的步驟;
  5. 案例研究:用Python解決多標籤圖像分類問題;

6.接下來的步驟和你的實驗;函數

7.尾記。性能

1. 什麼是多標籤圖像分類?

讓咱們經過一個直觀的例子來理解多標籤圖像分類的概念。 看看下面的圖片:

image.png

圖1中的對象是一輛汽車。這是顯而易見的。然而,在圖2中沒有汽車,只有一組建築物。你能看出咱們要怎麼作嗎?咱們將圖像分爲兩類,即,有車仍是沒車。

當咱們只有兩類圖像能夠分類時,這就稱爲二值圖像分類問題。

讓咱們再看一個圖片:

image.png

在這個圖片中,你識別出了多少個物體?有太多了——房子、帶噴泉的池塘、樹木、岩石等等。因此,當咱們能夠將一個圖像分類爲多個類(如上圖所示)時,就稱爲多標籤圖像分類問題。

如今,這裏有一個問題——咱們大多數人對多標籤和多類圖像分類感到困惑。當我第一次遇到這些術語時,我也被迷惑了。如今我對這兩個主題有了更好的理解,讓我來爲大家澄清一下區別。

2. 多標籤圖像分類與多類圖像分類有何不一樣?

假設給咱們一些動物的圖片,讓咱們把它們分紅相應的類別。爲了便於理解,咱們假設一個給定的圖像能夠分爲4類(貓、狗、兔子和鸚鵡)。如今,可能有兩種狀況:

  • 每一個圖像只包含一個對象(上述4個類別中的任何一個),所以,它只能被納入4個類別中的一個。
  • 圖像可能包含多個對象(來自上述4個類別),所以該圖像將屬於多個類別。

讓咱們經過例子來了解每種狀況,從第一個場景開始:

image.png

這裏,咱們的每一個圖像都只包含一個對象。敏銳的你會注意到在這個集合中有4種不一樣類型的對象(動物)。

這裏的每張圖片只能被分類爲貓、狗、鸚鵡或兔子。沒有任何一個圖像屬於多個類別的狀況。

  • 當圖像可分類的類別超過兩種時
  • 一個圖像不屬於一個以上的類別

若是知足上述兩個條件,則稱爲多類圖像分類問題。

如今,讓咱們思考第二種狀況 —— 看看下面的圖像:

image.png

  • 第一張圖片(左上角)包含一隻狗和一隻貓
  • 第二幅圖(右上角)包括一隻狗、一隻貓和一隻鸚鵡
  • 第三幅圖(左下角)包含一隻兔子和一隻鸚鵡,以及
  • 最後一張圖片(右下角)包含一隻狗和一隻鸚鵡

這些都是給定的圖像的標籤。這裏的每一個圖像都屬於一個以上的類,所以它是一個多標籤圖像分類問題。

這兩種狀況應該有助於你理解多類和多標籤圖像分類之間的區別。若是你須要進一步的說明,請在本文下面的評論部分與我聯繫。

在進入下一節以前,我建議你通讀這篇文章——在10分鐘內構建你的第一個圖像分類模型!它將幫助你瞭解如何解決一個多類圖像分類問題。

在10分鐘內構建你的第一個圖像分類模型:

www.analyticsvidhya.com/blog/2019/0…

3. 構建多標籤圖像分類模型的步驟

如今咱們已經對多標籤圖像分類有了一個直觀的認識,讓咱們深刻討論解決這個問題應該遵循的步驟。

第一步是以結構化格式獲取數據。這既適用於圖像二分類,也適用於多類圖像分類。

你應該有一個文件夾,其中包含您想要訓練模型的全部圖像。如今,爲了訓練這個模型,咱們還須要圖像的真實標籤。所以,你還應該有一個.csv文件,其中包含全部訓練圖像的名稱及其對應的真實標籤。

咱們將在本文後面學習如何建立這個.csv文件。如今,只要記住數據應該是一種特定的格式。數據準備好後,咱們能夠將進一步的步驟劃分以下:

加載和預處理數據

首先,加載全部圖像,而後根據項目的需求對它們進行預處理。爲了檢查咱們的模型將如何對不可見的數據(測試數據)執行,咱們建立了一個驗證集。咱們在訓練集上訓練咱們的模型並使用驗證集對其進行驗證(標準的機器學習方法)。

定義模型的結構

下一步是定義模型的結構。這包括決定隱藏層的數量、每層神經元的數量、激活函數等等。

訓練模型

是時候在訓練集上訓練咱們的模型了!咱們輸入訓練圖像及其對應的真標籤對模型進行訓練。咱們還在這裏傳入驗證圖像,以幫助咱們驗證模型在不可見數據上的性能。

做出預測

最後,咱們使用訓練過的模型對新圖像進行預測。

4. 瞭解多標籤圖像分類模型結構

如今,多標籤圖像分類任務的預處理步驟將相似於多類問題的預處理步驟。關鍵的區別在於咱們定義模型結構的步驟。

對於多類圖像分類模型,咱們在輸出層使用softmax激活函數。對於每一個圖像,咱們想要最大化單個類的機率。當一個類的機率增大時,另外一個類的機率就減少。因此,咱們能夠說每一個類的機率都依賴於其餘類。

可是在多標籤圖像分類的狀況下,單個圖像能夠有多個標籤。咱們但願機率彼此獨立。使用softmax激活函數並不合適。相反,咱們可使用sigmoid激活函數。這將獨立地預測每一個類的機率。它將在內部建立n個模型(這裏的n是總類數),每一個類一個模型,並預測每一個類的機率。

利用sigmoid激活函數將多標籤問題轉化爲n-二分類問題。所以對於每幅圖像,咱們將獲得機率來肯定圖像是否屬於第一類,以此類推。因爲咱們已經將其轉換爲一個n-二分類問題,咱們將使用binary_cross-sentropy損失。咱們的目標是儘可能減小這種損失,以提升模型的性能。

這是咱們在定義用於解決多標籤圖像分類問題的模型結構時必須作的主要更改。訓練部分將相似於一個多類問題。咱們將傳入訓練圖像及其對應的真實標籤,以及驗證集來驗證模型的性能。

最後,咱們將獲取一張新的圖像,並使用訓練過的模型來預測該圖像的標籤。還跟得上嗎?

5. 案例研究:用Python解決多標籤圖像分類問題

祝賀你來到這一步!你的獎勵——用Python解決一個可怕的多標籤圖像分類問題。是時候啓動你最喜歡的Python IDE了!

讓咱們明確問題陳述。咱們的目標是經過電影的海報圖像來預測電影的類型。你能猜到爲何這是一個多標籤圖像分類問題嗎?在你往下看以前想一下。

一部電影能夠屬於多種類型,對吧?它不只僅屬於一個類別,如動做片或喜劇片。電影能夠是兩種或多種類型的結合。所以,它是多標籤圖像分類。

咱們將使用的數據集包含多個多類型電影的海報圖像。我對數據集作了一些更改,並將其轉換爲結構化格式,即一個包含圖像的文件夾和一個存儲真正標籤的.csv文件。你能夠從這裏下載結構化數據集。下面是一些來自咱們數據集的海報:

這裏

drive.google.com/file/d/1dNa…

image.png

若是你願意,能夠在這裏下載原始數據集和基準真值。

這裏

www.cs.ccu.edu.tw/~wtchu/proj…

讓咱們開始編程!

首先,導入全部須要的Python庫:

  1. import keras
  2. from keras.models import Sequential
  3. from keras.layers import Dense, Dropout, Flatten
  4. from keras.layers import Conv2D, MaxPooling2D
  5. from keras.utils import to_categorical
  6. from keras.preprocessing import image
  7. import numpy as np
  8. import pandas as pd
  9. import matplotlib.pyplot as plt
  10. from sklearn.model_selection import train_test_split
  11. from tqdm import tqdm
  12. %matplotlib inline

如今,讀取.csv文件並查看前五行的內容:

  1. train = pd.read_csv('multi_label_train.csv') # reading the csv file
  2. train.head() # printing first five rows of the file

image.png

這個文件中有27列。 讓咱們輸出這些列的名字看看:

  1. train.columns

image.png

Genre列包含每一個圖像的列表,其中明確了每一個圖像對應的電影的類型。所以,從.csv文件的頭部開始,第一個圖像的類型是喜劇和戲劇。

剩下的25列是獨熱碼列。所以,若是一部電影屬於動做類型,它的值將爲1,不然爲0。每一個圖像能夠屬於25種不一樣的類型。

咱們將構建一個返回給定電影海報類型的模型。但在此以前,你還記得構建圖像分類模型的第一步嗎?

沒錯——就是正確的加載和預處理數據。因此,讓咱們看看全部的訓練圖片:

  1. train_image = []
  2. for i in tqdm(range(train.shape[0])):
  3. img = image.load_img('Multi_Label_dataset/Images/'+train'Id'+'.jpg',target_size=(400,400,3))
  4. img = image.img_to_array(img)
  5. img = img/255
  6. train_image.append(img)
  7. X = np.array(train_image)

快速瀏覽一下數組的形狀:

  1. X.shape

image.png

這裏共有7254個海報圖像,全部圖像都已轉換爲(400,300,3)的形狀。 讓咱們繪製並可視化其中一個圖像:

  1. plt.imshow(X[2])

image.png

這是電影《交易場所》的海報。讓咱們輸出這部電影的類型:

  1. train'Genre'

image.png

這部電影僅有一個類型——喜劇。咱們的模型所需的下一步是全部圖像的真實標籤。你能猜出這7254個圖像真實標籤的形狀是什麼嗎?

讓咱們來看看。 咱們知道總共有25種可能的類型。對於每一個圖像,咱們將有25個目標,即電影是否屬於該類型。 所以,全部這25個目標的值都爲0或1。

咱們將從訓練文件中刪除Id和Genre列,並將剩餘的列轉換爲將成爲咱們圖像目標的數組:

  1. y = np.array(train.drop(['Id', 'Genre'],axis=1))
  2. y.shape

輸出數組的形狀是(7254,25),正如咱們預想的那樣。 如今,讓咱們建立一個驗證集,它將幫助咱們檢查模型在不可見的數據上的性能。 咱們將隨機分離10%的圖像做爲咱們的驗證集:

  1. X_train, X_test, y_train, y_test =
  2. train_test_split(X, y, random_state=42, test_size=0.1)

下一步是定義模型結構。輸出層將有25個神經元(等於類型的數量),咱們將使用sigmoid做爲激活函數。

我將使用某一結構(以下所示)來解決這個問題。 你也能夠經過更改隱藏層數,激活函數和其餘超參數來修改此架構。

  1. model = Sequential()
  2. model.add(Conv2D(filters=16, kernel_size=(5, 5), activation="relu", input_shape=(400,400,3)))
  3. model.add(MaxPooling2D(pool_size=(2, 2)))
  4. model.add(Dropout(0.25))
  5. model.add(Conv2D(filters=32, kernel_size=(5, 5), activation='relu'))
  6. model.add(MaxPooling2D(pool_size=(2, 2)))
  7. model.add(Dropout(0.25))
  8. model.add(Conv2D(filters=64, kernel_size=(5, 5), activation="relu"))
  9. model.add(MaxPooling2D(pool_size=(2, 2)))
  10. model.add(Dropout(0.25))
  11. model.add(Conv2D(filters=64, kernel_size=(5, 5), activation='relu'))
  12. model.add(MaxPooling2D(pool_size=(2, 2)))
  13. model.add(Dropout(0.25))
  14. model.add(Flatten())
  15. model.add(Dense(128, activation='relu'))
  16. model.add(Dropout(0.5))
  17. model.add(Dense(64, activation='relu'))
  18. model.add(Dropout(0.5))
  19. model.add(Dense(25, activation='sigmoid'))

讓咱們顯示咱們的模型總結:

  1. model.summary()

image.png

有至關多的參數要學習! 如今,編譯模型。 我將使用binary_crossentropy做爲損失函數,使用ADAM做爲優化器(一樣,你也可使用其餘優化器):

  1. model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

最後,咱們最有趣的部分——訓練模型。咱們將訓練模型10個循環,並傳入咱們以前建立的驗證數據,以驗證模型的性能:

  1. model.fit(X_train, y_train, epochs=10, validation_data=(X_test, y_test), batch_size=64)

image.png

咱們能夠看到訓練損失已降至0.24,驗證損失也下降了。 下一步是什麼? 是時候作預測了!

全部《權力的遊戲(GoT)》和《復仇者聯盟(Avengers)》的粉絲——這是給大家的禮物。 讓我獲取GoT和Avengers的海報,並將它們提供給咱們的模型。 在繼續以前下載GOT和Avengers的海報。

GOT

drive.google.com/file/d/1cfI…

Avengers

drive.google.com/file/d/1buN…

在進行預測以前,咱們須要使用前面看到的相同步驟預處理這些圖像。

  1. img = image.load_img('GOT.jpg',target_size=(400,400,3))
  2. img = image.img_to_array(img)
  3. img = img/255

如今,咱們將使用咱們訓練好的模型預測這些海報的類型。該模型將告訴咱們每種類型的機率,咱們將從中得到前3個預測結果。

  1. classes = np.array(train.columns[2:])
  2. proba = model.predict(img.reshape(1,400,400,3))
  3. top_3 = np.argsort(proba[0])[:-4:-1]
  4. for i in range(3):
  5. print("{}".format(classes[top_3[i]])+" ({:.3})".format(proba0]))
  6. plt.imshow(img)

image.png

真棒!咱們的模型爲《權力的遊戲》預測了戲劇,驚悚和動做類型。在我看來,這個分類很好。讓咱們在《復仇者聯盟》海報上試試咱們的模型。圖像預處理:

  1. img = image.load_img('avengers.jpeg',target_size=(400,400,3))
  2. img = image.img_to_array(img)
  3. img = img/255

而後作預測:

  1. classes = np.array(train.columns[2:])
  2. proba = model.predict(img.reshape(1,400,400,3))
  3. top_3 = np.argsort(proba[0])[:-4:-1]
  4. for i in range(3):
  5. print("{}".format(classes[top_3[i]])+" ({:.3})".format(proba0]))
  6. plt.imshow(img)

image.png

咱們的模型給出的類型是戲劇、動做和驚悚。一樣,這些都是很是準確的結果。這個模型能在好萊塢電影分類上表現的同樣優秀嗎?讓咱們來看看。咱們將使用這張Golmal 3的海報。

image.png

你知道在這個階段該作什麼——加載和預處理的圖像:

  1. img = image.load_img('golmal.jpeg',target_size=(400,400,3))
  2. img = image.img_to_array(img)
  3. img = img/255

而後爲這個海報預測電影類型:

  1. classes = np.array(train.columns[2:])
  2. proba = model.predict(img.reshape(1,400,400,3))
  3. top_3 = np.argsort(proba[0])[:-4:-1]
  4. for i in range(3):
  5. print("{}".format(classes[top_3[i]])+" ({:.3})".format(proba0]))
  6. plt.imshow(img)

image.png

《Golmaal 3》是一部喜劇,咱們的模型預測它爲最受歡迎的類型。其餘預測類型是劇情片和浪漫片——相對準確的評估。咱們能夠看到該模型可以僅經過海報預測電影類型。

6. 接下來的步驟和你本身的實驗

這就是如何解決多標籤圖像分類問題。儘管咱們只有大約7000張圖片來訓練模型,但咱們的模型表現得很是好。

你能夠嘗試收集更多的訓練海報。個人建議是使全部的流派類別有相對平等的分佈的數據集。爲何?

若是某一類型在大多數訓練圖像中重複出現,那麼咱們的模型可能會與該類型過分匹配。對於每一張新圖片,該模型均可能預測出相同的類型。爲了克服這個問題,你應該嘗試均衡的流派類別分佈。

這些是你能夠嘗試改進模型性能的一些關鍵點。你還能想到別的嗎?告訴我!

7. 尾記

除了流派類型預測外,多標籤圖像分類還有多種應用。例如,你可使用此技術自動標記圖像。假設你想預測圖像中服裝的類型和顏色。你能夠創建一個多標籤圖像分類模型,這將幫助你預測同時二者!


文章來自阿里雲開發者社區

原文連接:developer.aliyun.com/article/715…

相關文章
相關標籤/搜索