【学习笔记】用VGG16实现猫狗分类
与前一篇博文不同,这次使用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 pl
首先下载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.541
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.807
训练过程会比之前的慢,因为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: