《python深度学习》笔记---5.2-4、猫狗分类(数据增强)
《python深度学习》笔记---5.2-4、猫狗分类(数据增强)
一、总结
一句话总结:
相比于之前的基本模型,数据增强只是在对应的train_datagen的ImageDataGenerator中增加了一些数据增强的参数
可以看到,数据增强的效果非常好,测试集准确率从71提升到了83左右
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)
1、WARNING:tensorflow:Your input ran out of data; interrupting training. Make sure that your dataset or generator can generate at least steps_per_epoch * epochs batches?
保证batch_size(图像增强中)*steps_per_epoch(fit中)小于等于训练样本数
train_generator = train_datagen.flow_from_directory( train_dir, # 目标目录 target_size=(150, 150), # 将所有图像的大小调整为 150×150 batch_size=20, # 因为使用了 binary_crossentropy 损失,所以需要用二进制标签 class_mode='binary') history = model.fit( train_generator, steps_per_epoch=100, epochs=150, validation_data=validation_generator, validation_steps=50) # case 1 # 如果上面train_generator的batch_size是32,如果这里steps_per_epoch=100,那么会报错 """ tensorflow:Your input ran out of data; interrupting training. Make sure that your dataset or generator can generate at least `steps_per_epoch * epochs` batches (in this case, 50 batches). You may need to use the repeat() function when building your dataset. """ # 因为train样本数是2000(猫1000,狗1000),小于100*32 # case 2 # 如果上面train_generator的batch_size是20,如果这里steps_per_epoch=100,那么不会报错 # 因为大小刚好 # case 3 # 如果上面train_generator的batch_size是32,如果这里steps_per_epoch=int(1000/32), # 那么不会报错,但是会有警告,因为也是不整除 # 不会报错因为int(1000/32)*32 < 2000 # case 4 # 如果上面train_generator的batch_size是40,如果这里steps_per_epoch=100,照样报错 # 因为40*100>2000
2、图像预处理,显示图像?
img = image.load_img(img_path, target_size=(150, 150)) # 读取图像并调整大小
# 图像预处理 工具的模块 fnames = [os.path.join(train_cats_dir, fname) for fname in os.listdir(train_cats_dir)] # 选择一张图像进行增强 img_path = fnames[3] # 读取图像并调整大小 img = image.load_img(img_path, target_size=(150, 150)) # 将其转换为形状 (150, 150, 3) 的 Numpy 数组 x = image.img_to_array(img) # 将其形状改变为 (1, 150, 150, 3) x = x.reshape((1,) + x.shape) # 生成随机变换后的图像批量。 循环是无限的,因此你需要 在某个时刻终止循环 i = 0 for batch in datagen.flow(x, batch_size=1): plt.figure(i) imgplot = plt.imshow(image.array_to_img(batch[0])) i += 1 if i % 4 == 0: break plt.show()
二、5.2-4、猫狗分类(数据增强)
博客对应课程的视频位置:
import os, shutil
# 原始数据集解压目录的路径
original_dataset_dir = 'E:\\78_recorded_lesson\\001_course_github\\AI_dataSet\\dogs-vs-cats\\kaggle_original_data\\train'
# 保存较小数据集的目录
base_dir = 'E:\\78_recorded_lesson\\001_course_github\\AI_dataSet\\dogs-vs-cats\\cats_and_dogs_small'
# 分别对应划分后的训练、验证和测试的目录
train_dir = os.path.join(base_dir, 'train')
validation_dir = os.path.join(base_dir, 'validation')
test_dir = os.path.join(base_dir, 'test')
# 猫的训练图像目录
train_cats_dir = os.path.join(train_dir, 'cats')
# 狗的训练图像目录
train_dogs_dir = os.path.join(train_dir, 'dogs')
# 猫的验证图像目录
validation_cats_dir = os.path.join(validation_dir, 'cats')
# 狗的验证图像目录
validation_dogs_dir = os.path.join(validation_dir, 'dogs')
# 猫的测试图像目录
test_cats_dir = os.path.join(test_dir, 'cats')
# 狗的测试图像目录
test_dogs_dir = os.path.join(test_dir, 'dogs')
In [2]:
import pandas as pd
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
In [3]:
from tensorflow.keras.preprocessing import image
from tensorflow.keras.preprocessing.image import ImageDataGenerator
In [4]:
datagen = tf.keras.preprocessing.image.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')
In [5]:
# 图像预处理 工具的模块
fnames = [os.path.join(train_cats_dir, fname) for fname in os.listdir(train_cats_dir)]
# 选择一张图像进行增强
img_path = fnames[3]
# 读取图像并调整大小
img = image.load_img(img_path, target_size=(150, 150))
# 将其转换为形状 (150, 150, 3) 的 Numpy 数组
x = image.img_to_array(img)
# 将其形状改变为 (1, 150, 150, 3)
x = x.reshape((1,) + x.shape)
# 生成随机变换后的图像批量。 循环是无限的,因此你需要 在某个时刻终止循环
i = 0
for batch in datagen.flow(x, batch_size=1):
plt.figure(i)
imgplot = plt.imshow(image.array_to_img(batch[0]))
i += 1
if i % 4 == 0:
break
plt.show()
2、定义一个包含 dropout 的新卷积神经网络
In [6]:
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Conv2D(32, (3, 3), activation='relu',
input_shape=(150, 150, 3)))
model.add(tf.keras.layers.MaxPooling2D((2, 2)))
model.add(tf.keras.layers.Conv2D(64, (3, 3), activation='relu'))
model.add(tf.keras.layers.MaxPooling2D((2, 2)))
model.add(tf.keras.layers.Conv2D(128, (3, 3), activation='relu'))
model.add(tf.keras.layers.MaxPooling2D((2, 2)))
model.add(tf.keras.layers.Conv2D(128, (3, 3), activation='relu'))
model.add(tf.keras.layers.MaxPooling2D((2, 2)))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dropout(0.5))
model.add(tf.keras.layers.Dense(512, activation='relu'))
model.add(tf.keras.layers.Dense(1, activation='sigmoid'))
model.summary