百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

使用PyTorch进行深度学习的图像增强

toyiye 2024-06-21 19:11 11 浏览 0 评论


在这篇文章中,我们将了解图像增强的概念以及有什么不同的图像增强技术。我们还将使用PyTorch实现这些图像增强技术来构建一个图像分类深度学习模型。

为什么我们需要图像增强?

深度学习模型通常需要大量的数据来进行训练。通常,数据越多,模型的性能越好。但是获取海量数据面临着自身的挑战。并非每个人都拥有大公司的财力。

深度学习模型通常需要大量的训练数据。一般来说,数据越多,模型的性能越好。但获取大量数据本身也存在挑战。

缺乏数据的问题是,我们的深度学习模型可能无法从数据中学习模式或功能,因此它可能无法在不可见的数据上提供良好的性能。

在这种情况下我们能怎么做呢?我们可以利用图像增强技术来降低数据收集难度。


图像增强技术

图像旋转

图像旋转是最常用的增强技术之一。它可以帮助我们的模型对对象方向的变化变得健壮。即使我们旋转图像,图像的信息也保持不变。即从不同的角度看汽车,汽车也还是汽车:


我们可以使用此技术通过从原始图像创建旋转图像来增加数据大小。让我们看看如何旋转图像:

让我们导入图像并首先对其进行可视化:


这是原始图像。现在让我们看看如何旋转它。我将使用skimage库的rotate函数旋转图像:


图像平移

在某些情况下,图像中的对象未完全对准中心。在这些情况下,可以使用图像平移为图像添加平移不变性。

通过移动图像,我们可以更改对象在图像中的位置,从而使模型更具多样性。最终将导致更通用的模型。

图像平移是一种几何变换,可将图像中每个对象的位置映射到最终输出图像中的新位置。

平移操作之后,输入图像中位置(x,y)上存在的对象将移位到新位置(X,Y):

  • X = x + dx
  • Y = y + dy

此处,dx和dy是沿不同尺寸的相应位移。让我们看看如何将平移应用于图像:



平移超参数定义图像应移动的像素数。在这里,我将图像移动了(25,25)像素。我再次使用了“wrap”,用图像的其余像素填充输入边界外的点。

翻转图像

翻转是旋转的延伸。它使我们可以在左右以及上下方向上翻转图像。让我们看看如何实现翻转:


在这里,我使用了NumPy的fliplr函数来将图像从左到右翻转。它翻转每行的像素值。同样,我们可以上下翻转图像:


给图像添加噪声

图像降噪是重要的增强步骤,可让我们的深度学习模型学习如何将图像中的信号与噪声分离。

我们将使用skimage库的random_noise函数为原始图像添加一些随机噪声。我将要添加的噪声的标准偏差设为0.155(您也可以更改此值)。


图像模糊

由于图像来自不同的源,因此,图像的质量将不一样。有些图片可能是高质量的,而另一些可能是很差的。

在这种情况下,我们可以模糊图像。这有什么用呢?这有助于使我们的深度学习模型更健壮。


Sigma是标准偏差。sigma值越高,模糊效果越多。将“ Multichannel”设置为true可确保分别过滤图像的每个通道。

选择正确的增强技术的基本准则

在根据您要解决的问题确定增强技术时,有一些准则很重要。

  1. 任何机器学习模型构建过程的第一步都是确保输入的大小符合模型的期望。我们还必须确保所有图像的大小应该相似。为此,我们可以调整图像的大小到适当的大小。
  2. 假设您正在处理分类问题,并且数据样本的数量相对较少。在这种情况下,您可以使用不同的增强技术,例如图像旋转,图像降噪,翻转,移位等。请记住,所有这些操作都适用于图像中对象位置无关紧要的分类问题。
  3. 如果您正在执行对象检测任务,而对象的位置正是我们要检测的位置,那么这些技术可能不合适。
  4. 对图像像素值进行归一化是保证机器学习模型更好更快收敛的一种良好策略。如果机器学习模型有特定的要求,我们必须根据机器学习模型的要求对图像进行预处理。

案例研究:解决图像分类问题并应用图像增强

该项目的目的是将车辆图像分类为non-emergency 或emergency 。这是图像分类问题。您可以从此处下载数据集。

加载机器学习数据集

我们将应用图像增强技术,最后建立卷积神经网络(CNN)模型。让我们导入所需的Python库:

# importing the libraries
from torchsummary import summary
import pandas as pd
import numpy as np
from skimage.io import imread, imsave
from tqdm import tqdm
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from skimage.transform import rotate
from skimage.util import random_noise
from skimage.filters import gaussian
from scipy import ndimage


现在,我们将读取包含图像名称及其相应标签的CSV文件:

# loading dataset
data = pd.read_csv('emergency_vs_non-emergency_dataset/emergency_train.csv')
data.head()



这里的0表示该车辆为non-emergency 车辆,1表示其为emergency 车辆。现在,让我们从机器学习数据集中导入有图像:

# loading images
train_img = []
for img_name in tqdm(data['image_names']):
 image_path = 'emergency_vs_non-emergency_dataset/images/' + img_name
 img = imread(image_path)
 img = img/255
 train_img.append(img)
train_x = np.array(train_img)
train_y = data['emergency_or_not'].values
train_x.shape, train_y.shape



机器学习数据集中共有1,646张图像。让我们将这些数据分为训练集和验证集。我们将使用验证集来评估深度学习模型在看不见的数据上的表现:

train_x, val_x, train_y, val_y = train_test_split(train_x, train_y, test_size = 0.1, random_state = 13, stratify=train_y)
(train_x.shape, train_y.shape), (val_x.shape, val_y.shape)



我将test_size保持为0.1,因此将随机选择10%的数据作为验证集,其余的90%的数据将用于训练模型。我们在训练集中有1,481张图像,这不足以训练深度学习模型。

因此,接下来,我们将增强这些训练图像,以增强训练集,这可以改善深度学习模型的性能。

图像增强

final_train_data = []
final_target_train = []
for i in tqdm(range(train_x.shape[0])):
 final_train_data.append(train_x[i])
 final_train_data.append(rotate(train_x[i], angle=45, mode = 'wrap'))
 final_train_data.append(np.fliplr(train_x[i]))
 final_train_data.append(np.flipud(train_x[i]))
 final_train_data.append(random_noise(train_x[i],var=0.2**2))
 for j in range(5):
 final_target_train.append(train_y[i])



我们为训练集中的1,481张图像中的每张图像生成了4张增强图像。让我们以数组形式转换图像并验证数据集的大小:

len(final_target_train), len(final_train_data)
final_train = np.array(final_train_data)
final_target_train = np.array(final_target_train)



让我们可视化这些图像:

fig,ax = plt.subplots(nrows=1,ncols=5,figsize=(20,20))
for i in range(5):
 ax[i].imshow(final_train[i+30])
 ax[i].axis('off')



这里的第一张图片是数据集中的原始图片。其余四幅图像是使用不同的图像增强技术生成的。

现在是时候定义深度学习模型的体系结构了,然后在训练集上对其进行训练了。

# PyTorch libraries and modules
import torch
from torch.autograd import Variable
from torch.nn import Linear, ReLU, CrossEntropyLoss, Sequential, Conv2d, MaxPool2d, Module, Softmax, BatchNorm2d, Dropout
from torch.optim import Adam, SGD


我们必须将训练集和验证集都转换为PyTorch格式:

# converting training images into torch format
final_train = final_train.reshape(7405, 3, 224, 224)
final_train = torch.from_numpy(final_train)
final_train = final_train.float()
# converting the target into torch format
final_target_train = final_target_train.astype(int)
final_target_train = torch.from_numpy(final_target_train)


同样,我们将转换验证集:

# converting validation images into torch format
val_x = val_x.reshape(165, 3, 224, 224)
val_x = torch.from_numpy(val_x)
val_x = val_x.float()
# converting the target into torch format
val_y = val_y.astype(int)
val_y = torch.from_numpy(val_y)


模型架构

接下来,我们将定义深度学习模型的体系结构。该体系结构包含4个卷积块,然后是4个全连接的dense层:

torch.manual_seed(0)
class Net(Module): 
 def __init__(self):
 super(Net, self).__init__()
self.cnn_layers = Sequential(
 # Defining a 2D convolution layer
 Conv2d(3, 32, kernel_size=3, stride=1, padding=1),
 ReLU(inplace=True),
 # adding batch normalization
 BatchNorm2d(32),
 MaxPool2d(kernel_size=2, stride=2),
 # adding dropout
 Dropout(p=0.25),
 # Defining another 2D convolution layer
 Conv2d(32, 64, kernel_size=3, stride=1, padding=1),
 ReLU(inplace=True),
 # adding batch normalization
 BatchNorm2d(64),
 MaxPool2d(kernel_size=2, stride=2),
 # adding dropout
 Dropout(p=0.25),
 # Defining another 2D convolution layer
 Conv2d(64, 128, kernel_size=3, stride=1, padding=1),
 ReLU(inplace=True),
 # adding batch normalization
 BatchNorm2d(128),
 MaxPool2d(kernel_size=2, stride=2),
 # adding dropout
 Dropout(p=0.25),
 # Defining another 2D convolution layer
 Conv2d(128, 128, kernel_size=3, stride=1, padding=1),
 ReLU(inplace=True),
 # adding batch normalization
 BatchNorm2d(128),
 MaxPool2d(kernel_size=2, stride=2),
 # adding dropout
 Dropout(p=0.25),
 )
self.linear_layers = Sequential(
 Linear(128 * 14 * 14, 512),
 ReLU(inplace=True),
 Dropout(),
 Linear(512, 256),
 ReLU(inplace=True),
 Dropout(),
 Linear(256,10),
 ReLU(inplace=True),
 Dropout(),
 Linear(10,2)
 )
# Defining the forward pass 
 def forward(self, x):
 x = self.cnn_layers(x)
 x = x.view(x.size(0), -1)
 x = self.linear_layers(x)
 return x


让我们定义模型的其他超参数,包括优化器,学习率和损失函数:

# defining the model
model = Net()
# defining the optimizer
optimizer = Adam(model.parameters(), lr=0.000075)
# defining the loss function
criterion = CrossEntropyLoss()
# checking if GPU is available
if torch.cuda.is_available():
 model = model.cuda()
 criterion = criterion.cuda()
print(model)



训练模型

让我们训练20个epochs:

torch.manual_seed(0)
# batch size of the model
batch_size = 64
# number of epochs to train the model
n_epochs = 20
for epoch in range(1, n_epochs+1):
train_loss = 0.0
 
 permutation = torch.randperm(final_train.size()[0])
training_loss = []
 for i in tqdm(range(0,final_train.size()[0], batch_size)):
indices = permutation[i:i+batch_size]
 batch_x, batch_y = final_train[indices], final_target_train[indices]
 
 if torch.cuda.is_available():
 batch_x, batch_y = batch_x.cuda(), batch_y.cuda()
 
 optimizer.zero_grad()
 outputs = model(batch_x)
 loss = criterion(outputs,batch_y)
training_loss.append(loss.item())
 loss.backward()
 optimizer.step()
 
 training_loss = np.average(training_loss)
 print('epoch: \t', epoch, '\t training loss: \t', training_loss)



您会注意到,随着时间的增加,训练损失会减少。让我们保存经过训练的深度学习模型的权重:

torch.save(model, 'model.pt')

加载这个深度学习模型的Python代码:

the_model = torch.load('model.pt')

检查模型的性能

最后,让我们对训练和验证集进行预测,并检查各自的准确性:

torch.manual_seed(0)
# prediction for training set
prediction = []
target = []
permutation = torch.randperm(final_train.size()[0])
for i in tqdm(range(0,final_train.size()[0], batch_size)):
 indices = permutation[i:i+batch_size]
 batch_x, batch_y = final_train[indices], final_target_train[indices]
if torch.cuda.is_available():
 batch_x, batch_y = batch_x.cuda(), batch_y.cuda()
with torch.no_grad():
 output = model(batch_x.cuda())
softmax = torch.exp(output).cpu()
 prob = list(softmax.numpy())
 predictions = np.argmax(prob, axis=1)
 prediction.append(predictions)
 target.append(batch_y)
 
# training accuracy
accuracy = []
for i in range(len(prediction)):
 accuracy.append(accuracy_score(target[i].cpu(),prediction[i]))
 
print('training accuracy: \t', np.average(accuracy))



我们在训练集上的准确性超过91%!我们需要对验证集进行相同的检查:

# checking the performance on validation set
torch.manual_seed(0)
output = model(val_x.cuda())
softmax = torch.exp(output).cpu()
prob = list(softmax.detach().numpy())
predictions = np.argmax(prob, axis=1)
accuracy_score(val_y, predictions)


最后

在本文中,我们介绍了大多数常用的图像增强技术。您可以在任何图像分类问题上尝试这些图像增强技术,然后比较有无增强时的性能。

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码