您现在的位置:首页 > IT资讯 > 使用Tensorflow构建您的第一个CNN

使用Tensorflow构建您的第一个CNN

2023-11-14 17:07:35 | 来源:Admin

计算机视觉是当今的热门话题之一。它为涉及图像的不同问题提供了稳健的解决方案。在本文中,我们将使用Tensorflow从头开始创建一个卷积神经网络(CNN)。然后,我们将使用它对猫和狗的图像进行分类,这是最流行的图像分类数据集之一。

本文旨在帮助该领域的新手,尤其是Tensorflow,学习获取数据、处理数据、建立模型、训练数据并最终使用数据进行预测的基本原理。



 

什么是分类?

我们必须回答的第一个问题是什么是分类。我会尽可能简短地介绍这些原则,并提供其他有价值的文章,更深入地介绍它们。

分类是为给定的输入数据分配标签的过程。例如,我们可以对电子邮件是否为垃圾邮件进行分类。在这种情况下,对于给定的图像,我们将预测图像是猫还是狗。

为了更详细地解释什么是分类以及最流行的算法,我建议通过中培IT学院机器学习、深度学习、计算机图像处理及知识图谱应用与核心技术实战课程进行系统学习。

 

卷积神经网络(CNN)

以下关键概念是CNN(或ConvNet)。CNN是一类神经网络,它将图像作为输入,对其应用一系列操作并返回输出。该输出可以是概率、图像类别的预测或另一个新图像。这取决于网络架构和我们试图解决的问题。

在这种情况下,我们将使用一个简单的CNN来对狗或猫类中的输入图像进行分类。它将返回给定图像是狗或猫的概率。

为了更好地理解这种神经网络在图像中执行的操作,亦可参考IT学院机器学习、深度学习、计算机图像处理及知识图谱应用与核心技术实战课程。

 

建立我们的网络

是时候开始工作并构建我们的分类器了。正如我们之前所说,我们将使用Tensorflow和Keras,使用简单的CNN架构来制作猫/狗分类器。

加载数据集

我们将使用牛津IIIT宠物数据集,其中包含7000多张猫和狗的图像。该数据集具有CC-BY-SA 4.0许可证,这意味着我们可以将数据共享和调整用于任何目的。

首先,我们将需要以下库。

 

import pandas as pd

import glob

import numpy as np

import matplotlib.pyplot as plt

 

import tensorflow as tf

from tensorflow import keras

from keras.preprocessing.image import ImageDataGenerator

 

接下来,我们将加载数据集。你可以从Kaggle下载它,并将文件夹复制到你的工作目录中。此外,您可以直接从数据集的网站获取数据。

一旦我们有了数据集,它将包含一个名为“images”的文件夹,里面有所有宠物图像。

每个图像都将在文件名中包含其标签。正如我们在数据集的信息中看到的,数据被划分为不同的品种。


 

12种猫和25种狗。我们将遵循的策略是使用所有的狗品种作为狗的图像,并使用所有的猫品种作为猫的图像。我们不会考虑品种,因为我们想建立一个二进制分类器。

让我们看看我们有多少数据。、

 

print('There are {} images in the dataset'.format(len(glob.glob('images/*.jpg'))))

 

正如我们所看到的,总共有7390张图片。现在是时候摆脱这些品种了。我们将创建两个列表,一个包含所有狗的照片,另一个包含猫的所有图像。

 

CATS = ['Abyssinian', 'Bengal', 'Birman', 'Bombay', 'British_Shorthair', 'Egyptian_Mau', 'Maine_Coon', 'Persian', 'Ragdoll', 'Russian_Blue', 'Siamese', 'Sphynx']

 

cats_images = []

dogs_images = []

 

for img in glob.glob('images/*.jpg'):

    if any(cat in img for cat in CATS):

        cats_images.append(img)

    else:

        dogs_images.append(img)

 

现在我们可以看看我们有多少动物的图像。

 

print('There are {} images of cats'.format(len(cats_images)))

print('There are {} images of dogs'.format(len(dogs_images)))

 

该数据集有2400只猫和4990只狗。

 

数据分区

对于我们的网络,我们希望使用三个不同的集合:

训练用于训练模型的图像。

验证:在训练过程中测试模型的图像。

测试:在模型完成训练后,对其进行测试的图像。

我们将使用70%的图像进行训练,10%用于验证,剩下的20%用于测试。

由于我们只有两个图像列表(狗和猫),我们需要将这些列表划分为不同的集合。我们将用熊猫来做到这一点。

首先,我们对数据进行混洗,并将其分为三组,其对应的数据分布为70/10/20。

 

#shuffle the lists

np.random.shuffle(cats_images)

np.random.shuffle(dogs_images)

 

#split the data into train, validation and test sets

train_d, val_d, test_d = np.split(dogs_images, [int(len(dogs_images)*0.7), int(len(dogs_images)*0.8)])

train_c, val_c, test_c = np.split(cats_images, [int(len(cats_images)*0.7), int(len(cats_images)*0.8)])

 

接下来,我们必须使用panda创建数据帧。

 

train_dog_df = pd.DataFrame({'image':train_d, 'label':'dog'})

val_dog_df = pd.DataFrame({'image':val_d, 'label':'dog'})

test_dog_df = pd.DataFrame({'image':test_d, 'label':'dog'})

 

train_cat_df = pd.DataFrame({'image':train_c, 'label':'cat'})

val_cat_df = pd.DataFrame({'image':val_c, 'label':'cat'})

test_cat_df = pd.DataFrame({'image':test_c, 'label':'cat'})

 

它们将只有两列,一列带有图像名称,另一列带有标签“cat”或“dog”。

最后,我们可以连接数据帧。

 

train_df = pd.concat([train_dog_df, train_cat_df])

val_df = pd.concat([val_dog_df, val_cat_df])

test_df = pd.concat([test_dog_df, test_cat_df])

 

print('There are {} images for training'.format(len(train_df)))

print('There are {} images for validation'.format(len(val_df)))

print('There are {} images for testing'.format(len(test_df)))

 

我们已经从数据集中完美的创建了三个分区。

 

数据预处理

以下步骤是对所有图像进行预处理。我们希望它们具有相同的维度(因为CNN需要具有相同维度的所有输入数据),并且它们的像素被归一化。这样做的原因是为了更快地训练我们的神经网络模型。

我们将使用Keras中的ImageDataGenerator类。

 

BATCH_SIZE = 32

IMG_HEIGHT = 224

IMG_WIDTH = 224

 

#create the ImageDataGenerator object and rescale the images

trainGenerator = ImageDataGenerator(rescale=1./255.)

valGenerator = ImageDataGenerator(rescale=1./255.)

testGenerator = ImageDataGenerator(rescale=1./255.)

 

#convert them into a dataset

trainDataset = trainGenerator.flow_from_dataframe(

  dataframe=train_df,

  class_mode="binary",

  x_col="image",

  y_col="label",

  batch_size=BATCH_SIZE,

  seed=42,

  shuffle=True,

  target_size=(IMG_HEIGHT,IMG_WIDTH) #set the height and width of the images

)

 

valDataset = valGenerator.flow_from_dataframe(

  dataframe=val_df,

  class_mode='binary',

  x_col="image",

  y_col="label",

  batch_size=BATCH_SIZE,

  seed=42,

  shuffle=True,

  target_size=(IMG_HEIGHT,IMG_WIDTH)

)

 

testDataset = testGenerator.flow_from_dataframe(

  dataframe=test_df,

  class_mode='binary',

  x_col="image",

  y_col="label",

  batch_size=BATCH_SIZE,

  seed=42,

  shuffle=True,

  target_size=(IMG_HEIGHT,IMG_WIDTH)

)

 

我们刚刚创建了3个新的数据集,每个数据集都有经过预处理的图像。此外,我们应用shuffle属性来随机重组图像的顺序,并使用batch_size将图像连接到32个元素的组中。这意味着我们将一次向CNN提供32张图片。每一步中的图像越少,模型学习得越好,但完成训练过程需要更长的时间。这是一个我们可以用来检查性能如何随它而变化的参数。

 

可视化

如果我们想检查数据集的结果,我们可以进行以下编译。

 

images, labels = next(iter(testDataset))

 

print('Batch shape: ', images.shape)

print('Label shape: ', labels.shape)

 

我们有32张带有相关标签的图片。此外,我们可以绘制这些图像(例如,第四个图像)。

 

plt.imshow(images[3])

print('Label: ', labels[3])


 

 

标签为1表示狗,0表示猫。

 

模型

既然我们已经准备好了所有的数据,现在是时候构建模型了。

 

model = keras.Sequential([

    keras.layers.InputLayer(input_shape=(IMG_HEIGHT, IMG_WIDTH, 3)),

    keras.layers.Conv2D(64, (3, 3), activation='relu'),

    keras.layers.MaxPooling2D((2, 2)),

    keras.layers.Conv2D(128, (3, 3), activation='relu'),

    keras.layers.MaxPooling2D((2, 2)),

    keras.layers.Conv2D(256, (3, 3), activation='relu'),

    keras.layers.MaxPooling2D((2, 2)),

    keras.layers.Conv2D(512, (3, 3), activation='relu'),

    keras.layers.GlobalAveragePooling2D(),

    keras.layers.Dense(1, activation='sigmoid')

])

 

这是一个简单的CNN模型,具有四个卷积层和一个由具有1个输出神经元的密集层组成的输出层。

让我们进入训练阶段。我们需要编译并拟合模型。我们将使用二进制交叉熵作为损失函数,因为我们使用的是带有整数标签的类(0表示cat,1表示dog)。优化器将是adam算法,我们将使用准确性作为过程的度量。

我们将对网络进行15代的培训。

 

epochs=15

 

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

history = model.fit(trainDataset, epochs=epochs, validation_data=(valDataset))

 

现在我们已经训练了我们的第一个CNN!我们可以在训练过程中查看网络的准确性和损失值。

 

plt.plot(history.history['accuracy'])

plt.plot(history.history['val_accuracy'])

plt.xlabel('Epoch')

plt.ylabel('Accuracy')

plt.legend(['Training', 'Validation'])

plt.show()

 

 

最后一步是评估这个模型。为此,我们将使用测试数据集。

 

loss, acc = model.evaluate(testDataset)

 

print('Loss:', loss)

print('Accuracy:', acc)

 

该模型的准确率为80%。

你已经训练出了你的第一个卷积神经网络,祝贺你!现在我们已经训练了我们的新模型,我们可以用它来预测猫和狗的真实图像。这是我们可以使用我们的模型进行预测的部分。这些图像以前在任何过程阶段都不应该被看到。

 

预测

预测阶段是与现实世界问题最相似的场景,一旦模型经过训练,它就必须对看不见的数据进行分类。

在我们的例子中,我们将为下面的图像预测类。


 

 

对于人类来说,这显然是一只可爱的猫的形象,但让我们看看我们的模型对此有什么看法。

 

def preprocess(image):

    img_resize = tf.image.resize(image, [IMG_HEIGHT, IMG_WIDTH])

    img_norm = img_resize / 255

    return img_norm

  

img = plt.imread('pexels-cat-predict.jpg')

img = tf.reshape(img, (-1, IMG_HEIGHT, IMG_HEIGHT, 3))

img = preprocess(img)

model.predict(img)

 

在这种情况下,我们必须将图像重塑为网络的输入格式,并将其标准化,就像我们对所有数据集的图像所做的那样。

然后我们把它交给模型,输出为0.08。该输出可以在0到1之间变化,因为网络的输出层具有s形激活函数。由于我们的类对于猫是0,对于狗是1,所以我们的模型同意这个图像是猫的。

 

本文介绍了一个简单的方法,从零开始CNN。它的表现不错,但仍有很大的改进空间。在这里,我向大家推荐中培IT学院机器学习、深度学习、计算机图像处理及知识图谱应用与核心技术实战课程,课程涉及了深度学习、机器学习、神经网络、图像识别、知识图谱等人工智能领域的核心技术知识,将会给学员带来较大收获。

标签: 人工智能

近期开班