用Python OpenCV Keras创建自己的图像分类

用Python OpenCV Keras创建自己的图像分类

首页休闲益智2048分类更新时间:2024-04-30

来源 | 机器学习与计算机视觉

作者 |磐怼怼

介绍

你是否曾经偶然发现一个数据集或图像,并想知道是否可以创建一个能够区分或识别图像的系统?

图像分类的概念将帮助我们解决这个问题。图像分类是计算机视觉最热门的应用之一,是任何想在这个领域工作的人都必须知道的概念。

在本文中,我们将看到一个非常简单但使用频率很高的应用程序,那就是图像分类。我们不仅将看到如何使一个简单和有效的模型分类数据,而且还将学习如何实现一个预先训练的模型,并比较两者的性能。

在本文结束时,你将能够找到自己的数据集并轻松实现图像分类。

先决条件:

听起来有趣吗?准备创建你自己的图像分类器吧!

目录

  1. 图像分类
  2. 理解问题陈述
  3. 设置图像数据
  4. 让我们构建我们的图像分类模型
    1. 数据预处理
    2. 数据扩充
    3. 模型定义和训练
    4. 评估结果
  5. 迁移学习的艺术
    1. 导入基础MobileNetV2模型
    2. 微调
    3. 训练
    4. 评估结果
  6. 下一步是什么?

什么是图像分类?

图像分类是分配输入图像(一组固定类别中的一个标签)的任务。这是计算机视觉的核心问题之一,尽管它很简单,却有各种各样的实际应用。

让我们举个例子来更好地理解。当我们进行图像分类时,我们的系统将接收图像作为输入,例如,一只猫。现在,系统将已知一组类别,它的目标是为图像分配一个类别。

这个问题似乎很简单,但对于计算机来说却是一个很难解决的问题。你可能知道,电脑看到的是一组数字,而不是我们看到的猫的图像。图像是由0到255的整数组成的三维数组,大小为宽x高x 3。3代表红色、绿色、蓝色三个颜色通道。

那么我们的系统如何学习识别这幅图像呢?通过卷积神经网络。卷积神经网络(CNN)是深度学习神经网络的一种,是图像识别领域的巨大突破。到目前为止,你可能已经对CNN有了一个基本的了解,我们知道CNN由卷积层、Relu层、池化层和全连接层组成。

要阅读关于图像分类和CNN的详细信息,你可以查看以下资源:

现在我们已经理解了这些概念,让我们深入了解如何构建和实现图像分类模型。

理解问题陈述

考虑下面的图像:

一个精通体育运动的人可以认出橄榄球的形象。图像的不同方面可以帮助你识别它是橄榄球,它可以是球的形状或球员的服装。但你有没有注意到,这张照片很可能是一个足球形象?

让我们考虑另一张图片:

你认为这个图像代表什么?很难猜对吧?对于没有受过训练的人来说,这幅图像很容易被误认为是足球,但实际上,这是橄榄球的图像,因为我们可以看到后面的球门柱不是网,而且尺寸更大。现在的问题是,我们能否建立一个能够正确分类图像的系统。

这就是我们项目背后的想法,我们想要建立一个系统能够识别图像中所代表的运动。这里分为橄榄球和足球两大类。问题陈述可能有点棘手,因为体育运动有很多共同的方面,尽管如此,我们将学习如何解决问题,并创建一个良好的表现系统。

设置我们的图像数据

由于我们正在处理一个图像分类问题,我使用了两个最大的图像数据源,即ImageNet和谷歌OpenImages。我实现了两个python脚本,我们可以轻松地下载图像。一共下载了3058张图片,分为train和test两部分。我用训练文件夹有2448张图片,测试文件夹有610张图片,进行了80-20的分割。橄榄球和足球两个类别各有1224张图片。

我们的数据结构如下:


我们来建立我们的图像分类模型!

步骤1: 导入所需的库

这里,我们将使用Keras库来创建模型并对其进行训练。我们还使用Matplotlib和Seaborn来可视化我们的数据集,以便更好地理解我们将要处理的图像。另一个处理图像数据的重要库是Opencv。

importmatplotlib.pyplotasplt importseabornassns importkeras fromkeras.modelsimportSequential fromkeras.layersimportDense,Conv2D,MaxPool2D,Flatten,Dropout fromkeras.preprocessing.imageimportImageDataGenerator fromkeras.optimizersimportAdam fromsklearn.metricsimportclassification_report,confusion_matrix importtensorflowastf importcv2 importos importnumpyasnp 步骤2: 加载数据

接下来,让我们定义数据的路径。让我们定义一个名为get_data()的函数,它使我们更容易创建我们的训练和验证数据集。我们定义了我们将要使用的两个标签“Rugby”和“Soccer”。我们使用Opencv imread函数读取RGB格式的图像,并将图像大小调整到我们想要的宽度和高度(在本例中都是224)。

labels=['rugby','soccer'] img_size=224 defget_data(data_dir): data=[] forlabelinlabels: path=os.path.join(data_dir,label) class_num=labels.index(label) forimginos.listdir(path): try: img_arr=cv2.imread(os.path.join(path,img))[...,::-1]#convertBGRtoRGBformat resized_arr=cv2.resize(img_arr,(img_size,img_size))#Reshapingimagestopreferredsize data.append([resized_arr,class_num]) exceptExceptionase: print(e) returnnp.array(data)

Nowwecaneasilyfetchourtrainandvalidationdata. train=get_data('../input/traintestsports/Main/train') val=get_data('../input/traintestsports/Main/test') 步骤3: 可视化数据

让我们可视化我们的数据,看看我们到底在使用什么。我们使用seaborn来绘制这两个类中的图像数量,你可以看到输出是什么样的。

l=[] foriintrain: if(i[1]==0): l.append("rugby") else l.append("soccer") sns.set_style('darkgrid') sns.countplot(l)

输出:

让我们可视化来自橄榄球和足球的随机图像:

plt.figure(figsize=(5,5)) plt.imshow(train[1][0]) plt.title(labels[train[0][1]])

输出:

足球图片也应用相同操作:

plt.figure(figsize=(5,5)) plt.imshow(train[-1][0]) plt.title(labels[train[-1][1]])

输出:

步骤4: 数据预处理和数据增强

接下来,在继续构建模型之前,我们执行一些数据预处理和数据增强。

x_train=[] y_train=[] x_val=[] y_val=[] forfeature,labelintrain: x_train.append(feature) y_train.append(label) forfeature,labelinval: x_val.append(feature) y_val.append(label) #Normalizethedata x_train=np.array(x_train)/255 x_val=np.array(x_val)/255 x_train.reshape(-1,img_size,img_size,1) y_train=np.array(y_train) x_val.reshape(-1,img_size,img_size,1) y_val=np.array(y_val)

对训练数据的数据增强:

datagen=ImageDataGenerator( featurewise_center=False,#setinputmeanto0overthedataset samplewise_center=False,#seteachsamplemeanto0 featurewise_std_normalization=False,#divideinputsbystdofthedataset samplewise_std_normalization=False,#divideeachinputbyitsstd zca_whitening=False,#applyZCAwhitening rotation_range=30,#randomlyrotateimagesintherange(degrees,0to180) zoom_range=0.2,#Randomlyzoomimage width_shift_range=0.1,#randomlyshiftimageshorizontally(fractionoftotalwidth) height_shift_range=0.1,#randomlyshiftimagesvertically(fractionoftotalheight) horizontal_flip=True,#randomlyflipimages vertical_flip=False)#randomlyflipimages datagen.fit(x_train) 步骤5: 定义模型

让我们定义一个简单的CNN模型,有3个卷积层,然后是max-pooling层。在第3次maxpool操作后添加一个dropout层,以避免过度拟合。

model=Sequential() model.add(Conv2D(32,3,padding="same",activation="relu",input_shape=(224,224,3))) model.add(MaxPool2D()) model.add(Conv2D(32,3,padding="same",activation="relu")) model.add(MaxPool2D()) model.add(Conv2D(64,3,padding="same",activation="relu")) model.add(MaxPool2D()) model.add(Dropout(0.4)) model.add(Flatten()) model.add(Dense(128,activation="relu")) model.add(Dense(2,activation="softmax")) model.summary()

现在让我们使用Adam作为优化器,SparseCategoricalCrossentropy作为损失函数来编译模型。我们使用较低的学习率0.000001来获得更平滑的曲线。

opt=Adam(lr=0.000001) model.compile(optimizer=opt,loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),metrics=['accuracy'])

现在,让我们训练我们的模型500个epochs,因为我们的学习速率非常小。

history=model.fit(x_train,y_train,epochs=500,validation_data=(x_val,y_val)) 步骤6: 评估结果

我们将绘制我们的训练和验证的准确性以及训练和验证的损失。

acc=history.history['accuracy'] val_acc=history.history['val_accuracy'] loss=history.history['loss'] val_loss=history.history['val_loss'] epochs_range=range(500) plt.figure(figsize=(15,15)) plt.subplot(2,2,1) plt.plot(epochs_range,acc,label='TrainingAccuracy') plt.plot(epochs_range,val_acc,label='ValidationAccuracy') plt.legend(loc='lowerright') plt.title('TrainingandValidationAccuracy') plt.subplot(2,2,2) plt.plot(epochs_range,loss,label='TrainingLoss') plt.plot(epochs_range,val_loss,label='ValidationLoss') plt.legend(loc='upperright') plt.title('TrainingandValidationLoss') plt.show()

让我们看看曲线是怎样的-

我们可以打印出分类报告,看看精度和准确性。

predictions=model.predict_classes(x_val) predictions=predictions.reshape(1,-1)[0] print(classification_report(y_val,predictions,target_names=['Rugby(Class0)','Soccer(Class1)']))

我们可以看到,我们简单的CNN模型能够达到83%的准确率。通过一些超参数调整,我们或许可以提高2-3%的精度。

我们还可以将一些预测错误的图像可视化,看看我们的分类器哪里出错了。

迁移学习的艺术

我们先来看看迁移学习是什么。迁移学习是一种机器学习技术,在一个任务上训练的模型被重新用于第二个相关的任务。迁移学习的另一个关键应用是当数据集很小的时候,通过在相似的图像上使用预先训练过的模型,我们可以很容易地提高性能。既然我们的问题陈述很适合迁移学习,那么让我们看看我们可以如何执行一个预先训练好的模型,以及我们能够达到什么样的精度。

步骤1: 导入模型

我们将从MobileNetV2模型创建一个基本模型。这是在ImageNet数据集上预先训练的,ImageNet数据集是一个包含1.4M图像和1000个类的大型数据集。这个知识库将帮助我们从特定数据集中对橄榄球和足球进行分类。

通过指定参数 include_top=False,可以加载一个不包含顶部分类层的网络。

base_model=tf.keras.applications.MobileNetV2(input_shape=(224,224,3),include_top=False,weights="imagenet")

在编译和训练模型之前冻结基础模型是很重要的。冻结后将防止我们的基础模型中的权重在训练期间被更新。

base_model.trainable=False

接下来,我们使用base_model定义模型,然后使用GlobalAveragePooling函数将每个图像的特征转换为单个矢量。我们添加0.2的dropout和最终的全连接层,有2个神经元和softmax激活。

model=tf.keras.Sequential([base_model, tf.keras.layers.GlobalAveragePooling2D(), tf.keras.layers.Dropout(0.2), tf.keras.layers.Dense(2,activation="softmax") ])

接下来,让我们编译模型并开始训练它。

base_learning_rate=0.00001 model.compile(optimizer=tf.keras.optimizers.Adam(lr=base_learning_rate), loss=tf.keras.losses.BinaryCrossentropy(from_logits=True), metrics=['accuracy']) history=model.fit(x_train,y_train,epochs=500,validation_data=(x_val,y_val)) 步骤2: 评估结果

acc=history.history['accuracy'] val_acc=history.history['val_accuracy'] loss=history.history['loss'] val_loss=history.history['val_loss'] epochs_range=range(500) plt.figure(figsize=(15,15)) plt.subplot(2,2,1) plt.plot(epochs_range,acc,label='TrainingAccuracy') plt.plot(epochs_range,val_acc,label='ValidationAccuracy') plt.legend(loc='lowerright') plt.title('TrainingandValidationAccuracy') plt.subplot(2,2,2) plt.plot(epochs_range,loss,label='TrainingLoss') plt.plot(epochs_range,val_loss,label='ValidationLoss') plt.legend(loc='upperright') plt.title('TrainingandValidationLoss') plt.show()

让我们看看曲线是怎样的-

我们也打印一下分类报告,以便得到更详细的结果。

predictions=model.predict_classes(x_val) predictions=predictions.reshape(1,-1)[0] print(classification_report(y_val,predictions,target_names=['Rugby(Class0)','Soccer(Class1)']))

我们可以看到,通过迁移学习,我们可以得到更好的结果。橄榄球和足球的精度都高于我们的CNN模型,而且总体精度达到了91%,这对于这样一个小数据集来说是非常好的。通过一些超参数调优和更改参数,我们也可以获得更好的性能!

下一步是什么?

这只是计算机视觉领域的起点。事实上,试着改进你的基础CNN模型来匹配或超过基准性能。

总结

祝贺你已经学习了如何创建自己的数据集、创建CNN模型或执行迁移学习来解决问题。我们在这篇文章中学到了很多,从学习寻找图像数据到创建能够实现合理性能的简单CNN模型。我们还学习了迁移学习的应用,进一步提高了我们的绩效。

这还没有结束,我们看到我们的模型错误分类了很多图像,这意味着仍然有改进的空间。我们可以从寻找更多的数据开始,甚至实现更好的、最新的架构,以便更好地识别特性。

查看全文
大家还看了
也许喜欢
更多游戏

Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved