在實體店買衣服的過程中,我們會被眼花繚亂的信息轟炸。要兼顧某件衣服的款式、價格、商場優惠還不夠,商場的燈光、擁擠的過道,無時無刻不在考驗著人們分辨信息的能力。
那么,電腦能自動檢測襯衫、褲子、連衣裙或運動鞋的照片嗎?事實證明,如果有高質量的訓練數據,準確地對時尚單品圖片進行分類是很很容易做到的。在本文中,我們將講解如何用Fashion-MNIST數據集搭建一個用于辨認時尚單品的機器學習模型。我們會提到如何訓練模型、針對類別分類設計輸入和輸出以及每個模型的最終結果。
圖像分類
這一任務中涉及到的問題包括視角的變化、尺度變化、同類的多種變化、照片形變、照片遮擋、光線條件、背景等問題。如何寫出一套可以區分圖片類型的算法呢?計算機視覺研究人員提出了一種數據驅動的方法來解決。過去,人們會了解每一圖片類別的代碼,從而進行分類?,F在,研究人員從每類圖像中都選出一些樣本,訓練深度學習算法學習每種類別的特點。換句話說,他們首先收集帶標簽的訓練數據集,然后輸入到計算機中,讓計算機熟悉這些數據。
主要步驟如下:
輸入的是一個含有N張圖片的數據集,每張圖片都帶有類別標簽,數據集中共有K個不同的類別。
之后,我們用訓練集去訓練一個分類器,學習每種類別的樣式。
最后,讓分類器對陌生圖片進行標簽預測,從而對分類器質量進行評估。之后我們會比較真實標簽和分類器的預測標簽。
Fashion MNIST數據集
去年八月份,德國研究機構Zalando Research在GitHub上推出了一個全新的數據集,其中訓練集包含60000個樣例,測試集包含10000個樣例,分為10類,其中的樣本都來自日常穿著的衣褲鞋包,每個都是28×28的灰度圖像,其中總共有10類標簽,每張圖像都有各自的標簽。
10種標簽包括:
0:T-shirt/上衣
1:褲子
2:套頭衫
3:連衣裙
4:大衣
5:涼鞋
6:襯衣
7:運動鞋
8:包
9:高幫鞋
Fashion MNIST的可視化嵌入
嵌入是一種將分散目標(圖像、文字等等)映射到高維向量中的方法。這些向量中的每個維度通常都沒有內在意義,機器學習運用的是想兩件的距離和總體的模式。在這里,我打算用TensorBoard表示高維的Fashion 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 Label ')
for index, label in enumerate(labels):
meta.write('{} {} '.format(index, label))
該投射器有三種對數據集降維的方法,兩種線性方法,一種非線性方法。每種方法都能用于創建二維或三維場景。
PCA:PCA是一種用于直接降維的技術,嵌入投射器計算前十位的主要成分,通過菜單,我們可以將那些成分投射成任意兩種或三種的結合上。PCA是一個線性工具,通常在檢查全局幾何結構上非常高效。
t-SNE:這是一種流行的非線性降維方法,嵌入投射器會同時提供二維和三維的t-SNE視圖。在客戶端可以看到平面圖,能展示出每一步算法。由于t-SNE通常會保留一些局部結構,這在探索局部近鄰、找尋聚類中是很有用的。
Custom:我還可以基于文本搜索創建特殊的線性投射器,用于在空間中尋找有意義的方向。程序可以計算這些點集的中心點,他們的標簽可以與搜索匹配,利用向量之間的不同作為投射器的軸。
查看完成的可視化步驟代碼,可點擊此網址:github.com/khanhnamle1994/fashion-mnist/blob/master/TensorBoard-Visualization.ipynb
在Fashion MNIST上訓練CNN模型
接下來,我會創建多個基于CNN的分類模型,在Fashion MNIST上評估模型性能。我會用Keras框架搭建模型,想了解框架的更多信息,可以點擊此網址:keras.io/。下面是我想要比較的四種模型:
有一層卷積層的CNN
有三層卷積層的CNN
有四層卷積層的CNN
經過與訓練的VGG-19模型
除了預訓練模型,我的實驗方法如下:
將原始訓練數據(共60000張圖片)分成訓練集和驗證集兩部分,80%是訓練集,20%是驗證集,另外還有10000張測試圖片,用于最終測試模型在陌生圖像上的表現。這可以研究模型是否在訓練數據上過度擬合,以及是否應該降低學習速率。
用256的batch size訓練模型10個epoch,同時用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之間。此前,訓練數據都被存儲在一個(60000,28,28)的數組中,其中的值在0到255之間。
# 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
一層卷積層CNN
下面是只有一層卷積層的CNN代碼:
from keras.models importSequential
from keras.layers importDense, Dropout, Flatten
from keras.layers importConv2D, 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'])
訓練完模型后,下面是測試損失和測試精確度:
進行數據增強后的測試損失和測試精確度:
訓練和驗證精確度和損失的可視化:
完整代碼請點擊:github.com/khanhnamle1994/fashion-mnist/blob/master/CNN-1Conv.ipynb
三層卷積層CNN
有三層卷積層的CNN代碼:
from keras.models importSequential
from keras.layers importDense, Dropout, Flatten
from keras.layers importConv2D, 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'])
訓練模型后,測試損失和測試精確度:
數據增強后的測試損失和精確度:
訓練和驗證的精確度和損失:
完整代碼請點擊:github.com/khanhnamle1994/fashion-mnist/blob/master/CNN-3Conv.ipynb
四層卷積層的CNN
下面是四層卷積層的CNN代碼:
from keras.models importSequential
from keras.layers importDense, Dropout, Flatten
from keras.layers importConv2D, 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'])
訓練模型后的測試損失和精確度:
數據增強后的測試損失和精確度:
訓練和驗證的精確度和損失:
完整代碼請點擊:github.com/khanhnamle1994/fashion-mnist/blob/master/CNN-4Conv.ipynb
遷移學習
在小數據集上常用的一種高效深度學習方法就是使用預訓練網絡。一種預訓練網絡是此前在大型數據集上訓練過的網絡,通常處理過大型圖像分類任務。如果這樣的原始數據集足夠大并且足夠通用,那么預訓練網絡學習到的特征空間分層可以用于視覺世界的普通模型,它的特征可以解決很多不同的計算機視覺問題。
我嘗試使用VGG19預訓練模型,這在ImageNet中廣泛使用的ConvNets架構。以下是所用的代碼:
import keras
from keras.applications import VGG19
from keras.applications.vgg19 import preprocess_input
from keras.layers importDense, Dropout
from keras.models importModel
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'])
模型訓練后,測試損失和精確度如下:
可視化:
結語
時尚領域是計算機視覺和機器學習應用的熱門,由于其中的予以復雜性,導致問題難度增加。希望這篇文章能對你在圖像分類任務上有所啟發。
-
神經網絡
+關注
關注
42文章
4773瀏覽量
100890 -
機器學習
+關注
關注
66文章
8424瀏覽量
132766 -
數據集
+關注
關注
4文章
1208瀏覽量
24737
原文標題:用卷積神經網絡模型辨認不同時尚服裝,四種方法對比
文章出處:【微信號:jqr_AI,微信公眾號:論智】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論