import tensorflow as tf import matplotlib.pyplot as plt %matplotlib inline import numpy as np import glob import os

打印Tensorflow版本

1
print('Tensorflow version:{}'.format(tf.__version__))

打印是否支持GPU加速

1
print(tf.test.is_gpu_available())

设置keras与layers(方便调用)

1
2
keras = tf.keras
layers = tf.keras.layers

读取train、test数据集图片路径

1
2
train_image_path = glob.glob('./dc_2000/train/*.jpg')
test_image_path = glob.glob('./dc_2000/test/*.jpg')

将路径的图片名称提取出来

1
2
train_image_label = [label.split('\\')[1].split('.')[0] for label in train_image_path]
test_image_label = [label.split('\\')[1].split('.')[0] for label in test_image_path]

图片label有哪些

1
label_names = np.unique(train_image_label)#返回单个不重复元素的列表

标签与下标之间的转换

  • Label to Index

1
label_to_index = dict((name,i) for i,name in enumerate(label_names)) 
  • Index to Label

1
index_to_label = dict((i,name) for name,i in label_to_index.items())

train_label和test_label转index

1
2
3
#cat -> 0 ,dog -> 1
train_image_label = [label_to_index.get(name) for name in train_image_label]
test_image_label = [label_to_index.get(name) for name in test_image_label]

图片加载函数

1
2
3
4
5
6
7
8
def load_preprosess_image(path,label):
image = tf.io.read_file(path)#读取
image = tf.image.decode_jpeg(image,channels=3)#channel默认0,因为是彩色图像有RGB三个通道
image = tf.image.resize(image,[256,256])#resize
image = tf.cast(image,tf.float32)#改变数据类型
image = image /255#归一化
# label = tf.reshape(label,[1])#变化维度 [1,2,3] -> [[1],[2],[3]]
return image,label

设置AUTOTUNE

1
AUTOTUNE = tf.data.experimental.AUTOTUNE#AUTOTUNE根据CPU的个数自动使用进行运算

设置train_Dataset

1
2
train_image_ds = tf.data.Dataset.from_tensor_slices((train_image_path,train_image_label))#train图片路径与对应label
train_image_ds = train_image_ds.map(load_preprosess_image,num_parallel_calls=AUTOTUNE)#num_parallel_calls是cpu个数,默认None,传入AUTOTUNE可以最大限度发挥速度(并行运算)

设置test_Dataset

1
2
test_image_ds = tf.data.Dataset.from_tensor_slices((test_image_path,test_image_label))#test图片路径与对应label
test_image_ds = test_image_ds.map(load_preprosess_image,num_parallel_calls=AUTOTUNE)#num_parallel_calls是cpu个数,默认None,传入AUTOTUNE可以最大限度发挥速度(并行运算)

定义BATCH_SIZE大小

1
2
# 设置BATCH
BATCH_SIZE = 32

获取train、test的数据长度

1
2
train_count = len(train_image_path)
test_count = len(test_image_path)

对train_Dataset数据进行乱序、定义批次和加速运行

1
2
train_image_ds = train_image_ds.shuffle(train_count).repeat().batch(BATCH_SIZE)#buffer_size 多大范围进行乱序
train_image_ds = train_image_ds.prefetch(AUTOTUNE)#在后台,一部分数据进行训练过程中读取另外一部分数据,能加速训练过程,prefetch(buffer_size) 让计算机自己计算

对test_Dataset数据定义批次和加速运行

1
2
test_image_ds = test_image_ds.repeat().batch(BATCH_SIZE)#buffer_size 多大范围进行乱序
test_image_ds = test_image_ds.prefetch(AUTOTUNE)#在后台,一部分数据进行训练过程中读取另外一部分数据,能加速训练过程,prefetch(buffer_size) 让计算机自己计算

==Datasetimgs,labels = next(iter(train_image_ds))#iter转换成生成器,next下一批次数据是iter可以进行迭代==

keras 内置经典网络实现

VGG16

1
covn_base = keras.applications.VGG16(weights='imagenet',include_top=False)#weights='imagenet'使用VGG的预训练权重,不使用None;include_to是否引入训练好的分类器(False只引入卷积基)

Xception

1
2
3
4
covn_base = keras.applications.xception.Xception(weights='imagenet',
include_top=False,#weights='imagenet'使用预训练权重,不使用None;include_to是否引入训练好的分类器(False只引入卷积基)
input_shape=(256,256,3),#图片输入
pooling='avg')

冻结预训练模型(将预训练卷积基权重设置为不可训练)

1
covn_base.trainable = False #将covn_base 的权重设置为不可训练(卷积基设置为不可训练)

模型搭建

VGG16

1
2
3
4
5
model = keras.Sequential()#顺序模型
model.add(covn_base)#添加VGG16
model.add(layers.GlobalAveragePooling2D())#类类似latten,将后面三维扁平成为一维,.GlobalAveragePooling2D更高效,效果更好
model.add(layers.Dense(512,activation='relu'))
model.add(layers.Dense(1,activation='sigmoid'))

Xception

1
2
3
4
model = keras.Sequential()#顺序模型
model.add(covn_base)#添加VGG16 pooling='avg' 在输出时添加了GlobalPooling2D,不用再添加GlobalPooling2D
model.add(layers.Dense(512,activation='relu'))
model.add(layers.Dense(1,activation='sigmoid'))

设置Compile

1
2
3
4
model.compile(optimizer=keras.optimizers.Adam(learning_rate=0.0005),
loss=keras.losses.binary_crossentropy,#loss='binary_crossentropy'
metrics=['accuracy'] #metrics=['acc']
)

模型训练

1
2
3
4
5
6
7
history = model.fit(
train_image_ds,
steps_per_epoch=train_count//BATCH_SIZE,
epochs=5,
validation_data=test_image_ds,
validation_steps=test_count//BATCH_SIZE
)

==模型微调==

冻结模型库的底部的卷积层, 共同训练新添加的分类器层和顶部部分卷积层。

==微调步骤==

  1. 在预训练卷积基上添加自定义层
  2. 冻结卷积基所有层
  3. 训练添加的分类层
  4. ==解冻卷积基的一部分层==
  5. 联合训练解冻的卷积层和添加的自定义层}

预训练模型解冻

1
2
#将预训练的全部解冻
covn_base.trainable = True

查看层数

1
len(covn_base.layers)

设置微调层

1
fine_tune_at = -3#调整最后三层,倒数三层

冻结非微调层

1
2
for layer in covn_base.layers[:fine_tune_at]:
layer.trainable = False#倒数第三层以前都冻结

设置Compile

1
2
3
4
model.compile(optimizer=keras.optimizers.Adam(learning_rate=0.0005/10),#要更低的学习速率来嗅探
loss=keras.losses.binary_crossentropy,#loss='binary_crossentropy'
metrics=['accuracy'] #metrics=['acc']
)

训练

1
2
3
4
5
6
7
8
9
10
11
inital_epochs = 5 # 前面训练的次数
fine_tune_epochs = 5 #对新的数据进行训练次数
total_epochs = inital_epochs + fine_tune_epochs
history = model.fit(
train_image_ds,
steps_per_epoch=train_count//BATCH_SIZE,
epochs=total_epochs,#总共epoch
initial_epoch=inital_epochs,#初始训练epoch
validation_data=test_image_ds,
validation_steps=test_count//BATCH_SIZE
)

epochs=total_epochs,#总共epoch

initial_epoch=inital_epochs,#初始训练epoch