摘要
将深度学习与人物穿着上的服装图像分类结合是目前的研究热点之一,然而目前对服装图像分类主要是分成单个标签单独处理。在现实生活中,随着网络购物等服装商务新模式的出现、复杂决策的迫切需要,单标签服装图像分类已经不能解决问题,多标签服装图像分类成为一个重要的学习问题,展现出巨大的应用价值。多标签服装图像分类的目标是预测每张服装图像的一组服装属性标签。
1. 多标签分类定义
multi-label classification problem:多标签分类(或者叫多标记分类),是指一个样本的标签数量不止一个,即一个样本对应多个标签。
为了方便大家理解多标签,举个例子:一个女生穿个蓝色的裙子
那么黑色加粗字体的标签的可以设置为:
Black | Blue | Dress | Jeans | Red | Shirt | male | famale | .... | |
[“female' ‘red’ ’shirt’] | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | ... |
通过MultiLabelBinarizer()的fit就可以得到上述label的编码。
2. 多标签分类模型的输出问题
传统在进行实现多分类任务时,常采用softmax函数,其输出为:
z = np.array([-1.0, 5.0, -0.5, 5.0, -0.5])
print(Softmax_sim(z))
# 输出为[ 0.00123281 0.49735104 0.00203256 0.49735104 0.00203256]
通过使用softmax,我们可以清楚地选择标签2和标签4。但我们必须知道每个样本需要多少个标签,或者为概率选择一个阈值。这显然不是我们想要的,因为样本属于每个标签的概率应该是独立的。因此,在完成整个模型构建之后,最后一步中最重要的是为模型的编译选择损失函数。在多标签分类中,大多使用binary_crossentropy损失而不是在多类分类中使用categorical_crossentropy损失函数。这可能看起来不合理,但因为每个输出节点都是独立的,选择二元损失,并将网络输出建模为每个标签独立的bernoulli分布。整个多标签分类的模型为:
from keras.models import Model
from keras.layers import Input,Dense
inputs = Input(shape=(10,))
hidden = Dense(units=10,activation='relu')(inputs)
output = Dense(units=5,activation='sigmoid')(hidden)
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
3. 多标签数据集
本人的数据集有6类,在网上爬虫分类整理得到的。
女性蓝色裙子:female_bule_dress:415张
女性蓝色T袖:female_bule_shirt:311张
女性红色裙子:female_red_dress:259张
男性黑色T袖:male_black_shirt:257张
男性蓝色T袖:male_bule_shirt:247张
男性红色T袖:male_bule_shirt:194张
4. 模型实现与训练
class SmallerVGGNet:
@staticmethod
def build(width, height, depth, classes, finalAct="softmax"):
model = Sequential()
inputShape = (height, width, depth)
chanDim = -1
if K.image_data_format() == "channels_first":
inputShape = (depth, height, width)
chanDim = 1
model.add(Conv2D(32, (3, 3), padding="same",
input_shape=inputShape))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(MaxPooling2D(pool_size=(3, 3)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(Conv2D(64, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(128, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(Conv2D(128, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(1024))
model.add(Activation("relu"))
model.add(BatchNormalization())
model.add(Dropout(0.5))
model.add(Dense(classes))
model.add(Activation(finalAct))
# return the constructed network architecture
return model
5.实验结果展示
从上面的损失图中,我们可以看到训练损失在 20 个 epoch 结束之前非常平稳地下降。但是验证损失图波动很大。似乎训练时间超过 20 个 epoch 会导致过度拟合。最终,我们应用测试函数进行了测试:
数据集下载链接:
数据集加代码下载资源:
代码运行环境配置:python3.6.5,tensorflow==1.12,keras==2.2.4