利用Xception预训练网络对猫狗数据分类
首先需要下载相关的数据集,可从kaggle官网进行下载。
导入包
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import glob
查看tensorflow的版本
print('Tensorflow version: {}'.format(tf.__version__))
Tensorflow version: 2.3
读取数据:
获取图片数据集,把数据标签转换为0和1,通过提取图片名字拆分定义该图是猫是狗,如果是猫标签转换为1
train_image = glob.glob('./dataset/dc_2000/train/*/*.jpg')
train_image_label = [int(p.split('/')[4] == 'cat') for p in train_image]
print(train_image_label[:5])
print(train_image_label[-5:])
[0, 0, 0, 0, 0]
[1, 1, 1, 1, 1]
图片加载与预处理,并进行图像增强
自定义训练数据函数
def load_image_train(path, label):
image = tf.io.read_file(path) #读取图片
image = tf.image.decode_jpeg(image, channels=3)# 对图片进行解码
image = tf.image.resize(image, [360, 360])# 对图片进行变形300*300像素
image = tf.image.random_crop(image, [256, 256, 3])# 对图片进行随机裁减为256*256像素
image = tf.image.random_flip_left_right(image)# 对图片进行左右翻转
image = tf.image.random_flip_up_down(image)# 对图片进行上下翻转
image = tf.image.random_brightness(image, 0.5)# 随机修改亮度 50%的范围
image = tf.image.random_contrast(image, 0, 1) #调整图像的对比度 在[lower, upper]的范围随机调整图的对比度
image = tf.cast(image, tf.float32) # 改变图片格式
image = image / 255# 对图片进行归一化
label = tf.reshape(label, [1])# 把目标值转换成2维形状 如:[1,2,3] =>[[1],[2],[3]]
return image, label
def load_image_test(path, label):
image = tf.io.read_file(path)
image = tf.image.decode_jpeg(image, channels=3)
image = tf.image.resize(image, [256, 256])
image = tf.cast(image, tf.float32)
image = image / 255
label = tf.reshape(label, [1])
return image, label
构建dataset
train_image_dataset = tf.data.Dataset.from_tensor_slices((train_image, train_image_label))
AUTOTUNE = tf.data.experimental.AUTOTUNE
train_image_dataset = train_image_dataset.map(load_image_train, num_parallel_calls=AUTOTUNE)
print(train_image_dataset)
AUTOTUNE 根据计算机cpu个数自动进行计算
BATCHSIZE = 64
train_count = len(train_image)
print("train_count={}".format(train_count))
train_image_dataset = train_image_dataset.repeat().shuffle(train_count).batch(BATCHSIZE)
train_image_dataset = train_image_dataset.prefetch(buffer_size=AUTOTUNE)
train_count=2000
构建测试集
test_image = glob.glob('./dataset/dc_2000/test/*/*.jpg')
test_image_label = [int(p.split('/')[4] == 'cat') for p in test_image]
test_image_dataset = tf.data.Dataset.from_tensor_slices((test_image, test_image_label))
test_image_dataset = test_image_dataset.map(load_image_test, num_parallel_calls=AUTOTUNE)
test_image_dataset = test_image_dataset.batch(BATCHSIZE)
test_image_dataset = test_image_dataset.prefetch(AUTOTUNE)
测试集数量
test_count = len(test_image)
print("test_count={}".format(test_count))
test_count=1000
加载Xception预训练网络的训练参数
conv_base = tf.keras.applications.VGG16(weights='imagenet', include_top=False, input_shape=(256, 256, 3), pooling='avg')
weights="imagenet"使用预训练权重,include_top= False不包含全链接层
建立模型
model = tf.keras.Sequential()
conv_base.trainable = False
conv_base.summary()
model.add(conv_base)
model.add(tf.keras.layers.Dense(512, activation='relu'))
model.add(tf.keras.layers.Dense(1, activation='sigmoid'))
conv_base.summary()
model.compile(optimizer=tf.keras.optimizers.Adam(lr=0.0005), loss='binary_crossentropy', metrics=['acc'])
model.fit(train_image_dataset, epochs=initial_epochs, steps_per_epoch=train_count//BATCHSIZE, validation_data=test_image_dataset, validation_steps=test_count//BATCHSIZE)
微调
initial_epochs = 5
conv_base.trainable=True
print(len(conv_base.layers))
fine_tune_at = -33
for layer in conv_base.layers[:fine_tune_at]:
conv_base.trainable = False
微调后,网络需要重新编译后再训练
model.compile(optimizer=tf.keras.optimizers.Adam(lr=0.0005/10), loss='binary_crossentropy', metrics=['acc'])
fine_tune_epochs = 5
total_epochs = fine_tune_epochs + initial_epochs
model.fit(train_image_dataset, epochs=total_epochs, initial_epoch=initial_epochs, steps_per_epoch=train_count//BATCHSIZE, validation_data=test_image_dataset, validation_steps=test_count//BATCHSIZE)