【深度学习实验】卷积神经网络(三):自定义二维卷积层:步长、填充、输入输出通道

news2024/11/25 1:30:38

目录

一、实验介绍

二、实验环境

1. 配置虚拟环境

2. 库版本介绍

三、实验内容

0. 导入必要的工具包

1. 步长、填充

a. 二维互相关运算(corr2d)

b. 二维卷积层类(Conv2D)

c. 模型测试

d. 代码整合

2. 输入输出通道

a. corr2d_multi_in

b. corr2d_multi_in_out

c. Conv2D

d. 模型测试

e. 代码整合


一、实验介绍

        本实验实现了二维卷积神经网络的卷积层设置步长、填充、输入输出通道等功能。

二、实验环境

    本系列实验使用了PyTorch深度学习框架,相关操作如下:

1. 配置虚拟环境

conda create -n DL python=3.7 
conda activate DL
pip install torch==1.8.1+cu102 torchvision==0.9.1+cu102 torchaudio==0.8.1 -f https://download.pytorch.org/whl/torch_stable.html
conda install matplotlib
 conda install scikit-learn

2. 库版本介绍

软件包本实验版本目前最新版
matplotlib3.5.33.8.0
numpy1.21.61.26.0
python3.7.16
scikit-learn0.22.11.3.0
torch1.8.1+cu1022.0.1
torchaudio0.8.12.0.2
torchvision0.9.1+cu1020.15.2

三、实验内容

ChatGPT:

        卷积神经网络(Convolutional Neural Network,简称CNN)是一种深度学习模型,广泛应用于图像识别、计算机视觉和模式识别等领域。它的设计灵感来自于生物学中视觉皮层的工作原理。

        卷积神经网络通过多个卷积层、池化层全连接层组成。

  • 卷积层主要用于提取图像的局部特征,通过卷积操作和激活函数的处理,可以学习到图像的特征表示。
  • 池化层则用于降低特征图的维度,减少参数数量,同时保留主要的特征信息。
  • 全连接层则用于将提取到的特征映射到不同类别的概率上,进行分类或回归任务。

        卷积神经网络在图像处理方面具有很强的优势,它能够自动学习到具有层次结构的特征表示,并且对平移、缩放和旋转等图像变换具有一定的不变性。这些特点使得卷积神经网络成为图像分类、目标检测、语义分割等任务的首选模型。除了图像处理,卷积神经网络也可以应用于其他领域,如自然语言处理和时间序列分析。通过将文本或时间序列数据转换成二维形式,可以利用卷积神经网络进行相关任务的处理。

0. 导入必要的工具包

import torch
from torch import nn
import torch.nn.functional as F

1. 步长、填充

承接上文:

【深度学习实验】卷积神经网络(二):自定义简单的二维卷积神经网络_QomolangmaH的博客-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_63834988/article/details/133278280?spm=1001.2014.3001.5501

  • 卷积算子增加步长零填充
  • 改进了互相关函数 corr2d

  • 改进了卷积算子 Conv2D

  • 在 forward 方法中,对输入 x 进行了填充操作,通过在输入的边缘周围添加零值像素来处理填充。这样做可以确保卷积核在输入的边缘位置也能进行有效的卷积操作,从而保持输出尺寸与输入尺寸的一致性。

  • 在使用 Conv2D 类创建对象时,可以通过传递不同的参数来对步长和填充进行灵活的设置。这样可以根据具体任务的需求来调整卷积操作的步长和填充方式,以获得更好的性能和适应性。

a. 二维互相关运算(corr2d)

        修改为:

def corr2d(X, K, s): 
    h, w = K.shape
    Y = torch.zeros(((X.shape[0] - h + 1)//s , (X.shape[1] - w + 1)//s))
    for i in range(Y.shape[0]):
        for j in range(Y.shape[1]):
            Y[i, j] = (X[i*s:i*s + h, j*s:j*s + w] * K).sum()
    return Y

        添加了一个步长参数 s。通过指定步长,可以控制卷积操作在输入上的滑动步长,从而实现对输出大小的调整。在原始代码中,步长相当于固定为1,而修改后的代码可以通过调整 s 的值来改变步长。

b. 二维卷积层类(Conv2D)

        修改为:

class Conv2D(nn.Module):
    def __init__(self, kernel_size, stride=1, padding=0, weight=None):
        super().__init__()
        if weight is not None:
            self.weight = weight
        else:
            self.weight = nn.Parameter(torch.rand(kernel_size))
        self.bias = nn.Parameter(torch.zeros(1))
        self.stride = stride
        self.padding = padding

    def forward(self, x):
        new_x = torch.zeros((x.shape[0] + 2*self.padding, x.shape[1] + 2*self.padding))
        new_x[self.padding:x.shape[0] + self.padding,self.padding:x.shape[1] + self.padding] = x

        return corr2d(new_x, self.weight, self.stride) + self.bias
  • 添加了步长和填充参数:
    • 步长参数 stride 控制卷积核在输入上的滑动步长
    • 填充参数 padding 在输入的边缘周围添加零值像素,以控制输出尺寸。
      • 在 forward 方法中,对输入 x 进行了填充操作,通过在输入的边缘周围添加零值像素来处理填充。(这样做可以确保卷积核在输入的边缘位置也能进行有效的卷积操作,从而保持输出尺寸与输入尺寸的一致性。)

c. 模型测试

# 由于卷积层还未实现多通道,所以我们的图像也默认是单通道的
fake_image = torch.randn((5,5))

# 需要为步长和填充指定参数,若未指定,则使用默认的参数1和0
narrow_conv = Conv2D(kernel_size=(3,3))
output1 = narrow_conv(fake_image)
print(output1.shape)

wide_conv = Conv2D(kernel_size=(3,3),stride=1,padding=2)
output2 = wide_conv(fake_image)
print(output2.shape)

same_width_conv = Conv2D(kernel_size=(3,3),stride=1,padding=1)
output3 = same_width_conv(fake_image)
print(output3.shape)

输出:

torch.Size([3, 3])
torch.Size([7, 7])
torch.Size([5, 5])

d. 代码整合

# 导入必要的工具包
import torch
from torch import nn
import torch.nn.functional as F


# 修改后的互相关函数
def corr2d(X, K, s):
    h, w = K.shape
    Y = torch.zeros(((X.shape[0] - h + 1)//s , (X.shape[1] - w + 1)//s))
    for i in range(Y.shape[0]):
        for j in range(Y.shape[1]):
            Y[i, j] = (X[i*s:i*s + h, j*s:j*s + w] * K).sum()
    return Y

# 修改后的卷积算子
class Conv2D(nn.Module):
    def __init__(self, kernel_size, stride=1, padding=0, weight=None):
        super().__init__()
        if weight is not None:
            self.weight = weight
        else:
            self.weight = nn.Parameter(torch.rand(kernel_size))
        self.bias = nn.Parameter(torch.zeros(1))
        self.stride = stride
        self.padding = padding

    def forward(self, x):
        new_x = torch.zeros((x.shape[0] + 2*self.padding, x.shape[1] + 2*self.padding))
        new_x[self.padding:x.shape[0] + self.padding,self.padding:x.shape[1] + self.padding] = x

        return corr2d(new_x, self.weight, self.stride) + self.bias

# 由于卷积层还未实现多通道,所以我们的图像也默认是单通道的
fake_image = torch.randn((5,5))

# 需要为步长和填充指定参数,若未指定,则使用默认的参数1和0
narrow_conv = Conv2D(kernel_size=(3,3))
output1 = narrow_conv(fake_image)
print(output1.shape)

wide_conv = Conv2D(kernel_size=(3,3),stride=1,padding=2)
output2 = wide_conv(fake_image)
print(output2.shape)

same_width_conv = Conv2D(kernel_size=(3,3),stride=1,padding=1)
output3 = same_width_conv(fake_image)
print(output3.shape)

2. 输入输出通道

a. corr2d_multi_in

def corr2d_multi_in(X, K, s):
    # 先遍历“X”和“K”的第0个维度(通道维度),再把它们加在一起
    return sum(corr2d(x, k, s) for x, k in zip(X, K))

        遍历输入张量 X 和核张量 K 的第一个维度(通道维度),并对每个通道执行互相关操作,然后将结果加在一起。

b. corr2d_multi_in_out

def corr2d_multi_in_out(X, K, s):
    # 迭代“K”的第0个维度,每次都对输入“X”执行互相关运算。
    # 最后将所有结果都叠加在一起
    return torch.stack([corr2d_multi_in(X, k, s) for k in K], 0)

        用于处理多通道输入和多通道输出。它迭代核张量 K 的第一个维度,并对输入张量 X 执行多通道的互相关操作,将所有结果叠加在一起。

c. Conv2D

        进一步修改:

class Conv2D(nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size=None, stride=1, padding=0, weight=None):
        super().__init__()
        self.in_channels = in_channels
        self.out_channels = out_channels
        if weight is not None:
            h, w = weight.shape
            weight = weight * torch.ones(in_channels, out_channels, h, w)
            self.weight = nn.Parameter(weight)
        else:
            self.weight = nn.Parameter(torch.rand((in_channels, out_channels, kernel_size, kernel_size)))
        self.bias = nn.Parameter(torch.zeros(1))
        self.stride = stride
        self.padding = padding

    def forward(self, x):
        new_x = torch.zeros((x.shape[0], x.shape[1] + 2 * self.padding, x.shape[2] + 2 * self.padding))
        new_x[:, self.padding:x.shape[1] + self.padding, self.padding:x.shape[2] + self.padding] = x
        return corr2d_multi_in_out(new_x, self.weight, self.stride)
  • 在 Conv2D 类的构造函数中,添加了输入通道数 in_channels 和输出通道数 out_channels 的参数。根据输入参数的不同,可以创建具有不同输入和输出通道数的卷积算子。

  • 在 Conv2D 类中,对权重参数进行了一些修改。如果传入了 weight 参数,则将其扩展为具有相同形状的多通道权重。否则,将随机生成一个具有指定输入和输出通道数的权重。

  • 在 forward 方法中,对输入张量 x 进行扩展,以适应填充操作。然后调用新的互相关函数 corr2d_multi_in_out 进行多通道的互相关操作。

d. 模型测试

fake_image = torch.randn((3,5,5))
conv = Conv2D(in_channels=3, out_channels=1, kernel_size=3, stride=2,padding=1)
output = conv(fake_image)
print(output.shape)

e. 代码整合

# 导入必要的工具包
import torch
from torch import nn
import torch.nn.functional as F


# 修改后的互相关函数
def corr2d(X, K, s):
    h, w = K.shape
    Y = torch.zeros(((X.shape[0] - h + 1) // s, (X.shape[1] - w + 1) // s))
    for i in range(Y.shape[0]):
        for j in range(Y.shape[1]):
            Y[i, j] = (X[i * s:i * s + h, j * s:j * s + w] * K).sum()
    return Y


# 修改后的卷积算子
# X为输入图像,K是输入的二维的核数组
def corr2d_multi_in(X, K, s):
    # 先遍历“X”和“K”的第0个维度(通道维度),再把它们加在一起
    return sum(corr2d(x, k, s) for x, k in zip(X, K))


def corr2d_multi_in_out(X, K, s):
    # 迭代“K”的第0个维度,每次都对输入“X”执行互相关运算。
    # 最后将所有结果都叠加在一起
    return torch.stack([corr2d_multi_in(X, k, s) for k in K], 0)


class Conv2D(nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size=None, stride=1, padding=0, weight=None):
        super().__init__()
        self.in_channels = in_channels
        self.out_channels = out_channels
        if weight is not None:
            h, w = weight.shape
            weight = weight * torch.ones(in_channels, out_channels, h, w)
            self.weight = nn.Parameter(weight)
        else:
            self.weight = nn.Parameter(torch.rand((in_channels, out_channels, kernel_size, kernel_size)))
        self.bias = nn.Parameter(torch.zeros(1))
        self.stride = stride
        self.padding = padding

    def forward(self, x):
        new_x = torch.zeros((x.shape[0], x.shape[1] + 2 * self.padding, x.shape[2] + 2 * self.padding))
        new_x[:, self.padding:x.shape[1] + self.padding, self.padding:x.shape[2] + self.padding] = x
        return corr2d_multi_in_out(new_x, self.weight, self.stride)


fake_image = torch.randn((3,5,5))
conv = Conv2D(in_channels=3, out_channels=1, kernel_size=3, stride=2,padding=1)
output = conv(fake_image)
print(output.shape)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1043179.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

面试打底稿④ 专业技能的第四部分

简历原文 抽查部分 了解Python的使用(第一篇关于Python升级版本bug解决的文章斩获6W阅读),用python实现了几篇图像信息隐藏领 域论文的复现(博客中有提及); 了解Django基本框架,写过Django框架的…

手把手教你实现法玛三因子模型

数量技术宅团队在CSDN学院推出了量化投资系列课程 欢迎有兴趣系统学习量化投资的同学,点击下方链接报名: 量化投资速成营(入门课程) Python股票量化投资 Python期货量化投资 Python数字货币量化投资 C语言CTP期货交易系统开…

xxl-job 执行器注册成功,但是xxl-admin 不显示

问题:项目启动成功后,日志显示执行器注册成功,但是xxl-job-admin 管理页面后台确无法查看到执行器信息。 经过百度后并结合官方文档说明,执行器客户端启动完成后,数据只会放在注册表xxl_job_registry 中。 而执行器管…

隐语 Meetup 北京站|精彩时刻大盘点!新品发布、行业案例、专家解读......欢迎围观

“隐语”是开源的可信隐私计算框架,内置 MPC、TEE、同态等多种密态计算虚拟设备供灵活选择,提供丰富的联邦学习算法和差分隐私机制 开源项目 github.com/secretflow gitee.com/secretflow 9月23日,隐语开源社区 Meetup 北京专场顺利举行&am…

sox音频处理和ffmpeg评测

ffmpeg音频处理不如sox,ffmpeg切分,最低切分是0.1秒,而sox可以切分更小单位0.001这种 ffmpeg处理视频等功能更全。 命令 ffmpeg -i 2.wav -y -ss 0.01 -acodec copy test.wav sox 2.wav output2.wav trim 0.01

redis部署与管理

目录 一、关系数据库与非关系型数据库: 1. 关系型数据库: 2.非关系型数据库: 二、关系型数据库和非关系型数据库区别: (1)数据存储方式不同: (2)扩展方式不同&#xf…

【100天精通Python】Day67:Python可视化_Matplotlib 绘制动画,2D、3D 动画 示例+代码

1 绘制2D动画(animation) Matplotlib是一个Python绘图库,它提供了丰富的绘图功能,包括绘制动画。要绘制动画,Matplotlib提供了FuncAnimation类,允许您创建基于函数的动画。下面是一个详细的Matplotlib动画示…

Django — 类视图和中间件

目录 一、类视图1、基于类的结构2、常见的类视图基类3、类视图的优点4、代码案例 二、中间件1、定义2、工作原理3、自带中间件4、中间件开发流程5、自定义中间件6、案例 一、类视图 类视图(Class-Based Views)是 Django 中用于处理 HTTP 请求和生成 HTT…

24届近3年河海大学自动化考研院校

⚜️所谓又专又精,专是指我们售后群团队上百人都是自动化研究生,精是指我们只做自动化这一门专业学科7年了,研究到极致! 🔉今天学长给大家带来的是河海大学控制考研分析 满满干货~还不快快点赞收藏 目录…

XC9700 单通道限流电流负载开关 低内阻负载开关

XC9700是一种低成本、低电压、单P-MOSFET负载开关,为自供电和总线供电的通用串行总线(USB)应用进行了优化。该开关的输入范围从2.4V到5.5V,使它非常适合3V和5V系统。该开关的低RDS(ON),80mΩ&am…

怒刷LeetCode的第16天(Java版)

目录 第一题 题目来源 题目内容 解决方法 方法一:迭代 方法二:模拟 方法三:循环模拟 方法四:传递 第二题 题目来源 题目内容 解决方法 方法一:回溯 方法二:枚举优化 第三题 题目来源 题目…

Unity之NetCode多人网络游戏联机对战教程(3)--NetworkObject组件讲解

文章目录 NetworkObjectAlways Replicate As RootSynchronization TransformActive Scene SynchronizationScene Migration SynchronizationSpawn With ObserversDont Destroy With OwnerAuto Object Parent Sync 后话 NetworkObject 为了复制任何Netcode感知属性或发送/接收R…

Linux生产者和消费者模型 条件变量 信号量

/*条件变量类型 pthread_cond_tint pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);int pthread_cond_destory(pthread_cond_t * cond);int pthread_cond_wait(pthread_cond_t *restrict cond, const pthread_mutex_t *restrict …

人生第一个java项目 学生管理系统

开始编程 建类 开始主要部分 main()部分 方法部分

Nodejs+vue高校机房设备管理系统jt07u

开发语言 node.js 框架:Express 前端:Vue.js 数据库:mysql 数据库工具:Navicat 开发软件:VScode 集成IDE对高校机房设备管理系统统进行开发,整合系统的各个模块。 拟开发的高校机房设备管理系统通过测试,确保在最大负载的情况下…

新型crypt勒索病毒,都有哪些特征?勒索病毒解密,数据恢复

近日,云天数据恢复中心在接受用户咨询的过程中发现,市场上悄然出现了一种新型的勒索病毒——crypt勒索病毒,接下来我们将这种类型的勒索病毒做一个全面的分析。 一,中了crypt勒索病毒的特征 在桌面以及多个文件夹中都有一个名称为…

matlab产生指定功率的噪声信号、固定SNR的信号

randn函数产生噪声信号 首先要理解信号的幅度和功率,例如信号的幅度为 U U U,那么信号的功率就是 U 2 U^2 U2,他们之间是平方的关系。 matlab中randn函数用法,产生正态分布的随机数或矩阵的函数。 randn:产生均值为0…

基于Java+vue开发的企事业移动培训考试平台

随着移动互联网的快速发展,越来越多的企业开始关注移动培训和考试平台的开发。为了满足这一需求,我们可以使用Java和Vue来开发一个基于移动端的企事业培训考试平台。 一、背景和需求 企事业移动培训考试平台是一个基于Web的应用程序,旨在提…

el-upload上传文件(vue2,Element中的 el-upload文件上传)

简介:el-upload是一个基于Element UI的上传组件,大家应该都知道,它可以方便地实现文件上传功能,今天来记录下如何(在vue2中)使用el-upload上传文件。 1、首先,我们想要使用el-upload&#xff0c…

Redux Toolkit中action派发但state值不更新的原因

最近一个react项目使用了Redux Toolkit,但是遇到了一个问题:数组始终返回为null,读取不到length. 这个只是问题的表象,真正的原因是productList数据没能从redux中结构出来 但是postman请求是由数据返回的: 推断&#x…