Pytorch的CNN,RNNLSTM

news2024/9/21 20:48:03

CNN

拿二维卷积举例,我们先来看参数
在这里插入图片描述
卷积的基本原理,默认你已经知道了,然后我们来解释pytorch的各个参数,以及其背后的计算过程。
首先我们先来看卷积过后图片的形状的计算:
参数:

kernel_size :卷积核的大小,可以是一个元组,也就是(行大小,列大小)
stride : 移动步长,同样的可以是一个元组
padding:填充,同样的可以是一个元组。注意,填充是两边都填,如果原本宽是x,填充1后,宽会变成x+2,因为左右都填充了1
dilation : 空洞卷积大小

空洞卷积:

这里解释一下dilation,你可以认为他就是把卷积核之间加了一些洞,在不改变参数量的情况下增加了感受野。
下面两张图片引用自下面的链接,想详细了解空洞卷积的,可以看这篇文章。
https://zhuanlan.zhihu.com/p/50369448
dilation=1,此时卷积核的每个参数都是相邻的
在这里插入图片描述
dilation=2,此时卷积核的每个参数和上下左右都有一个空隙,这个空隙是一种间隔并不是一种参数,所以从形式上来看,卷积核变大变稀疏了,能够捕获更大的范围,但参数量没有变化。
![在这里插入图片描述](https://img-blog.csdnimg.cn/3dd7a254c03c4c89afe7e6257164aa78.png
所以,假设原卷积核形状是(a, b)那么dilation=k时,行增加了(k - 1)(a - 1),列增加了(k - 1)(b - 1)。
于是卷积核变成了(a + (k - 1)(a - 1), b + (k - 1)(b - 1))

输出行的计算:

我们来推导行的计算,列的计算同理。
我们可以把行分成两个部分第一个部分是卷积核做的第一次卷积,第二个部分是卷积核向右移动做的卷积。
此时行的大小应该是1 + 向右移动的次数。向右移动的次数应该等于(行大小 - 卷积核宽度) / 步长 再向下取整
行大小 = 图片宽度 + pandding[0] * 2
卷积核宽度 = kernel_size[0] + (dilation[0] - 1)(kernel_size[0] - 1)
我们把卷积核宽度计算展开得到:
卷积核宽度 = dilation[0](kernel_size[0] - 1) + 1
于是把上述公式整合就得到pytorch里的计算式
在这里插入图片描述

分组卷积:

我们可以看到Pytorch的CNN里有一个参数叫groups,是为分组卷积做准备的参数。
分组卷积的思路是吧in_channel和out_channel都进行分组,每个组内分别进行卷积运算,最后再把结果进行concat。下面举个例子:
输入in_channel = 4, out_channel = 6, groups = 2。
此时in_channel分成了两组,每组的channel数都是in_channel/groups = 2,同理out_channel 也分成了两组每组的channel数都是out_channel/groups=3
此时输入通道变成了in_channel_groups = (sub_in_channel1=2, sub_in_channel1=2)
输出通道变成了out_channel_groups = (sub_out_channel1=3, sub_out_channel1=3)
我们让sub_in_channel1和sub_out_channel1做卷积,sub_in_channel2和sub_out_channel2做卷积。
最后我们再把两个组的卷积结果concat一下,得到最终结果,第一个组的输出channel数是3,第二个组的数也是3,所以concat之后,输出的通道数还是6.

那么,分组卷积的意义何在呢?我们看参数数量就知道了。由于输出通道要除以groups,所以输入通道的数目会减少,此时每一个卷积核要负责的输入通道也就减少了,也就是说,卷积核的参数数目会减少groups倍,这就是分组卷积的意义。

参数量的计算

weight的大小为(out_channel, i n _ c h a n n e l g r o u p s \frac{in\_channel}{groups} groupsin_channel, kernel_size[0], kernel_size[1]),从这里也可以看出groups减少了参数量。
bias的大小就是out_channel的大小了。

示例代码:

conv = torch.nn.Conv2d(in_channels=3, out_channels=3, kernel_size=(3, 3),\
                       stride=(2, 2), padding=(0, 0), groups=3)
"""
上述代码创建了一个处理3通道图片的卷积层
其中输出通道为3,卷积核形状为(3, 3)没有padding,横向和垂直的步长都是2
输出通道和输入通道都会被平均的分为3组
"""

RNN

同理,这里也默认了你知道了RNN的基础知识,我们来看Pytorch中RNN的官方文档。
在这里插入图片描述
这里我们先忽略num_layers, bias, 等参数,先专注于hidden_size和input_size。
先创建一个RNN然后查看参数

rnn = torch.nn.RNN(input_size = 3, hidden_size=5, bias=False)
print(rnn.all_weights)
"""
[[Parameter containing:
tensor([[-0.2646, -0.4045, -0.1925],
        [-0.3035, -0.4026, -0.2005],
        [ 0.0181,  0.0157, -0.0804],
        [ 0.4191,  0.0750,  0.1659],
        [ 0.1848,  0.1085,  0.4351]], requires_grad=True), Parameter containing:
tensor([[ 0.4092,  0.1956, -0.1648,  0.0278, -0.3483],
        [ 0.3865,  0.3441,  0.1004, -0.4226, -0.2988],
        [ 0.2640,  0.3169, -0.2568, -0.3115,  0.3268],
        [-0.3311, -0.1856,  0.3827, -0.1265, -0.4149],
        [ 0.0930, -0.1986,  0.1813,  0.3944,  0.1576]], requires_grad=True)]]
"""

可以看到有两个参数,一个是wi=(5, 3)一个是wh=(5, 5),第一个参数wi用于乘以输入的数据,而第二个参数wh用于和隐藏层的向量相乘,在结合官方给出的RNN计算,我们就可以手动模拟以下RNN的推理过程了,RNN有两个输出,一个是out_put,一个是h_0
手动模拟:

data = torch.randn(size=(2, 4, 3), dtype=torch.float32) # 输入的数据
rnn = torch.nn.RNN(input_size = 3, hidden_size=5, bias=False)
wh = rnn.all_weights[0][0]
wi = rnn.all_weights[0][1]
h0 = torch.zeros(size=(1, 4, 5))

up_out = [] # out_put的数据
right_out = None # 隐藏层最终输出
acfun = torch.nn.Tanh()

for i in range(2): # 2代表时序
	tmp1 = data[i].matmul(wh.T) # 计算输入
    tmp2 = h0.matmul(wi.T) # 计算隐藏层
    res = acfun(tmp1 + tmp2) # 计算新的h_0
    up_out.append(res) # 本时刻的输出
    h0 = res # 更新隐藏层
print(torch.cat(up_out, dim=0), h0) # 把每一个时刻的输出都concat一下
print(rnn(data))

其余参数:

其余的参数就好理解了,num_layer是控制层数的,这会使得隐藏层增加。Bidirectional是控制是否开双向的最后输出会被叠加在out_put上,batch_first是为了方便输入数据的batch位于第一个维度。

LSTM

LSTM比RNN要复杂很多,同样的,通过模拟LSTM计算的过程,搞清楚pytorch的LSTM是怎么输出的。
首先先回忆一下LSTM的计算过程:
在这里插入图片描述
LSTM有三个门,分别是:输入门,输出门,遗忘门。每个门都需要对应一个权重。
除此之外对于输入也还需要做一个做一个变换,所以也需要一个参数。
对于Pytorch的LSTM来说,他还考虑上一次的输出,也就是说,Pytorch的LSTM计算时是这样的
在这里插入图片描述也可以看到,上一次的输出 h t h_t ht被接到了下一次输入中。那么我们针对于新增的 h t h_t ht也需要对应的参数。
那么Pytorch的LSTM一共有八个参数(除去bias)

观察参数:

首先,对于input_size = a, hidden_size=b的LSTM,针对输入数据的矩阵的形状应该是bxa的。针对上一次输出数据的形状应该是bxb的。
我们来看Pytorch的LSTM的参数

rnn = nn.LSTM(input_size = 3, hidden_size=5, bias=False)
print(rnn.all_weights[0][0].shape, rnn.all_weights[0][1].shape)
"""
torch.Size([20, 3]) torch.Size([20, 5])
"""

我们发现只有两组,其实这是八组。因为针对于输入数据,一共有4个5x3的数据。对于 h t h_t ht一共有4个5x5的数据。为了加快运算,Pytorch把这些数据concat到一起了。于是出现了两个20列的数据。

模拟LSTM运算

根据Pytorch官方给的计算公式和,LSTM的计算图解。我们来进行模拟
在这里插入图片描述
在这里插入图片描述
首先我们先拆分出来参数

wii = rnn.all_weights[0][0][:5, :]
wif = rnn.all_weights[0][0][5:10, :]
wig = rnn.all_weights[0][0][10:15, :]
wio = rnn.all_weights[0][0][15:20, :]

whi = rnn.all_weights[0][1][:5, :]
whf = rnn.all_weights[0][1][5:10, :]
whg = rnn.all_weights[0][1][10:15, :]
who = rnn.all_weights[0][1][15:20, :]

然后我们把LSTM的三个输入给构造出来

data = torch.randn(size=(2, 4, 3), dtype=torch.float32)
h = torch.zeros(size=(1, 4, 5)) # 隐藏层,也就是上一次的输出
c = torch.zeros(size=(1, 4, 5)) # 记忆单元

然后我们按照上面的公式进行计算,就会得到最终的结果

import torch
from torch import nn

data = torch.randn(size=(2, 4, 3), dtype=torch.float32)
rnn = nn.LSTM(input_size = 3, hidden_size=5, bias=False)

wii = rnn.all_weights[0][0][:5, :]
wif = rnn.all_weights[0][0][5:10, :]
wig = rnn.all_weights[0][0][10:15, :]
wio = rnn.all_weights[0][0][15:20, :]

whi = rnn.all_weights[0][1][:5, :]
whf = rnn.all_weights[0][1][5:10, :]
whg = rnn.all_weights[0][1][10:15, :]
who = rnn.all_weights[0][1][15:20, :]

h = torch.zeros(size=(1, 4, 5))
c = torch.zeros(size=(1, 4, 5))
up_out = []

tanh = nn.Tanh()
sigmoid = nn.Sigmoid()

for k in range(2):
    i = sigmoid(data[k].matmul(wii.T) + h.matmul(whi.T))
    f = sigmoid(data[k].matmul(wif.T) + h.matmul(whf.T))
    g = tanh(data[k].matmul(wig.T) + h.matmul(whg.T))
    o = sigmoid(data[k].matmul(wio.T) + h.matmul(who.T))
    
    c = c * f + i * g
    o = tanh(c) * o
    up_out.append(o) # 本次的输出加到output中
    h = o # 把本次的输出替换h
print(torch.cat(up_out, dim=0), (h, c))
print(rnn(data))

模拟完之后我们就搞懂了Pytorch的LSTM的输入和输出都是啥了:
输入:三个参数,data,隐藏层初始值,记忆单元初始值
输出:两个值,第二个值是一个元组。每一个时刻的输出,隐藏层输出(就是最后一个时刻的输出),记忆单元的值
其余的参数和RNN一致就不再说了

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

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

相关文章

【AI炼丹术】写深度学习代码的一些心得体会

写深度学习代码的一些心得体会 体会1体会2体会3总结内容来源 一般情况下,拿到一批数据之后,首先会根据任务先用领域内经典的Model作为baseline跑通,然后再在这个框架内加入自己设计的Model,微调代码以及修改一些超参数即可。总体流…

Matlab进阶绘图第18期—相关性气泡热图

相关性气泡热图是一种特殊的气泡热图。 与一般的气泡热图相比,其数值位于[-1 1]区间,其颜色用于表示正负,而其气泡的大小用于表示数值绝对值的大小,可以十分直观地对两个变量的相关性进行分析。 由于Matlab中未收录相关性气泡热…

In-Context Learning中的示例选择及效果

一. ICL的背景 大型语言模型(LLM)如GPT-3是在大规模的互联网文本数据上训练,以给定的前缀来预测生成下一个token(Next token prediction)。这样简单的训练目标,大规模数据集以及高参数量模型相结合&#x…

国内可直接使用的OpenAI DALL*E 图片AI体验站,可通过自然语言生成图片

体验站最终演示效果 国内可直接使用的图片AI体验站:https://zizhu888.cn/text2img/index.html ChatGPT3.5 Turbo国内体验站: https://zizhu888.cn/chatgpt/index.html OpenAI DALL*E可以通过自然语言生成图片,内容创作者的福音,大大降低了创…

基于飞桨 PaddleVideo 的骨骼行为识别模型 CTR-GCN

main.pysame_seedsparse_argsmain ensemble.pyconfigs 文件夹Joint(J)的配置文件ctrgcn_fsd_J_fold0.yamlctrgcn_fsd_J_fold1.yaml Joint Angle(JA)的配置文件ctrgcn_fsd_JA_fold0.yaml paddlevideo 文件夹utils 文件夹__init__.p…

【Python 协程详解】

0.前言 前面讲了线程和进程,其实python还有一个特殊的线程就是协程。 协程不是计算机提供的,计算机只提供:进程、线程。协程是人工创造的一种用户态切换的微进程,使用一个线程去来回切换多个进程。 为什么需要协程? …

中国制造再击败一家海外企业,彻底取得垄断地位

中国制造已在13个行业取得领先优势,凸显出中国制造的快速崛起,日前中国制造又在一个行业彻底击败海外同行,再次证明了中国制造的实力。 一、海外企业承认失败 提前LGD宣布它位于广州的8.5代液晶面板生产线停产,预计该项目将出售给…

crm day03 创建市场活动

页面切割 div切割,ifram显示 如何分割的呢,在主页面上打开iframe $(function(){ //页面加载时window.open("workbench/main/index.do","workareaFrame"); })注意所有在WEB-INF的页面都会收到保护,因此到达此目录下的页…

不得不的创建型模式-建造者模式

目录 建造者模式是什么 下面是一个简单的示例代码,演示了如何使用建造者模式来构建一个复杂对象: 面试中可能遇到的问题及回答: 建造者模式是什么 建造者模式是一种创建型模式,它的目的是将复杂对象的构造过程分离成多个简单的…

你知道项目进度控制和跟踪的目的是什么吗?

项目进度控制和跟踪的目的是: 增强项目进度的透明度,当项目进展与项目计划出现偏差时,可以及时采取适当的措施。 1、计划是项目监控的有效手段 项目控制的手段是根据计划对项目的各项活动进行监控,项目经理可以使用甘特图来制…

界面控件DevExtreme使用指南 - 折叠组件快速入门(二)

DevExtreme拥有高性能的HTML5 / JavaScript小部件集合,使您可以利用现代Web开发堆栈(包括React,Angular,ASP.NET Core,jQuery,Knockout等)构建交互式的Web应用程序,该套件附带功能齐…

微信小程序nodejs+python+php+springboot+vue 微型整容医美挂号预约app系统

(a) 管理员;管理员使用本系统涉到的功能主要有首页、个人中心、用户管理、体检预约管理、项目预约、系统管理等功能 (b) 用户;用户进入app可以实现首页、美容产品、我的等,在我的页面可以对在线预约、体检预约、项目预约等功能进行操作 本基于…

Unity之OpenXR+XR Interaction Toolkit实现 UI交互

一.前言 在VR中我们经常会和一些3D的UI进行交互,今天我们就来说一下如何实现OpenXRXRInteraction Toolkit和UI的交互。 二.准备工作 有了前两篇的配置介绍,我们就不在详细说明这些了,大家自行复习 Unity之OpenXRXR Interaction Toolkit接入Pico VR一体…

钉钉用一条斜杠,金山系用一张表格,做了华为一直想做的事

阿里的“新钉钉”又一次站在风口上 一场疫情导致数万企业停工的同时,却让阿里的钉钉、腾讯会议,还有字节跳动的飞书等在线协同办公产品火得一塌糊涂。 今天,OpenAI公司的一个chatGPT,让阿里、百度等各大互联网巨头扎堆发布大模型产品。 回顾…

如何在Web上实现激光点云数据在线浏览和展示?

无人机激光雷达测量是一项综合性较强的应用系统,具有数据精度高、层次细节丰富、全天候作业等优势,能够精确测量三维现实世界,为各个行业提供了丰富有效的数据信息。但无人机激光雷达测量产生的点云数据需要占用大量的存储空间,甚…

Gantt图和PERT图的相关知识

1、Gantt 图 Gantt图以时间为基准描述项目任务,可以清晰的描述每个任务从何时开始,到何时结束,以及每个任务的并行关系,但是不能反映项目各任务之间的依赖关系,也无法确定整个任务的关键所在。 2、PERT图 计划评审…

Canvas实现动态绘制圆周效果(沿圆周运动的圆的绘制)

步骤实现: 首先,创建一个 HTML 画布和一个 JavaScript 动画函数。 在画布上绘制一个圆。 定义一个变量来表示圆心的坐标和半径。 进行动画循环以更新圆心坐标,使其沿外圆周运动。 使用三角函数(如 sin 和 cos)来计…

前端代码版本管理规范

Git 是目前最流行的源代码管理工具。为规范开发,保持代码提交记录以及 git分支结构清晰,方便后续维护,总结了如下规范。 分支约定 ├── master # 生产分支 ├── release # 测试分支├── develop # 开发分支…

学系统集成项目管理工程师(中项)系列11b_沟通管理(下)

1. 沟通过程的有效性 1.1. 效果 1.1.1. 在适当的时间、适当的方式、信息被准确的发送给适当的沟通参与方(信息的接收方),并且能够被正确的理解,最终参与方能够正确的采取行动 1.2. 效率 1.2.1. 强调的是及时提供所需的信息 2…

两数之和hash

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。 你可以按任意顺序返回…