与前一篇博文不同,这次使用VGG16 来完成猫狗分类。
在项目文件夹中新建VGGClassification.py文件,导入相关工具
from keras.applications.vgg16 import VGG16
from keras.models import Sequential
from keras.layers import Conv2D,MaxPool2D,Activation,Dropout,Flatten,Dense
from keras.optimizers import SGD
from keras.preprocessing.image import ImageDataGenerator,load_img,img_to_array
from keras.models import load_model
import numpy as np
from matplotlib import pyplot as plt
首先下载VGG16模型
#VGG16模型是使用imagenet数据集训练出来的
#include_top=False代表只需VGG16模型中的卷积和池化层
#input_shape=(150,150,3):特征提取
vgg16_model=VGG16(weights='imagenet',include_top=False,input_shape=(150,150,3))
这里只需要VGG16的卷积层和池化层是因为原本模型的全连接层是做1000个分类的,而这个猫狗识别只需要两个分类,所以去掉全连接层重新搭建。运行这行代码,就会从网上下载模型,在IDE中获取一般容易失败。也可以选择复制链接在网页中下载,或者其他渠道,但下载好的模型要放在C:\Users\Administrator\.keras\models 这个路径下。我是在程序中下载的:
因为我们已经获取到了VGG16的卷积层和池化层,接下来搭建全连接层:
#搭建全连接层
top_model=Sequential()
top_model.add(Flatten(input_shape=vgg16_model.output_shape[1:]))#图片输出四维,1代表数量
top_model.add(Dense(256,activation='relu'))
top_model.add(Dropout(0.5))
top_model.add(Dense(2,activation='softmax'))
创建训练模型
#把VGG16和全连接层整合
model=Sequential()
model.add(vgg16_model)
model.add(top_model)
接下来的内容和上一篇博文几乎一样,只是把优化器改为SGD
#数据增强
train_datagen=ImageDataGenerator(
rotation_range=40,#随机旋转度数
width_shift_range=0.2,#随机水平平移
height_shift_range=0.2,#随机竖直平移
rescale=1/255,#数据归一化
shear_range=0.2,#随机裁剪
zoom_range=0.2,#随机放大
horizontal_flip=True,#水平翻转
fill_mode='nearest',#填充方式
)
test_datagen=ImageDataGenerator(
rescale=1/255,#数据归一化
)
batch=32#每次训练传入32张照片
#生成训练数据
train_generator=train_datagen.flow_from_directory(
'images/training_set',#从训练集这个目录生成数据
target_size=(150,150),#把生成数据大小定位150*150
batch_size=batch,
)
#测试数据
test_generator=test_datagen.flow_from_directory(
'images/test_set',#从训练集这个目录生成数据
target_size=(150,150),#把生成数据大小定位150*150
batch_size=batch,
)
#查看定义类别分类
print(train_generator.class_indices)
#定义优化器、代价函数、训练过程中计算准确率
model.compile(optimizer=SGD(lr=1e-4,momentum=0.9),loss='categorical_crossentropy',metrics=['accuracy'])
#传入生成的训练数据、每张图片训练1次,验证数据为生成的测试数据
model.fit_generator(train_generator,epochs=1,validation_data=test_generator)
训练结果:
D:\Anaconda\envs\Tensorflow\python.exe "E:/cat_dog recognition/VGGClassification.py"
Using TensorFlow backend.
2020-04-07 16:19:21.125956: I tensorflow/core/platform/cpu_feature_guard.cc:145] This TensorFlow binary is optimized with Intel(R) MKL-DNN to use the following CPU instructions in performance critical operations: AVX AVX2
To enable them in non-MKL-DNN operations, rebuild TensorFlow with the appropriate compiler flags.
2020-04-07 16:19:21.127107: I tensorflow/core/common_runtime/process_util.cc:115] Creating new thread pool with default inter op setting: 4. Tune using inter_op_parallelism_threads for best performance.
Found 3873 images belonging to 2 classes.
Found 1018 images belonging to 2 classes.
{'cats': 0, 'dogs': 1}
Epoch 1/1
1/122 [..............................] - ETA: 2:20:26 - loss: 0.7548 - accuracy: 0.6250
2/122 [..............................] - ETA: 1:35:16 - loss: 0.8686 - accuracy: 0.5312
3/122 [..............................] - ETA: 1:13:30 - loss: 0.8074 - accuracy: 0.5417
121/122 [============================>.] - ETA: 15s - loss: 0.6540 - accuracy: 0.6228
122/122 [==============================] - 2123s 17s/step - loss: 0.6539 - accuracy: 0.6230 - val_loss: 0.4662 - val_accuracy: 0.8075
训练过程会比之前的慢,因为VGG16结构比自己写的要复杂。可以看到,起初的准确率是50%左右,训练完成达到了80%,这里主要看测试集的准确率。如果训练周期次数多,准确率可以达到90%以上。
接下来保存训练好的模型:
#保存模型
model.save('model_vgg.h5')
在文件夹中显示
和前一篇的程序也是一样的,分别用两个模型测试一张图片
label=np.array(['cat','dog'])
#载入模型
#model=load_model('model_cnn.h5')
model=load_model('model_vgg.h5')
#导入图片
image=load_img('images/test_set/dogs/dog.4024.jpg')
plt.imshow(image)
plt.show()
image=image.resize((150,150))
image=img_to_array(image)
image=image/255
image=np.expand_dims(image,0)
print(image.shape)
print(label[model.predict_classes(image)])
运行结果:
用随便写的模型输出是cat:
用VGG16输出就是dog: