《TensorFlow2.0》二、卷积神经网络在TensorFlow2.0中的应用 part 1

一、前言

在上一部分中,我们讲解了tensorflow2.0的简单应用,会建立简单的NN,CNN模型。我们了解了如何使用CNN来提高对手写数字的识别效率。 在本部分,我们将把它带入一个新的水平,识别猫和狗的真实图像,以便将传入的图像分类为一个或另一个。 尤其是手写识别功能,因为所有图像均具有相同的大小和形状,并且均为单色,因此使的处理很简单。现实世界中的图像并非如此—它们具有不同的形状,宽高比等,而且通常是彩色的!同时,这一部分,我们也会讲解一下在具体应用中我们会遇到的问题,如过拟合,欠拟合等。

二、猫狗二分类模型

我们先按前面的知识点写一个猫狗二分类的模型,这里的图像与现实世界中的图像一致-------它们具有不同的形状,宽高比等,而且通常是彩色的!

用卷积神经网络处理更复杂的图像

因此,作为任务的一部分,需要处理数据—尤其是将其大小调整为一致的形状。

步骤如下:

  1. 探索猫和狗的示例数据
  2. 建立和训练神经网络以识别两者之间的差异
  3. 评估培训和验证的准确性

以下python代码将使用OS库来使用操作系统库,从而使您可以访问文件系统,并使用zipfile库来解压缩数据。

import os
import tensorflow as tf
import zipfile

读取数据

local_zip = '/content/drive/My Drive/Colab Notebooks/DateSet/cats_and_dogs_filtered.zip'
zip_ref = zipfile.ZipFile(local_zip,'r')
zip_ref.extractall('/content/drive/My Drive/Colab Notebooks/tmp')
zip_ref.close

.zip的内容被提取到基本目录/tmp/cats_and_dogs_filtered中,该目录包含用于训练和验证数据集的训练和验证子目录,该目录依次包含猫和狗的子目录。
简而言之:训练集是用来告诉神经网络模型“这就是猫的样子”,“这就是狗的样子”等的数据。验证数据集是猫和狗的图像神经网络不会作为训练的一部分,因此可以测试在评估图像中是否包含猫或狗时,神经网络的效果如何。
在此示例中要注意的一件事:我们没有将图像明确标记为猫或狗。如果还记得上面的手写示例,我们将其标记为“这是1”,“这是7”等。稍后,您将看到正在使用的称为ImageGenerator的东西-编码为从子目录读取图像,并从该子目录的名称中自动标记它们。因此,例如,将有一个“train”目录,其中包含一个“猫”目录和一个“狗”目录。 ImageGenerator将为您适当地标记图像,从而减少了编码步骤。
让我们定义以下每个目录:

#起始路径
base_dir = '/content/drive/My Drive/Colab Notebooks/tmp/cats_and_dogs_filtered'
#训练集,验证集路径
train_dir = os.path.join(base_dir,'train')
validation_dir = os.path.join(base_dir,'validation')
#训练集猫狗路径
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')

现在,让我们看一下cats和dogs训练目录中的文件名是什么样的(验证目录中的文件命名约定是相同的):

train_cat_fnames = os.listdir(train_cats_dir)
train_dog_fnames = os.listdir(train_dogs_dir)

print(train_cat_fnames[:10])
print(train_dog_fnames[:10])

结果:

['cat.127.jpg', 'cat.126.jpg', 'cat.125.jpg', 'cat.124.jpg', 'cat.123.jpg', 'cat.122.jpg', 'cat.121.jpg', 'cat.120.jpg', 'cat.119.jpg', 'cat.118.jpg']
['dog.127.jpg', 'dog.126.jpg', 'dog.125.jpg', 'dog.124.jpg', 'dog.123.jpg', 'dog.122.jpg', 'dog.121.jpg', 'dog.120.jpg', 'dog.119.jpg', 'dog.118.jpg']

让我们查看训练集和验证目录中猫和狗的图像总数:

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)))

结果:

total training cat images : 1000
total training dog images : 1000
total validation cat images : 500
total validation dog images : 500

对于猫和狗,我们都有1000张训练图像和500张验证图像。 现在,让我们看一些图片,以更好地了解猫和狗数据集的外观。首先,配置matplot参数:

import matplotlib.pyplot as plt
import matplotlib.image as mpimg

nrows = 4
ncols = 4
pic_index = 0
#输出8只猫,8只狗
fig = plt.gcf()
fig.set_size_inches(ncols*4,nrows*4)   #图像大小
pic_index += 8

next_cat_pix = [ os.path.join(train_cats_dir,fname)  for fname in train_cat_fnames[pic_index-8:pic_index]  ]
next_dog_pix = [ os.path.join(train_dogs_dir,fname)  for fname in train_dog_fnames[pic_index-8:pic_index]  ]
#print(next_cat_pix[:10])
for i,img_path in enumerate(next_cat_pix+next_dog_pix):
  sp = plt.subplot(nrows,ncols,i+1)
  sp.axis('off')
  img = mpimg.imread(img_path)
  plt.imshow(img)
plt.show()

结果:
在这里插入图片描述
通过查看此网格中的图像可能不会很明显,但是这里需要注意的是,与上一课的显着区别是这些图像具有各种形状和大小。 在进行手写识别示例时,使用的是28x28灰度图像。这些是颜色,形状多样。在与他们一起训练神经网络之前,需要调整图像。 将在下一部分中看到。
好的,既然对数据的外观有所了解,那么下一步就是定义将要训练的模型,以从这些图像中识别猫或狗。

从零开始建立一个小模型,精度达到〜72%

在上一节中,看到图像具有各种形状和大小。 为了训练神经网络来处理它们,需要它们具有统一的大小。 因此我们选择了150x150。
让我们开始定义模型:
我们将像之前一样定义一个顺序层,首先添加一些卷积层。 注意这次输入的形状参数。 在较早的示例中,它是28x28x1,因为图像的灰度是28x28(8位,色深1个字节)。 这次大小为150x150,颜色深度为3(24位,3字节)。
然后,像前面的示例一样,添加几个卷积层,并将最终结果展平接入全连接层。
最后,我们添加全连接的层。
请注意,由于我们面临两类分类问题,即二进制分类问题,因此我们将以S型激活来结束网络,以便网络的输出将是介于0和1之间的单个标量,从而编码。当前图像是1类(而不是0类)。

model = tf.keras.Sequential([
           tf.keras.layers.Conv2D(16,(3,3),activation="relu",input_shape = (150,150,3)),
           tf.keras.layers.MaxPool2D(2,2),

           tf.keras.layers.Conv2D(32,(3,3),activation="relu"),
           tf.keras.layers.MaxPool2D(2,2),

           tf.keras.layers.Conv2D(64,(3,3),activation="relu"),
           tf.keras.layers.MaxPool2D(2,2),


           tf.keras.layers.Flatten(),
           tf.keras.layers.Dense(512,activation="relu"),
           tf.keras.layers.Dense(1,activation="sigmoid")   ])

查看一下网络的结构

model.summary()

在这里插入图片描述
“Output Shape”列显示了要素地图的大小在每个连续的图层中如何演变。 卷积层由于填充而使特征图的大小略微减少,每个合并层将尺寸减半。
接下来,我们将配置模型训练的规范。 我们将使用binary_crossentropy损失训练模型,因为这是一个二进制分类问题,而我们的最终激活是sigmoid型。 我们将使用RMSprop优化器,其学习率为0.001。 在训练期间,我们将要监控分类的准确性。
注意:在这种情况下,使用RMSprop优化算法要优于随机梯度下降(SGD),因为RMSprop可以自动为我们调整学习速率。 (其他优化器,例如Adam和Adagrad,也可以在训练过程中自动调整学习率,并且在此处同样适用。)

from tensorflow.keras.optimizers import RMSprop
model.compile(optimizer=RMSprop(lr = 0.001),loss='binary_crossentropy',metrics=['acc'])

数据预处理

让我们设置数据生成器,该数据生成器将读取源文件夹中的图片,将其转换为float32张量,并将它们(带有标签)馈送到我们的网络中。我们将为训练图像提供一个生成器,为验证图像提供一个生成器。我们的生成器将批量生产20张大小为150x150的图像及其标签(二进制)。
进入神经网络的数据通常应该以某种方式进行规范化,以使其更适合网络处理。 (将原始像素输入到卷积图中是很罕见的。)在本例中,我们将通过将像素值标准化为[0,1]范围(最初所有值都在[0,255]范围内)来预处理图像)。
在Keras中,这可以通过keras.preprocessing.image.ImageDataGenerator类使用rescale参数来完成。使用此ImageDataGenerator类,可以通过.flow(数据,标签)或.flow_from_directory(目录)实例化增强图像批处理(及其标签)的生成器。然后,这些生成器可以与Keras模型方法一起使用,这些方法将数据生成器作为输入:fit_generator,evaluate_generator和predict_generator。

from tensorflow.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,
                  batch_size = 20,
                  class_mode = 'binary',
                  target_size=(150,150))
                 
#验证集图片生成器
validation_generator = test_datagen.flow_from_directory(               
                  validation_dir,
                  batch_size = 20,
                  class_mode = 'binary',
                  target_size=(150,150))

结果:

Found 2000 images belonging to 2 classes.
Found 1000 images belonging to 2 classes.

train_generator 发现了2000张图片。属于2类
validation_generator发现了1000张图片。属于两类

训练

让我们训练所有2000张图像15个周期,并验证所有1000张测试图像。
请注意每个周期的值。
每个时期您将看到4个值----损失,准确度,验证损失和验证准确度。
损失和准确性是训练进度的重要标志。 它正在猜测训练数据的分类,然后根据已知标签对其进行测量,然后计算结果。 准确性是正确猜测的一部分。 验证准确度是对训练中未使用的数据的测量。 如预期的那样会更低。 您将在本课程后面的过度拟合部分中了解为什么会发生这种情况。

history = model.fit_generator( train_generator,
            validation_data=validation_generator,
            steps_per_epoch=100,
            epochs=15,
            validation_steps=50,
            )

结果:
在这里插入图片描述

模型训练好了,接下来就是运行模型了。

运行模型

现在让我们看一下使用模型实际运行预测。 此代码将允许从文件系统中选择1个或多个文件,然后将其上传并在模型中运行它们,从而指示对象是狗还是猫。

import numpy as np
from google.colab import files
from keras.preprocessing import image
uploaded = files.upload()
for fn in uploaded.keys():
  path = '/content/' + fn   #上传文件的位置
  img = image.load_img(path,target_size=(150,150))  #上传
  x = image.img_to_array(img)   #图片的数组格式
  x = np.expand_dims(x,axis=0)  #(1,150,150)
  images = np.vstack([x])  #将x的数据垂直相加,详见下方例子

  classes = model.predict(images,batch_size=10)
  print(classes[0])
  if classes[0]>0:
    print(fn + " is a dog")
  else:
    print(fn + " is a cat")
补充np.vstack()函数
"""
import numpy as np

In[4]:
a = np.array([[1,2,3]])
a.shape
Out[4]:
(1, 3)

In [5]:
b = np.array([[4,5,6]])
b.shape
Out[5]:
(1, 3)

In [6]:
c = np.vstack((a,b)) # 将两个(1,3)形状的数组按垂直方向叠加
print(c)
c.shape # 输出形状为(2,3)
[[1 2 3]
 [4 5 6]]
Out[6]:
(2, 3)

In [7]:
a = np.array([[1],[2],[3]])
a.shape
Out[7]:
(3, 1)

In [9]:
b = np.array([[4],[5],[6]])
b.shape
Out[9]:
(3, 1)

In [10]:
c = np.vstack((a,b))  # 将两个(3,1)形状的数组按垂直方向叠加
print(c)
c.shape # 输出形状为(6,1)
[[1]
 [2]
 [3]
 [4]
 [5]
 [6]]
Out[10]:
(6, 1)
"""

补充内容说完了,我们继续。。。。。。
我分别上传如下两张图片,测试一下结果。
在这里插入图片描述
结果:
在这里插入图片描述
在这里插入图片描述

可视化中间层

为了感觉一下我们的卷积网络学习了哪些功能,要做的一件有趣的事情是可视化输入在卷积网络中的转换方式。
让我们从训练集中选择一张随机的猫或狗图像,然后生成一个图形,其中每一行都是图层的输出,而行中的每一幅图像都是该输出要素图中的特定过滤器。 重新运行此单元格以生成各种训练图像的中间表示。

import numpy as np
import random
from tensorflow.keras.preprocessing.image import img_to_array,load_img
#让我们定义一个新模型,该模型将图像作为输入,并在第一个模型之后输出先前模型中所有层的中间表示。
successive_outputs = [layer.output for layer in model.layers[1:]]   #每层的情况
#print(successive_outputs)

#可视化模型
visualization_model = tf.keras.models.Model(inputs = model.input,outputs = successive_outputs)

#准备一个输入图像
cat_img_files = [os.path.join(train_cats_dir, f) for f in train_cat_fnames]
dog_img_files = [os.path.join(train_dogs_dir, f) for f in train_dog_fnames]


#随机选择一图象
img_path = random.choice(cat_img_files + dog_img_files)

#处理图像
img = load_img(img_path,target_size=(150,150))

#变为矩阵格式
x = img_to_array(img)        #(150, 150, 3)
x = x.reshape( (1,) + x.shape)   #(1, 150, 150, 3)


#规范化
x /= 255

#让我们通过网络运行图像,从而获得该图像的所有中间表示。
successive_feature_maps = visualization_model.predict(x)

#这些是图层的名称,因此可以将其作为绘图的一部分
layer_names = [layer.name for layer in model.layers]

#开始画图
for layer_name, feature_map in zip(layer_names, successive_feature_maps):
  if len(feature_map.shape) == 4:    
    # 只需对conv / maxpool层执行此操作,而不对完全连接的层执行此操作  
    n_features = feature_map.shape[-1]  # 图像中元素的个数
    size = feature_map.shape[1]  # feature map shape (1, size, size, n_features)
    
    # 我们将在此矩阵中平铺图像
    display_grid = np.zeros((size, size * n_features))
    # 对特征进行处理以使其可以观察
    for i in range(n_features):
      x  = feature_map[0, :, :, i]
      x -= x.mean()
      x /= x.std ()
      x *=  64
      x += 128
      x  = np.clip(x, 0, 255).astype('uint8')
      display_grid[:,i*size:(i+1)*size] = x 
    scale = 20. / n_features
    plt.figure( figsize=(scale * n_features, scale) )
    plt.title ( layer_name )
    plt.grid  ( False )
    plt.imshow( display_grid, aspect='auto', cmap='viridis' ) 

结果:
在这里插入图片描述
正如所见,从图像的原始像素过渡到越来越抽象和紧凑的表示形式。 下面的表示开始突出显示网络要注意的内容,并且显示“激活”的功能越来越少。 大多数设置为零。 这称为“稀疏”。 表示稀疏性是深度学习的关键特征。
这些表示所携带的关于图像原始像素的信息越来越少,但是携带的有关图像类别的信息却越来越精细。 可以将卷积网络(或通常称为深层网络)视为信息蒸馏管道。

评估模型的准确性和损失

让我们绘制训练期间收集的训练/验证准确性和损失:

acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']


#得到迭代次数
epochs = range(len(acc))

#画图
plt.plot(epochs,acc)
plt.plot(epochs,val_acc)
plt.title ('Training and validation accuracy')
plt.figure()

plt.plot  ( epochs,loss )
plt.plot  ( epochs,val_loss)
plt.title ('Training and validation loss' )

结果:
在这里插入图片描述
可以看到,我们过拟合了。我们的训练准确性(蓝色)接近100%,而我们的验证准确性(黄色)则停滞在70%。五个周期之后,我们的验证损失就达到了最小值。
由于我们的训练集数量相对较少(2000),因此过拟合应该是我们的头等大事。当暴露于过多示例的模型学习无法推广到新数据的模式时,即模型开始使用无关的功能进行预测时,就会发生过度拟合。例如,如果作为人类只看到三幅伐木工人的图像和三幅水手的图像,并且其中唯一戴着帽子的人是伐木工人,您可能会开始想到戴帽子是成为伐木工人而不是水手的标志。然后,做出一个非常糟糕的伐木工人/水手分类器。
过度拟合是机器学习中的核心问题:鉴于我们正在将模型的参数拟合到给定的数据集,我们如何确保模型学习的表示形式将适用于从未见过的数据?我们如何避免学习特定于训练数据的东西?

三、解决过拟合之数据/图像增强

当我们数据很少时,我们不能准确的判断出两种或几种类别。这时,数据量的多少就显得至关重要了。
让我们继续从对学习Cats-Dogs模型开始。它与上面模型相似,但是我更新了图层定义。请注意,现在有4个卷积层,分别具有32、64、128和128个卷积。另外,这将训练100个周期,因为我想绘制损耗和精度图。
代码如下:

import os
import zipfile
import tensorflow as tf
from tensorflow.keras.optimizers import RMSprop
from tensorflow.keras.preprocessing.image import ImageDataGenerator

# local_zip = '/tmp/cats_and_dogs_filtered.zip'
# zip_ref = zipfile.ZipFile(local_zip, 'r')
# zip_ref.extractall('/tmp')
# zip_ref.close()

#起始路径
base_dir = '/content/drive/My Drive/Colab Notebooks/tmp/cats_and_dogs_filtered'
#训练集,验证集路径
train_dir = os.path.join(base_dir,'train')
validation_dir = os.path.join(base_dir,'validation')
#训练集猫狗路径
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')



model = tf.keras.models.Sequential([
    tf.keras.layers.Conv2D(32, (3,3), activation='relu', input_shape=(150, 150, 3)),
    tf.keras.layers.MaxPooling2D(2, 2),
    tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
    tf.keras.layers.MaxPooling2D(2,2),
    tf.keras.layers.Conv2D(128, (3,3), activation='relu'),
    tf.keras.layers.MaxPooling2D(2,2),
    tf.keras.layers.Conv2D(128, (3,3), activation='relu'),
    tf.keras.layers.MaxPooling2D(2,2),

    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(512, activation='relu'),
    tf.keras.layers.Dense(1, activation='sigmoid')
])

model.compile(loss='binary_crossentropy',optimizer=RMSprop(lr=1e-4), metrics=['acc'])

# 规范化
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')

history = model.fit_generator(
      train_generator,
      steps_per_epoch=100,  # 2000 images = batch_size * steps
      epochs=100,
      validation_data=validation_generator,
      validation_steps=50,  # 1000 images = batch_size * steps
      verbose=2)

结果:
在这里插入图片描述
观察一下,训练集和测试集的准确度和损失值。

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(len(acc))

plt.plot(epochs, acc, 'bo', label='Training accuracy')
plt.plot(epochs, val_acc, 'b', label='Validation accuracy')
plt.title('Training and validation accuracy')

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()

结果为:
在这里插入图片描述
我们可以看到,训练集准确度接近100%,验证准确度在70%-80%范围内。 这就是过度拟合的一个很好的例子—简而言之,这意味着它可以很好地处理以前看到的图像,但是不能很好地处理过以前没有看到的图像。 让我们看看是否可以做得更好,避免过度拟合的一种简单的方法是图片增强/数据增强。 考虑一下,大多数猫的照片都非常相似-耳朵在顶部,然后是眼睛,然后是嘴等。诸如眼睛和耳朵之间的距离之类的东西也总是非常相似。 如果我们对图像进行调整以稍微改变它,该怎么办—旋转图像,挤压图像等。这就是图像增强的全部内容。 现在看一下ImageGenerator。 一些属性可以用来实现图片增强。

图片增强

	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')

相关参数:
rotation_range:一个值,单位为度(0–180),该范围是随机旋转图片的范围。rotation_range=40,旋转0–40中的随机度数。
width_shift/height_shift:在其中垂直或水平随机转换图片的范围(占总宽度或高度的一部分)。width_shift_range=0.2,随机移动20%的图片。
shear_range:用于随机应用剪切变换。shear_range=0.2,随机剪20%的图像。
zoom_range:用于随机放大图片。zoom_range=0.2,最大放大20%。
horizontal_flip:用于随机地水平翻转一半的图像。 当没有水平不对称性的假设时(例如真实图片),这是相关的。
fill_mode:是用于填充新创建的像素的策略,这些像素可以在旋转或宽度/高度偏移后出现。

这是一些我们添加了图像增强的代码。 运行它以查看影响。

import os
import zipfile
import tensorflow as tf
from tensorflow.keras.optimizers import RMSprop
from tensorflow.keras.preprocessing.image import ImageDataGenerator

# local_zip = '/tmp/cats_and_dogs_filtered.zip'
# zip_ref = zipfile.ZipFile(local_zip, 'r')
# zip_ref.extractall('/tmp')
# zip_ref.close()

#起始路径
base_dir = '/content/drive/My Drive/Colab Notebooks/tmp/cats_and_dogs_filtered'
#训练集,验证集路径
train_dir = os.path.join(base_dir,'train')
validation_dir = os.path.join(base_dir,'validation')
#训练集猫狗路径
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')

model = tf.keras.models.Sequential([
    tf.keras.layers.Conv2D(32, (3,3), activation='relu', input_shape=(150, 150, 3)),
    tf.keras.layers.MaxPooling2D(2, 2),
    tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
    tf.keras.layers.MaxPooling2D(2,2),
    tf.keras.layers.Conv2D(128, (3,3), activation='relu'),
    tf.keras.layers.MaxPooling2D(2,2),
    tf.keras.layers.Conv2D(128, (3,3), activation='relu'),
    tf.keras.layers.MaxPooling2D(2,2),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(512, activation='relu'),
    tf.keras.layers.Dense(1, activation='sigmoid')
])

model.compile(loss='binary_crossentropy',
              optimizer=RMSprop(lr=1e-4),
              metrics=['acc'])

#训练集图片增强
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')

history = model.fit_generator(
      train_generator,
      steps_per_epoch=100,  # 2000 images = batch_size * steps
      epochs=100,
      validation_data=validation_generator,
      validation_steps=50,  # 1000 images = batch_size * steps
      verbose=2)

结果:
在这里插入图片描述
图像增强完毕后,这时训练集与测试集的损失值和精度之间的关系如何呢?

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(len(acc))

plt.plot(epochs, acc, 'bo', label='Training accuracy')
plt.plot(epochs, val_acc, 'b', label='Validation accuracy')
plt.title('Training and validation accuracy')

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()

结果:
在这里插入图片描述
我们可以看到,验证集的精度和训练集大体一致,使得过拟合的情况消失了。

在次测验一样。我用如下两图测试,
注:ddd.jpg图使用一开始的模型进行测试时,给出的结果是dog,结果错误。我放入新模型还会出现这种错误嘛?来看一下。。。
在这里插入图片描述

import numpy as np
from google.colab import files
from keras.preprocessing import image
uploaded = files.upload()
for fn in uploaded.keys():
  path = '/content/' + fn   #上传文件的位置
  img = image.load_img(path,target_size=(150,150))  #上传
  x = image.img_to_array(img)   #图片的数组格式
  x = np.expand_dims(x,axis=0)  #(1,150,150)
  images = np.vstack([x])  #将x的数据垂直相加,详见下方例子
  classes = model.predict(images,batch_size=10)
  print(classes[0])
  if classes[0]>0:
    print(fn + " is a dog")
    
  else:
    print(fn + " is a cat")

结果:
在这里插入图片描述
在这里插入图片描述
在这个模型中,ddd.jpg成功的被分类为猫了。
最后的运行结果也要明显好于第一个模型。

四、结语

这章主要讲解了什么叫过拟合,为什么会过拟合以及如何解决过拟合。
下章我们会继续从实际出发解决问题,敬请期待吧!(❤´艸`❤)

  • 博主水平有限,如有错误,请不吝指教,谢谢!(❤ ω ❤)
  • 这章就先到这里吧,下节见!(ง •_•)ง
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值