qbytearray初始化全0_使用Keras和TensorFlow 2.0建立深度学习模型对图像进行分类

在本文中,我们将构建一个深度学习模型来对图像中的对象进行分类。为了构建卷积神经网络,我们将使用Kaggle提供的这个数据集。(https://www.kaggle.com/c/dogs-vs-cats-redux-kernels-edition/data)CNN是一种主要用于视觉任务的神经网络。该网络将检测动物的特征,然后使用这些特征将给定的输入图像分类为猫或狗。

51940f05f99b97393e222d3858ace1eb.png

导入必要的包文件

先激活虚拟环境

conda activate my_env

运行以下命令安装keras和tensorflow:

conda install tensorflow keras pillow

在这里,我们还安装了pillow以便于以后加载图像。

现在导入以下包:

  • 连续初始化人工神经网络
  • 用于实现处理图像的卷积网络
  • MaxPooling2D用于添加池化层
  • Flatten转换池的功能映射成一个列,将被馈送到全连接层
  • 这将为神经网络增加一个完全连接的层
from keras.models import Sequential
from keras.layers import Conv2D
from keras.layers import MaxPooling2D
from keras.layers import Flatten
from keras.layers import Dense

初始化神经网络

接下来,我们将使用该Sequential包来初始化线性的图层堆栈。对于像这样的分类问题,我们通常创建一个分类变量。

classifier = Sequential()

我们现在有了一个神经网络的实例,但它本身并不能做任何事情。我们需要对数据集应用一个函数,这意味着网络需要一个卷积层。我们将在下一步中添加这一层。

添加卷积层

通过调用分类器上的add函数并传递所需的参数来添加层。传递参数是使用Convolution2D完成的。第一个参数(滤波器)是卷积中输出滤波器的数量。它们也被称为特征检测器。

第二和第三参数代表2D卷积窗口的高度和宽度。input_shape是输入图像的形状。黑白图像转换为2D阵列,而彩色图像转换为3D阵列。

卷积是涉及两个函数的数学计算,旨在找出这两个函数如何相互影响。

该过程涉及三个关键项目:输入图像,特征检测器和特征图。通过将输入图像逐个元素的矩阵表示与特征检测器相乘,可以获得特征图。此过程旨在减小图像的大小,并保留了对分类输入图像很重要的功能,并丢弃了不分类的功能。每个特征图都会检测图像独特特征的位置。

在这种情况下,我们正在处理彩色图像。因此,我们将三个通道传递给该input_shape参数。我们还需要为每个通道传递2D数组的尺寸。我们将传递的最后一个参数是激活函数。由于图像分类是非线性任务,因此我们将使用整流器功能。这样可以确保我们在操作过程中不会得到负值。

classifier.add(Conv2D(32, (3, 3), input_shape = (256, 256, 3), activation='relu'))

我们现在有一个CNN,它将检测图像数据集中的特征。在下一步中,我们将使用池来减小这些特性的大小。这将有助于减少深度学习模型的计算时间

合并以减少要素图的大小

现在,我们将向网络中添加一个池层,以减少功能映射的大小。我们使用2x2池大小的最大池。这减少了图像的大小,同时保留了重要的信息。

物体在图像中的位置不会影响神经网络感知其独特特征的能力。由于图像在光照和拍摄角度方面有很大的不同,所以汇集确保了神经网络能够检测出独特的特征,尽管存在这些差异。

Max pooling将一个2x2矩阵放入feature map中,并从中选择最大的值。2x2矩阵在整个feature map中移动,并在每个移动中选择最大的值。获得的值形成一个矩阵,称为池功能映射。

最大池是重要的,因为它保持了图像的独特功能,同时减少了图像的大小。这个过程也减少了过度拟合,因为CNN只接收对分类任务很重要的特征。

classifier.add(MaxPooling2D(pool_size=(2,2)))

在下一步中,我们将把这些特征映射转换为一种可被深度学习模型接受的格式。

扁平化特征映射

是时候将所有的特征映射平铺成一个单独的向量了。然后将这个向量传递给CNN进行处理。这是通过调用分类器上的Flatten()函数实现的。

classifier.add(Flatten())

在这一点上,特征是在一个结构中,可以输入到神经网络。但是,我们必须添加一个层,在将特征输入到神经网络后,它将为我们提供输出。这将是下一步的主题。

向神经网络添加层

我们将使用上面得到的向量作为神经网络的输入,使用Keras中的稠密函数。

它采用的第一个参数是units,units是隐藏层中的节点数。通过实验可以确定最佳的单units。第二个参数是激活函数。这一层通常使用ReLu激活函数。

扁平的特征图被传递给CNN。这个过程涉及到输入层、全连接层和输出层。全连通层和人工神经网络中的隐层是一样的,只是现在它是全连通的。从输出层获得预测的图像类。

该网络计算预测和预测过程中的误差。网络通过误差的反向传播来改进预测。最后的结果是一个介于0和1之间的数字。这个数字表示每个类的概率。

classifier.add(Dense(units = 128, activation='relu'))

现在,我们准备添加输出层。在这一层,我们将使用sigmoid激活函数,因为我们期望一个二进制结果。如果我们期望有两个以上的可能结果,我们就会使用softmax函数。这里的单位是1,因为我们只期望类的预测概率。

classifier.add(Dense(units=1, activation='sigmoid'))

我们现在已经有了深度学习模型的所有层。然而,在开始训练模型之前,我们必须确保减少了训练过程中出现的错误。这最大化了从模型中获得良好结果的机会。因此,在下一个步骤中,我们将实现一个策略来减少训练中的错误。

编译CNN

用该compile函数完成CNN的编译。该函数需要三个参数:

  • 优化器
  • 损失函数
  • 绩效指标

我们将应用梯度下降作为模型的优化器。在这种情况下,binary_crossentropy损失函数最合适,因为这是二进制分类问题。梯度下降是一种优化策略,用于减少训练过程中的误差,以使误差最小。这是通过找到成本函数最小的点来实现的。这被称为局部最小值,是通过对特定点的斜率求微分并降到成本函数的最小值而发现的。在这里,我们将使用流行的Adam优化器。

classifier.compile(optimizer='adam', loss='binary_crossentropy',metrics=['accuracy'])

现在,我们确定在训练过程中可以正确处理错误,我们已经准备好将分类器适合训练图像。

拟合CNN

在拟合CNN之前,我们将使用Keras对图像进行预处理,以减少过度拟合。这个过程称为图像增强。为此,我们将使用ImageDataGenerator函数。

from keras.preprocessing.image import ImageDataGenerator

该功能将缩放、缩放、剪切和翻转图像。rescale参数对图像像素值进行重新排序,取值范围为0到1。horizontal_flip=真水平翻转图像。

train_datagen = ImageDataGenerator(rescale=1./255, shear_range=0.2, zoom_range=0.2, horizontal_flip=True)

之后,我们还需要使用ImageDataGenerator重新调整测试数据图像。

test_datagen = ImageDataGenerator(rescale=1./255)

接下来,我们将使用train_datagen创建一个训练集。使用flow_from_directory从当前工作目录获取图像。传入路径作为第一个参数,target_size作为第二个参数。

target_size是图像的大小。我们将使用256x256,因为我们已经在上面指定了它。batch_size是必须通过网络的图像数量,以便更新权重。我们将class_mode指定为二进制,因为这确实是一个二进制分类问题。

运行以下命令来加载训练图像。因为我们的笔记本和training_set在同一个文件夹中,所以加载图像不会有任何错误。

training_set = train_datagen.flow_from_directory('training_set', target_size=(256, 256), batch_size=32, class_mode='binary')

现在我们将创建一个具有与上面类似参数的测试集。同样,因为我们的Jupyter笔记本和test_set在同一个文件夹中,所以测试集的图像将被加载,没有任何错误。

test_set = test_datagen.flow_from_directory('test_set', target_size=(256, 256), batch_size=32, class_mode='binary')

steps_per_epoch是在完成一个epoch之前从生成器获得的步骤数。epochs是用来训练CNN的迭代次数。validation_steps是在停止之前要验证的步骤总数。

classifier.fit_generator(training_set, steps_per_epoch=40, epochs=25, validation_data=test_set, validation_steps=1000)
Output
Epoch 1/25
40/40 [==============================] - 7341s 1s/step - loss: 8.0578 - acc: 0.5000 - val_loss: 8.0575 - val_acc: 0.5001
<keras.callbacks.History at 0x7f87a8efb7f0>

回顾一下,在这一步中,我们加载了训练和测试图像,对它们进行预处理,并将训练集安装到我们创建的模型中。接下来就是测试的时候了~

预测


首先,我们必须对图像进行预处理。这可以在numpy和image的帮助下实现。image将用于加载新图像,而numpy将用于将它们转换为numpy数组。

import numpy as np
from keras.preprocessing import image

我们现在可以加载我们想要预测的图像。这是使用图像模块中的load_img函数完成的。将图像的位置作为第一个参数传递,并将图像的大小作为第二个参数传递。使用与模型训练时相同的图像大小。

test_image = image.load_img('dog.jpg', target_size=(256, 256))

由于我们使用彩色图像,我们必须将测试图像转换为3D数组。我们可以使用图像模块中的img_to_array函数来实现这一点。

test_image = image.img_to_array(test_image)

在这一点上,我们应该有三维的图像。然而,在进行预测之前,我们需要传入第四个参数。此参数对应于批大小。

图像现在是三维的。你可能已经注意到了,我们是分批传递图像的。在本例中,我们将有一批一个输入图像。NumPy中的expand_dims方法将使我们能够添加第四个维度。

我们传递给它的第一个参数是测试图像,第二个参数是我们想要添加的维度的位置,将它添加到第一个位置,因为这是神经网络期望的位置。第一个位置对应轴0:

test_image = np.expand_dims(test_image, axis=0)

现在使用predict方法预测图像属于哪一类:

prediction = classifier.predict(test_image)

来自训练集的class_indices属性将帮助我们获得类标签。

training_set.class_indices

我们得到的输出将是这样的:

Output
{'cats': 0, 'dogs': 1}

总结

在这篇文章中,我们使用Keras构建了一个可以对图像进行分类的深度学习模型。我们结合之前的人工神经网络知识来实现这个目标。为了进一步改进模型,可以尝试使用keras中的不同激活函数或优化器函数。如果想了解更多关于CNNs的信息,可以查看Keras文档:

https://keras.io/layers/convolutional/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值