不懂影象分類?這四種卷積神經網路模型瞭解一下!
服裝購買是一種繁重的體驗,眼睛被太多的資訊佔據了。視覺系統吸收了大量資訊,我應該去賣哪件H&M卡其褲嗎?那是Nike背心嗎?
機器能自動檢測襯衫、褲子、連衣裙和運動鞋的圖片嗎?事實證明,用高質量的訓練資料對機器進行訓練,準確地對時尚物品的影象進行分類是可行的。在本教程中,我們將從頭開始構建一個機器學習模型,使用Fashion-MNIST資料集訓練它們。我們將介紹如何訓練模型、設計類別分類的輸入和輸出,最後顯示每個模型的準確度結果。
影象分類
影象分類是這樣的:給定一組全部用單一類別標記的影象,我們要求為一組新的測試影象預測它們到底是什麼類別?並測量預測的準確性。這項任務涉及各種挑戰,包括視點變化、尺度變化、類內變化、影象變形、影象遮擋、光照條件、背景雜波等。
我們如何編寫可以將影象分類為不同類別的演算法?計算機視覺研究人員已經提出了一種資料驅動方法來解決這個問題。它們不是試圖直接在程式碼中指定每個感興趣的影象類別,而是為計算機提供每個影象類的許多示例,然後開發學習演算法,檢視這些示例並瞭解每個類的視覺外觀。換句話說,他們首先累積標記影象的訓練資料集,然後將其提供給計算機,以使其熟悉資料。
鑑於這一事實,完整的影象分類管道可以形式化如下:
· 輸 入是一個 訓練 資料集,由 N 個 圖 像 組 成,每個 圖 像都 標 有 K 個 不同 類別 中的一個。
· 然後,我 們 使用此 訓練 集來 訓練 分 類 器,以瞭解每個 類 的外 觀 。
· 最後,我 們 通 過 要求分 類 器 預測 從未 見過 的一 組 新 圖 像的 標籤 來 評 估分 類 器的 質 量。然後,我 們 將比 較這 些 圖 像的真 實標籤 與分 類 器 預測 的 標籤 。
卷 積 神 經 網 絡
卷積神經網路(CNN) 是用於影象分類問題的最流行的神經網路模型。CNN背後的一個重要思想是,對影象的區域性理解是好的。實際的好處是,引數少將大大縮短了學習所需的時間,並減少了訓練模型所需的資料量。CNN具有足夠的權重來檢視影象的小塊,而不是來自每個畫素的完全連線的權重網路。
比如一個256 x 256的影象。CNN可以通過區域性有效地掃描它,例如,用一個5×5的視窗,通常從左到右,從上到下,如下圖所示。它如何“快速”滑動稱為其 步幅 。例如,步幅長度2表示5×5滑動視窗一次移動2個畫素,直到它跨越整個影象。
卷積 是影象的畫素值的加權和,事實證明,整個帶有權重矩陣的影象的卷積過程會產生另一個影象。
滑動視窗發生在神經網路的 卷積層 中,典型的CNN具有多個卷積層。每個卷積層通常產生許多交替卷積,因此權重矩陣是5×5×n的張量,其中n是卷積數。
例如,假設影象通過5×5×64的權重矩陣上的卷積層。它通過滑動5×5視窗生成64個卷積。因此,該模型具有5×5×64=1,600個引數,其引數明顯少於完全連線的網路,256×256= 65,536個。
CNN 的優點在於引數的數量與原始影象的大小無關。你可以在300×300影象上執行相同的CNN,但卷積層中的引數數量不會改變。
資料 增強 (data augmentation)
影象分類研究資料集通常是非常大的。然而,經常使用資料增強來改善泛化屬性。通常,使用重新縮放影象的隨機裁剪以及隨機水平閃爍和隨機RGB顏色和亮度偏移。這其中存在用於重新縮放和裁剪影象的不同方案(即,單一規模與多規模訓練)。請注意,隨機重新縮放和裁剪的目標是學習不同尺度和位置的每個物件的重要特徵,不幸的是Keras沒有實現所有這些開箱即用的資料增強技術,
Fashion MNIST 資料集
最近,Zalando釋出了一個新的資料集,它與眾所周知的 ofollow,noindex"> MNIST 手寫數字資料庫 非常相似。該資料集專為機器學習分類任務而設計,包含總共60000個訓練和10000個測試影象(灰度),每個28x28畫素。每個訓練和測試用例與十個標籤之一(0-9)相關聯。直到這裡,Zalando的資料集基本上與原始手寫數字資料相同。然而,Zalando的資料不包含數字0-9的影象,而是包含10種不同時尚產品的影象。因此,資料集稱為 Fashion-MNIST 資料集 ,可以從 GitHub 下載。這些資料也可以在 Kaggle 上 下載 。下圖中顯示了一些示例,其中每行包含一個時尚項。
10 個不同的類別標籤是:
1 、T 恤 / 上衣 ;2、 褲 子;3、套 頭 衫; 4 、 連衣 裙; 5 、 外套;
6 、 涼鞋 ;7、 襯 衫;8、運 動 鞋;9、袋;10、靴子;
據作者稱,Fashion-MNIST資料旨在成為舊MNIST手寫數字資料的直接替代品,因為手寫數字存在若干問題。例如,通過簡單地檢視幾個畫素,可以正確地區分幾個數字。即使使用線性分類器,也可以實現高分類精度。Fashion-MNIST資料有望更加多樣化,因此機器學習(ML)演算法必須學習更多高階特徵,以便能夠可靠地分離各個類。
時 尚 MNIST 的 嵌入 可 視 化 (Embedding Visualization)
嵌入是一種將離散物件(影象,單詞等)對映到高維向量的方法。這些載體中的各個維度通常沒有固有的含義。相反,它是機器學習利用向量之間的位置和距離的整體模式。因此,嵌入對於機器學習的輸入很重要;因為分類器和神經網路更普遍地用於實數向量。它們在密集向量上訓練最好,其中所有值都有助於定義物件。
TensorBoard 有一個內建的視覺化器,稱為 嵌入式 視覺化工具( Embedding Projector ) ,用於互動式視覺化和分析嵌入等高維資料。嵌入式視覺化工具將從我的模型檢查點檔案中讀取嵌入,雖然它對嵌入最有用,但它會載入任何2D張量,包括訓練權重。
在這裡,我將嘗試使用TensorBoard表示高維時尚MNIST資料。在讀取資料並建立測試標籤後,我使用此程式碼構建TensorBoard的嵌入投影儀:
from tensorflow.contrib.tensorboard.plugins import projector logdir = 'fashionMNIST-logs' # Creating the embedding variable with all the images defined above under X_test embedding_var = tf.Variable(X_test, name='fmnist_embedding') # Format: tensorflow/contrib/tensorboard/plugins/projector/projector_config.proto config = projector.ProjectorConfig() # You can add multiple embeddings. Here I add only one. embedding = config.embeddings.add() embedding.tensor_name = embedding_var.name # Link this tensor to its metadata file (e.g. labels). embedding.metadata_path = os.path.join(logdir, 'metadata.tsv') # Use this logdir to create a summary writer summary_writer = tf.summary.FileWriter(logdir) # The next line writes a projector_config.pbtxt in the logdir. TensorBoard will read this file during startup. projector.visualize_embeddings(summary_writer,config) # Periodically save the model variables in a checkpoint in logdir. with tf.Session() as sesh: sesh.run(tf.global_variables_initializer()) saver = tf.train.Saver() saver.save(sesh, os.path.join(logdir, 'model.ckpt')) # Create the sprite image rows = 28 cols = 28 label = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot'] sprite_dim = int(np.sqrt(X_test.shape[0])) sprite_image = np.ones((cols * sprite_dim, rows * sprite_dim)) index = 0 labels = [] for i in range(sprite_dim): for j in range(sprite_dim): labels.append(label[int(Y_test[index])]) sprite_image[ i * cols: (i + 1) * cols, j * rows: (j + 1) * rows ] = X_test[index].reshape(28, 28) * -1 + 1 index += 1 # After constructing the sprite, I need to tell the Embedding Projector where to find it embedding.sprite.image_path = os.path.join(logdir, 'sprite.png') embedding.sprite.single_image_dim.extend([28, 28]) # Create the metadata (labels) file with open(embedding.metadata_path, 'w') as meta: meta.write('Index\tLabel\n') for index, label in enumerate(labels): meta.write('{}\t{}\n'.format(index, label))
嵌入視覺化工具有三種減少資料集維數的方法:兩個線性和一個非線性。每種方法都可用於建立二維或三維檢視。
主成分分析: 主成分分析(PCA)是一種簡單的減小尺寸的技術。嵌入視覺化工具有10個主要元件。PCA是一種線性視覺化效果,通常可用於檢查全域性幾何。
t-SNE :這是 一種流行的非 線 性降 維 技 術 是 t-SNE 。嵌入視覺化工具提供二 維 和三 維 t-SNE 檢視 。在客 戶 端 執 行區域性 動 畫演算法的每個步 驟 ,因 為 t-SNE 通常保留一些區域性 結 構,所以它 對 於探索區域性 鄰 域和 尋 找聚 類 是有用的。
自定 義(custom) : 我們 還 可以根據文字搜尋構建 專門 的 線 性視覺化,以便在空 間 中找到有意 義 的方向。首先定 義 可視 軸 , 接著輸 入兩個搜尋字串或正 則 表示式。程式 計 算其 標籤 與 這 些搜尋匹配的點集的 質 心,並使用 質 心之 間 的差向量作 為 可視 軸 。
你可以在此筆記本中檢視視覺化步驟的完整程式碼: TensorBoard-Visualization.ipynb
在 時 尚 MNIST 上訓練 CNN 模型
現在讓我們轉到有趣的部分:我將建立各種不同的基於CNN的分類模型來評估Fashion MNIST的表現。我將使用Keras框架構建我們的模型,關於它的更多資訊,請參閱 此處 的文件。以下是我將嘗試的模型列表,並比較它們的結果:
1. 具有 1 個卷 積層的 CNN ;
2. 具有 3 個卷 積層的 CNN ;
3. 有 4 個卷 積層的 CNN ;
4. VGG-19 預訓練模 型;
對於所有模型(預訓練模型除外),這是我常用的方式:
· 將原始 訓練 資料( 60,000 張影象)分 成 80 % 訓練集 ( 48,000 張影象) 和 20 % 驗證集 ( 12000 張影象)優化分類器,同時保留測試資料( 10,000 張影象)以最終評估模型對資料的準確性從未見過 。 這有助於瞭解我是否過度擬合訓練資料,以及如果驗證準確度高於訓練準確度 。
· 訓練模型 10 個 epoch ,批量大小 為 256 ,使用 categorical_crossentropy 損失函式 和 Adam 優化 器。
· 然後,新增 資料增 強 ,通 過 旋 轉 、移 動 和 縮 放 訓練樣 本生成新的 訓練樣 本,並在更新的資料上 訓練 模型另外 50 個 epoch 。
這是載入和增強資料的程式碼:
# Import libraries from keras.utils import to_categorical from sklearn.model_selection import train_test_split # Load training and test data into dataframes data_train = pd.read_csv('data/fashion-mnist_train.csv') data_test = pd.read_csv('data/fashion-mnist_test.csv') # X forms the training images, and y forms the training labels X = np.array(data_train.iloc[:, 1:]) y = to_categorical(np.array(data_train.iloc[:, 0])) # Here I split original training data to sub-training (80%) and validation data (20%) X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=13) # X_test forms the test images, and y_test forms the test labels X_test = np.array(data_test.iloc[:, 1:]) y_test = to_categorical(np.array(data_test.iloc[:, 0]))
在加 載 和增強資料之後,我通 過 將它 們 重新重構 為 網 絡 所需的形狀並 對 其 進 行 縮 放以使所有 值 都在 [0,1] 間隔中來對它們進行預處理 。例如,以前, 訓練 資料存 儲 在 uint8 型別的形狀( 60000,28,28 )的數 組 中,其 值 在 [0,255] 間隔中 。我將它 轉換為 float32 數 組 形狀( 60000,28 * 28 ),其 值 介於 0 和 1 之 間 。
# Each image's dimension is 28 x 28 img_rows, img_cols = 28, 28 input_shape = (img_rows, img_cols, 1) # Prepare the training images X_train = X_train.reshape(X_train.shape[0], img_rows, img_cols, 1) X_train = X_train.astype('float32') X_train /= 255 # Prepare the test images X_test = X_test.reshape(X_test.shape[0], img_rows, img_cols, 1) X_test = X_test.astype('float32') X_test /= 255 # Prepare the validation images X_val = X_val.reshape(X_val.shape[0], img_rows, img_cols, 1) X_val = X_val.astype('float32') X_val /= 255
1- 1-Conv CNN
以下是具有1個卷積層的CNN的程式碼:
from keras.models import Sequential from keras.layers import Dense, Dropout, Flatten from keras.layers import Conv2D, MaxPooling2D cnn1 = Sequential() cnn1.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=input_shape)) cnn1.add(MaxPooling2D(pool_size=(2, 2))) cnn1.add(Dropout(0.2)) cnn1.add(Flatten()) cnn1.add(Dense(128, activation='relu')) cnn1.add(Dense(10, activation='softmax')) cnn1.compile(loss=keras.losses.categorical_crossentropy, optimizer=keras.optimizers.Adam(), metrics=['accuracy'])
訓練模型後,這裡是test loss和測試精度 :
應用資料增強後,這裡是測試損失和測試準確度 :
出於 視覺 目的,我 繪 制了訓練和 驗證 的準確性和 損 失:
你可以在此筆記本上檢視此型號的完整程式碼: CNN-1Conv.ipynb
2- 3-Conv CNN
以下是CNN與3卷積層的程式碼:
from keras.models import Sequential from keras.layers import Dense, Dropout, Flatten from keras.layers import Conv2D, MaxPooling2D cnn3 = Sequential() cnn3.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=input_shape)) cnn3.add(MaxPooling2D((2, 2))) cnn3.add(Dropout(0.25)) cnn3.add(Conv2D(64, kernel_size=(3, 3), activation='relu')) cnn3.add(MaxPooling2D(pool_size=(2, 2))) cnn3.add(Dropout(0.25)) cnn3.add(Conv2D(128, kernel_size=(3, 3), activation='relu')) cnn3.add(Dropout(0.4)) cnn3.add(Flatten()) cnn3.add(Dense(128, activation='relu')) cnn3.add(Dropout(0.3)) cnn3.add(Dense(10, activation='softmax')) cnn3.compile(loss=keras.losses.categorical_crossentropy, optimizer=keras.optimizers.Adam(), metrics=['accuracy'])
訓練模型後,這裡是test loss和測試精度 :
應用資料增強後,這裡是測試損失和測試準確度 :
出於 視覺 目的,我 繪 制了訓練和 驗證 的準確性和 損 失:
你可以在此筆記本上檢視此型號的完整程式碼: CNN-3Conv.ipynb
3- 4-Conv CNN
以下是具有4個卷積層的CNN的程式碼:
from keras.models import Sequential from keras.layers import Dense, Dropout, Flatten from keras.layers import Conv2D, MaxPooling2D, BatchNormalization cnn4 = Sequential() cnn4.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=input_shape)) cnn4.add(BatchNormalization()) cnn4.add(Conv2D(32, kernel_size=(3, 3), activation='relu')) cnn4.add(BatchNormalization()) cnn4.add(MaxPooling2D(pool_size=(2, 2))) cnn4.add(Dropout(0.25)) cnn4.add(Conv2D(64, kernel_size=(3, 3), activation='relu')) cnn4.add(BatchNormalization()) cnn4.add(Dropout(0.25)) cnn4.add(Conv2D(128, kernel_size=(3, 3), activation='relu')) cnn4.add(BatchNormalization()) cnn4.add(MaxPooling2D(pool_size=(2, 2))) cnn4.add(Dropout(0.25)) cnn4.add(Flatten()) cnn4.add(Dense(512, activation='relu')) cnn4.add(BatchNormalization()) cnn4.add(Dropout(0.5)) cnn4.add(Dense(128, activation='relu')) cnn4.add(BatchNormalization()) cnn4.add(Dropout(0.5)) cnn4.add(Dense(10, activation='softmax')) cnn4.compile(loss=keras.losses.categorical_crossentropy, optimizer=keras.optimizers.Adam(), metrics=['accuracy'])
訓練模型後,這裡是test loss和測試精度 :
應用資料增強後,這裡是測試損失和測試準確度 :
出於 視覺 目的,我 繪 制了訓練和 驗證 的準確性和 損 失:
你可以在此筆記本上檢視此型號的完整程式碼: CNN-4Conv.ipynb
4–遷移學習
對小影象資料集進行深度學習的常用且高效的方法是使用預先訓練的網路。一個 預先訓練網路 是以前訓練的大型資料集,通常在大型影象分類任務儲存的網路。如果這個原始資料集足夠大且足夠通用,則預訓練網路所學習的特徵的空間層次結構可以有效地充當視覺世界的通用模型,因此其特徵可以證明對於許多不同的計算機視覺問題是有用的。即使這些新問題可能涉及與原始任務完全不同的類。
我試圖實現VGG19預訓練模型,這是ImageNet廣泛使用的ConvNets架構。這是你可以遵循的程式碼:
import keras from keras.applications import VGG19 from keras.applications.vgg19 import preprocess_input from keras.layers import Dense, Dropout from keras.models import Model from keras import models from keras import layers from keras import optimizers # Create the base model of VGG19 vgg19 = VGG19(weights='imagenet', include_top=False, input_shape = (150, 150, 3), classes = 10) # Preprocessing the input X_train = preprocess_input(X_train) X_val = preprocess_input(X_val) X_test = preprocess_input(X_test) # Extracting features train_features = vgg19.predict(np.array(X_train), batch_size=256, verbose=1) test_features = vgg19.predict(np.array(X_test), batch_size=256, verbose=1) val_features = vgg19.predict(np.array(X_val), batch_size=256, verbose=1) # Flatten extracted features train_features = np.reshape(train_features, (48000, 4*4*512)) test_features = np.reshape(test_features, (10000, 4*4*512)) val_features = np.reshape(val_features, (12000, 4*4*512)) # Add Dense and Dropout layers on top of VGG19 pre-trained model = models.Sequential() model.add(layers.Dense(512, activation='relu', input_dim=4 * 4 * 512)) model.add(layers.Dropout(0.5)) model.add(layers.Dense(10, activation="softmax")) # Compile the model model.compile(loss=keras.losses.categorical_crossentropy, optimizer=keras.optimizers.Adam(), metrics=['accuracy'])
訓練模型後,這裡是test loss和測試精度 :
出於 視覺 目的,我 繪 制了培 訓 和 驗證 的準確性和 損 失:
你可以在此筆記本上檢視此型號的完整程式碼: GPU.ipynb" target="_blank" rel="nofollow,noindex"> VGG19-GPU.ipynb
總結
時尚領域是一個非常受歡迎的機器學習和計算機視覺應用的戰場。由於高度的主觀性和所涉及的特徵的語義複雜性,該領域中的問題具有挑戰性。我希望這篇文章有助於你瞭解構建自己的卷積神經網路以對時尚影象進行分類的4種不同方法。
本文由 阿里云云棲社群 組織翻譯。
文章原標題《the-4-convolutional-neural-network-models-that-can-classify-your-fashion-images》
作者: James Le 譯者:烏拉烏拉,審校:。
文章為簡譯,更為詳細的內容,請檢視 原文 。