鸟类识别在之前做过,但是效果特别差。而且ResNet50的效果直接差到爆炸,这次利用VGG16与ResNet50的官方模型进行鸟类识别。
1.导入库
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import os,pathlib,PIL
from tensorflow.keras import layers,models,Sequential,Input,Model
from tensorflow.keras.layers import Conv2D,MaxPooling2D,Flatten,Dense,BatchNormalization,ZeroPadding2D,Activation,AveragePooling2D
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
2.数据准备
数据所在文件夹
data_dir = "E:/tmp/.keras/datasets/Birds_photos"
data_dir = pathlib.Path(data_dir)
img_count = len(list(data_dir.glob('*/*')))
print(img_count)
labels:一共是4类
all_images_paths = list(data_dir.glob('*'))
all_images_paths = [str(path) for path in all_images_paths]
all_label_names = [path.split("\\")[5].split(".")[0] for path in all_images_paths]
超参数的设置
height = 227
width = 227
batch_size = 8
epochs = 20
按照8:2的比例划分训练集与测试集
train_data_gen = tf.keras.preprocessing.image.ImageDataGenerator(
rescale=1./255,
validation_split=0.2
)
train_ds = train_data_gen.flow_from_directory(
directory=data_dir,
target_size=(height,width),
batch_size=batch_size,
shuffle=True,
class_mode='categorical',
subset='training'
)
test_ds = train_data_gen.flow_from_directory(
directory=data_dir,
target_size=(height,width),
batch_size=batch_size,
shuffle=True,
class_mode='categorical',
subset='validation'
)
查看数据
plt.figure(figsize=(15,10))
for images,labels in train_ds:
for i in range(32):
ax = plt.subplot(4,8,i+1)
plt.imshow(images[i])
plt.title(all_label_names[np.argmax(labels[i])])
plt.axis("off")
break
plt.show()
3.VGG16网络
迁移学习调用VGG16的官方模型
conv_base = tf.keras.applications.VGG16(weights='imagenet',include_top=False)
conv_base.trainable = False
model = tf.keras.Sequential()
model.add(conv_base)
model.add(tf.keras.layers.GlobalAveragePooling2D())
model.add(tf.keras.layers.Dense(512,activation='relu'))
model.add(tf.keras.layers.Dense(4,activation='sigmoid'))
模型编译&&训练
model.compile(
optimizer="adam",
loss='categorical_crossentropy',
metrics=['accuracy']
)
history = model.fit(
train_ds,
validation_data=test_ds,
epochs=epochs
)
模型的准确率很高,在博主实验的几个模型中,VGG16的模型准确率是最高的。
保存网络:
model.save("E:/Users/yqx/PycharmProjects/BirdsRec/model.h5")
利用网络模型进行预测:
new_model = tf.keras.models.load_model("E:/Users/yqx/PycharmProjects/BirdsRec/model.h5")
plt.figure(figsize=(18,18))
plt.suptitle("预测结果展示")
for images,labels in test_ds:
for i in range(8):
ax = plt.subplot(2,4,i+1)
plt.imshow(images[i])
img_array = tf.expand_dims(images[i],0)
pre = new_model.predict(img_array)
plt.title(all_label_names[np.argmax(pre)])
plt.axis("off")
break
plt.show()
绘制混淆矩阵
from sklearn.metrics import confusion_matrix
import seaborn as sns
import pandas as pd
def plot_cm(labels,pre):
conf_numpy = confusion_matrix(labels,pre)
conf_df = pd.DataFrame(conf_numpy,index=all_label_names,columns=all_label_names)
plt.figure(figsize=(8,8))
sns.heatmap(conf_df,annot=True,fmt="d",cmap="BuPu")
plt.title('混淆矩阵',fontsize = 15)
plt.ylabel('真实值',fontsize = 14)
plt.xlabel('预测值',fontsize = 14)
plt.show()
test_pre = []
test_label = []
for images,labels in test_ds:
for image,label in zip(images,labels):
img_array = tf.expand_dims(image,0)
pre = model.predict(img_array)
test_pre.append(all_label_names[np.argmax(pre)])
test_label.append(all_label_names[np.argmax(label)])
break
plot_cm(test_label,test_pre)
4.ResNet50网络
与VGG16不同的是,ResNet50的网络参数设置的是可以训练,经过多次实验,这样ResNet50的实验效果是最好的。
conv_base = tf.keras.applications.ResNet50(weights='imagenet',include_top=False)
conv_base.trainable = True
model = tf.keras.Sequential()
model.add(conv_base)
model.add(tf.keras.layers.GlobalAveragePooling2D())
model.add(tf.keras.layers.Dense(512,activation='relu'))
model.add(tf.keras.layers.Dense(4,activation='sigmoid'))
虽然准确率在来回波动,但是整体的准确率是比较高的,比VGG16的准确率还是差一些的。博主关于ResNet50的了解还比较少,等到了解深刻了再回来更新。
|