PyTorch入门------卷积神经网络

news2025/4/20 1:32:52

前言

        参考:神经网络 — PyTorch Tutorials 2.6.0+cu124 文档 - PyTorch 深度学习库

        一个典型的神经网络训练过程如下:

  1. 定义一个包含可学习参数(或权重)的神经网络

  2. 遍历输入数据集

  3. 将输入通过神经网络处理

  4. 计算损失(即输出结果与正确答案之间的差距)

  5. 将梯度反向传播到网络的参数中

  6. 更新网络的权重,通常使用一个简单的更新规则:weight = weight - learning_rate * gradient

        1.相关概念

        感受野: 在卷积神经网络中,对于某一层的任意元素x,其感受野(receptive field)是指在前向传播期间可能影响 x 计算的所有元素(来自所有先前层)。

        注意:感受野可能大于输入的实际大小。例如在如上所示的卷积结构,X 上 z 的感受野为其全部 9 个元素,Y 上 z 的感受野也为其全部 4 个元素,即 z 的感受野的大小为 9+4=13! 因此,当一个特征图中的任意元素需要检测更广区域的输入特征时,我们可以构建一个更深的网络

        2.多输入多输出通道

        参考:https://zhuanlan.zhihu.com/p/251068800

  • 输入通道个数 等于 卷积核通道个数
  • 卷积核个数 等于 输出通道个数

        2.1 多输入通道

        输入通道个数 等于 卷积核通道个数!

        当输入包含多个通道时,需要构造一个与输入数据具有相同输入通道数的卷积核,以便与输入数据进行互相关运算。

        由于输入和卷积核都有 c_i 个通道,我们可以对每个通道输入的二维张量卷积核的二维张量进行互相关运算,再对通道求和(将 c_i 的结果相加)得到二维张量。这是多通道输入多输入通道卷积核之间进行二维互相关运算的结果。

        2.2 多输出通道

        卷积核个数 等于 输出通道个数!

         用 c_ic_o 分别表示输入和输出通道的数目,并让 k_h 和 k_w 为卷积核的高度和宽度。为了获得多个通道的输出,我们可以为每个输出通道创建一个形状为 c_i \times k_h \times k_w 的卷积核张量,这样卷积核的形状是 c_o\times c_i \times k_h \times k_w (即 c_o 个卷积核,每个卷积核的形状为 c_i \times k_h \times k_w)。

        在互相关运算中,每个输出通道先获取所有输入通道,再以对应该输出通道的卷积核计算出结果。最后将每个卷积核对应的输出通道结果(feature map)进行拼接得到多通道输出。

        3. 1x1 卷积层        

        卷积(Convolution)的本质正是通过局部的加权和运算,提取图像中相邻像素之间的相关特征。

        但 1x1 卷积并没此作用,1×1卷积的唯一计算发生在通道上!

  • 当以每像素为基础应用时,1×1卷积层相当于全连接层
  • 1×1卷积层通常用于调整网络层的通道数量和控制模型复杂性

        下图展示了使用 1×1卷积核与3个输入通道和2个输出通道的互相关计算。 这里输入和输出具有相同的高度和宽度,输出中的每个元素都是从输入图像中同一位置的元素的线性组合。 我们可以将1×1卷积层看作在每个像素位置应用的全连接层,将 c_i 个输入值转换为 c_o 个输出值。 因为这仍然是一个卷积层,所以跨像素的权重是一致的。 同时,1×1卷积层需要的权重维度为 c_o\times c_i,再额外加上一个偏置。

        4. 池化层

  • 池化层通过减少特征图的空间分辨率来降低计算量,并降低卷积层对空间分辨率的敏感性。
  • 池化层可以降低隐藏表示的空间分辨率,从而聚集更多的高层次特征信息 (将局部的低级特征逐步整合成更高级的抽象特征)
  • 池化操作(如最大池化)会在局部区域内提取最显著的特征,从而降低卷积层对位置的敏感性。
  • 池化层的输出通道数通常与输入通道数相同,因为池化是独立作用于每个通道的。

        5. 总结

        增加每个神经元感受野的方式:

  • 增加卷积层的层数,构建更深的网络。
  • 添加池化层,降低分辨率,聚合信息。随着分辨率的降低,每个神经元所覆盖的区域也会增大,即感受野增大。

一、网络结构

        一个对数字图像进行分类的网络的结构如下:

        该网络结构和 LeNet(LeNet-5)的网络结构基本一致。(对原始模型做了一点小改动,去掉了最后一层的高斯激活。除此之外,这个网络与最初的LeNet-5一致。) 

 

        这是一个简单的前馈神经网络(RNN)。它接收输入,将其依次传递通过多个层,最终输出结果。        

        在使用 pytorch 定义该网络结构时,只需要定前向传播 forward 函数,而反向传播 backward 函数(用于计算梯度)会通过 autograd 自动生成。在 forward 函数中,可以使用任意的张量操作(Tensor operations)模型中所有的可学习参数可以通过 net.parameters() 返回。

#----- 1.定义网络结构 -----#
import torch
import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):
    """
        Conv2d(): 初始化一个二维卷积层。

        参数:
        in_channels (int)  -- 输入图像中的通道数
        out_channels (int) -- 卷积产生的通道数
        kernel_size (int 或 tuple) -- 卷积核的大小,可以是一个整数或包含两个整数的元组 (height, width)
        stride (int 或 tuple, 可选) -- 卷积的步长,默认值为 1。如果是元组, 则分别表示高和宽方向上的步长。
        padding (int, tuple 或 str, 可选) -- 输入的所有四个边的填充。默认值为 0, 可以是整数、元组或字符串('valid' 或 'same'),
                                               'valid' 表示不填充,'same' 表示填充以保持输出尺寸与输入相同。
        dilation (int 或 tuple, 可选) -- 卷积核元素之间的间距,默认为 1, 表示常规卷积。增大该值会引入空洞卷积。
        groups (int, 可选) -- 控制卷积的分组,默认为 1。大于 1 时会做分组卷积,即输入和输出通道被分为多个组,每组独立卷积。
        bias (bool, 可选) -- 是否添加偏置项,默认为 True。如果设置为 False, 则没有偏置。
        padding_mode (str, 可选) -- 填充模式,'zeros' 表示填充 0, 默认值为 'zeros'。可以选择 'reflect' 或 'replicate' 进行反射或复制填充。
        device (torch.device, 可选) -- 卷积层所使用的设备,默认为 None。
        dtype (torch.dtype, 可选) -- 卷积层所使用的数据类型,默认为 None。

        返回:
        nn.Conv2d -- 一个二维卷积层对象
    """

    def __init__(self):
        super(Net, self).__init__()
        # 1 个输入图像通道,6 个输出通道,5x5 的卷积核
        self.conv1 = nn.Conv2d(1, 6, 5)   # bias=False
        # 6 个输入图像通道,16 个输出通道,5x5 的卷积核
        self.conv2 = nn.Conv2d(6, 16, 5)  # bias=False
        # 一个仿射变换操作:y = Wx + b
        self.fc1 = nn.Linear(16 * 5 * 5, 120)  # 5*5 来源于图像尺寸
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, input):
        # 卷积层 C1:1 个输入图像通道,6 个输出通道,5x5 的卷积核,使用 ReLU 激活函数,
        # 输出尺寸为 (N, 6, 28, 28) 的张量,N 是批次大小
        c1 = F.relu(self.conv1(input))

        # 池化层 S2:2x2 的最大池化网格,纯函数实现,没有可训练参数,
        # 输出尺寸为 (N, 6, 14, 14) 的张量
        s2 = F.max_pool2d(c1, (2, 2))

        # 卷积层 C3:6 个输入通道,16 个输出通道,5x5 的卷积核,使用 ReLU 激活函数,
        # 输出尺寸为 (N, 16, 10, 10) 的张量
        c3 = F.relu(self.conv2(s2))

        # 池化层 S4:2x2 的最大池化网格,纯函数实现,没有可训练参数,
        # 输出尺寸为 (N, 16, 5, 5) 的张量
        s4 = F.max_pool2d(c3, 2)

        # 展平操作:纯函数实现,输出尺寸为 (N, 400) 的张量
        s4 = torch.flatten(s4, 1)

        # 全连接层 F5:输入为 (N, 400) 的张量,
        # 输出为 (N, 120) 的张量,使用 ReLU 激活函数
        f5 = F.relu(self.fc1(s4))

        # 全连接层 F6:输入为 (N, 120) 的张量,
        # 输出为 (N, 84) 的张量,使用 ReLU 激活函数
        f6 = F.relu(self.fc2(f5))

        # 高斯输出层:输入为 (N, 84) 的张量,
        # 输出为 (N, 10) 的张量
        output = self.fc3(f6)
        return output


net = Net()
print(net)


# 模型的可学习参数
params = list(net.parameters())
print(len(params))       # (卷积层数量 + 全连接层数量) * 2。2 为权重和偏置,卷积层和全连接层均有权重和偏置
print(params[0].size())  # 卷积层 conv1 的权重矩阵的形状,格式为 [输出通道数, 输入通道数, 卷积核高度, 卷积核宽度]
print(params[2].size())


# 随机的 32x32 输入。格式为 (batch_size, Channel, Height, Width)
input = torch.randn(1, 1, 32, 32)
out = net(input)
print(out)


# 梯度清零后进行反向传播
net.zero_grad()
out.backward(torch.randn(1, 10))

二、损失函数

#----- 2.损失函数 -----#
output = net(input)
target = torch.randn(10)  # a dummy target, for example
target = target.view(1, -1)  # make it the same shape as output
criterion = nn.MSELoss()

loss = criterion(output, target)
print(loss)


print(loss.grad_fn)  # MSELoss
print(loss.grad_fn.next_functions[0][0])  # Linear
print(loss.grad_fn.next_functions[0][0].next_functions[0][0])  # ReLU

三、反向传播

#----- 3.反向传播 -----#
net.zero_grad()     # 将所有参数的梯度缓冲区置零

print('conv1.bias.grad before backward')
print(net.conv1.bias.grad)

loss.backward()

print('conv1.bias.grad after backward')
print(net.conv1.bias.grad)

四、更新权重

#----- 4.更新模型权重 -----#
import torch.optim as optim

# 创建优化器
optimizer = optim.SGD(net.parameters(), lr=0.01)

# 在训练循环中:
optimizer.zero_grad()   # 将梯度缓冲区清零
output = net(input)     # 前向传播
loss = criterion(output, target)  # 计算损失值
loss.backward()         # 反向传播,计算梯度
optimizer.step()        # 更新参数

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

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

相关文章

Edge浏览器安卓版流畅度与广告拦截功能评测【不卡还净】

安卓设备上使用浏览器的体验,很大程度取决于两个方面。一个是滑动和页面切换时的反应速度,另一个是广告干扰的多少。Edge浏览器的安卓版本在这两方面的表现比较稳定,适合日常使用和内容浏览。 先看流畅度。Edge在中端和高端机型上启动速度快&…

Docker 和 Docker Compose 使用指南

Docker 和 Docker Compose 使用指南 一、Docker 核心概念 镜像(Image) :应用的静态模板(如 nginx:latest​)。容器(Container) :镜像的运行实例。仓库(Registry&#xf…

vue3环境搭建、nodejs22.x安装、yarn 1全局安装、npm切换yarn 1、yarn 1 切换npm

vue3环境搭建 node.js 安装 验证nodejs是否安装成功 # 检测node.js 是否安装成功----cmd命令提示符中执行 node -v npm -v 设置全局安装包保存路径、全局装包缓存路径 在node.js 安装路径下 创建 node_global 和 node_cache # 设置npm全局安装包保存路径(新版本…

Python人工智能 使用可视图方法转换时间序列为复杂网络

基于可视图方法的时间序列复杂网络转换实践 引言 在人工智能与数据科学领域,时间序列分析是一项基础且重要的技术。本文将介绍一种创新的时间序列分析方法——可视图方法,该方法能将时间序列转换为复杂网络,从而利用复杂网络理论进行更深入…

spring:加载配置类

在前面的学习中,通过读取xml文件将类加载,或他通过xml扫描包,将包中的类加载。无论如何都需要通过读取xml才能够进行后续操作。 在此创建配置类。通过对配置类的读取替代xml的功能。 配置类就是Java类,有以下内容需要执行&#…

从零搭建一套前端开发环境

一、基础环境搭建 1.NVM(Node Version Manager)安装 简介 nvm(Node Version Manager) 是一个用于管理多个 Node.js 版本的工具,允许开发者在同一台机器上轻松安装、切换和使用不同版本的 Node.js。它特别适合需要同时维护多个项目&#xff…

金融数据库转型实战读后感

荣幸收到老友太保科技有限公司数智研究院首席专家林春的签名赠书。 这是国内第一本关于OceanBase数据库实际替换过程总结的的实战书。打个比方可以说是从战场上下来分享战斗经验。读后感受颇深。我在这里讲讲我的感受。 第三章中提到的应用改造如何降本。应用改造是国产化替换…

代码审计系列2:小众cms oldcms

目录 sql注入 1. admin/admin.php Login_check 2. admin/application/label/index.php 3. admin/application/hr/index.php 4. admin/application/feedback/index.php 5. admin/application/article/index.php​ sql注入 1. admin/admin.php Login_check 先看一下p…

Cursor + MCP,实现自然语言操作 GitLab 仓库

本分分享如何使用 cursor mcp 来操作极狐GitLab 仓库,体验用自然语言在不接触极狐GitLab 的情况下来完成一些仓库操作。 极狐GitLab 是 GitLab 在中国的发行版,关于中文参考文档和资料有: 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitL…

Vue el-from的el-form-item v-for循环表单如何校验rules(一)

实际业务需求场景: 新增或编辑页面(基础信息表单,一个数据列表的表单),数据列表里面的表单数是动态添加的。数据可新增、可删除,在表单保存前,常常需要做表单必填项的校验,校验通过以…

【Reading Notes】(8.3)Favorite Articles from 2025 March

【March】 雷军一度登顶中国首富,太厉害了(2025年03月02日) 早盘,小米港股一路高歌猛进,暴涨4%,股价直接飙到52港元的历史新高。这一波猛如虎的操作,直接把雷军的身家拉到了2980亿元&#xff0c…

从PDF到播客:MIT开发的超越NotebookLM的工具

NotebookLM是谷歌推出的更具创意的AI产品之一,几个月前刚刚推出。 许多人对它的能力感到惊叹——尤其是将长文本转化为两位播客主持人之间有趣对话的功能。 NotebookLM提供的不仅仅是这些,还包括聊天(问答)甚至生成思维导图。 如果你还没有尝试过NotebookLM,我强烈建议…

Kotlin协程Semaphore withPermit约束并发任务数量

Kotlin协程Semaphore withPermit约束并发任务数量 import kotlinx.coroutines.* import kotlinx.coroutines.sync.Semaphore import kotlinx.coroutines.sync.withPermit import kotlinx.coroutines.launch import kotlinx.coroutines.runBlockingfun main() {val permits 1 /…

Redis的下载安装和使用(超详细)

目录 一、所需的安装包资源小编放下述网盘了,提取码:wshf 二、双击打开文件redis.desktop.manager.exe 三、点击next后,再点击i agree 四、点击箭头指向,选择安装路径,然后点击Install进行安装 五、安装完后依次点…

无线网络入侵检测系统实战 | 基于React+Python的可视化安全平台开发详解

随着无线网络的普及,网络攻击风险也日益严峻。本项目旨在构建一个实时监测、智能识别、高效防护的无线网络安全平台,通过结合前后端技术与安全算法,实现对常见攻击行为的有效监控和防御。 一、项目简介与功能目的 本系统是一款基于 React 前…

[经验总结]Linux双机双网卡Keepalived高可用配置及验证细节

1. 前言 这种配置需求比较少见,在网上也很少有相关文章,于是记录在此,供有需要的朋友参考。 本篇重点介绍配置的关键点,基础部分简单提及,不赘述。 2. 需求描述 如上图,即给两个主机配置两对高可用主从配…

2025.04.17【Dendrogram】生信数据可视化:Dendrogram图表详解

Dendrogram customization Go further with ggraph: edge style, general layout, node features, adding labels, and more. Customized circular dendrogram Learn how to build a circular dendrogram with proper labels. 文章目录 Dendrogram customizationCustomized c…

Linux下的网络管理

一、ipv4原理 网络接口是指网络中的计算机或网络设备与其他设备实现通讯的进出口,一般是指计算机的网络接口即网卡设备 从RHEL7开始引入了一种新的“一致网络设备命名”的方式为网络接口命名,该方式可以根据固件、设备拓扑、设备类型和位置信息分配固…

Zookeeper介绍与安装配置

1.综述 1.1.Zookeeper介绍 Zookeeper 是一个分布式协调服务,由 Apache 开发,主要用于管理分布式应用中的配置信息、命名服务、分布式同步和组服务。它通过简单的接口提供高性能、高可用性和严格的顺序访问控制,广泛应用于分布式系统的协调与…

实验五 内存管理实验

实验五 内存管理实验 一、实验目的 1、了解操作系统动态分区存储管理过程和方法。 2、掌握动态分区存储管理的主要数据结构--空闲表区。 3、加深理解动态分区存储管理中内存的分配和回收。 4、掌握空闲区表中空闲区3种不同放置策略的基本思想和实现过程。 5、通过模拟程…