【跨年博客/轻松向】Pytorch卷积神经网络图像识别

2023-12-27 03:30

本文主要是介绍【跨年博客/轻松向】Pytorch卷积神经网络图像识别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【跨年博客/轻松向】Pytorch卷积神经网络图像识别

  • 导语
  • 注意
  • 程序
    • 需要导入的库
    • 设置数据集
    • 定义网络
    • 训练
    • 预测
  • 一些闲谈

写于2021-12-31 23:04,2021年最后一篇博客了,也是2022年第一篇博客。


今年的格言:有一分热,发一分光,就令萤火一般,也可以在黑暗里发一点光,不必等候炬火,此后如竟没有炬火,我便是唯一的光。


导语

前几天不是发了一个MNIST图像识别的文章吗,但那篇还是有一些东西没讲的很好。MNIST图像是灰度图像,很多小伙伴想看看RGB的写法。这次拿RGB图做一个细胞分类吧~
看右下角时间~

注意

此篇博客是对上篇博客的修正、补充以及拓展。
请先参阅上期博客:【Pytorch】MNIST 图像分类代码 - 超详细解读_CSDN_千鱼干的博客
有地方看不懂没事,看完后看这篇的补充内容。

程序

需要导入的库

import torch
import torch.nn as nn
from torch.nn import Sequential
from matplotlib import pyplot as plt
import torchvision.datasets as datasets
from torch.utils.data import DataLoader
import torchvision.transforms as transforms

torch库就不解释了。
torch.nn库是一个包含了神经网络的Modules和用来继承的包以及一些函数方法,比如nn.functional。因为我们之后定义网络时是从nn.Module继承的,还用了nn里面的卷积、激活函数等等,所以这个库必不可少。
Sequential(中文:序列)是torch.nn里面“整合”层用的。就相当于饼干盒,把饼干“像序列一样”装进去。
matplotlib在这里是一个显示图像的库。我们引入了pyplot,用来显示图像。
torchvision包含一些数据集、模型、图像处理方法。这里用datasets来处理数据集(我们自己的图片)。
torch.utils.data里面的DataLoader是用来将数据集装载用的,以便训练。
torchvision.transforms在这里用于定义数据集处理形式。往下看就知道。

设置数据集

这里假设我们数据集的路径是当前你的python文件所在文件夹下data/CELLS/。这个文件夹下有两个子文件夹,一个叫“linba”,另一个叫“xianxingli”

插播一句,现在是2022-1-1 0:00,这篇博客写了一年(笑)

也就是说,我们的数据集分为淋巴细胞和线性粒细胞两种细胞的图片。
所以我们要设置两个类别:classes = [“linba”, “zhongxingli”]
我们这里设置一下批次大小位64,迭代250次,学习率0.001。
学习率选一个小小的数,这样有助于梯度下降。具体原因见上一篇博客。
这里还要写一个get_variable()函数以获取cuda加速后的自动求导结果。


这里 再次 详细解释一下epochs和batch_szie:
->batch_size表示每轮迭代训练时每次训练的数据量;
->epochs表示训练几轮。

每一次迭代(Iteration)都是一次权重更新,每一次权重更新需要batch_size个数据进行正向传递(Forward)运算得到损失函数,再通过反向传导(Backward)更新参数(注意,在这个过程中需要把梯度(Grad)设置为0,这个后面再讲)。1个迭代等于使用batch_size个样本训练一次。比如有256个样本数据,完整训练完这些样本数据需要:
->batch_size=64;
->迭代4次;
->epochs=1。


而通常会将epochs设为不仅1次,这就跟磨面一样,磨完一轮不够,磨多轮才能得到更加精细的面粉。

这时候因为我们处理的是图片,而我们处理的应该是张量(Pytorch处理的是张量,类似向量,矩阵)。我们怎么让数据集图片变成数据集矩阵呢?
这时就要设置transform(翻译:转换)了。
同时,我们的图片不能太大,否则会让训练很慢。
所以我们首先将图片转化为张量,然后将裁剪为 w ∗ h = 128 ∗ 128 w*h=128*128 wh=128128(w是width,宽;h是height,高;c是channel,通道,就是颜色通道,RGB是红绿蓝三通道)大小的张量。同时我们还要让每个像素数值服从标准为0.5的正态分布。
因为我们需要训练集和测试集两部分,所以将数据集分成两个处理内容,最后将训练集和测试集装载,数据集处理完毕。

最后,我们展示一下某张数据集图片转换为向量并处理之后的样子(可选)。

全部代码如下:

path = "./data/CELLS/"
classes = ["linba", "zhongxingli"]def get_variable(x):x = torch.autograd.Variable(x)return x.cuda() if torch.cuda.is_available() else xbatch_size = 64
epochs = 250
lr = 0.001test_path = "./data/CELLS/"transform = transforms.Compose([transforms.ToTensor(),transforms.Resize((128, 128)),transforms.CenterCrop(128),transforms.Normalize(mean=[0.5, 0.5, 0.5],std=[0.5, 0.5, 0.5])
])data_train = datasets.ImageFolder(root=path, transform=transform)
train_loader = DataLoader(data_train, batch_size=batch_size, shuffle=True)data_test = datasets.ImageFolder(root=test_path, transform=transform)
test_loader = DataLoader(data_test, batch_size=batch_size, shuffle=True)# -----------------------展示数据集---------------------------
images, labels = next(iter(train_loader))
img = images[0].numpy().transpose(1, 2, 0)
plt.imshow(img)
plt.title(labels[0])
plt.show()# -----------------------展示数据集---------------------------

定义网络

网络结构如下图:
结构
注意,输入出的“?x128x128x3”的意思是“?”张图片,“128x128x3”是 w ∗ h ∗ c = 128 ∗ 128 ∗ 3 w*h*c=128*128*3 whc=1281283

怎样定义网络呢?首先我们要从nn.Module继承,然后“装填”入我们的架构,最后在前向计算(forward)函数中进行前向计算。
这里注意一下:forward函数不需要显式调用,因为nn.Module类中有一个函数会自动调用forward。


上一篇博客没写明这里每层的参数是怎么计算的。这一部分相当重要,因为最后传入全连接层时必须要求输入和输出匹配,但这里我上篇没细讲。
这里贴出nn.Conv2d()在Pytorch官方文档里的图:

–>猛戳我 - 原文链接<–

计算的方式
注意这里的符号, H o u t H_{out} Hout是进行的向下取整
定义类的方式和上一篇相似。
代码:

class CNN(nn.Module):def __init__(self):super(CNN, self).__init__()self.conv1 = Sequential(nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, stride=1, padding=1),nn.BatchNorm2d(32),nn.ReLU(),nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, stride=1, padding=2),nn.BatchNorm2d(32),nn.ReLU(),nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, stride=1, padding=2),nn.BatchNorm2d(32),nn.ReLU(),nn.MaxPool2d(2, 2))self.conv2 = Sequential(nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, stride=1, padding=1),nn.BatchNorm2d(64),nn.ReLU(),nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, stride=1, padding=1),nn.BatchNorm2d(64),nn.ReLU(),nn.MaxPool2d(2, 2))self.conv3 = Sequential(nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, stride=1, padding=1),nn.BatchNorm2d(128),nn.ReLU(),nn.Conv2d(in_channels=128, out_channels=128, kernel_size=3, stride=1, padding=1),nn.BatchNorm2d(128),nn.ReLU(),nn.MaxPool2d(2, 2))self.conv4 = Sequential(nn.Conv2d(in_channels=128, out_channels=256, kernel_size=3, stride=1, padding=1),nn.BatchNorm2d(256),nn.ReLU(),nn.Conv2d(in_channels=256, out_channels=256, kernel_size=3, stride=1, padding=1),nn.BatchNorm2d(256),nn.ReLU(),nn.MaxPool2d(2, 2))self.dense = Sequential(nn.Linear(8 * 8 * 256, 256),nn.ReLU(),nn.Dropout(p=0.5),nn.Linear(256, 128),nn.ReLU(),nn.Dropout(p=0.5),nn.Linear(128, 2))def forward(self, x):x1 = self.conv1(x)x2 = self.conv2(x1)x3 = self.conv3(x2)x4 = self.conv4(x3)x5 = x4.view(-1, 8 * 8 * 256)out = self.dense(x5)return out

训练

这一部分我上一篇讲的很详细了。我只贴出代码:

cnn = CNN()
if torch.cuda.is_available():cnn = cnn.cuda()lossF = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(cnn.parameters(), lr=lr)cnn.train()loss_pth = 999999999.99
i_pth = 0for epoch in range(epochs):running_loss = 0.0running_correct = 0.0print("Epochs [{}/{}]".format(epoch, epochs))for data in train_loader:X_train, y_train = dataX_train, y_train = get_variable(X_train), get_variable(y_train)outputs = cnn(X_train)_, predict = torch.max(outputs.data, 1)# ----------------------------------optimizer.zero_grad()loss = lossF(outputs, y_train)loss.backward()optimizer.step()# ----------------------------------running_loss += loss.item()running_correct += torch.sum(predict == y_train.data)testing_correct = 0.0for data in test_loader:X_test, y_test = dataX_test, y_test = get_variable(X_test), get_variable(y_test)outputs = cnn(X_test)_, predict = torch.max(outputs.data, 1)testing_correct += torch.sum(predict == y_test.data)print("Loss: {}    Training Accuracy: {}%    Testing Accuracy:{}%".format(running_loss,100 * running_correct / len(data_train),100 * testing_correct / len(data_test)))if running_loss < loss_pth:loss_pth = running_losstorch.save(cnn, "./models/cell_classify_%d.pth" % i_pth)i_pth = i_pth + 1torch.save(cnn, "cell_classify.pth")
print("训练完成!最小损失为:%f" % loss_pth)

预测

这一部分我在上一篇博客也是讲得比较详细。我只贴出代码。
这里设pics文件夹下还有一个文件夹,里面有待预测图片:

import torch
import torch.nn as nn
from torch.nn import Sequential
from matplotlib import pyplot as plt
import torchvision.datasets as datasets
from torch.utils.data import DataLoader
import torchvision.transforms as transformsmodel_path = "./models/cell_classify.pth"
test_path = "./pics/"classes = ["linbaxibao", "zhongxinglixibao"]transform = transforms.Compose([transforms.ToTensor(),transforms.Resize((128, 128)),transforms.CenterCrop(128),transforms.Normalize(mean=[0.5, 0.5, 0.5],std=[0.5, 0.5, 0.5])
])data_test = datasets.ImageFolder(root=test_path, transform=transform)
test_loader = DataLoader(data_test, batch_size=64, shuffle=True)class CNN(nn.Module):def __init__(self):super(CNN, self).__init__()self.conv1 = Sequential(nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, stride=1, padding=1),nn.BatchNorm2d(32),nn.ReLU(),nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, stride=1, padding=2),nn.BatchNorm2d(32),nn.ReLU(),nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, stride=1, padding=2),nn.BatchNorm2d(32),nn.ReLU(),nn.MaxPool2d(2, 2))self.conv2 = Sequential(nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, stride=1, padding=1),nn.BatchNorm2d(64),nn.ReLU(),nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, stride=1, padding=1),nn.BatchNorm2d(64),nn.ReLU(),nn.MaxPool2d(2, 2))self.conv3 = Sequential(nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, stride=1, padding=1),nn.BatchNorm2d(128),nn.ReLU(),nn.Conv2d(in_channels=128, out_channels=128, kernel_size=3, stride=1, padding=1),nn.BatchNorm2d(128),nn.ReLU(),nn.MaxPool2d(2, 2))self.conv4 = Sequential(nn.Conv2d(in_channels=128, out_channels=256, kernel_size=3, stride=1, padding=1),nn.BatchNorm2d(256),nn.ReLU(),nn.Conv2d(in_channels=256, out_channels=256, kernel_size=3, stride=1, padding=1),nn.BatchNorm2d(256),nn.ReLU(),nn.MaxPool2d(2, 2))self.dense = Sequential(nn.Linear(8 * 8 * 256, 256),nn.ReLU(),nn.Dropout(p=0.5),nn.Linear(256, 128),nn.ReLU(),nn.Dropout(p=0.5),nn.Linear(128, 2))def forward(self, x):x1 = self.conv1(x)x2 = self.conv2(x1)x3 = self.conv3(x2)x4 = self.conv4(x3)x5 = x4.view(-1, 8 * 8 * 256)out = self.dense(x5)return outnet = torch.load(model_path)
net.eval()def get_variable(x):x = torch.autograd.Variable(x)return x.cuda() if torch.cuda.is_available() else xdef inference_model(test_img):for data in test_loader:test, _ = dataimg, _ = datatest = get_variable(test)outputs = net(test)rate, predict = torch.max(outputs.data, 1)for i in range(len(data_test)):print("It may be %s." % classes[predict[i]])img0 = img[i]img0 = img0.numpy().transpose(1, 2, 0)plt.imshow(img0)plt.title("It may be %s." % classes[predict[i]])# plt.title("It may be %s, probability is %f." % (classes[predict[i]], rate[i]))plt.show()inference_model(test_path)

结果(预测结果在图片上方和console里):预测结果在图片上方
预测结果在图片上方
可以看到预测还是蛮准的嘛~

一些闲谈

现在已经是2022年1月1日1:24了。我又长大了一岁(唉,我又老了
回首2021年。我2021年4月19日突发感想 脑瓜一热 记下了这么一句话:
哈哈
可惜的是,这个愿望只实现了,但没完全实现(谁说人工智能就一定只是会聊天的机器人啊(~o ̄3 ̄)~),我的初衷是做一个和小爱同学一样的人工智能…
目前在做超分辨率重构。
2021年初,我报名了CSDN上的一个深度学习课,当时只是打算听着玩,谁知道听的感兴趣了,就自己自学。没人指导,走了不少弯路,但还是走下来了。
笔者小时候最讨厌电脑了(小学6年级之前)。可是六年级一次电脑课上我接触了画画,我就觉得很好玩,就去研究怎么下载这样的软件,结果接触了Photoshop。谁知道这东西收费,就自己去学怎么破解。初中一年级我想为什么我自己不能编一个这样的程序呢?我就这样接触了编程。(后来还因为进了某网站后台差点惹出事,幸亏自己悬崖勒马)。
笔者从前并不喜欢数学,从前数学一直是我最讨厌的科目之一,因为我觉得我学的数学知识没有什么用到的地方,很枯燥,不理解为什么有人那么喜欢数学(我从前单纯觉得这些人是骗人的)(尽管为了高考要自我欺骗我很爱数学)。大学在某普通本科读计算机科学与技术。大一学了半年ACM,但是并不能听懂(呜呜呜)。大一上学期的寒假接触的机器学习。有趣的是,从接触机器学习开始,我发现数学原来这么实用。和编程结合后,似乎孕育出了某种神奇的力量。
啊。已经1:47了啊。以后再聊吧,我睡了()。

最后祝大家:

2022 新年快乐!

贴一张喜欢的图(侵删):
长草颜团子

这篇关于【跨年博客/轻松向】Pytorch卷积神经网络图像识别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/541769

相关文章

PyTorch中的词嵌入层(nn.Embedding)详解与实战应用示例

《PyTorch中的词嵌入层(nn.Embedding)详解与实战应用示例》词嵌入解决NLP维度灾难,捕捉语义关系,PyTorch的nn.Embedding模块提供灵活实现,支持参数配置、预训练及变长... 目录一、词嵌入(Word Embedding)简介为什么需要词嵌入?二、PyTorch中的nn.Em

小白也能轻松上手! 路由器设置优化指南

《小白也能轻松上手!路由器设置优化指南》在日常生活中,我们常常会遇到WiFi网速慢的问题,这主要受到三个方面的影响,首要原因是WiFi产品的配置优化不合理,其次是硬件性能的不足,以及宽带线路本身的质... 在数字化时代,网络已成为生活必需品,追剧、游戏、办公、学习都离不开稳定高速的网络。但很多人面对新路由器

SpringBoot+EasyPOI轻松实现Excel和Word导出PDF

《SpringBoot+EasyPOI轻松实现Excel和Word导出PDF》在企业级开发中,将Excel和Word文档导出为PDF是常见需求,本文将结合​​EasyPOI和​​Aspose系列工具实... 目录一、环境准备与依赖配置1.1 方案选型1.2 依赖配置(商业库方案)二、Excel 导出 PDF

Pytorch介绍与安装过程

《Pytorch介绍与安装过程》PyTorch因其直观的设计、卓越的灵活性以及强大的动态计算图功能,迅速在学术界和工业界获得了广泛认可,成为当前深度学习研究和开发的主流工具之一,本文给大家介绍Pyto... 目录1、Pytorch介绍1.1、核心理念1.2、核心组件与功能1.3、适用场景与优势总结1.4、优

conda安装GPU版pytorch默认却是cpu版本

《conda安装GPU版pytorch默认却是cpu版本》本文主要介绍了遇到Conda安装PyTorchGPU版本却默认安装CPU的问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的... 目录一、问题描述二、网上解决方案罗列【此节为反面方案罗列!!!】三、发现的根本原因[独家]3.1 p

电脑蓝牙连不上怎么办? 5 招教你轻松修复Mac蓝牙连接问题的技巧

《电脑蓝牙连不上怎么办?5招教你轻松修复Mac蓝牙连接问题的技巧》蓝牙连接问题是一些Mac用户经常遇到的常见问题之一,在本文章中,我们将提供一些有用的提示和技巧,帮助您解决可能出现的蓝牙连接问... 蓝牙作为一种流行的无线技术,已经成为我们连接各种设备的重要工具。在 MAC 上,你可以根据自己的需求,轻松地

PyTorch中cdist和sum函数使用示例详解

《PyTorch中cdist和sum函数使用示例详解》torch.cdist是PyTorch中用于计算**两个张量之间的成对距离(pairwisedistance)**的函数,常用于点云处理、图神经网... 目录基本语法输出示例1. 简单的 2D 欧几里得距离2. 批量形式(3D Tensor)3. 使用不

Go语言使用slices包轻松实现排序功能

《Go语言使用slices包轻松实现排序功能》在Go语言开发中,对数据进行排序是常见的需求,Go1.18版本引入的slices包提供了简洁高效的排序解决方案,支持内置类型和用户自定义类型的排序操作,本... 目录一、内置类型排序:字符串与整数的应用1. 字符串切片排序2. 整数切片排序二、检查切片排序状态:

PyTorch高级特性与性能优化方式

《PyTorch高级特性与性能优化方式》:本文主要介绍PyTorch高级特性与性能优化方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、自动化机制1.自动微分机制2.动态计算图二、性能优化1.内存管理2.GPU加速3.多GPU训练三、分布式训练1.分布式数据

POI从入门到实战轻松完成EasyExcel使用及Excel导入导出功能

《POI从入门到实战轻松完成EasyExcel使用及Excel导入导出功能》ApachePOI是一个流行的Java库,用于处理MicrosoftOffice格式文件,提供丰富API来创建、读取和修改O... 目录前言:Apache POIEasyPoiEasyExcel一、EasyExcel1.1、核心特性