Pytorch学习之torch.nn.functional.pad()函数

PyTorch学习之torch.nn.functional.pad函数

一、简介

torch.nn.functional.pad 是 PyTorch 中用于对张量进行填充操作的函数。填充操作在处理图像、序列数据等任务时非常常见,它可以在张量的指定维度两端添加一定数量的元素,填充方式多样,包括零填充、常数填充、反射填充和边界填充等。

二、基本语法

torch.nn.functional.pad(input, pad, mode='xxx', value=x)

三、参数说明

  • input (Tensor): 输入的张量。
  • pad (tuple): 指定每个维度填充的数目。格式为 (left, right, top, bottom, …)。
  • mode (str, 可选): 填充模式,包括 constant(常数填充,默认)、reflect(反射填充)、replicate(边界填充)和 circular(循环填充)。
  • value (float, 可选): 常数填充模式下填充值,仅当 mode 为 ‘constant’ 时有效,其他模式时即使指定了值也会被忽略掉。

四、返回值

返回一个新的张量,对输入张量进行了指定方式的填充。

五、填充模式详解

在详细讲解和演示每一种模式的效果前,我想对填充的一些规则进行提前说明:

  • 我们会填充【 d i m = l e n ( p a d ) 2 \mathrm{dim=\frac{len(pad)}{2}} dim=2len(pad)】个维度

    举个例子:有一个(4, 4)形状的矩阵,我给的pad=(1,1),那么根据公式 d i m = 2 2 = 1 \mathrm{dim=\frac22=1} dim=22=1因此我们只填充1个维度。有人想,既然只填充1个维度,那为什么给两个值?

    矩阵是4x4的,有横向有纵向对吧,最后一个维度肯定是横向的(我们常说矩阵存储是行优先的),此时矩阵是不是有左右两边?那么给出的2个填充值分别对应于在左边(left)要填充1个像素,在右边(right)要填充一个像素。

    同样的随着维度扩展,pad可以提供更长的参数,如pad=(1, 1, 2, 2, 3, 3),根据公式填充3个维度,哪3个?(left, right, top, bottom, front, back)

  • 填充是从内向外的:例如pad=(1, 1, 2, 2, 3, 3),(1, 1)对应填充(left, right),(2, 2)对应填充(top, bottom),(3, 3)对应填充(front, back)

5.1 constant模式

在该模式下,我们必须指定参数value,value的值将填充到我们扩充的区域。

例如有如下代码:

import torch
import torch.nn as nndata = torch.tensor([[[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12],[13, 14, 15, 16]
]])print(data.size())
print(data)
paddata1 = nn.functional.pad(data, (1, 1, 1, 1), mode="constant", value=1)
print(paddata1.size())
print(paddata1)

输出:

torch.Size([1, 4, 4])
tensor([[[ 1,  2,  3,  4],[ 5,  6,  7,  8],[ 9, 10, 11, 12],[13, 14, 15, 16]]])
torch.Size([1, 6, 6])
tensor([[[ 1,  1,  1,  1,  1,  1],[ 1,  1,  2,  3,  4,  1],[ 1,  5,  6,  7,  8,  1],[ 1,  9, 10, 11, 12,  1],[ 1, 13, 14, 15, 16,  1],[ 1,  1,  1,  1,  1,  1]]])

可以看到,我们在(left,right,top,bottom)四个方向都填充了一个像素,像素值=value

5.2 reflect模式

该模式分我们既可以说是反射模式,也可以说是镜像模式,当然我个人认为镜像模式更形象:

我们看代码:

import torch
import torch.nn as nndata = torch.tensor([[[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12],[13, 14, 15, 16]
]])print(data.size())
print(data)
paddata2 = nn.functional.pad(data, (1, 1, 1, 1), mode="reflect", value=0) # value指定值将无效
print(paddata2.size())
print(paddata2)

输出:

torch.Size([1, 4, 4])
tensor([[[ 1,  2,  3,  4],[ 5,  6,  7,  8],[ 9, 10, 11, 12],[13, 14, 15, 16]]])
torch.Size([1, 6, 6])
tensor([[[ 6,  5,  6,  7,  8,  7],[ 2,  1,  2,  3,  4,  3],[ 6,  5,  6,  7,  8,  7],[10,  9, 10, 11, 12, 11],[14, 13, 14, 15, 16, 15],[10,  9, 10, 11, 12, 11]]])

此刻,我们来看,为什么说用镜像一词更贴切:

  • 第1列是以第2列为镜子的第3列的镜像
  • 最后1列是以倒数第2列为镜子的倒数第3列的镜像
  • 左上角的6是以1为镜子的6的镜像,右上角的7是以4为镜子的7的镜像
  • 以此类推,可以看出符合我们的说法

再看一组测试,此时我们将填充语句变更为

paddata2 = nn.functional.pad(data, (2, 1, 1, 1), mode="reflect", value=0)

输出:

torch.Size([1, 4, 4])
tensor([[[ 1,  2,  3,  4],[ 5,  6,  7,  8],[ 9, 10, 11, 12],[13, 14, 15, 16]]])
torch.Size([1, 6, 7])
tensor([[[ 7,  6,  5,  6,  7,  8,  7],[ 3,  2,  1,  2,  3,  4,  3],[ 7,  6,  5,  6,  7,  8,  7],[11, 10,  9, 10, 11, 12, 11],[15, 14, 13, 14, 15, 16, 15],[11, 10,  9, 10, 11, 12, 11]]])

读者体会一下吧,看看此时各方向的镜子是哪些列?被镜像的又是哪一列?相信读者通过这两个实例对该填充模式有比较清晰的认识。

5.3 replicate模式

该模式称为复制模式拷贝模式:其将数据的边缘(1像素)进行原封不动的拷贝。说起来抽象,直接上代码:

import torch
import torch.nn as nndata = torch.tensor([[[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12],[13, 14, 15, 16]
]])print(data.size())
print(data)
paddata3 = nn.functional.pad(data, (1, 1, 1, 1), mode="replicate")
print(paddata3)
print(paddata3)

输出:

torch.Size([1, 4, 4])
tensor([[[ 1,  2,  3,  4],[ 5,  6,  7,  8],[ 9, 10, 11, 12],[13, 14, 15, 16]]])
torch.Size([1, 6, 6])
tensor([[[ 1,  1,  2,  3,  4,  4],[ 1,  1,  2,  3,  4,  4],[ 5,  5,  6,  7,  8,  8],[ 9,  9, 10, 11, 12, 12],[13, 13, 14, 15, 16, 16],[13, 13, 14, 15, 16, 16]]])

从输出易得,确实是将边缘进行了复制,这样做可以使得我们对张量进行扩充填充后,张量的边缘信息不变:图像处理时,这种机制会经常用到。

如果修改pad参数,会修改拷贝的列数吗?我们对填充语句做如下修改:

paddata3 = nn.functional.pad(data, (2, 1, 4, 1), mode="replicate")

输出:

torch.Size([1, 4, 4])
tensor([[[ 1,  2,  3,  4],[ 5,  6,  7,  8],[ 9, 10, 11, 12],[13, 14, 15, 16]]])
torch.Size([1, 9, 7])
tensor([[[ 1,  1,  1,  2,  3,  4,  4],[ 1,  1,  1,  2,  3,  4,  4],[ 1,  1,  1,  2,  3,  4,  4],[ 1,  1,  1,  2,  3,  4,  4],[ 1,  1,  1,  2,  3,  4,  4],[ 5,  5,  5,  6,  7,  8,  8],[ 9,  9,  9, 10, 11, 12, 12],[13, 13, 13, 14, 15, 16, 16],[13, 13, 13, 14, 15, 16, 16]]])

从输出可以看出,不论你怎么修改pad参数元组,被拷贝的总是一个像素宽的边缘。而你更改的填充宽度如果大于1,至于将1像素边缘复制多次罢了。

5.4 circular模式

该模式称为循环填充模式,它是怎么干的呢?以2维矩阵上下左右均填充1个像素为例,它的填充值取自其对立面:左侧填充列的值=原矩阵最右侧1列的值,右侧填充列的值=原矩阵最左侧1列的值;上下同理,直接看代码:

import torch
import torch.nn as nndata = torch.tensor([[[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12],[13, 14, 15, 16]
]])print(data.size())
print(data)
paddata4 = nn.functional.pad(data, (1, 1, 1, 1), mode="circular", value=0)
print(paddata4.size())
print(paddata4)

输出:

torch.Size([1, 4, 4])
tensor([[[ 1,  2,  3,  4],[ 5,  6,  7,  8],[ 9, 10, 11, 12],[13, 14, 15, 16]]])
torch.Size([1, 6, 6])
tensor([[[16, 13, 14, 15, 16, 13],[ 4,  1,  2,  3,  4,  1],[ 8,  5,  6,  7,  8,  5],[12,  9, 10, 11, 12,  9],[16, 13, 14, 15, 16, 13],[ 4,  1,  2,  3,  4,  1]]])

从输出可得,我们的解释是正确的。

哪如果我要填充多个像素又是什么样的效果?我们将填充语句进行修改如下:

paddata4 = nn.functional.pad(data, (2, 3, 1, 1), mode="circular", value=0)

输出:

torch.Size([1, 4, 4])
tensor([[[ 1,  2,  3,  4],[ 5,  6,  7,  8],[ 9, 10, 11, 12],[13, 14, 15, 16]]])
torch.Size([1, 6, 9])
tensor([[[15, 16, 13, 14, 15, 16, 13, 14, 15],[ 3,  4,  1,  2,  3,  4,  1,  2,  3],[ 7,  8,  5,  6,  7,  8,  5,  6,  7],[11, 12,  9, 10, 11, 12,  9, 10, 11],[15, 16, 13, 14, 15, 16, 13, 14, 15],[ 3,  4,  1,  2,  3,  4,  1,  2,  3]]])

读者可以自行体会一下,该模式下,它的多像素填充有什么规律。

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

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

相关文章

Git的基本使用方法

Git的基本使用方法 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将深入探讨Git的基本使用方法,Git作为目前最流行的版本控制系统之一&…

Day 48 消息队列集群RabbitMQ

消息队列集群-RabbitMQ 一、消息中间件 中间件 tomcat java web中间件 web容器 mysql php php mysql uwsgi python mysql mycat 数据库中间件 rabbitMQ 消息中间件 1、简介 MQ 全称为(Message Queue消息队列)。是一种应用程序对应用程序的通信方…

【全球首个开源AI数字人】DUIX数字人-打造你的AI伴侣!

目录 1. 引言1.1 数字人技术的发展背景1.2 DUIX数字人项目的开源意义1.3 DUIX数字人技术的独特价值1.4 本文目的与结构 2. DUIX数字人概述2.1 定义与核心概念2.2 硅基智能与DUIX的关系2.3 技术架构2.4 开源优势2.5 应用场景2.6 安全与合规性 3. DUIX数字人技术特点3.1 开源性与…

【Java Gui精美界面】IDEA安装及配置SwingX

SwingX 是一个基于 Swing 的 Java GUI 库,旨在为 Swing 提供额外的功能和丰富的组件 特点描述基于 Swing继承了 Swing 的所有特性和功能。丰富组件SwingX 提供了一组高级 UI 组件,例如 TreeTable仍在发展中不活跃的发展ing。。。支持搜索高亮如 TreeTab…

【分布式系列】分布式锁的设计与实现

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

steam社区加载异常、加载失败、无法加载、黑屏的解决方法

随着steam夏季特卖的临近,最近几天开启史低折扣的大作已经越来越少了,不过也并不是没有。最经典的知名大作文明6之前已经打到1折的骨折价了,没想到也能背刺,现在是新史低价0.5折11元,很多玩家入手后纷纷前往社区看新手…

ZABBIX-7.0LTS在线部署部署教程

ZABBIX-7.0LTS在线部署部署教程 环境: 操作系统: ubuntu 22.04zabbix-server版本: 7.0LTS系统配置[需结合监控的业务量提供配置]: 建议2C(CPU)8G(运行) 100GB(存储)架构:LNMP 第一步: 系统初始化 1.配置…

计算机网络知识整理笔记

目录 1.对网络协议的分层? 2.TCP/IP和UDP之间的区别? 3.建立TCP连接的三次握手? 4.断开TCP连接的四次挥手? 5.TCP协议如何保证可靠性传输? 6.什么是TCP的拥塞控制? 7.什么是HTTP协议? 8…

MySQL InnoDB支持几种行格式

数据库表的行格式决定了一行数据是如何进行物理存储的,进而影响查询和DML操作的性能。 在InnoDB中,常见的行格式有4种: 1、COMPACT:是MySQL 5.0之前的默认格式,除了保存字段值外,还会利用空值列表保存null…

快速傅里叶变换(Fast Fourier Transform,FFT)

快速傅里叶变换(Fast Fourier Transform,FFT)是一种算法,用于快速计算离散傅里叶变换(DFT)及其逆变换。傅里叶变换将时间或空间域的信号转换为频率域的信号,便于分析信号的频率特性。FFT显著提高…

动手学深度学习(Pytorch版)代码实践 -卷积神经网络-20填充与步幅

20填充与步幅 import torch from torch import nn# 此函数初始化卷积层权重,并对输入和输出提高和缩减相应的维数 def comp_conv2d(conv2d, X):# 这里的(1,1)表示批量大小和通道数都是1#将输入张量 X 的形状调整为 (1, 1, height,…

Grafana-11.0.0 在线部署教程

Grafana-11.0.0 在线部署教程 环境: 操作系统: ubuntugrafana版本: 11.0.0 (建议不要按照最新版)grafana要求的系统配置不高,建议直接部署在监控服务器上,比如zabbix服务器、prometheus服务器…

从菌群代谢到健康影响——认识肠道丙酸和丁酸

谷禾健康 短链脂肪酸这一词经常出现在谷禾的文章和报告中,那你真的了解短链脂肪酸吗?短链脂肪酸(SCFA)主要是肠道微生物群在结肠内通过发酵碳水化合物(包括膳食和内源性碳水化合物,主要是抗性淀粉和膳食纤维)和一些微生物可利用的蛋白质而产生…

光线追踪:原理与实现

版权声明 本文为“优梦创客”原创文章,您可以自由转载,但必须加入完整的版权声明文章内容不得删减、修改、演绎本文视频版本:见文末 各位同学大家好,今天我要给大家分享的是光线追踪的原理和实现大家知道在过往很多年里面&#x…

超简单的nodejs使用log4js保存日志到本地(可直接复制使用)

引入依赖 npm install log4js 新建配置文件logUtil.js const log4js require(log4js);// 日志配置 log4js.configure({appenders: {// 控制台输出consoleAppender: { type: console },// 文件输出fileAppender: {type: dateFile,filename: ./logs/default, //日志文件的存…

如何从0构建一款类似pytest的工具

Pytest主要模块 Pytest 是一个强大且灵活的测试框架,它通过一系列步骤来发现和运行测试。其核心工作原理包括以下几个方面:测试发现:Pytest 会遍历指定目录下的所有文件,找到以 test_ 开头或 _test.py 结尾的文件,并且…

python 实例002 - 数据转换

题目: 有一组用例数据如下: cases [[case_id, case_title, url, data, excepted],[1, 用例1, www.baudi.com, 001, ok],[4, 用例4, www.baudi.com, 002, ok],[2, 用例2, www.baudi.com, 002, ok],[3, 用例3, www.baudi.com, 002, ok],[5, 用例5, www.ba…

MS-Net: A Multi-Path Sparse Model for Motion Prediction in Multi-Scenes

MS-Net: A Multi-Path Sparse Model for Motion Prediction in Multi-Scenes 基本信息 期刊:IEEE ROBOTICS AND AUTOMATION LETTERS (IF 4.6 SCI3区)单位:同济大学,上海人工智能实验室时间:2023年12月数据…

架构师必知的绝活-JVM调优

前言 为什么要学JVM? 首先:面试需要 了解JVM能帮助回答面试中的复杂问题。面试中涉及到的JVM相关问题层出不穷,难道每次面试都靠背几百上千条面试八股? 其次:基础知识决定上层建筑 自己写的代码都不知道是怎么回事&a…

精准图像识别:算法与应用的双重突破

精准图像识别在近年来取得了算法与应用的双重突破,这些突破不仅推动了技术的发展,也极大地拓宽了图像识别的应用领域。以下是对这些突破的详细概述: 算法突破 深度学习技术的崛起:深度学习,特别是卷积神经网络&#…