最近我通过这本书Deep Learning with Python在学习,其中第一个例子是采用了kaggle上面的cats-vs-dogs 猫狗大战,根据书上的代码,第一次发生了过拟合现象,根据第二次通过数据增强之后,发现一直在提示run out of data,因此记录这一部分的学习过程。
第二部分为了解决过拟合采用数据增强的代码
首先分为两部分,第一部分是对数据进行分类,第二部分是对数据进行处理。在对数据进行分类的时候,我们需要从dataset里面取出数据构造新的数据集,其中我们需要取出一部分数据作为train文件,另一部分作为validation文件,最后一部分作为test文件,在train文件中我们需要有cat train和dog train,同样我们需要cat validation和dog validation,还有cat test和dog test。
之后是数据处理,我们在第一次的小型神经网络的密集链接分类器之前添加一个Dropout层即可。
import os , shutil #导入这几个库 original_dataset_dir = '/home/weijia/Desktop/deeplearning-practice/dogs-vs-cats/train' #这段话的意思是 原数据集在这个文件夹里 base_dir = '/home/weijia/Desktop/deeplearning-practice/dogs-vs-cats/base_dir' os.mkdir(base_dir) #这段话的意思是在/home/weijia/Desktop/deeplearning-parctice/dogs-vs-cats路径里新建一个base_dir来储存要创建的文件 train_dir = os.path.join(base_dir , 'train') os.mkdir(train_dir) #os.path.join的意思是在和上面相同的路径上,base_dir就是在要生成的文件里,‘train’可以理解为文件类型,os.mkdir就是在那个陆经理创建,括号里的train_dir就是要创建的内容 validation_dir = os.path.join(base_dir , 'validation') os.mkdir(validation_dir) #这一部分同理了,意思是在相同路径的base_dir里面创建一个validation_dir文件,这个文件类型是‘validation’,注意这个文件类型不是真正的文件类型的意思 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_dir文件里创建train_cats_dir文件,意思是train_dir中的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) #上面几行代码不难理解,到此为止我们在base_dir文件中创建了train_dir , validation_dir , test_dir ,其中train_dir 中又包含了train_cats_dir,train_dogs_dir, #validation_dir中又包含了validation_dogs_dir,validation_dogs_dir,同理test_dir文件夹中... 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) #这段代码的意思是我们取数据来把它们分到这个文件夹里,因为从网上下载下来的训练集的文件名格式都是cat.number.jpg,所以我们在这里写cat.{}.jpg意思就是名字是这个的文件统一做这个操作, #range(1000)就是0到1000,src表示源,可以理解为从哪来的数据,dst表示要放到哪,最后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) 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) fname = ['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(len(os.listdir(train_cats_dir))) print(len(os.listdir(train_dogs_dir))) print(len(os.listdir(validation_cats_dir))) print(len(os.listdir(validation_dogs_dir))) print(len(os.listdir(test_cats_dir))) print(len(os.listdir(test_dogs_dir)))''' '''这一部分查看自己整理的数据中都有多少张照片''' 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))) #第一个Conv2D层,激活函数为relu,输入形状为(150 , 150 , 3) model.add(layers.MaxPool2D((2 , 2))) #第一个池化层 model.add(layers.Conv2D(64 , (3 , 3) , activation = 'relu')) model.add(layers.MaxPool2D((2 , 2))) model.add(layers.Conv2D(128 , (3 , 3) , activation = 'relu')) model.add(layers.MaxPool2D((2 , 2))) model.add(layers.Flatten()) model.add(layers.Dropout(0.5)) model.add(layers.Dense(512 , activation = 'relu')) model.add(layers.Dense(1 , activation = 'sigmoid')) #构建神经网络 from tensorflow.keras import optimizers model.compile(loss = 'binary_crossentropy' , optimizer = optimizers.RMSprop(lr= 1e-4) , metrics = ['acc']) #构建optimizer优化器 from keras.preprocessing.image import ImageDataGenerator #数据增强 注意只对训练集进行增强,因为测试集是测试用途,所以不需要增强。 train_datagen = ImageDataGenerator( rescale = 1./255 ,#除以255,让这个东西小于1 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) ,#目标大小为(150 , 150),统一大小 batch_size = 32 ,#每一批有多少数据 class_mode = 'binary'#因为使用了binary_crossentropy损失,所以这里用二进制标签 ) validation_generator = test_datagen.flow_from_directory( validation_dir ,#数据来自于验证集 target_size = (150 , 150) , batch_size = 32 ,#每一批有32个数据 class_mode = 'binary' ) history = model.fit_generator( train_generator , steps_per_epoch = 63 , epochs = 100 , validation_data = validation_generator , validation_steps = 32 ) #这里需要注意, # epoch意思是一共训练多少批, # steps_per_epoch意思是一批训练多少个 #根据我们的训练集有猫1000只,狗1000只来看,我们共有2000张图片作为训练集,其中每一批有32个数据,那么2000/32=62.5 , 取整数一共有63批, #简单来说就是在2000张照片中,把照片按照规律摞在一起,每一摞有32张照片,只能多不能少,那么一共需要63摞才能把这些照片摞在一起 #所以steps_per_epoch = 63 , validation_steps = 32(和第126行一样),这是书上的错误之处 model.save('cats_and_dogs_small_2.h5') #保存模型 import matplotlib.pyplot as plt #导入库准备绘制图像 acc = history.history['acc']#acc就是历史中的acc val_acc = history.history['val_acc']#val_acc就是validation 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')#横坐标是epoch,纵坐标是acc,类型为bo,标签为Training acc plt.plot(epochs , val_acc , 'b' , label = 'Validation acc')#同理 plt.title('Training and validation accuracy')#图片名字为Training and validation accurary 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() #最终显示图像并完成