使用卷积深度神经网络和 PyTorch 库对花卉图像进行分类
作者 | Avishek Nag
来源 | Medium
编辑 | 代码医生团队
语言图像数据是深度学习技术的一种非常流行的用法。在本文中将讨论使用深度卷积神经网络识别花卉图像。
为此将使用Python的PyTorch,TorchVision和PIL库
数据探索
可以在Kaggle找到此问题所需的数据集。它包含文件夹结构和花卉图像。有5种不同类型的花。文件夹结构如下所示
https://www.kaggle.com/alxmamaev/flowers-recognition/
图1
现在将看到文件夹'rose'中的花卉图像样本
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
def show_image(path):
img = Image.open(path)
img_arr = np.array(rose_img)
plt.figure(figsize=(5,5))
plt.imshow(np.transpose(img_arr, (0, 1, 2)))
show_image("../data/flowers/rose/537207677_f96a0507bb.jpg")
数据预处理
PyTorch总是期望以“张量”的形式提供数据。这些“张量”在神经网络的节点之间运行,包含原始和预处理或后处理的数据。基本上,简而言之,“张量”类似于“numpy”阵列。
对于图像数据,还必须将图像作为张量读取,并在进行任何分类之前应用几个预处理阶段。
可以将图像视为三维张量。每个图像可以有3种类型的像素颜色值 - 分别为红色,绿色和蓝色。我们称之为RGB颜色编码。另外两个维度是长度和宽度方向的像素值。
通常,图像数据需要两个非常常见的预处理阶段,如下所示:
1.调整大小为模板:将图像调整为方形。将每个图像的大小调整为64x64图像。
2.归一化:使用每个像素值的(x - mean)/ sd机制进行统计归一化。它有助于改善图像中的可视化,增强功能和拉伸对比度。
使用PyTorch,将进行这组预处理。
还可以定义一个函数来显示一组变换图像
def show_transformed_image(image):
np_image = image.numpy()
plt.figure(figsize=(20,20))
plt.imshow(np.transpose(np_image, (1, 2, 0)))
现在,可以看到第一批的转换图像
show_transformed_image(make_grid(image))
也可以让类索引数据字典
这将有助于识别类。
构建模型
要构建图像数据的机器学习模型,仅提供像素值是不够的。图像中有许多隐藏的功能仍未被发现。为此,应该使用卷积和最大池层的组合来提取重要特征。
卷积层
在数学上,两个函数f&g之间的卷积运算被定义为
实际上,如果将f视为图像张量,则g应该是另一个可以作为“卷积核”的张量。
它是两个张量的乘法值的逐像素求和。
下图显示了卷积运算对样本图像张量的影响
大小为3x3的卷积核在图像张量周围移动,作为从(0,0)位置开始的窗口,输出张量(0,0)处的样本结果如下所示
输出(0,0)=图像张量(0,0)x内核(0,0)+图像张量(0,1)x内核(0,1)+图像张量(0,2)x内核(0,2) )+图像张量(1,0)x内核(1,0)+图像张量(1,1)x内核(1,1)+图像张量(1,2)x内核(1,2)+图像张量( 2,0)x内核(2,0)+图像张量(2,1)x内核(2,1)+图像张量(2,2)x内核(2,2)= 1 x 1 + 1 x 0 + 1 x 1 + 0 x 0 + 1 x 1 + 1 x 0 + 0 x 1 + 0 x 0 + 1 x 1 = 4
内核将位置移位1位以计算输出张量的其他位置的值。这种“转变”被称为“跨步”。
需要卷积层来增强和提取图像的重要和隐藏特征。在我们的例子中,可能会发生'花'位于图像的中心位置,因此应用卷积有助于检索花的核心特征,忽略其他背景对象和颜色。
由于每个图像都遵循RGB颜色编码,将对每种颜色应用卷积运算,因此将得到三个输出张量。最终输出将是所有三个的张量总和。这些“颜色代码”中的每一个在PyTorch API术语中称为“通道”。
在数学上,如果在大小为WxH的图像上应用大小为kxk的滤波器,则它会产生大小为(W-k + 1)x(H-k + 1)的输出图像/张量
在例子中,卷积是这样创建的
self.conv1 = nn.Conv2d(in_channels=3, out_channels=12, kernel_size=3,stride=1, padding=1)
'out_channels'指定要应用的过滤器数量。在这里应用了12个滤镜,这些滤镜将产生12个尺寸为62x62的中间图像张量。这些图像中的每一个都包含原始图像的一个独特特征。
ReLU层
'ReLU'是一种激活函数,可捕获另一函数输出中的非线性。在数学上,它被定义为
f(x)=max(0,x)
所以它总是返回正值。可以说,它是一个'正面过滤器'。将在卷积后应用'ReLU'层。
在例子中,'ReLU'创建如下
self.relu1 = nn.ReLU()
最大池层
“最大汇集层”通常位于“ReLU”之后。大小为2的“最大池”是2x2窗口,它遍历“ReLU”操作的输出张量并选择窗口内的最大像素值。该操作可以通过下图解释
“最大池”图层的目标是仅选择那些具有高影响力且具有较大价值的特征。它有助于减少功能的尺寸。
在例子中,'Max Pool'的创建如下
self.maxpool1 = nn.MaxPool2d(kernel_size=2)
它会将图像尺寸减小50%(32 = 64/2)。
线性功能层
顾名思义,它是一个线性函数,它将“Max Pool”的输出作为一个展平数组,并将输出作为类索引。预测类索引的“线性函数”的输出值将是最大值。
在例子中,'线性函数'的创建方式如下
self.lf = nn.Linear(in_features=32 * 32 * 24, out_features=num_classes)
整体架构的模型
将应用不同的图层,如下图所示
有两套'卷积'和'ReLU'层。'View'使输出张量从最后一个'ReLU'层变平。将大小为64x64的图像张量作为输入,由于应用了内核大小为2x2(32 = 64/2)的“MaxPool2D”,它将减少到32x32。
首先,将数据集按80:20的比例划分为训练和测试
from torch.utils.data import random_split
train_size = int(0.8 * len(total_dataset))
test_size = len(total_dataset) - train_size
train_dataset, test_dataset = random_split(total_dataset, [train_size, test_size])
train_dataset_loader = DataLoader(dataset = train_dataset, batch_size = 100)
test_dataset_loader = DataLoader(dataset = test_dataset, batch_size = 100)
然后,将通过扩展PyTorch库给出的“Module”来编写一个自定义类来堆叠这些层
import torch.nn as nn
class FlowerClassifierCNNModel(nn.Module):
def __init__(self, num_classes=5):
super(FlowerClassifierCNNModel,self).__init__()
self.conv1 = nn.Conv2d(in_channels=3, out_channels=12, kernel_size=3,stride=1, padding=1)
self.relu1 = nn.ReLU()
self.maxpool1 = nn.MaxPool2d(kernel_size=2)
self.conv2 = nn.Conv2d(in_channels=12, out_channels=24, kernel_size=3, stride=1, padding=1)
self.relu2 = nn.ReLU()
self.lf = nn.Linear(in_features=32 * 32 * 24, out_features=num_classes)
def forward(self, input):
output = self.conv1(input)
output = self.relu1(output)
output = self.maxpool1(output)
output = self.conv2(output)
output = self.relu2(output)
output = output.view(-1, 32 * 32 * 24)
output = self.lf(output)
return output
'__init__'定义每个图层及其参数,而'forward'函数执行实际调用和图层堆叠。最后一层的输出从'forward'函数返回。
模型训练
需要有一个优化器和损失函数用于模型训练。将使用' Adam optimizer '和' Cross-Entropy Loss '。
from torch.optim import Adam
cnn_model = FlowerClassifierCNNModel()
optimizer = Adam(cnn_model.parameters())
loss_fn = nn.CrossEntropyLoss()
使用PyTorch,需要在训练模式下设置模型,然后通过迭代训练数据集,计算优化器的丢失和递增步骤来运行训练。
可以为此编写一个函数
def train_and_build(n_epoches):
for epoch in range(n_epoches):
cnn_model.train()
for i, (images, labels) in enumerate(train_dataset_loader):
optimizer.zero_grad()
outputs = cnn_model(images)
loss = loss_fn(outputs, labels)
loss.backward()
optimizer.step()
函数调用'loss.backward'返回到层并计算过程中发生的损失。
将使用200的'epoche'来训练模型
train_and_build(200)
模型测试和准确性
应该将模型设置为'eval'模式,以便在测试数据集上测试其准确性
import torch
cnn_model.eval()
test_acc_count = 0
for k, (test_images, test_labels) in enumerate(test_dataset_loader):
test_outputs = cnn_model(test_images)
_, prediction = torch.max(test_outputs.data, 1)
test_acc_count += torch.sum(prediction == test_labels.data).item()
test_accuracy = test_acc_count / len(test_dataset)
'torch.max'函数返回'线性函数'输出张量的最大值。最大值推断出预测的类别标签。
'torch.sum'函数总结了张量中的'1',它是'预测'和'实际测试输出'张量之间'AND'运算的输出。因此,这个总和给出了正确预测图像的数量。
在这里得到准确性
test_accuracy
几乎是70.52%。用简单的模型获得了很好的准确性。这个模型可以进一步调整。
使用模型进行样本图像预测
现在将看到如何将此模型与数据集中的示例图像一起使用。
show_image("../data/flowers/dandelion/13920113_f03e867ea7_m.jpg")
这是'蒲公英'的形象。
现在将使用PIL图像API读取图像并将其输入到转换管道中以进行必要的预处理,然后使用该模型进行预测
test_image = Image.open("../data/flowers/dandelion/13920113_f03e867ea7_m.jpg")
test_image_tensor = transformations(test_image).float()
test_image_tensor = test_image_tensor.unsqueeze_(0)
output = cnn_model(test_image_tensor)
class_index = output.data.numpy().argmax()
class_index
因此如上所述,从类到索引字典,可以确认它是一个'蒲公英'。所以图像分类器模型运行良好!
结论
学习了如何使用PyTorch库进行图像分类。在此过程中,介绍了图像的预处理,构建卷积层以及测试输入图像的模型。
通过'Hyperparameter'调整可以进一步提高模型的准确性,例如尝试使用'Adam optimizer'参数,添加额外的卷积层,调整内核大小和最大池窗口大小等。本文的读者可以自己尝试这些技术。
Jupyter笔记本可以从下面的链接找到
https://github.com/avisheknag17/public_ml_models/blob/master/image_classification_cnn_pytorch/notebook/cnn_image_classification_pytorch.ipynb?source=post_page---------------------------
推荐阅读
重磅!字节跳动开源高性能分布式训练框架BytePS:兼容TensorFlow、PyTorch等
点击“阅读原文”图书配套资源
上一篇: 冬天来了,分享两个雪花效果代码
下一篇: 稳定、高性价比!腾讯云地图床位服务来了!
推荐阅读
-
人工智能:162 - 如何使用 Python 进行图像识别和处理 深度学习和卷积神经网络应用
-
[姿势估计] 实践记录:使用 Dlib 和 mediapipe 进行人脸姿势估计 - 本文重点介绍方法 2):方法 1:基于深度学习的方法:。 基于深度学习的方法:基于深度学习的方法利用深度学习模型,如卷积神经网络(CNN)或递归神经网络(RNN),直接从人脸图像中学习姿势估计。这些方法能够学习更复杂的特征表征,并在大规模数据集上取得优异的性能。方法二:基于二维校准信息估计三维姿态信息(计算机视觉 PnP 问题)。 特征点定位:人脸姿态估计的第一步是通过特征点定位来检测和定位人脸的关键点,如眼睛、鼻子和嘴巴。这些关键点提供了人脸的局部结构信息,可用于后续的姿势估计。 旋转表示:常见的旋转表示方法包括欧拉角和旋转矩阵。欧拉角通过三个旋转角度(通常是俯仰、偏航和滚动)描述头部的旋转姿态。旋转矩阵是一个 3x3 矩阵,表示头部从一个坐标系到另一个坐标系的变换。 三维模型重建:根据特征点的定位结果,三维人脸模型可用于姿势估计。通过将人脸的二维图像映射到三维模型上,可以估算出人脸的旋转和平移信息。这就需要建立人脸的三维模型,然后通过优化方法将模型与特征点对齐,从而获得姿势估计结果。 特征点定位 特征点定位是用于检测人脸关键部位的五官基础部分,还有其他更多的特征点表示方法,大家可以参考我上一篇文章中介绍的特征点检测方案实践:人脸校正二次定位操作来解决人脸校正的问题,客户在检测关键点的代码上略有修改,坐标转换部分客户见上图 def get_face_info(image). img_copy = image.copy image.flags.writeable = False image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) results = face_detection.process(image) # 在图像上绘制人脸检测注释。 image.flags.writeable = True image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) box_info, facial = None, None if results.detections: for detection in results. for detection in results.detections: mp_drawing.Drawing.detection = 无 mp_drawing.draw_detection(image, detection) 面部 = detection.location_data.relative_keypoints 返回面部 在上述代码中,返回的数据是五官(6 个关键点的坐标),这是用 mediapipe 库实现的,下面我们可以尝试用另一个库:dlib 来实现。 使用 dlib 使用 Dlib 库在 Python 中实现人脸关键点检测的步骤如下: 确保已安装 Dlib 库,可使用以下命令: pip install dlib 导入必要的库: 加载 Dlib 的人脸检测器和关键点检测器模型: 读取图像并将其灰度化: 使用人脸检测器检测图像中的人脸: 对检测到的人脸进行遍历,并使用关键点检测器检测人脸关键点: 显示绘制了关键点的图像: 以下代码将参数 landmarks_part 添加到要返回的关键点坐标中。
-
使用卷积深度神经网络和 PyTorch 库对花卉图像进行分类
-
DeepShip-它由四个类别的265艘不同船只的47小时4分钟的真实世界水下录音组成。建议的数据集包括全年不同海况和噪音水平的记录。所提供的数据集不仅有助于评估现有算法的性能,而且还将使研究团体在未来受益。使用提出的数据集,我们还对六种基于时频提取特征的各种机器学习和深度学习算法进行了全面研究。此外,我们提出了一种新的基于可分离卷积的自编码器网络,以提高分类精度。对比分类准确率、精密度、查全率、fl-score等方面的实验结果,并进行配对抽样统计测试,结果表明,基于CQT特征的网络分类准确率达到77.53%,优于其他方法。 1.Introduction 近年来,由于水声分类在海洋船舶分类和探测、测量这些船舶的声音对环境的影响、退出船设计和海洋生物分类等方面的应用,引起了广泛的关注(Erbe et al., 2019;Malfante, Mars, Dalla Mura, & Gervaise, 2018)。复杂的水下环境、背景噪声、声音数据的频率依赖性吸收和散射等因素使其成为一个具有挑战性的领域(Erbe et al., 2019)。此外,螺旋桨、发动机和隐形船体技术的改进使该领域更具挑战性(Khishe &摩萨维,2020 年)。