该数据集来自2013年的Kaggle竞赛,其包含25000张猫狗图像(猫狗各12500张),该问题属于猫狗二分类问题。
包括三个子集:包含每个类别各1000个样本的训练集,500个样本的验证集和500个样本的测试集。
import os,shutil
original_dataset_dir = 'C:/Users/Xiaoqi/Desktop/deeplearning/dogs-vs-cats/train'
base_dir = 'C:/Users/Xiaoqi/Desktop/deeplearning/dogs-vs-cats-small/'
os.mkdir(base_dir)
### 建立狗和猫的训练、验证和测试数据集
train_dir = os.path.join(base_dir,'train')
os.mkdir(train_dir)
validation_dir = os.path.join(base_dir,'validation')
os.mkdir(validation_dir)
test_dir = os.path.join(base_dir,'test')
os.mkdir(test_dir)
train_cats_dir = os.path.join(train_dir,'cats')
os.mkdir(train_cats_dir)
train_dogs_dir = os.path.join(train_dir,'dogs')
os.mkdir(train_dogs_dir)
validation_cats_dir = os.path.join(validation_dir,'cats')
os.mkdir(validation_cats_dir)
validation_dogs_dir = os.path.join(validation_dir,'dogs')
os.mkdir(validation_dogs_dir)
test_cats_dir = os.path.join(test_dir,'cats')
os.mkdir(test_cats_dir)
test_dogs_dir = os.path.join(test_dir,'dogs')
os.mkdir(test_dogs_dir)
## 将图片复制到相应数据集
# cats
fnames = ['cat.{}.jpg'.format(i) for i in range(1000)]
for fname in fnames:
src = os.path.join(original_dataset_dir,fname)
dst = os.path.join(train_cats_dir,fname)
shutil.copyfile(src,dst)
fnames = ['cat.{}.jpg'.format(i) for i in range(1000,1500)]
for fname in fnames:
src = os.path.join(original_dataset_dir,fname)
dst = os.path.join(validation_cats_dir,fname)
shutil.copyfile(src,dst)
fnames = ['cat.{}.jpg'.format(i) for i in range(1500,2000)]
for fname in fnames:
src = os.path.join(original_dataset_dir,fname)
dst = os.path.join(test_cats_dir,fname)
shutil.copyfile(src,dst)
# dogs
fnames = ['dog.{}.jpg'.format(i) for i in range(1000)]
for fname in fnames:
src = os.path.join(original_dataset_dir,fname)
dst = os.path.join(train_dogs_dir,fname)
shutil.copyfile(src,dst)
fnames = ['dog.{}.jpg'.format(i) for i in range(1000,1500)]
for fname in fnames:
src = os.path.join(original_dataset_dir,fname)
dst = os.path.join(validation_dogs_dir,fname)
shutil.copyfile(src,dst)
fnames = ['dog.{}.jpg'.format(i) for i in range(1500,2000)]
for fname in fnames:
src = os.path.join(original_dataset_dir,fname)
dst = os.path.join(test_dogs_dir,fname)
shutil.copyfile(src,dst)
print('Totol number of training cat images:',len(os.listdir(train_cats_dir)))
print('Totol number of validation cat images:',len(os.listdir(validation_cats_dir)))
print('Totol number of test cat images:',len(os.listdir(test_cats_dir)))
print('Totol number of training dog images:',len(os.listdir(train_dogs_dir)))
print('Totol number of validation dog images:',len(os.listdir(validation_dogs_dir)))
print('Totol number of test dog images:',len(os.listdir(test_dogs_dir)))
conv2D(relu) + MaxPooling2D
from keras import layers
from keras import models
model = models.Sequential()
model.add(layers.Conv2D(32,(3,3),activation = 'relu',input_shape = (150,150,3))) ## 上述数据的输入尺寸为150*150,3个色道
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Conv2D(64,(3,3),activation = 'relu'))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Conv2D(128,(3,3),activation = 'relu'))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Conv2D(128,(3,3),activation = 'relu'))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Flatten())
model.add(layers.Dense(512,activation = 'relu'))
model.add(layers.Dense(1,activation = 'sigmoid')) ## 2分类问题
model.summary()
from keras import optimizers
model.compile(loss = 'binary_crossentropy',
optimizer=optimizers.RMSprop(lr = 1e-4),
metrics = ['acc'])
from keras.preprocessing.image import ImageDataGenerator
train_datagen = ImageDataGenerator(rescale=1./255)
test_datagen = ImageDataGenerator(rescale=1./255)
train_generator = train_datagen.flow_from_directory(train_dir,
target_size=(150,150),
batch_size=20,
class_mode='binary')
validation_generator = test_datagen.flow_from_directory(validation_dir,
target_size=(150,150),
batch_size=20,
class_mode='binary')
for data_batch, labels_batch in train_generator:
print('data batch shape: ',data_batch.shape)
print('label batch shape: ',labels_batch.shape)
break
history = model.fit_generator(train_generator,
steps_per_epoch=100,
epochs=30,
validation_data=validation_generator,
validation_steps=50)
model.save('cats_and_dogs_small_1.h5')
import matplotlib.pyplot as plt
acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(1,len(acc)+1)
plt.plot(epochs,acc,'bo',label = "Training acc")
plt.plot(epochs,val_acc,'b',label = "Validation acc")
plt.title('Training and validation accuracy')
plt.legend()
plt.figure()
plt.plot(epochs,loss,'bo',label = "Training loss")
plt.plot(epochs,val_loss,'b',label = "Validation loss")
plt.title('Training and validation loss')
plt.legend()
plt.show()
出现过拟合现象。可以考虑如下办法:1. dropout,2. L2正则化,3. 数据增强
datagen = ImageDataGenerator(rotation_range=40, ## 随机旋转的角度范围
width_shift_range=0.2, ## 水平左右移动的范围
height_shift_range=0.2,
shear_range=0.2, # 随机错切变换
zoom_range=0.2, # 随机缩放范围
horizontal_flip=True, # 随机将一半图像翻转
fill_mode='nearest')# 填充创建新像素方法
model = models.Sequential()
model.add(layers.Conv2D(32,(3,3),activation = 'relu',input_shape = (150,150,3))) ## 上述数据的输入尺寸为150*150,3个色道
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Conv2D(64,(3,3),activation = 'relu'))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Conv2D(128,(3,3),activation = 'relu'))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Conv2D(128,(3,3),activation = 'relu'))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Flatten())
model.add(layers.Dropout(0.5)) ## add dropout
model.add(layers.Dense(512,activation = 'relu'))
model.add(layers.Dense(1,activation = 'sigmoid')) ## 2分类问题
model.compile(loss = 'binary_crossentropy',
optimizer=optimizers.RMSprop(lr = 1e-4),
metrics = ['acc'])
model.summary()
train_datagen = ImageDataGenerator(rescale=1./255,
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
test_datagen = ImageDataGenerator(rescale=1./255) ##测试集不增强
train_generator = train_datagen.flow_from_directory(train_dir,
target_size=(150,150),
batch_size=32,
class_mode='binary')
validation_generator = test_datagen.flow_from_directory(validation_dir,
target_size=(150,150),
batch_size=32,
class_mode='binary')
history = model.fit_generator(train_generator,
steps_per_epoch=100,
epochs=100,
validation_data=validation_generator,
validation_steps=50)
model.save('cats_and_dogs_small_2.h5')
import matplotlib.pyplot as plt
acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(1,len(acc)+1)
plt.plot(epochs,acc,'bo',label = "Training acc")
plt.plot(epochs,val_acc,'b',label = "Validation acc")
plt.title('Training and validation accuracy')
plt.legend()
plt.figure()
plt.plot(epochs,loss,'bo',label = "Training loss")
plt.plot(epochs,val_loss,'b',label = "Validation loss")
plt.title('Training and validation loss')
plt.legend()
plt.show()
from keras.applications import VGG16
conv_base = VGG16(weights = 'imagenet',
include_top = False,
input_shape = (150,150,3))
from keras import models
from keras import layers
model = models.Sequential()
model.add(conv_base)
model.add(layers.Flatten())
model.add(layers.Dense(256,activation = 'relu'))
model.add(layers.Dense(1,activation = 'sigmoid'))
model.summary()
## 冻结conv_base的参数
conv_base.trainable = False
train_datagen = ImageDataGenerator(rescale=1./255,
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest')
test_datagen = ImageDataGenerator(rescale=1./255) ##测试集不增强
train_generator = train_datagen.flow_from_directory(train_dir,
target_size=(150,150),
batch_size=20,
class_mode='binary')
validation_generator = test_datagen.flow_from_directory(validation_dir,
target_size=(150,150),
batch_size=20,
class_mode='binary')
model.compile(loss = 'binary_crossentropy',
optimizer=optimizers.RMSprop(lr = 1e-5),
metrics = ['acc'])
history = model.fit_generator(train_generator,
steps_per_epoch=100,
epochs=30,
validation_data=validation_generator,
validation_steps=50)
import matplotlib.pyplot as plt
acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(1,len(acc)+1)
plt.plot(epochs,acc,'bo',label = "Training acc")
plt.plot(epochs,val_acc,'b',label = "Validation acc")
plt.title('Training and validation accuracy')
plt.legend()
plt.figure()
plt.plot(epochs,loss,'bo',label = "Training loss")
plt.plot(epochs,val_loss,'b',label = "Validation loss")
plt.title('Training and validation loss')
plt.legend()
plt.show()
联合上面的训练,再执行如下操作: 解冻基网络的一部分,联合训练解冻的这些层和添加的部分。
conv_base.trainable = True
set_trainable = False
for layer in conv_base.layers():
if layer.name == 'block5_conv1':
set_trainable = True
if set_trainable:
layer.trainable = True
else:
layer.trainable = False
model.compile(loss = 'binary_crossentropy',
optimizer=optimizers.RMSprop(lr = 1e-5),
metrics = ['acc'])
history = model.fit_generator(train_generator,
steps_per_epoch=100,
epochs=100,
validation_data=validation_generator,
validation_steps=50)
import matplotlib.pyplot as plt
acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(1,len(acc)+1)
plt.plot(epochs,acc,'bo',label = "Training acc")
plt.plot(epochs,val_acc,'b',label = "Validation acc")
plt.title('Training and validation accuracy')
plt.legend()
plt.figure()
plt.plot(epochs,loss,'bo',label = "Training loss")
plt.plot(epochs,val_loss,'b',label = "Validation loss")
plt.title('Training and validation loss')
plt.legend()
plt.show()
test_generator = test_datagen.flow_from_directory(test_dir,
target_size=(150,150),
batch_size=20,
class_mode='binary')
test_loss,test_acc = model.evaluate_generator(test_generator,steps=50)
print('test acc:',test_acc)