#输出数据集对应目录下图片数量
print('total training cat images:',len(os.listdir(train_cats_dir)))print('total training dog images:',len(os.listdir(train_dogs_dir)))print('total validation cat images:',len(os.listdir(validation_cats_dir)))print('total validation dog images:',len(os.listdir(validation_dogs_dir)))print('total test cat images:',len(os.listdir(test_cats_dir)))print('total test dog images:',len(os.listdir(test_dogs_dir)))
猫狗训练图片各 1000 张,验证图片各 500 张,测试图片各 500 张。
3.2 基准模型
第①步:构建网络模型:
#网络模型构建
from keras import layers
from keras import models
#keras的序贯模型
model = models.Sequential()
#卷积层,卷积核是3*3,激活函数relu
model.add(layers.Conv2D(32,(3,3), activation='relu',
input_shape=(150,150,3)))
#最大池化层
model.add(layers.MaxPooling2D((2,2)))
#卷积层,卷积核2*2,激活函数relu
model.add(layers.Conv2D(64,(3,3), activation='relu'))
#最大池化层
model.add(layers.MaxPooling2D((2,2)))
#卷积层,卷积核是3*3,激活函数relu
model.add(layers.Conv2D(128,(3,3), activation='relu'))
#最大池化层
model.add(layers.MaxPooling2D((2,2)))
#卷积层,卷积核是3*3,激活函数relu
model.add(layers.Conv2D(128,(3,3), activation='relu'))
#最大池化层
model.add(layers.MaxPooling2D((2,2)))#flatten层,用于将多维的输入一维化,用于卷积层和全连接层的过渡
model.add(layers.Flatten())
#全连接,激活函数relu
model.add(layers.Dense(512, activation='relu'))
#全连接,激活函数sigmoid
model.add(layers.Dense(1, activation='sigmoid'))
训练结果如上图所示,很明显模型上来就过拟合了,主要原因是数据不够,或者说相对于数据量,模型过复杂(训练损失在第30个epoch就降为0了),训练精度随着时间线性增长,直到接近100%,而我们的验证精度停留在70-72%。我们的验证损失在5个epoch后达到最小,然后停止,而训练损失继续线性下降,直到接近0。 这里先解释下什么是过拟合? 过拟合的定义: 给定一个假设空间 H HH,一个假设 h hh 属于 H HH,如果存在其他的假设 h ’ h’h’ 属于 H HH,使得在训练样例上 h hh 的错误率比 h ’ h’h’ 小,但在整个实例分布上 h ’ h’h’ 比 h hh 的错误率小,那么就说假设 h hh 过度拟合训练数据。 举个简单的例子,( a )( b )过拟合,( c )( d )不过拟合,如下图所示:
import matplotlib.pyplot as plt
#This is module with image preprocessing utilities
from keras.preprocessing import image
fnames =[os.path.join(train_cats_dir, fname)for fname in os.listdir(train_cats_dir)]#We pick one image to "augment"
img_path = fnames[3]#Read the image and resize it
img = image.load_img(img_path, target_size=(150,150))#Convert it to a Numpy array with shape(150,150,3)
x = image.img_to_array(img)#Reshape it to(1,150,150,3)
x = x.reshape((1,)+ x.shape)#The .flow() command below generates batches of randomly transformed images.#It will loop indefinitely, so we need to `break` the loop at some point!
i =0for batch in datagen.flow(x, batch_size=1):
plt.figure(i)
imgplot = plt.imshow(image.array_to_img(batch[0]))
i +=1if i %4==0:break
plt.show()
结果如下(共4张,这里只截取了三张):
图片格式转化。
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,)#Note that the validation data should not be augmented!
test_datagen =ImageDataGenerator(rescale=1./255)
train_generator = train_datagen.flow_from_directory(#This is the target directory
train_dir,#All images will be resized to 150x150
target_size=(150,150),
batch_size=32,#Since we use binary_crossentropy loss, we need binary labels
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('E:\\Cat_And_Dog\\kaggle\\cats_and_dogs_small_2.h5')