【跨年博客/轻松向】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自动求梯度autograd的实现

《pytorch自动求梯度autograd的实现》autograd是一个自动微分引擎,它可以自动计算张量的梯度,本文主要介绍了pytorch自动求梯度autograd的实现,具有一定的参考价值,感兴趣... autograd是pytorch构建神经网络的核心。在 PyTorch 中,结合以下代码例子,当你

使用Python构建一个Hexo博客发布工具

《使用Python构建一个Hexo博客发布工具》虽然Hexo的命令行工具非常强大,但对于日常的博客撰写和发布过程,我总觉得缺少一个直观的图形界面来简化操作,下面我们就来看看如何使用Python构建一个... 目录引言Hexo博客系统简介设计需求技术选择代码实现主框架界面设计核心功能实现1. 发布文章2. 加

在PyCharm中安装PyTorch、torchvision和OpenCV详解

《在PyCharm中安装PyTorch、torchvision和OpenCV详解》:本文主要介绍在PyCharm中安装PyTorch、torchvision和OpenCV方式,具有很好的参考价值,... 目录PyCharm安装PyTorch、torchvision和OpenCV安装python安装PyTor

pytorch之torch.flatten()和torch.nn.Flatten()的用法

《pytorch之torch.flatten()和torch.nn.Flatten()的用法》:本文主要介绍pytorch之torch.flatten()和torch.nn.Flatten()的用... 目录torch.flatten()和torch.nn.Flatten()的用法下面举例说明总结torch

Python将博客内容html导出为Markdown格式

《Python将博客内容html导出为Markdown格式》Python将博客内容html导出为Markdown格式,通过博客url地址抓取文章,分析并提取出文章标题和内容,将内容构建成html,再转... 目录一、为什么要搞?二、准备如何搞?三、说搞咱就搞!抓取文章提取内容构建html转存markdown

macOS无效Launchpad图标轻松删除的4 种实用方法

《macOS无效Launchpad图标轻松删除的4种实用方法》mac中不在appstore上下载的应用经常在删除后它的图标还残留在launchpad中,并且长按图标也不会出现删除符号,下面解决这个问... 在 MACOS 上,Launchpad(也就是「启动台」)是一个便捷的 App 启动工具。但有时候,应

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件

使用PyTorch实现手写数字识别功能

《使用PyTorch实现手写数字识别功能》在人工智能的世界里,计算机视觉是最具魅力的领域之一,通过PyTorch这一强大的深度学习框架,我们将在经典的MNIST数据集上,见证一个神经网络从零开始学会识... 目录当计算机学会“看”数字搭建开发环境MNIST数据集解析1. 认识手写数字数据库2. 数据预处理的

Pytorch微调BERT实现命名实体识别

《Pytorch微调BERT实现命名实体识别》命名实体识别(NER)是自然语言处理(NLP)中的一项关键任务,它涉及识别和分类文本中的关键实体,BERT是一种强大的语言表示模型,在各种NLP任务中显著... 目录环境准备加载预训练BERT模型准备数据集标记与对齐微调 BERT最后总结环境准备在继续之前,确

pytorch+torchvision+python版本对应及环境安装

《pytorch+torchvision+python版本对应及环境安装》本文主要介绍了pytorch+torchvision+python版本对应及环境安装,安装过程中需要注意Numpy版本的降级,... 目录一、版本对应二、安装命令(pip)1. 版本2. 安装全过程3. 命令相关解释参考文章一、版本对