深度學習進階,多個輸出和多個損失實現多標簽分類

      網友投稿 1070 2022-05-29

      Keras:多個輸出和多個損失

      幾周前,我們討論了如何使用 Keras 和深度學習執行多標簽分類。 今天,我們將討論一種更高級的技術,稱為多輸出分類。 那么,兩者有什么區別呢?

      在多標簽分類中,您的網絡在負責分類的網絡末端只有一組全連接層(即“頭”)。 但是在多輸出分類中,您的網絡至少分支兩次(有時更多),在網絡末端創建多組完全連接的頭——然后您的網絡可以為每個頭預測一組類標簽,從而有可能學習不相交的標簽組合。 您甚至可以將多標簽分類與多輸出分類結合起來,這樣每個全連接的頭部都可以預測多個輸出!

      今天的教程來指導你使用 Keras 進行多輸出分類,要了解如何通過 TensorFlow 和 Keras 使用多個輸出和多個損失,請繼續閱讀!

      在今天的博客文章中,我們將學習如何使用:

      多重損失函數

      多路輸出

      多輸出深度學習數據集

      數據集地址:鏈接:https://pan.baidu.com/s/1eANXTnWl2nf853IEiLOvWg

      提取碼:jo4h

      我們的數據集由5547張圖片組成,它們來自12個不同的種類,包括:

      black_dress(333張圖片)

      black_jeans(344張圖片)

      black_shirt(436張圖片)

      black_shoe(534張圖片)

      blue_dress(386張圖片)

      blue_jeans(356張圖片)

      blue_shirt(369張圖片)

      red_dress(384張圖片)

      red_shirt(332張圖片)

      red_shoe(486張圖片)

      white_bag(747張圖片)

      white_shoe(840張圖片)

      我們的卷積神經網絡的目標是同時預測顏色和服飾類別。代碼使用Tensorflow2.0以上版本編寫。下面對我實現算法的代碼作講解:

      項目結構

      $ tree --filelimit 10 --dirsfirst . ├── dataset │ ├── black_jeans [344 entries] │ ├── black_shoes [358 entries] │ ├── blue_dress [386 entries] │ ├── blue_jeans [356 entries] │ ├── blue_shirt [369 entries] │ ├── red_dress [380 entries] │ └── red_shirt [332 entries] ├── examples │ ├── black_dress.jpg │ ├── black_jeans.jpg │ ├── blue_shoes.jpg │ ├── red_shirt.jpg │ └── red_shoes.jpg ├── output │ ├── fashion.model │ ├── category_lb.pickle │ ├── color_lb.pickle │ ├── output_accs.png │ └── output_losses.png ├── model │ ├── __init__.py │ └── fashionnet.py ├── train.py └── classify.py

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      在上面你可以找到我們的項目結構,但在我們繼續之前,讓我們先回顧一下內容。 有 3 個值得注意的 Python 文件:

      model/fashionnet.py :我們的多輸出分類網絡文件包含由三種方法組成的 FashionNet 架構類: build_category_branch 、 build_color_branch 和 build 。我們將在下一節詳細回顧這些方法。

      train.py :此腳本將訓練 FashionNet 模型并在此過程中生成輸出文件夾中的所有文件。

      category.py :此腳本加載我們訓練好的網絡并使用多輸出分類對示例圖像進行分類。

      我們還有 4 個頂級目錄:

      dataset/ :我們的時尚數據集,是使用他們的 API 從 Bing Image Search 中抓取的。我們在上一節中介紹了數據集。要以與我相同的方式創建您自己的數據集,請參閱如何(快速)構建深度學習圖像數據集。

      examples/ :我們有一些示例圖像,我們將在本博文的最后一節中將它們與我們的分類.py 腳本結合使用。

      output/ :我們的 train.py 腳本生成了一些輸出文件:

      fashion.model :我們的序列化 Keras 模型。

      category_lb.pickle :服裝類別的序列化 LabelBinarizer 對象由 scikit-learn 生成。這個文件可以通過我們的classify.py 腳本加載(并調用標簽

      color_lb.pickle :顏色的 LabelBinarizer 對象。

      output_accs.png :精度訓練圖圖像。

      output_losses.png :損失訓練圖圖像。

      model/ :這是一個包含 FashionNet 類的 Python 模塊。

      快速回顧我們的多輸出 Keras 架構

      為了使用 Keras 執行多輸出預測,我們將實現一個名為 FashionNet 的特殊網絡架構(我為這篇博文而創建)。

      FashionNet 架構包含兩個特殊組件,包括:

      網絡早期的一個分支,將網絡分成兩個“子網絡”——一個負責服裝類型分類,另一個負責顏色分類。

      網絡末端的兩個(不相交)全連接頭,每個頭負責各自的分類職責。

      在我們開始實現 FashionNet 之前,讓我們可視化這些組件中的每一個,第一個是分支:

      在這個網絡架構圖中,您可以看到我們的網絡接受 96 x 96 x 3 的輸入圖像。

      然后我們立即創建兩個分支:

      左邊的分支負責對服裝類別進行分類。

      右側的分支處理顏色分類。

      每個分支執行其各自的一組卷積、激活、批量歸一化、池化和 dropout 操作,直到我們達到最終輸出:

      圖 5:我們的深度學習 Keras 多輸出分類網絡可以學習不相交的標簽組合。

      請注意這些全連接 (FC) 頭集如何與我們在本博客中研究過的其他架構中的 FC 層相似——但現在有兩個,每個都負責其給定的分類任務。

      網絡右側的分支明顯比左側分支淺(沒有那么深)。 預測顏色比預測服裝類別要容易得多,因此顏色分支相對較淺。

      為了了解我們如何實現這樣的架構,讓我們繼續下一節。

      實施我們的“FashionNet”架構

      圖 6:Keras 深度學習庫具有執行多輸出分類所需的所有功能。

      新建fashionnet.py 在里面增加:

      # import the necessary packages from tensorflow.keras.models import Model from tensorflow.keras.layers import BatchNormalization from tensorflow.keras.layers import Conv2D from tensorflow.keras.layers import MaxPooling2D from tensorflow.keras.layers import Activation from tensorflow.keras.layers import Dropout from tensorflow.keras.layers import Lambda from tensorflow.keras.layers import Dense from tensorflow.keras.layers import Flatten from tensorflow.keras.layers import Input import tensorflow as tf

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      我們首先從 Keras 庫導入模塊,然后導入 TensorFlow 本身。

      由于我們的網絡由兩個子網絡組成,我們將定義兩個函數來負責構建各自的分支。

      第一個, build_category_branch ,用于分類服裝類型,定義如下:

      class FashionNet: @staticmethod def build_category_branch(inputs, numCategories, finalAct="softmax", chanDim=-1): # utilize a lambda layer to convert the 3 channel input to a # grayscale representation x = Lambda(lambda c: tf.image.rgb_to_grayscale(c))(inputs) # CONV => RELU => POOL x = Conv2D(32, (3, 3), padding="same")(x) x = Activation("relu")(x) x = BatchNormalization(axis=chanDim)(x) x = MaxPooling2D(pool_size=(3, 3))(x) x = Dropout(0.25)(x)

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      build_category_branch 具有三個值得注意的參數:

      輸入:我們類別分支子網絡的輸入量。

      numCategories :類別的數量,例如“連衣裙”、“鞋子”、“牛仔褲”、“襯衫”等。

      finalAct :最終激活層類型,默認為 softmax 分類器。如果您同時執行多輸出和多標簽分類,您可能希望將此激活更改為 sigmoid。

      我們使用 Lambda 層將圖像從 RGB 轉換為灰度。

      為什么要這樣做? 嗯,不管是紅色、藍色、綠色、黑色還是紫色,裙子都是裙子,對吧? 因此,我們決定丟棄任何顏色信息,轉而關注圖像中的實際結構成分,確保我們的網絡不會學習將特定顏色與服裝類型聯合關聯。

      然后我們繼續構建我們的 CONV => RELU => POOL 塊和 dropout。請注意,我們使用的是 TensorFlow/Keras 的函數式 API;我們需要功能性 API 來創建我們的分支網絡結構。

      我們的第一個 CONV 層有 32 個濾波器,帶有 3 x 3 內核和 RELU 激活(整流線性單元)。我們應用批量歸一化、最大池化和 25% dropout。 Dropout是將節點從當前層隨機斷開到下一層的過程。這種隨機斷開的過程自然有助于網絡減少過度擬合,因為層中沒有一個節點負責預測某個類、對象、邊緣或角。

      接下來是我們的兩組 (CONV => RELU) * 2 => POOL 塊:

      # (CONV => RELU) * 2 => POOL x = Conv2D(64, (3, 3), padding="same")(x) x = Activation("relu")(x) x = BatchNormalization(axis=chanDim)(x) x = Conv2D(64, (3, 3), padding="same")(x) x = Activation("relu")(x) x = BatchNormalization(axis=chanDim)(x) x = MaxPooling2D(pool_size=(2, 2))(x) x = Dropout(0.25)(x) # (CONV => RELU) * 2 => POOL x = Conv2D(128, (3, 3), padding="same")(x) x = Activation("relu")(x) x = BatchNormalization(axis=chanDim)(x) x = Conv2D(128, (3, 3), padding="same")(x) x = Activation("relu")(x) x = BatchNormalization(axis=chanDim)(x) x = MaxPooling2D(pool_size=(2, 2))(x) x = Dropout(0.25)(x)

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      此代碼塊中過濾器、內核和池大小的變化協同工作,以逐漸減小空間大小但增加深度。

      讓我們將它與 FC => RELU 層結合起來:

      # define a branch of output layers for the number of different # clothing categories (i.e., shirts, jeans, dresses, etc.) x = Flatten()(x) x = Dense(256)(x) x = Activation("relu")(x) x = BatchNormalization()(x) x = Dropout(0.5)(x) x = Dense(numCategories)(x) x = Activation(finalAct, name="category_output")(x) # return the category prediction sub-network return x

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      最后一個激活層是完全連接的,并且具有與我們的 numCategories 相同數量的神經元/輸出。

      請注意,我們將最終激活層命名為“category_output”。這很重要,因為我們稍后將在 train.py 中按名稱引用該層。

      讓我們定義用于構建多輸出分類網絡的第二個函數。 這個名為 build_color_branch ,顧名思義,它負責對圖像中的顏色進行分類:

      @staticmethod def build_color_branch(inputs, numColors, finalAct="softmax", chanDim=-1): # CONV => RELU => POOL x = Conv2D(16, (3, 3), padding="same")(inputs) x = Activation("relu")(x) x = BatchNormalization(axis=chanDim)(x) x = MaxPooling2D(pool_size=(3, 3))(x) x = Dropout(0.25)(x) # CONV => RELU => POOL x = Conv2D(32, (3, 3), padding="same")(x) x = Activation("relu")(x) x = BatchNormalization(axis=chanDim)(x) x = MaxPooling2D(pool_size=(2, 2))(x) x = Dropout(0.25)(x) # CONV => RELU => POOL x = Conv2D(32, (3, 3), padding="same")(x) x = Activation("relu")(x) x = BatchNormalization(axis=chanDim)(x) x = MaxPooling2D(pool_size=(2, 2))(x) x = Dropout(0.25)(x)

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      我們的 build_color_branch 參數與 build_category_branch 基本相同。

      我們用 numColors (不同于 numCategories )來區分最后一層的激活次數。

      這一次,我們不會應用 Lambda 灰度轉換層,因為我們實際上關心的是網絡這個區域的顏色。 如果我們轉換為灰度,我們將丟失所有顏色信息!

      網絡的這個分支比服裝類別分支淺得多,因為手頭的任務要簡單得多。 我們要求子網絡完成的只是對顏色進行分類——子網絡不必那么深。

      就像我們的類別分支一樣,我們有第二個完全連接的頭部。 讓我們構建 FC => RELU 塊來完成:

      # define a branch of output layers for the number of different # colors (i.e., red, black, blue, etc.) x = Flatten()(x) x = Dense(128)(x) x = Activation("relu")(x) x = BatchNormalization()(x) x = Dropout(0.5)(x) x = Dense(numColors)(x) x = Activation(finalAct, name="color_output")(x) # return the color prediction sub-network return x

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      為了區分顏色分支的最終激活層,我提供了 name=“color_output” 關鍵字參數。我們將在訓練腳本中引用名稱。 我們構建 FashionNet 的最后一步是將我們的兩個分支放在一起并構建最終架構:

      @staticmethod def build(width, height, numCategories, numColors, finalAct="softmax"): # initialize the input shape and channel dimension (this code # assumes you are using TensorFlow which utilizes channels # last ordering) inputShape = (height, width, 3) chanDim = -1 # construct both the "category" and "color" sub-networks inputs = Input(shape=inputShape) categoryBranch = FashionNet.build_category_branch(inputs, numCategories, finalAct=finalAct, chanDim=chanDim) colorBranch = FashionNet.build_color_branch(inputs, numColors, finalAct=finalAct, chanDim=chanDim) # create the model using our input (the batch of images) and # two separate outputs -- one for the clothing category # branch and another for the color branch, respectively model = Model( inputs=inputs, outputs=[categoryBranch, colorBranch], name="fashionnet") # return the constructed network architecture return model

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      定義build函數,有5個參數。 build 函數假設我們使用的是 TensorFlow 和最后一次排序的通道。

      inputShape 元組是明確排序的 (height, width, 3) ,其中 3 代表 RGB 通道。 如果您想使用 TensorFlow 以外的后端,您需要修改代碼以:(1) 正確地為您的后端設置正確的通道順序,以及 (2) 實現一個自定義層來處理 RGB 到灰度的轉換。 從那里,我們定義了網絡的兩個分支,然后將它們放在一個模型中。 關鍵是我們的分支有一個共同的輸入,但有兩個不同的輸出(服裝類型和顏色分類)。

      實現多輸出和多損失訓練腳本

      現在我們已經實現了我們的 FashionNet 架構,讓我們訓練它! 準備好后,打開 train.py 并深入研究:

      # set the matplotlib backend so figures can be saved in the background import matplotlib matplotlib.use("Agg") # import the necessary packages from tensorflow.keras.optimizers import Adam from tensorflow.keras.preprocessing.image import img_to_array from sklearn.preprocessing import LabelBinarizer from sklearn.model_selection import train_test_split from model.fashionnet import FashionNet from imutils import paths import matplotlib.pyplot as plt import numpy as np import argparse import random import pickle import cv2 import os

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      我們首先為腳本導入必要的包。

      從那里我們解析我們的命令行參數:

      # construct the argument parser and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-d", "--dataset", required=True, help="path to input dataset (i.e., directory of images)") ap.add_argument("-m", "--model", required=True, help="path to output model") ap.add_argument("-l", "--categorybin", required=True, help="path to output category label binarizer") ap.add_argument("-c", "--colorbin", required=True, help="path to output color label binarizer") ap.add_argument("-p", "--plot", type=str, default="output", help="base filename for generated plots") args = vars(ap.parse_args())

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      我們很快就會看到如何運行訓練腳本。 現在,只知道 --dataset 是我們數據集的輸入文件路徑, --model 、 --categorybin 、 --colorbin 都是三個輸出文件路徑。

      或者,您可以使用 --plot 參數為生成的精度/損失圖指定基本文件名。

      現在,讓我們建立四個重要的訓練變量:

      # initialize the number of epochs to train for, initial learning rate, # batch size, and image dimensions EPOCHS = 50 INIT_LR = 1e-3 BS = 32 IMAGE_DIMS = (96, 96, 3)

      1

      2

      3

      4

      5

      6

      我們設置以下變量:

      EPOCHS : epoch 數設置為 50 。通過實驗,我發現 50 個 epoch 生成的模型具有低損失并且沒有過擬合到訓練集(或盡可能不過擬合)。

      INIT_LR :我們的初始學習率設置為 0.001 。學習率控制著我們沿著梯度所做的“步驟”。較小的值表示較小的步長,較大的值表示較大的步長。我們很快就會看到我們將使用 Adam 優化器,同時隨著時間的推移逐漸降低學習率。

      BS:我們將以 32 的批量大小訓練我們的網絡。

      IMAGE_DIMS :所有輸入圖像都將調整為 96 x 96,具有 3 個通道 (RGB)。我們正在使用這些維度進行訓練,我們的網絡架構輸入維度也反映了這些維度。當我們在后面的部分中使用示例圖像測試我們的網絡時,測試維度必須與訓練維度匹配。

      我們的下一步是抓取我們的圖像路徑并隨機打亂它們。我們還將初始化列表以分別保存圖像本身以及服裝類別和顏色:

      # grab the image paths and randomly shuffle them print("[INFO] loading images...") imagePaths = sorted(list(paths.list_images(args["dataset"]))) random.seed(42) random.shuffle(imagePaths) # initialize the data, clothing category labels (i.e., shirts, jeans, # dresses, etc.) along with the color labels (i.e., red, blue, etc.) data = [] categoryLabels = [] colorLabels = []

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      隨后,我們將遍歷 imagePaths 、預處理并填充 data 、 categoryLabels 和 colorLabels 列表:

      # loop over the input images for imagePath in imagePaths: # load the image, pre-process it, and store it in the data list image = cv2.imread(imagePath) image = cv2.resize(image, (IMAGE_DIMS[1], IMAGE_DIMS[0])) image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) image = img_to_array(image) data.append(image) # extract the clothing color and category from the path and # update the respective lists (color, cat) = imagePath.split(os.path.sep)[-2].split("_") categoryLabels.append(cat) colorLabels.append(color)

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      我們開始遍歷我們的 imagePaths。

      在循環內部,我們加載圖像并將其調整為 IMAGE_DIMS 。 我們還將圖像從 BGR 排序轉換為 RGB。 我們為什么要進行這種轉換? 回想一下我們在 build_category_branch 函數中的 FashionNet 類,我們在 Lambda 函數/層中使用了 TensorFlow 的 rgb_to_grayscale 轉換。 因此,我們首先轉換為 RGB,并最終將預處理后的圖像附加到數據列表中。

      接下來,仍然在循環內部,我們從當前圖像所在的目錄名稱中提取顏色和類別標簽。

      要查看此操作,只需在終端中啟動 Python,并提供一個示例 imagePath 進行實驗,如下所示:

      $ python >>> import os >>> imagePath = "dataset/red_dress/00000000.jpg" >>> (color, cat) = imagePath.split(os.path.sep)[-2].split("_") >>> color 'red' >>> cat 'dress'

      1

      2

      3

      4

      5

      6

      7

      8

      您當然可以按您希望的任何方式組織您的目錄結構(但您必須修改代碼)。 我最喜歡的兩種方法包括 (1) 為每個標簽使用子目錄或 (2) 將所有圖像存儲在單個目錄中,然后創建 CSV 或 JSON 文件以將圖像文件名映射到它們的標簽。 讓我們將三個列表轉換為 NumPy 數組,對標簽進行二值化,并將數據劃分為訓練和測試分割:

      # scale the raw pixel intensities to the range [0, 1] and convert to # a NumPy array data = np.array(data, dtype="float") / 255.0 print("[INFO] data matrix: {} images ({:.2f}MB)".format( len(imagePaths), data.nbytes / (1024 * 1000.0))) # convert the label lists to NumPy arrays prior to binarization categoryLabels = np.array(categoryLabels) colorLabels = np.array(colorLabels) # binarize both sets of labels print("[INFO] binarizing labels...") categoryLB = LabelBinarizer() colorLB = LabelBinarizer() categoryLabels = categoryLB.fit_transform(categoryLabels) colorLabels = colorLB.fit_transform(colorLabels) # partition the data into training and testing splits using 80% of # the data for training and the remaining 20% for testing split = train_test_split(data, categoryLabels, colorLabels, test_size=0.2, random_state=42) (trainX, testX, trainCategoryY, testCategoryY, trainColorY, testColorY) = split

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      我們的最后一個預處理步驟——轉換為 NumPy 數組并將原始像素強度縮放為 [0, 1]。

      我們還將 categoryLabels 和 colorLabels 轉換為 NumPy 數組。 這是必要的,因為在我們的下一個中,我們將使用我們之前導入的 scikit-learn 的 LabelBinarizer對標簽進行二值化。 由于我們的網絡有兩個獨立的分支,我們可以使用兩個獨立的標簽二值化器——這與我們使用 MultiLabelBinarizer(也來自 scikit-learn)的多標簽分類不同。

      接下來,我們對數據集執行典型的 80% 訓練/20% 測試拆分。

      讓我們構建網絡,定義我們的獨立損失,并編譯我們的模型:

      # initialize our FashionNet multi-output network model = FashionNet.build(96, 96, numCategories=len(categoryLB.classes_), numColors=len(colorLB.classes_), finalAct="softmax") # define two dictionaries: one that specifies the loss method for # each output of the network along with a second dictionary that # specifies the weight per loss losses = { "category_output": "categorical_crossentropy", "color_output": "categorical_crossentropy", } lossWeights = {"category_output": 1.0, "color_output": 1.0} # initialize the optimizer and compile the model print("[INFO] compiling model...") opt = Adam(lr=INIT_LR, decay=INIT_LR / EPOCHS) model.compile(optimizer=opt, loss=losses, loss_weights=lossWeights, metrics=["accuracy"])

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      實例化多輸出 FashionNet 模型。我們在創建 FashionNet 類并在其中構建函數時剖析了參數,因此請務必查看我們在此處實際提供的值。

      接下來,我們需要為每個完全連接的頭部定義兩個損失。

      定義多個損失是通過使用每個分支激活層的名稱的字典來完成的——這就是我們在 FashionNet 實現中命名輸出層的原因!每個損失都將使用分類交叉熵,這是訓練網絡進行大于 2 類分類時使用的標準損失方法。

      我們還在單獨字典(具有相同值的同名鍵)中定義了相等的 lossWeights。在您的特定應用程序中,您可能希望對一個損失進行比另一個更重的加權。

      現在我們已經實例化了我們的模型并創建了 loss + lossWeights 字典,讓我們用學習率衰減初始化 Adam 優化器并編譯我們的模型。

      我們的下一個塊只是開始訓練過程:

      # train the network to perform multi-output classification H = model.fit(x=trainX, y={"category_output": trainCategoryY, "color_output": trainColorY}, validation_data=(testX, {"category_output": testCategoryY, "color_output": testColorY}), epochs=EPOCHS, verbose=1) # save the model to disk print("[INFO] serializing network...") model.save(args["model"], save_format="h5")

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      請注意,對于 TensorFlow 2.0+,我們建議明確設置 save_format=“h5”(HDF5 格式)。

      回想一下第 87-90 行,我們將數據拆分為訓練 (trainX) 和測試 (testX)。 在第 114-119 行,我們在提供數據的同時啟動了訓練過程。 請注意第 115 行,我們將標簽作為字典傳入。 第 116 行和第 117 行也是如此,我們為驗證數據傳入了一個 2 元組。 在使用 Keras 執行多輸出分類時,需要以這種方式傳遞訓練和驗證標簽。 我們需要指示 Keras 哪一組目標標簽對應于網絡的哪個輸出分支。 使用我們的命令行參數 (args[“model”] ),我們將序列化模型保存到磁盤以備將來調用。 我們也會做同樣的事情來將我們的標簽二值化器保存為序列化的 pickle 文件:

      # save the category binarizer to disk print("[INFO] serializing category label binarizer...") f = open(args["categorybin"], "wb") f.write(pickle.dumps(categoryLB)) f.close() # save the color binarizer to disk print("[INFO] serializing color label binarizer...") f = open(args["colorbin"], "wb") f.write(pickle.dumps(colorLB)) f.close()

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      使用命令行參數路徑(args[“categorybin”] 和 args[“colorbin”]),我們將兩個標簽二值化器(categoryLB 和 colorLB)寫入磁盤上的序列化 pickle 文件。

      從那里開始,就是在這個腳本中繪制結果:

      # plot the total loss, category loss, and color loss lossNames = ["loss", "category_output_loss", "color_output_loss"] plt.style.use("ggplot") (fig, ax) = plt.subplots(3, 1, figsize=(13, 13)) # loop over the loss names for (i, l) in enumerate(lossNames): # plot the loss for both the training and validation data title = "Loss for {}".format(l) if l != "loss" else "Total loss" ax[i].set_title(title) ax[i].set_xlabel("Epoch #") ax[i].set_ylabel("Loss") ax[i].plot(np.arange(0, EPOCHS), H.history[l], label=l) ax[i].plot(np.arange(0, EPOCHS), H.history["val_" + l], label="val_" + l) ax[i].legend() # save the losses figure plt.tight_layout() plt.savefig("{}_losses.png".format(args["plot"])) plt.close()

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      上面的代碼塊負責在單獨但堆疊的圖上繪制每個損失函數的損失歷史,包括:

      總體損耗

      類別輸出的損失

      顏色輸出的損失

      同樣,我們將在單獨的圖像文件中繪制精度:

      # create a new figure for the accuracies accuracyNames = ["category_output_accuracy", "color_output_accuracy"] plt.style.use("ggplot") (fig, ax) = plt.subplots(2, 1, figsize=(8, 8)) # loop over the accuracy names for (i, l) in enumerate(accuracyNames): # plot the loss for both the training and validation data ax[i].set_title("Accuracy for {}".format(l)) ax[i].set_xlabel("Epoch #") ax[i].set_ylabel("Accuracy") ax[i].plot(np.arange(0, EPOCHS), H.history[l], label=l) ax[i].plot(np.arange(0, EPOCHS), H.history["val_" + l], label="val_" + l) ax[i].legend() # save the accuracies figure plt.tight_layout() plt.savefig("{}_accs.png".format(args["plot"])) plt.close()

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      訓練多輸出/多損失 Keras 模型

      打開終端。 然后粘貼以下命令以開始訓練過程:

      $ python train.py --dataset dataset --model output/fashion.model \ --categorybin output/category_lb.pickle --colorbin output/color_lb.pickle Using TensorFlow backend. [INFO] loading images... [INFO] data matrix: 2521 images (544.54MB) [INFO] loading images... [INFO] data matrix: 2521 images (544.54MB) [INFO] binarizing labels... [INFO] compiling model... Epoch 1/50 63/63 [==============================] - 1s 20ms/step - loss: 0.8523 - category_output_loss: 0.5301 - color_output_loss: 0.3222 - category_output_accuracy: 0.8264 - color_output_accuracy: 0.8780 - val_loss: 3.6909 - val_category_output_loss: 1.8052 - val_color_output_loss: 1.8857 - val_category_output_accuracy: 0.3188 - val_color_output_accuracy: 0.4416 Epoch 2/50 63/63 [==============================] - 1s 14ms/step - loss: 0.4367 - category_output_loss: 0.3092 - color_output_loss: 0.1276 - category_output_accuracy: 0.9033 - color_output_accuracy: 0.9519 - val_loss: 7.0533 - val_category_output_loss: 2.9279 - val_color_output_loss: 4.1254 - val_category_output_accuracy: 0.3188 - val_color_output_accuracy: 0.4416 Epoch 3/50 63/63 [==============================] - 1s 14ms/step - loss: 0.2892 - category_output_loss: 0.1952 - color_output_loss: 0.0940 - category_output_accuracy: 0.9350 - color_output_accuracy: 0.9653 - val_loss: 6.2512 - val_category_output_loss: 2.0540 - val_color_output_loss: 4.1972 - val_category_output_accuracy: 0.4020 - val_color_output_accuracy: 0.4416 ... Epoch 48/50 63/63 [==============================] - 1s 14ms/step - loss: 0.0189 - category_output_loss: 0.0106 - color_output_loss: 0.0083 - category_output_accuracy: 0.9960 - color_output_accuracy: 0.9970 - val_loss: 0.2625 - val_category_output_loss: 0.2250 - val_color_output_loss: 0.0376 - val_category_output_accuracy: 0.9564 - val_color_output_accuracy: 0.9861 Epoch 49/50 63/63 [==============================] - 1s 14ms/step - loss: 0.0190 - category_output_loss: 0.0041 - color_output_loss: 0.0148 - category_output_accuracy: 0.9985 - color_output_accuracy: 0.9950 - val_loss: 0.2333 - val_category_output_loss: 0.1927 - val_color_output_loss: 0.0406 - val_category_output_accuracy: 0.9604 - val_color_output_accuracy: 0.9881 Epoch 50/50 63/63 [==============================] - 1s 14ms/step - loss: 0.0188 - category_output_loss: 0.0046 - color_output_loss: 0.0142 - category_output_accuracy: 0.9990 - color_output_accuracy: 0.9960 - val_loss: 0.2140 - val_category_output_loss: 0.1719 - val_color_output_loss: 0.0421 - val_category_output_accuracy: 0.9624 - val_color_output_accuracy: 0.9861 [INFO] serializing network... [INFO] serializing category label binarizer... [INFO] serializing color label binarizer...

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      對于我們的類別輸出,我們獲得了:

      訓練集上 99.90% 的準確率

      在測試集上的準確率為 96.24%

      對于我們達到的顏色輸出:

      99.60% 的訓練集準確率

      在測試集上的準確率為 98.61%

      您可以在下面找到我們多個損失中的每一個的圖:

      圖 7:我們的 Keras 深度學習多輸出分類訓練損失是用 matplotlib 繪制的。 我們的總損失(頂部)、服裝類別損失(中間)和顏色損失(底部)被獨立繪制以供分析。

      以及我們的多重精度:

      圖 8:FashionNet,一個多輸出分類網絡,用 Keras 訓練。 為了分析訓練,最好在單獨的圖中顯示準確度。 服裝類別訓練準確率圖(上)。 顏色訓練精度圖(底部)。

      實現多輸出分類腳本

      打開classify.py,插入如下代碼:

      # import the necessary packages from tensorflow.keras.preprocessing.image import img_to_array from tensorflow.keras.models import load_model import tensorflow as tf import numpy as np import argparse import imutils import pickle import cv2 # construct the argument parser and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-m", "--model", required=True, help="path to trained model model") ap.add_argument("-l", "--categorybin", required=True, help="path to output category label binarizer") ap.add_argument("-c", "--colorbin", required=True, help="path to output color label binarizer") ap.add_argument("-i", "--image", required=True, help="path to input image") args = vars(ap.parse_args())

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      我們有四個命令行參數,這些參數是在您的終端中運行此腳本所必需的:

      –model :我們剛剛訓練的序列化模型文件的路徑(我們之前腳本的輸出)。

      –categorybin :類別標簽二值化器的路徑(我們之前腳本的輸出)。

      –colorbin :顏色標簽二值化器的路徑(我們之前腳本的輸出)。

      –image :我們的測試圖像文件路徑——這個圖像將來自我們的 examples/ 目錄。

      從那里,我們加載我們的圖像并對其進行預處理:

      # load the image image = cv2.imread(args["image"]) output = imutils.resize(image, width=400) image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # pre-process the image for classification image = cv2.resize(image, (96, 96)) image = image.astype("float") / 255.0 image = img_to_array(image) image = np.expand_dims(image, axis=0)

      1

      2

      3

      4

      5

      6

      7

      8

      9

      在我們運行推理之前需要預處理我們的圖像。 在上面的塊中,我們加載圖像,調整其大小以用于輸出目的,并交換顏色通道,以便我們可以在 FashionNet 的 Lambda 層中使用 TensorFlow 的 RGB 灰度函數。 然后我們調整 RGB 圖像的大小(從我們的訓練腳本中調用 IMAGE_DIMS),將其縮放為 [0, 1],轉換為 NumPy 數組,并為批次添加維度。

      預處理步驟遵循在我們的訓練腳本中采取的相同操作是至關重要的。

      接下來,讓我們加載我們的序列化模型和兩個標簽二值化器:

      # load the trained convolutional neural network from disk, followed # by the category and color label binarizers, respectively print("[INFO] loading network...") model = load_model(args["model"], custom_objects={"tf": tf}) categoryLB = pickle.loads(open(args["categorybin"], "rb").read()) colorLB = pickle.loads(open(args["colorbin"], "rb").read())

      1

      2

      3

      4

      5

      6

      深度學習進階,多個輸出和多個損失實現多標簽分類

      使用四個命令行參數中的三個,我們加載 model 、 categoryLB 和 colorLB 。

      現在 多輸出 Keras 模型和 標簽二值化器都在內存中,我們可以對圖像進行分類:

      # classify the input image using Keras' multi-output functionality print("[INFO] classifying image...") (categoryProba, colorProba) = model.predict(image) # find indexes of both the category and color outputs with the # largest probabilities, then determine the corresponding class # labels categoryIdx = categoryProba[0].argmax() colorIdx = colorProba[0].argmax() categoryLabel = categoryLB.classes_[categoryIdx] colorLabel = colorLB.classes_[colorIdx]

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      執行多輸出分類,得出類別和顏色的概率(分別為 categoryProba 和 colorProba)。

      注意:我沒有包含包含代碼,因為它有點冗長,但您可以通過檢查輸出張量的名稱來確定 TensorFlow + Keras 模型返回多個輸出的順序。

      從那里,我們將提取類別和顏色的最高概率指數。 使用高概率指數,我們可以提取類名。 這似乎有點太容易了,不是嗎? 但這就是使用 Keras 將多輸出分類應用于新輸入圖像的全部內容!

      讓我們顯示結果來證明它:

      # draw the category label and color label on the image categoryText = "category: {} ({:.2f}%)".format(categoryLabel, categoryProba[0][categoryIdx] * 100) colorText = "color: {} ({:.2f}%)".format(colorLabel, colorProba[0][colorIdx] * 100) cv2.putText(output, categoryText, (10, 25), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2) cv2.putText(output, colorText, (10, 55), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2) # display the predictions to the terminal as well print("[INFO] {}".format(categoryText)) print("[INFO] {}".format(colorText)) # show the output image cv2.imshow("Output", output) cv2.waitKey(0)

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      我們在輸出圖像上顯示結果。 如果我們遇到“紅色連衣裙”,它會在左上角的綠色文本中看起來像這樣: 類別:連衣裙 (89.04%) 顏色:紅色(95.07%) 相同的信息打印到終端,之后輸出圖像顯示在屏幕上。

      使用 Keras 執行多輸出分類

      現在是有趣的部分了!

      在本節中,我們將向我們的網絡展示示例目錄中不屬于訓練集的五張圖像。 關鍵是我們的網絡只經過專門訓練,可以識別兩個示例圖像類別。 前兩張圖片(“黑色牛仔褲”和“紅色襯衫”)應該特別容易讓我們的網絡正確分類類別和顏色。

      剩下的三個圖像對我們的模型來說是完全陌生的——我們沒有用“紅鞋”、“藍鞋”或“黑裙”進行訓練,但我們將嘗試多輸出分類,看看會發生什么。

      讓我們從“黑色牛仔褲”開始——這個應該很容易,因為在訓練數據集中有很多相似的圖像。 請務必使用四個命令行參數,如下所示:

      $ python classify.py --model output/fashion.model \ --categorybin output/category_lb.pickle --colorbin output/color_lb.pickle \ --image examples/black_jeans.jpg Using TensorFlow backend. [INFO] loading network... [INFO] classifying image... [INFO] category: jeans (100.00%) [INFO] color: black (97.04%)

      1

      2

      3

      4

      5

      6

      7

      8

      總結

      在今天的博文中,我們學習了如何利用 Keras 深度學習庫中的多個輸出和多個損失函數。

      為了完成這項任務,我們定義了一個 Keras 架構,用于時尚/服裝分類,稱為 FashionNet。

      FashionNet 架構包含兩個分支:

      一個叉負責對給定輸入圖像的服裝類型(例如,襯衫、連衣裙、牛仔褲、鞋子等)進行分類。

      而第二個叉子負責對衣服的顏色進行分類(黑色、紅色、藍色等)。 這個分支發生在網絡的早期,本質上創建了兩個“子網絡”,它們負責各自的分類任務,但都包含在同一個網絡中。

      最值得注意的是,多輸出分類使我們能夠解決上一篇關于多標簽分類的文章中的一個問題,其中: 我們在六個類別上訓練我們的網絡,包括:黑色牛仔褲、藍色連衣裙、藍色牛仔褲、藍色襯衫、紅色連衣裙和紅色襯衫…… ……但我們無法對“黑裙”進行分類,因為我們的網絡以前從未見過這種數據組合!

      通過創建兩個完全連接的頭部和相關的子網絡(如有必要),我們可以訓練一個頭部對服裝類型進行分類,另一個可以學習如何識別顏色——最終結果是一個可以對“黑色連衣裙”進行分類的網絡它從未接受過此類數據的訓練!

      源碼和數據集-:

      https://download.csdn.net/download/hhhhhhhhhhwwwwwwwwww/35593098

      機器學習 深度學習

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:超詳細的Java容器、面板及四大布局管理器應用講解!
      下一篇:Windows上使用Vagrant打造Laravel Homestead可協同跨平臺開發環境
      相關文章
      亚洲国产视频网站| 亚洲AV无码国产精品麻豆天美| 久久久久久久综合日本亚洲| 亚洲男人天堂2020| 日本亚洲中午字幕乱码| 亚洲s码欧洲m码吹潮| 亚洲一区二区无码偷拍| 亚洲愉拍一区二区三区| 亚洲熟妇AV乱码在线观看| 亚洲国产日韩精品| 亚洲一卡2卡三卡4卡无卡下载| 亚洲AV综合色区无码二区偷拍| 狠狠色香婷婷久久亚洲精品| 亚洲av无码久久忘忧草| 亚洲av无码电影网| 99999久久久久久亚洲| 在线精品亚洲一区二区| 亚洲国产美女精品久久久| 亚洲av无码成人精品国产| 噜噜综合亚洲AV中文无码| 处破女第一次亚洲18分钟| 国产精品亚洲精品日韩电影| 国产天堂亚洲国产碰碰| 亚洲国产精品日韩| 亚洲毛片不卡av在线播放一区| 精品亚洲成α人无码成α在线观看| 亚洲熟伦熟女新五十路熟妇| 精品国产香蕉伊思人在线在线亚洲一区二区 | 亚洲av福利无码无一区二区 | 亚洲人成电影网站色www| 亚洲欧美日韩中文字幕在线一区| 亚洲丁香婷婷综合久久| mm1313亚洲精品国产| 亚洲真人日本在线| 久久亚洲高清观看| 亚洲四虎永久在线播放| 亚洲国产综合在线| 亚洲人成色77777在线观看| 亚洲AV无码成人精品区大在线| 中文字幕亚洲无线码a| 亚洲国产精品成人精品无码区|