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

打印Tensorflow版本

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

打印是否能使用GPU加速运行

1
print(tf.test.is_gpu_available())

获取图片路径

1
imgs_path = glob.glob("birds/*/*.jpg")

从路径中截取鸟类名称

1
2
3
img_p.split('\\')[1].split('.')[1]
all_labels_name = [img_p.split('\\')[1].split('.')[1] for img_p in imgs_path]
lable_names = np.unique(all_labels_name)#返回单个不重复元素的列表

label_to_index

1
label_to_index = dict((name,i) for i,name in enumerate(lable_names)) 

index_to_label

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

将所有图片的label由鸟类名称转为数字编码

1
all_labels = [label_to_index.get(name) for name in all_labels_name]

进行伪随机乱序

1
2
np.random.seed(200)#伪随机
random_index = np.random.permutation(len(imgs_path))
1
2
imgs_path = np.array(imgs_path)[random_index]
all_labels = np.array(all_labels)[random_index]

分配训练数据

1
2
#train
i = int(len(imgs_path)*0.8)
1
2
3
4
train_path = imgs_path[:i]
train_labels = all_labels[:i]
test_path = imgs_path[i:]
test_labels = all_labels[i:]

train_dataset

1
train_ds = tf.data.Dataset.from_tensor_slices((train_path,train_labels))

test_dataset

1
test_ds = tf.data.Dataset.from_tensor_slices((test_path,test_labels))

创建加载图片函数

1
2
3
4
5
6
7
8
9
10
def load_img(path,label):
image = tf.io.read_file(path)
image = tf.image.decode_jpeg(image,channels=3)
#进行图片resize
image = tf.image.resize(image,[256,256])
#改变图片数据类型
image = tf.cast(image,tf.float32)
#归一化
image = image / 255
return image,label

Dataset加载图片读取函数

1
2
3
4
AUTOTUNE = tf.data.experimental.AUTOTUNE
#num_parallel_calls根据需要多线程读入
train_ds = train_ds.map(load_img,num_parallel_calls=AUTOTUNE)
test_ds = test_ds.map(load_img,num_parallel_calls=AUTOTUNE)

设置BATCH_SIZE

1
BATCH_SIZE = 16

对Dataset设置repeat、shuffle、batch

1
2
train_ds = train_ds.repeat().shuffle(buffer_size=300).batch(BATCH_SIZE)
test_ds = test_ds.batch(BATCH_SIZE)

建立模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
model = tf.keras.Sequential([
tf.keras.layers.Conv2D(64,(3,3),input_shape=(256,256,3),
activation='relu'),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.Conv2D(64,(3,3),activation='relu'),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(128,(3,3),activation='relu'),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.Conv2D(128,(3,3),activation='relu'),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(256,(3,3),activation='relu'),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.Conv2D(256,(3,3),activation='relu'),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(512,(3,3),activation='relu'),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.Conv2D(512,(3,3),activation='relu'),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.GlobalAvgPool2D(),
tf.keras.layers.Dense(1024,activation='relu'),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.Dense(200)#不激活输出
])

配置模型

1
2
3
4
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.0001),
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),#输出层未激活,from_logits=True
metrics=['acc']
)

设置steps_per_epoch、validation_steps

1
2
steps_per_epoch = train_count//BATCH_SIZE
validtion_steps = test_count//BATCH_SIZE

模型训练

1
2
3
4
5
history = model.fit(train_ds,epochs=20,
steps_per_epoch=steps_per_epoch,
validation_data=test_ds,
validation_steps=validtion_steps
)

查看history中的参数

1
history.history.keys()

dict_keys(['loss', 'acc', 'val_loss', 'val_acc'])

绘制训练中train_accuracy、test_accuracy

1
2
3
plt.plot(history.epoch, history.history.get('acc'), label='acc')
plt.plot(history.epoch, history.history.get('val_acc'), label='val_acc')
plt.legend()

绘制训练中train_loss、test_loss

1
2
3
plt.plot(history.epoch, history.history.get('loss'), label='loss')
plt.plot(history.epoch, history.history.get('val_loss'), label='val_loss')
plt.legend()

使用模型进行预测

创建预测图片的加载函数

1
2
3
4
5
6
7
8
9
10
def load_and_preprocess_image(path):
image = tf.io.read_file(path)
image = tf.image.decode_jpeg(image,channels=3)
#进行图片resize
image = tf.image.resize(image,[256,256])
#改变图片数据类型
image = tf.cast(image,tf.float32)
#归一化
image = image / 255
return image

预测图片

1
2
3
4
test_img = 'Fox_Sparrow.jpg'
test_tensor = load_and_preprocess_image(test_img)
test_tensor = tf.expand_dims(test_tensor,axis=0)#扩展维度
pred = model.predict(test_tensor)
1
index_to_label.get(np.argmax(pred))

'Red_winged_Blackbird'