当前位置: 首页 > news >正文

卷积神经网络——pytorch与paddle实现卷积神经网络

卷积神经网络——pytorch与paddle实现卷积神经网络

本文将深入探讨卷积神经网络的理论基础,并通过PyTorch和PaddlePaddle两个深度学习框架来展示如何实现卷积神经网络模型。我们将首先介绍卷积神经网络、图像处理的基本概念,这些理论基础是理解和实现卷积神经网络的基础。通过PyTorch和PaddlePaddle的代码示例,我们将展示如何设计、训练和评估一个卷积神经网络模型,从而让读者能够直观地理解并掌握这两种框架在计算机视觉问题中的应用。

本文部分为torch框架以及部分理论分析,paddle框架对应代码可见卷积神经网络paddle

import torch
print("pytorch version:",torch.__version__)
pytorch version: 2.0.1+cu118

图像卷积的基本原理

图像卷积运算实际上是在进行图像空间域的滤波。卷积层是CNN的核心组件,通过卷积运算提取特征。卷积运算是指从图像的左上角开始,开一个与模板(也称为卷积核或滤波器)同样大小的活动窗口,窗口图像与模板像元对应起来相乘再相加,并用计算结果代替窗口中心的像元亮度值。然后,活动窗口向右移动一列(或一行),并作同样的运算。以此类推,从左到右、从上到下,即可得到一幅新图像。

二维离散卷积公式用于描述两个二维信号(在图像处理中通常是一个图像和一个滤波器或卷积核)之间的卷积运算。给定一个二维图像信号 f [ i , j ] f[i, j] f[i,j] 和一个二维滤波器 h [ k , l ] h[k, l] h[k,l],二维离散卷积的结果 g [ x , y ] g[x, y] g[x,y] 可以通过以下公式计算:

g [ x , y ] = ∑ k = − ∞ ∞ ∑ l = − ∞ ∞ f [ i , j ] ⋅ h [ x − i , y − j ] g[x, y] = \sum_{k=-\infty}^{\infty} \sum_{l=-\infty}^{\infty} f[i, j] \cdot h[x-i, y-j] g[x,y]=k=l=f[i,j]h[xi,yj]

其中, i i i j j j 表示图像中像素的坐标,而 x x x y y y 表示卷积结果中像素的坐标。实际上,在离散环境中,图像的尺寸是有限的,所以卷积核 h [ k , l ] h[k, l] h[k,l] 只在有限的区域内非零,因此上述求和实际上也只在有限的范围内进行。

更具体地,如果我们有一个 M × N M \times N M×N 的图像和一个 m × n m \times n m×n 的滤波器,那么对于输出图像中的每个位置 ( x , y ) (x, y) (x,y),卷积操作可以定义为:

g [ x , y ] = ∑ k = 0 m − 1 ∑ l = 0 n − 1 f [ x + k − m / 2 , y + l − n / 2 ] ⋅ h [ k , l ] g[x, y] = \sum_{k=0}^{m-1} \sum_{l=0}^{n-1} f[x+k-m/2, y+l-n/2] \cdot h[k, l] g[x,y]=k=0m1l=0n1f[x+km/2,y+ln/2]h[k,l]

在实际应用中,我们还需要处理边界条件,例如通过填充(如零填充)或裁剪图像边缘。下方动图过程来源于CoolGPU’s Blog,展示了卷积运算的过程。
在这里插入图片描述

该过程展示了一张 1 × 5 × 5 1 \times 5 \times 5 1×5×5的图像,以及一个 3 × 3 3 \times 3 3×3的卷积核。在卷积运算中,我们首先将卷积核在图像上滑动,每次滑动一个像素的距离。在每次滑动中,我们计算卷积核与图像对应位置像素的乘积,并将这些乘积相加得到一个值,作为卷积运算的结果。最后,我们将这些结果拼接在一起,得到一个新的 1 × 3 × 3 1 \times 3 \times 3 1×3×3的图像。
在这里插入图片描述

该过程展示了一张 3 × 5 × 5 3 \times 5 \times 5 3×5×5的图像,即该图像有三个通道,以及一个 3 × 3 × 3 3 \times 3 \times 3 3×3×3的卷积核。卷积核与图像进行卷积运算。最后,将这些结果对应值加在一起,算上偏置项,得到一个新的 1 × 3 × 3 1 \times 3 \times 3 1×3×3的图像。
在这里插入图片描述

该过程与上方过程类似,但此时,我们给图像外边填充了一圈0,同时卷积核每次移动步长变为2,这样我们最终也得到了一个 1 × 3 × 3 1 \times 3 \times 3 1×3×3的图像。

卷积层设计及其梯度反向传播

首先我们导入一张图片,然后利用卷积层对其进行滤波,提取特征。

import cv2  
import numpy as np  
import matplotlib.pyplot as plt  
%matplotlib inline# 展示图像
image = cv2.imread('img/cells.png')  
plt.imshow(image)

在这里插入图片描述

可以看到,该图片为 1133 × 1700 × 3 1133 \times 1700 \times 3 1133×1700×3的形状,我们将其转化为 1 × 3 × 1133 × 1700 1 \times 3 \times 1133 \times 1700 1×3×1133×1700的形式

# 将 ndarray 转换为 torch tensor  
tensor = torch.from_numpy(image)  
tensor = tensor.to(torch.float32)  # 将数据类型转化为float# 调整 tensor 的维度,使其变为 (1, 3, 1133, 1700)  
tensor = tensor.permute(2, 0, 1).unsqueeze(0)  

接下来我们设计一个卷积层,实现图像的卷积操作。

import torch.nn as nn
import torch.nn.functional as Fclass ConvLayer(nn.Module):'''卷积层设计'''def __init__(self, in_channels, out_channels, kernel_size, stride=1, padding=0):super(ConvLayer, self).__init__()# 构建卷积核self.kernel = nn.Parameter(torch.randn(out_channels, in_channels, kernel_size, kernel_size))# 构建偏置项self.bias = nn.Parameter(torch.randn(out_channels))self.stride = strideself.padding = paddingdef forward(self, x):# 卷积操作out = F.conv2d(x, self.kernel, self.bias, stride=self.stride, padding=self.padding)return out

接下来,我们利用该卷积层,实现对图像在空间域的均值滤波,让我们来试试吧!

conv = ConvLayer(in_channels=1, out_channels=1, kernel_size=3, stride=1, padding=1)# 构建均值滤波卷积核
conv.kernel = nn.Parameter(torch.ones_like(conv.kernel))
conv.bias = nn.Parameter(torch.zeros_like(conv.bias))out_1 = conv(tensor[0, 0, :, :].reshape(1, 1, 1133, 1700))
out_2 = conv(tensor[0, 1, :, :].reshape(1, 1, 1133, 1700))
out_3 = conv(tensor[0, 2, :, :].reshape(1, 1, 1133, 1700))
# 分析可知,每一个像素由9个值相加得到,我们对每一个像素除以9,并将其合并为图像
out_1, out_2, out_3 = out_1/9, out_2/9, out_3/9out = torch.cat((out_1, out_2, out_3), dim=0)  # 合并
# 将out转化为ndarry,并将形状调整为1133*1700*3的整形数组
out = out.squeeze().detach().numpy().transpose(1, 2, 0)  # 从tensor中取出数据,调整形状,转置
out = out.astype(np.uint8)  # 转化为整形数组
plt.imshow(out)

在这里插入图片描述

这样,我们就利用卷积神经网络实现了图像的均值滤波过程。

卷积神经网络解决分类问题的简单实现

从上述过程可以看到,卷积实际上是对图像进行某种滤波,提取图像特征的过程。下方我们将利用卷积神经网络,实现对图像的分类任务。首先我们导入数据集,并构建卷积神经网络。

import torch  
import torch.nn as nn  
import torch.optim as optim  
from torch.utils.data import DataLoader  
from torchvision import datasets, transforms  # 构建数据集  
train_dataset = datasets.MNIST(root='./data', train=True, transform=transforms.ToTensor(), download=True)
test_dataset = datasets.MNIST(root='./data', train=False, transform=transforms.ToTensor(), download=True)  # 构建数据加载器  
train_loader = DataLoader(dataset=train_dataset, batch_size=64, shuffle=True)  
test_loader = DataLoader(dataset=test_dataset, batch_size=64, shuffle=False)  # 构建卷积神经网络  
class CNN(nn.Module):def __init__(self):super(CNN, self).__init__()# 构建卷积层self.conv1 = nn.Conv2d(in_channels=1, out_channels=16, kernel_size=3, stride=1, padding=1)self.conv2 = nn.Conv2d(in_channels=16, out_channels=32, kernel_size=3, stride=1, padding=1)# 构建全连接层self.fc1 = nn.Linear(32 * 7 * 7, 128)self.fc2 = nn.Linear(128, 10)def forward(self, x):# 卷积操作x = F.relu(self.conv1(x))x = F.max_pool2d(x, 2)x = F.relu(self.conv2(x))x = F.max_pool2d(x, 2)# 展平操作x = x.view(x.size(0), -1)# 全连接操作x = F.relu(self.fc1(x))x = self.fc2(x)return x# 构建模型实例
device = 'cuda' if torch.cuda.is_available else 'cpu'
model = CNN().to(device)
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)# 训练模型
model.train()
for epoch in range(5):for data in train_loader:imgs, labels = dataoutputs = model(imgs.to(device))loss = criterion(outputs, labels.to(device))optimizer.zero_grad()loss.backward()optimizer.step()# 测试模型
model.eval()
total = 0
correct = 0
for data in test_loader:imgs, labels = dataoutputs = model(imgs.to(device))_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels.to(device)).sum()print('Accuracy: %.2f %%' % (100 * correct / total))
Accuracy: 98.80 %

可以看到该模型具有较高的精度,我们不妨将图像进行的每一次操作呈现出来,看看卷积层到底提取了什么样的特征。

首先我们将模型参数保存下来。

# 保存模型参数  
torch.save(model, 'data/model_CNN_parameters.pt')

接下来,我们就可以在任意时间点加载这次训练好的模型了。

# 加载模型
model = torch.load('data/model_CNN_parameters.pt')

让我们看看每一次操作时,图像的特征变换

# 加载某个图片
img = imgs[3, :].reshape(1, 28, 28)
img = img.detach().numpy().transpose(1, 2, 0)  # 从tensor中取出数据,调整形状,转置
# 将图像放缩到0~255
img  = 255 * img
img = img.astype(np.uint8)  # 转化为整形数组
plt.imshow(img)

在这里插入图片描述

人类可以较明显的识别出该数字是几,让我们将图像送入网络看看网络的识别结果。

model = model.to(device)
test_out = model(imgs[3, :].reshape(1, 1, 28, 28).to(device))
_, prediction = torch.max(test_out.data, 1)
prediction
tensor([4], device='cuda:0')

可以看到,网络的识别结果也是准确的。让我们将网络每一步图像处理进行的操作展示出来。

x_out1 = F.relu(model.conv1(imgs[3, :].reshape(1, 1, 28, 28).to(device)))
x_out2 = F.max_pool2d(x_out1, 2)
x_out3 = F.relu(model.conv2(x_out2))
x_out4 = F.max_pool2d(x_out3, 2)
import math
def transform_imag(img):# 将tensor格式转换为合适的图片_, channels, cols, rows = img.shapeimg = img.reshape(channels, cols, rows).to('cpu')img = img.detach().numpy().transpose(1, 2, 0)  # 从tensor中取出数据,调整形状,转置# 将图像放缩到0~255img  = 255 * imgimg = img.astype(np.uint8)  # 转化为整形数组return imgdef show_Features(img):# 展示img中包含的特征c, r, channels = img.shapecols = round(math.sqrt(channels))for i in range(channels):plt.subplot(cols, math.ceil(channels / cols), i+1)plt.imshow(img[:, :, i].reshape(c, r, 1))plt.show()img1 = transform_imag(x_out1)
show_Features(img1)

在这里插入图片描述

img2 = transform_imag(x_out2)
show_Features(img2)

在这里插入图片描述

img3 = transform_imag(x_out3)
show_Features(img3)

在这里插入图片描述

img4 = transform_imag(x_out4)
show_Features(img4)

在这里插入图片描述

可以看到,网络图像越到后边层,各图像内容越简单且越抽象。

卷积神经网络(CNN)提取高阶特征的过程是一个层次性的数据处理与抽象过程,CNN通过卷积层利用卷积核在输入图像上滑动,执行卷积操作以捕捉图像的局部特征,如边缘、纹理等;随着网络层次的加深,这些简单特征被逐层抽象与组合,形成更复杂的特征表示,例如形状、物体的部分等。在此过程中,多个卷积核被用于每一层以提取不同的特征,而池化层则通过下采样操作降低特征图的维度,同时保留重要信息,增强特征的鲁棒性。最终,通过全连接层整合前面提取的特征,形成针对特定任务(如分类或回归)的高度抽象的特征表示,从而实现高阶特征的提取与利用。这一过程体现了CNN从底层到高层的特征学习和表示能力,是其在图像识别等任务中取得优异表现的关键。

相关文章:

卷积神经网络——pytorch与paddle实现卷积神经网络

卷积神经网络——pytorch与paddle实现卷积神经网络 本文将深入探讨卷积神经网络的理论基础,并通过PyTorch和PaddlePaddle两个深度学习框架来展示如何实现卷积神经网络模型。我们将首先介绍卷积神经网络、图像处理的基本概念,这些理论基础是理解和实现卷…...

云平台虚拟机运维笔记整理,使用libvirt创建和管理虚拟机,以及开启虚拟机嵌套,虚拟磁盘扩容,物理磁盘扩容等等

云平台虚拟机运维笔记整理,使用libvirt创建和管理虚拟机,以及开启虚拟机嵌套,虚拟磁盘扩容,物理磁盘扩容等等。 掌握和使用qemu和libvirt,分别使用它们创建一个cirros虚拟机,并配置好网络。 宿主机node0的系统为ubuntu16,IP为192.168.56.200。 qemu和libvirt简介 QEMU…...

最佳实践:如何实现函数参数之间的TS类型相依赖和自动推断

引入 最近在开发一款极致优雅的前端状态管理库AutoStore时碰到这样一个问题。 拟实现Field组件,该组件相关类型简化代码如下: type Field (props:{validate,render:(props:{value,isValid}) })该组件,具有validate和render两个属性: 其中…...

Linux基础指令1

好久没写博客了,这次我将重新做人,每星期都更,做不到的话直接倒立洗头。最近在学Linux,感觉很厉害的样子,先浅学一下再弄数据结构去。 Linux的基本操作是通过指令来执行的,所以我们先来学习下指令。 1.简…...

软件设计师:排序算法总结

一、直接插入 排序方式:从第一个数开始,拿两个数比较,把后面一位跟前面的数比较,把较小的数放在前面一位 二、希尔 排序方式:按“增量序列(步长)”分组比较,组内元素比较交换 假设…...

「Mac畅玩鸿蒙与硬件25」UI互动应用篇2 - 计时器应用实现

本篇将带领你实现一个实用的计时器应用,用户可以启动、暂停或重置计时器。该项目将涉及时间控制、状态管理以及按钮交互,是掌握鸿蒙应用开发的重要步骤。 关键词 UI互动应用时间控制状态管理用户交互 一、功能说明 在这个计时器应用中,用户…...

计算机专业开题报告写法,该怎么写好?

不会写开题报告,或者想要一些论文模版的,欢迎评论,会第一时间给大家。 题报告是计算机专业大学毕业生在开展毕业设计或论文研究前,对研究课题进行详细介绍和计划的重要环节。作为开题者对科研课题的一种文字说明,开题…...

Vue(JavaScript)读取csv表格并求某一列之和(大浮点数处理: decimal.js)

文章目录 想要读这个表格,并且求第二列所有价格的和方法一:通过添加文件输入元素上传csv完整(正确)代码之前的错误部分因为价格是小数,所以下面的代码出错。如果把parseFloat改成parseInt,那么求和没有意义…...

Pyraformer复现心得

Pyraformer复现心得 引用 Liu, Shizhan, et al. “Pyraformer: Low-complexity pyramidal attention for long-range time series modeling and forecasting.” International conference on learning representations. 2021. 代码部分 def long_forecast(self, x_enc, x_m…...

成绩排序c++

说明 给出了班里某门课程的成绩单&#xff0c;请你按成绩从高到低对成绩单排序输出&#xff0c;如果有相同分数则名字字典序小的在前。 输入格式 第一行为nn(0<n<200<n<20)&#xff0c;表示班里的学生数目; 接下来的nn行&#xff0c;每行为每个学生的名字和他的…...

人脸检测之MTCNN算法网络结构

MTCNN&#xff08;Multi-task Cascaded Convolutional Networks&#xff09;是一种用于人脸检测和关键点检测的深度学习模型&#xff0c;特别适合在复杂背景下识别出多尺度的人脸。它通过多任务学习来实现人脸检测和人脸关键点定位&#xff08;如眼睛、鼻子、嘴巴的位置&#x…...

蓝桥杯顺子日期(填空题)

题目&#xff1a;小明特别喜欢顺子。顺子指的就是连续的三个数字&#xff1a;123、456 等。顺子日期指的就是在日期的 yyyymmdd 表示法中&#xff0c;存在任意连续的三位数是一个顺子的日期。例如 20220123 就是一个顺子日期&#xff0c;因为它出现了一个顺子&#xff1a;123&a…...

Java云HIS医院管理系统源码 病案管理、医保业务、门诊、住院、电子病历编辑

云HIS系统优势 &#xff08;1&#xff09;客户/用户角度 无需安装&#xff0c;登录即用 多终端同步&#xff0c;轻松应对工作环境转换 系统使用简单、易上手&#xff0c;信息展示主次分明、重点突出 极致降低用户操作负担&#xff1a;关联功能集中、减少跳转&#xff0c;键盘快…...

【C++的vector、list、stack、queue用法简单介绍】

【知识预告】 vector的介绍及使用list的介绍及使用list与vector的对比stack的介绍和使用queue的介绍和使用priority_queue的介绍和使用 1 vector的介绍及使用 1.1 vector的介绍 vector是表示可变大小数组的序列容器和数组类似&#xff0c;vector也采用连续存储空间来存储元…...

git中使用tag(标签)的方法及重要性

在Git中打标签&#xff08;tag&#xff09;通常用于标记发布版本或其他重要提交。 Git中打标签的步骤&#xff1a; 列出当前所有的标签 git tag创建一个指向特定提交的标签 git tag <tagname> <commit-hash>创建一个带注释的标签&#xff0c;通常用于发布版本 git…...

【专题】2024年文旅微短剧专题研究报告汇总PDF洞察(附原数据表)

原文链接&#xff1a; https://tecdat.cn/?p38187 当今时代&#xff0c;各类文化与消费领域呈现出蓬勃发展且不断变革的态势。 微短剧作为新兴内容形式&#xff0c;凭借网络发展与用户需求&#xff0c;从低成本都市题材为主逐步走向多元化&#xff0c;其内容供给类型正历经深…...

celery加速爬虫 使用flower 可视化地查看celery的实时监控情况

重点: celery ==5.4.0 python 3.11 flower ==2.0.1 请对齐celery与flower的版本信息,如果过低会导致报错 报错1: (venv) PS D:\apploadpath\pythonPath\Lib\site-packages> celery -A tasks flower Traceback (most recent call last):File …...

Angular进阶之十:toPromise废弃原因及解决方案

背景 Rxjs从V7开始废弃了toPromise, V8中会删除它。 原因 1&#xff1a;toPromise()只返回一个值 toPromise()将 Observable 序列转换为符合 ES2015 标准的 Promise 。它使用 Observable 序列的最后一个值。 例&#xff1a; import { Observable } from "rxjs"; ………...

python实现RSA算法

目录 一、算法简介二、算法描述2.1 密钥产生2.2 加密过程2.3 解密过程2.4 证明解密正确性 三、相关算法3.1 欧几里得算法3.2 扩展欧几里得算法3.3 模重复平方算法3.4 Miller-Rabin 素性检测算法 四、算法实现五、演示效果 一、算法简介 RSA算法是一种非对称加密算法&#xff0c…...

可灵开源视频生成数据集 学习笔记

目录 介绍 可灵团队提出了四个模块的改进&#xff1a; video caption 新指标 vtss 动态质量 静态质量 视频自然性 介绍 在视频数据处理中&#xff0c;建立准确且细致的条件是关键&#xff0c;可灵团队认为&#xff0c;解决这一问题需要关注三个主要方面&#xff1a; 文本…...

告别软文营销瓶颈!5招助你突破限制,实现宣传效果最大化

在当今信息爆炸的时代&#xff0c;软文营销作为品牌推广的重要手段之一&#xff0c;面临着日益激烈的竞争和受众日益提高的辨别力。传统的软文营销方式往往难以穿透消费者的心理防线&#xff0c;实现有效的信息传递和品牌塑造。为了突破这一瓶颈&#xff0c;实现宣传效果的最大…...

秋冬进补防肥胖:辨证施补,健康过冬不增脂

中医理论中的秋冬“封藏” 在中医理论中&#xff0c;认为秋冬季节是人体“封藏”的时期&#xff0c;而“封藏”指的是秋冬季节人体应当减少消耗&#xff0c;蓄积能源&#xff0c;此时进补可以使营养物质易于吸收并蓄积于体内&#xff0c;从而增强体质和抵抗力&#xff0c;为来…...

uniapp radio单选

<uni-data-checkbox v-model"selectedValue" :localdata"quTypeList" change"radioChange"/> //产品类型列表 const quTypeList [{ text: 漆面膜, value: 100, }, { text: 改色…...

通熟易懂地讲解GCC和Makefile

1. 嵌入式开发工具链&#xff1a;GCC GCC&#xff08;GNU Compiler Collection&#xff09;是一个强大且常用的编译器套件&#xff0c;支持多种编程语言&#xff0c;比如 C 和 C。在嵌入式开发中&#xff0c;GCC 可以帮助我们把人类可读的 C/C 代码编译成机器可以理解的二进制…...

Java Agent使用

文章目录 基本使用premain使用场景 agentmain 关于tools.jar https://docs.oracle.com/en/java/javase/20/docs/specs/jvmti.html com.sun的API&#xff0c;如果使用其他厂商的JVM&#xff0c;可能没有这个API了&#xff0c;比如Eclipse的J9 https://www.ibm.com/docs/en/sdk…...

selenium 点击元素报错element not interactable

描述说明&#xff1a; 我这里是获取一个span标签后并点击&#xff0c;用的元素自带的element.click()&#xff0c;报错示例代码如下&#xff1a; driver.find_element(By.XPATH,//span[id"my_span"]).click() # 或者 elementdriver.find_element(By.XPATH,//span[i…...

【大数据技术基础 | 实验七】HBase实验:部署HBase

文章目录 一、实验目的二、实验要求三、实验原理四、实验环境五、实验内容和步骤&#xff08;一&#xff09;验证Hadoop和ZooKeeper已启动&#xff08;二&#xff09;修改HBase配置文件&#xff08;三&#xff09;启动并验证HBase 六、实验结果七、实验心得 一、实验目的 掌握…...

Android进程保活,lmkd杀进程相关

lmk原理 Android进程回收之LowMemoryKiller原理 lmkd 更新进程oomAdj; 设备端进程被杀可能原因...

SDL 播放PCM

SDL2播放PCM使用SDL2播放PCM音频采样数据。SDL实际上是对底层绘图API&#xff08;Direct3D&#xff0c;OpenGL&#xff09;的封装&#xff0c;使用起来明显简单于直接调用底层API。 测试的PCM数据采用采样率44.1k, 采用精度S16SYS, 通道数2 函数调用步骤如下: [初始化]SDL_In…...

基于MPPT最大功率跟踪的光伏发电蓄电池控制系统simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于MPPT最大功率跟踪的光伏发电蓄电池控制系统simulink建模与仿真。本系统包括PV模块&#xff0c;电池模块&#xff0c;电池控制器模块&#xff0c;MPPT模块&#xff0c;PWM模…...