对服装数据进行类别和颜色分类,称为多输出模型。
/black_jeans,/black_shoes,/blue_dress,/blue_jeans,/blue_shirt,/red_dress,/red_shirt,共3种颜色,4个类别。
导入包
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
import random
import glob
import IPython.display as display
查看tensorflow的版本
print('Tensorflow version: {}'.format(tf.__version__))
Tensorflow version: 2.3
读取数据:
all_images = glob.glob('./dataset/*/*')
all_images_count = len(all_images)
print(len(all_images))
print(all_images[:5])
数据的数量和前5个数据
2525
['./dataset/black_jeans/00000364.jpeg',
'./dataset/black_jeans/00000204.jpeg',
'./dataset/black_jeans/00000169.png',
'./dataset/black_jeans/00000241.jpg', '
./dataset/black_jeans/00000145.jpg']
数据预处理
先建立两个集合,类别结合和颜色集合
color_labels_names = set(p.split('/')[2].split('_')[0] for p in all_images)
item_labels_names = set(p.split('/')[2].split('_')[1] for p in all_images)
print(color_labels_names)
print(item_labels_names)
集合一3种颜色,集合二4个类别
{'red', 'black', 'blue'}
{'dress', 'jeans', 'shoes', 'shirt'}
两个集合数据进行编码
color_labels_to_index = dict((name,index) for index, name in enumerate(color_labels_names))
item_labels_to_index = dict((name,index) for index, name in enumerate(item_labels_names))
print(color_labels_to_index)
print(item_labels_to_index)
{'red': 0, 'black': 1, 'blue': 2}
{'dress': 0, 'jeans': 1, 'shoes': 2, 'shirt': 3}
前五个数据的类别和颜色
all_images_labels = sorted([p.split('/')[2] for p in all_images])
print(all_images_labels[:5])
['black_jeans', 'black_jeans', 'black_jeans', 'black_jeans', 'black_jeans']
把"black_jeans" 这种类别和颜色分开处理
颜色标签和数量
color_labels = [color_labels_to_index[label.split('_')[0]] for label in all_images_labels]
print(color_labels[:5])
print(len(color_labels))
[1, 1, 1, 1, 1]
2525
类别标签和数量
item_labels = [item_labels_to_index[item.split('_')[1]] for item in all_images_labels]
print(item_labels[:5])
print(len(item_labels))
[1, 1, 1, 1, 1]
2525
自定义一个函数,完成图片的读取,解码,形状变化,类型变化,标准化
def load_image(path):
image = tf.io.read_file(path)
image = tf.image.decode_jpeg(image, channels=3)
image = tf.image.resize(image, [224, 224])
image = tf.cast(image, tf.float32)
image = image/255.0
image = 2 * image - 1
return image
利用tf.data模块构建dataset
image_dataset = tf.data.Dataset.from_tensor_slices(all_images)
AUTOTUNE = tf.data.experimental.AUTOTUNE
AUTOTUNE 根据计算机cpu个数自动进行计算
image_dataset map到自定义函数上。
image_dataset = image_dataset.map(load_image, num_parallel_calls=AUTOTUNE)
利用tf.data模块构建label_dataset ,把颜色和类别构造到一个dataset中
label_dataset = tf.data.Dataset.from_tensor_slices((color_labels, item_labels))
print(image_label_dataset)
查看label_dataset中的元素
for ele in label_dataset.take(3):
print(ele[0].numpy(), ele[1].numpy())
0 2
0 2
0 2
构造数据集,把图片和label ZIP在一起
image_label_dataset = tf.data.Dataset.zip((image_dataset, label_dataset))
print(image_label_dataset)
设置训练数据和测试数据的数量
test_count = int(all_images_count * 0.2)
train_count = all_images_count - test_count
划分训练集和测试集
train_dataset = image_label_dataset.skip(test_count)
test_dataset = image_label_dataset.take(test_count)
设置每批次输入的数据量大小
BATCHSIZE = 32
设置训练和测试输入模式
train_dataset = train_dataset.shuffle(buffer_size=train_count).repeat().batch(BATCHSIZE)
train_dataset = train_dataset.prefetch(buffer_size=AUTOTUNE)#电脑根据内存预先读取数据等待训练
test_dataset = test_dataset.batch(BATCHSIZE)
print(train_dataset)
print(test_dataset)
加载MobileNetV2预训练网络参数,设置训练参数不可训练
mobile_net = tf.keras.applications.MobileNetV2(input_shape=(224, 224, 3), include_top=False, weights='imagenet')
mobile_net.trainable = False
mobile_net.summary()
模型的输入
inputs = tf.keras.Input(shape=(224, 224, 3))
x = mobile_net(inputs)
print(x.get_shape()) #mobile_net输出的形状
x = tf.keras.layers.GlobalAveragePooling2D()(x)
print(x.get_shape())#mobile_net输出是4维,所以在全连接输出前要使用GlobalAveragePooling2D
(None, 7, 7, 1280)
(None, 1280)
构建模型的输出,因为是要类别和颜色分别预测,所以有两个输出
x1 = tf.keras.layers.Dense(1024, activation='relu')(x)
out_color = tf.keras.layers.Dense(len(color_labels_names), activation='softmax', name='out_color')(x1)
x2 = tf.keras.layers.Dense(1024, activation='relu')(x)
out_item = tf.keras.layers.Dense(len(item_labels_names), activation='softmax', name='out_item')(x2)
model = tf.keras.Model(inputs=inputs, outputs=[out_color, out_item])
model.summary()
模型编译
model.compile(optimizer=tf.keras.optimizers.Adam(lr=0.0001),
loss={
'out_color': 'sparse_categorical_crossentropy', 'out_item': 'sparse_categorical_crossentropy'},
metrics=['acc'])
设置训练批次
train_steps = train_count//BATCHSIZE
test_steps = test_count//BATCHSIZE
模型训练
model.fit(train_dataset, epochs=5, steps_per_epoch=train_steps, validation_data=test_dataset, validation_steps=test_steps)
模型评估
print(model.evaluate(test_dataset)) #输出5个指标
my_image = load_image(r'./dataset/blue_jeans/00000001.jpeg')
print(my_image.shape)
my_image = tf.expand_dims(my_image, 0)#因为训练的时候是以batch的形式输入的,所以要维度扩张
print(my_image.shape)
pred = model.predict(my_image)
print(pred)
print(np.argmax(pred[1]))
[4.383560657501221, 0.25813135504722595, 4.125428676605225, 0.908910870552063, 0.31881189346313477]
(224, 224, 3)
(1, 224, 224, 3)
[array[[0.00171686, 0.00872022,0.98965629, ]],dtype=float32),
array[[ 3.9509824e-04,9.9927169e-01 , 3.298579e-04,3.3366025e-6]],dtype=float32)]
1
```{'red': 0, 'black': 1, 'blue': 2}
{'dress': 0, 'jeans': 1, 'shoes': 2, 'shirt': 3}
多分类输出,pred输出的是两个维度,第一维度pred[0]是颜色长度为3,0.98965629这个概率最大处在第三位,所以预测颜色是blue,第二维度pred[1]是类别, 9.9927169e-01,预测类别的概率最大值是99%,为jeans。