多输出模型
多输出模型指的是模型里边有多个输出。
实例:将图像以颜色和服饰分类
导入需要用的库
import tensorflow as tf
from tensorflow import keras
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
import pathlib
import IPython.display as display
根据图片路径提取图片
# 图片存放地址
data_dir = './multi-output-classification/dataset'
data_root = pathlib.Path(data_dir)
>>>WindowsPath('multi-output-classification/dataset')
for item in data_root.iterdir():
print(item)
>>>multi-output-classification\dataset\black_jeans
multi-output-classification\dataset\black_shoes
multi-output-classification\dataset\blue_dress
multi-output-classification\dataset\blue_jeans
multi-output-classification\dataset\blue_shirt
multi-output-classification\dataset\red_dress
multi-output-classification\dataset\red_shirt
# 获取所有图片路径
all_image_paths = list(data_root.glob('*/*'))
image_count = len(all_image_paths)
对获取的图片路径进行乱序处理并提取标签
# 将图片乱序
import random
all_image_paths = [str(path) for path in all_image_paths]
random.shuffle(all_image_paths)
# 从文件路径中获取对应的label
label_names = sorted(item.name for item in data_root.glob('*/') if item.is_dir())
>>>['black_jeans',
'black_shoes',
'blue_dress',
'blue_jeans',
'blue_shirt',
'red_dress',
'red_shirt']
# 将两个label拆分
color_label_names = set(name.split('_')[0] for name in label_names)
>>>{'black', 'blue', 'red'}
item_label_names = set(name.split('_')[1] for name in label_names)
>>>{'dress', 'jeans', 'shirt', 'shoes'}
为获取的标签生成索引
# 给颜色标签生成索引
color_label_to_index = dict((name,index) for index,name in enumerate(color_label_names))
>>>{'black': 0, 'blue': 1, 'red': 2}
# 给服饰标签生成索引
item_label_to_index = dict((name,index) for index,name in enumerate(item_label_names))
>>>{'dress': 0, 'jeans': 1, 'shirt': 2, 'shoes': 3}
提取图片对应标签并将其转为对应编码
# 提取图片标签
all_image_labels = [pathlib.Path(path).parent.name for path in all_image_paths]
# 拆分标签并将标签转为对应编码
color_labels = [color_label_to_index[label.split('_')[0]] for label in all_image_labels]
item_labels = [item_label_to_index[label.split('_')[1]] for label in all_image_labels]
随机选择三张图片显示
for n in range(3):
image_index = random.choice(range(len(all_image_paths)))
display.display(display.Image(all_image_paths[image_index],width=100,height=100))
print(all_image_labels[image_index])
加载和格式化图像
def load_and_preprocess_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
label = all_image_labels[0]
plt.imshow((load_and_preprocess_image(img_path) + 1)/2)
plt.grid(False)
plt.xlabel(label)
print()
创建训练和测试dataset数据集
# 创建路径dataset
path_ds = tf.data.Dataset.from_tensor_slices(all_image_paths)
AUTOTUNE = tf.data.experimental.AUTOTUNE
image_ds = path_ds.map(load_and_preprocess_image,num_parallel_calls=AUTOTUNE)
# 创建标签dataset
label_ds = tf.data.Dataset.from_tensor_slices((color_labels,item_labels))
image_label_ds = tf.data.Dataset.zip((image_ds,label_ds))
>>><ZipDataset shapes: ((224, 224, 3), ((), ())), types: (tf.float32, (tf.int32, tf.int32))>
# 划分train数据集和test数据集
test_count = int(image_count *0.2)
train_count = image_count - test_count
train_data = image_label_ds.skip(test_count)
test_data = image_label_ds.take(test_count)
BATCH_SIZE= 32
train_data = train_data.shuffle(buffer_size=train_count).repeat(-1)
train_data = train_data.batch(BATCH_SIZE)
train_data = train_data.prefetch(buffer_size=AUTOTUNE)
test_data = test_data.batch(BATCH_SIZE)
建立模型
# 初始化预训练网络mobilenet,不包含预训练网络头部,只使用网络架构,不使用权重
mobile_net = tf.keras.applications.MobileNetV2(input_shape=(224,224,3),include_top=False)
inputs = tf.keras.Input(shape=(224,224,3))
x = mobile_net(inputs)
x.get_shape()
>>>TensorShape([None, 7, 7, 1280])
x = tf.keras.layers.GlobalAveragePooling2D()(x)
x1 = tf.keras.layers.Dense(1024,activation='relu')(x)
output_color = tf.keras.layers.Dense(len(color_label_names),activation='softmax',name='output_color')(x1)
x2 = tf.keras.layers.Dense(1024,activation='relu')(x)
output_item = tf.keras.layers.Dense(len(item_label_names),activation='softmax',name='output_item')(x2)
model = tf.keras.Model(inputs=inputs,
outputs=[output_color,output_item])
model.summary()
多输出模型的编译与配置
model.compile(optimizer=tf.keras.optimizers.Adam(lr=0.0001),
loss={'output_color':'sparse_categorical_crossentropy',
'output_item':'sparse_categorical_crossentropy'},
metrics=['acc']
)
train_steps = train_count//BATCH_SIZE
test_steps = test_count//BATCH_SIZE
history = model.fit(train_data,
epochs=4,
steps_per_epoch=train_steps,
validation_data=test_data,
validation_steps=test_steps)