服裝購買是一種繁重的體驗,眼睛被太多的資訊占據了。視覺系統吸收了大量資訊,我應該去賣哪件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釋出了一個新的資料集,它與衆所周知的
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.ipynb2-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'])
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'])
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'])
出于視覺目的,我繪制了教育訓練和驗證的準确性和損失:
VGG19-GPU.ipynb總結
時尚領域是一個非常受歡迎的機器學習和計算機視覺應用的戰場。由于高度的主觀性和所涉及的特征的語義複雜性,該領域中的問題具有挑戰性。我希望這篇文章有助于你了解建構自己的卷積神經網絡以對時尚圖像進行分類的4種不同方法。
本文由
阿裡雲雲栖社群組織翻譯。
文章原标題《the-4-convolutional-neural-network-models-that-can-classify-your-fashion-images》
作者:
James Le譯者:烏拉烏拉,審校:。
文章為簡譯,更為詳細的内容,請檢視
原文。