1. 引言

  最近在刷开源的Pytorch版动手学深度学习,里面谈到几个高级选择函数,如index_select,masked_select,gather等。这些函数大多很容易理解,但是对于gather函数,确实有些难理解,官方文档开始也看得一脸懵,感觉不太直观。下面谈谈我对这几个函数的一些理解。

2. 维度的理解

  对于numpy和pytorch,其数组在做维度运算上刚开始可能会给人一种直观上的误解,以numpy求矩阵某个维度的最大值为例(pytorch的理解也是一样的)

import numpy as np
a = np.arange(1, 13).reshape(3, 4)
"""
result:
a = [[1, 2, 3, 4],
[5, 6, 7, 8,],
[9, 10, 11, 12]]
""" # 对a维度0求最大值
a.max(axis = 0)
"""
result:
[9, 10, 11, 12]
""" # 对a维度1求最大值
a.max(axis = 1)
"""
result:
[4, 8, 12]
"""

  如果对a矩阵在维度0上找最大值,根据我们直观上的经验应该是[4, 8, 12]。即从[1, 2, 3, 4]找到4,从[5, 6, 7, 8]找到8,从[9, 10, 11, 12]找到12。但是从上面结果来看,numpy运算却给了我们直观上认为是列最大值的结果[9, 10, 11, 12]。

  实际numpy(pytorch)运算应该理解为往给定的维度进行移动运算。还是以维度0为例,维度0上有3个向量,分别为[1, 2, 3, 4],[5, 6, 7, 8]和[9, 10, 11, 12]。往维度0移动,即[1, 2, 3, 4]和[5, 6, 7, 8]逐元素计算最大值,得到[5, 6, 7, 8],再和[9, 10, 11, 12]运算得到结果[9, 10, 11, 12]。

  另外,对于维度为3的数组,在numpy和pytorch中,应该把维度0理解为通道数,维度1和维度2才是对应高和宽。如果是3维数组对应着用于多输入通道和单输出通道的卷积核(维度为U x V x D),那么4维数组就对应着用于多输入通道和多输出通道的卷积核(维度为U x V x D x P),此时,维度0则为多通道卷积核数量的方向,维度1为通道数,维度2和3才是分别对应高和宽。

3. gather函数

pytorch和numpy中许多函数都涉及维度运算,gather也不例外,但是它相对于其他函数更难理解。依然先来看一个例子

import torch
a = torch.arange(1, 16).reshape(5, 3)
"""
result:
a = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12],
[13, 14, 15]]
""" # 定义两个index
b = torch.tensor([[0, 1, 2], [2, 3, 4], [0, 2, 4]])
c = torch.tensor([[1, 2, 0, 2, 1], [1, 2, 1, 0, 0]]) # axis=0
output1 = a.gather(0, b)
"""
result:
[[1, 5, 9],
[7, 11, 15],
[1, 8, 15]]
""" # axis=1
output2 = a.gather(1, c)
"""
result:
[[2, 3, 1, 3, 2],
[5, 6, 5, 4, 4]]
"""

上面的例子看起来可能有点复杂,我们来一步步的分析它,先从gather维度为0开始讲起。

  1. a.gather(0, b)分为3个部分,a是需要被提取元素的矩阵,0代表的是提取的维度为0,b是提取元素的索引

    • 其中规定b和a是同维张量,即a是2维张量,b也必须是2维张量
  2. 0除了代表往维度0的方向提取元素外,还有一个特权---提取结果output可以在这个维度上的长度与a不同。打个比方,a现在的shape为(5, 3),那么提取结果output1的shape可以是(1,3),(2, 3),甚至(n, 3)。具体维度0的长度到底为多少由b来决定。
  3. 根据0的特权,导致了给定的b张量除了维度0外,其他的维度大小必须和a一样。其中张量b实际上包含以下两个信息
    • b可以利用除用于gather的维度(此处为维度0)外的维度来定位出唯一一个向量,也就是a[:, ?](三维度也是同理的,有a[:, ?1, ?2]),?的取值范围为a同维度的index。
    • 对于上述定位出的向量,通过b中的元素来定位提取向量中的哪一个元素。
    • 上面说得可能有点抽象,实际上b中的每个元素都能在a中提取出一个元素。举个具体点的例子,按照上面所说的,b[0, 0]可以提取a中的一个元素。对于b[0,0],除了维度0外,可以通过维度1来定位出唯一一个向量a[:, 0]。因为b[0, 0]的元素为0,即提取的是a[:, 0]的第0个元素---1,并将其作为output1[0, 0]的提取结果。

      下图给出了维度0和维度1,gather运算的图示

对于3维或者更高维度的张量gather的原理也是一样的

4. index_select函数

其他的高级选择函数都比较容易理解,这里简单的提一下。torch.index_select主要是根据传入的tensor来往给定的axis方向来选取张量

import torch
a = torch.arange(9).reshape(3, 3)
torch.index_select(a, 0, torch.tensor([0, 2]))
"""
result:
[[0, 1, 2],
[6, 7, 8]]
"""

5. masked_select函数

实际上就是通过掩码条件来选择元素,像torch.masked_select(x, x>0.5),实际上是和x[x>0.5]等价的,最后返回的是一维张量

import torch
a = torch.rand(5, 3) # 结果和a[a > 0.5]等价
torch.masked_select(a, a>0.5)

6. nonzero函数

找到非零元素的index

import torch
a = torch.eye(3)
torch.nonzero(a) """
result: 对应着非零元素的index
[[0, 0],
[1, 1],
[2, 2]]
"""

理解pytorch几个高级选择函数(如gather)的更多相关文章

  1. 小白学习之pytorch框架(4)-softmax回归(torch.gather()、torch.argmax()、torch.nn.CrossEntropyLoss())

    学习pytorch路程之动手学深度学习-3.4-3.7 置信度.置信区间参考:https://cloud.tencent.com/developer/news/452418 本人感觉还是挺好理解的 交 ...

  2. 关于Pytorch的二维tensor的gather和scatter_操作用法分析

    看得不明不白(我在下一篇中写了如何理解gather的用法) gather是一个比较复杂的操作,对一个2维tensor,输出的每个元素如下: out[i][j] = input[index[i][j]] ...

  3. 理解PyTorch的自动微分机制

    参考Getting Started with PyTorch Part 1: Understanding how Automatic Differentiation works 非常好的文章,讲解的非 ...

  4. 理解pytorch中的softmax中的dim参数

    import torch import torch.nn.functional as F x1= torch.Tensor( [ [1,2,3,4],[1,3,4,5],[3,4,5,6]]) y11 ...

  5. [深度学习] pytorch学习笔记(1)(数据类型、基础使用、自动求导、矩阵操作、维度变换、广播、拼接拆分、基本运算、范数、argmax、矩阵比较、where、gather)

    一.Pytorch安装 安装cuda和cudnn,例如cuda10,cudnn7.5 官网下载torch:https://pytorch.org/ 选择下载相应版本的torch 和torchvisio ...

  6. 《深入理解Java虚拟机:JVM高级特性与最佳实践》【PDF】下载

    <深入理解Java虚拟机:JVM高级特性与最佳实践>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230062566 内容简介 作为一位 ...

  7. 什么是pytorch(1开始)(翻译)

    Deep Learning with PyTorch: A 60 Minute Blitz 作者: Soumith Chintala 部分翻译:me 本内容包含: 在高级层面理解pytorch的ten ...

  8. 万字综述,核心开发者全面解读PyTorch内部机制

    斯坦福大学博士生与 Facebook 人工智能研究所研究工程师 Edward Z. Yang 是 PyTorch 开源项目的核心开发者之一.他在 5 月 14 日的 PyTorch 纽约聚会上做了一个 ...

  9. 【小白学PyTorch】15 TF2实现一个简单的服装分类任务

    [新闻]:机器学习炼丹术的粉丝的人工智能交流群已经建立,目前有目标检测.医学图像.时间序列等多个目标为技术学习的分群和水群唠嗑的总群,欢迎大家加炼丹兄为好友,加入炼丹协会.微信:cyx64501661 ...

随机推荐

  1. log4j升级到log4j2

    log4j升级到log4j2 1.导入依赖 log4j2应尽量使用同一版本,否则可能出现不兼容的情况 <!-- log4j2 start --> <!-- log4j-1.2-api ...

  2. shrio总结

    AccessControlFilter(https://www.jianshu.com/p/9bfa22b0e905) SpringBoot+Shiro学习之自定义拦截器管理在线用户(踢出用户)   ...

  3. typedef的陷阱

    typedef定义了一种类型的新别名,不同于宏,它不是简单的字符串替换.比如: 先定义: typedef char* PSTR; 然后: int mystrcmp(const PSTR, const ...

  4. LuaProfiler

    Lua Profiler机制的源码解析 https://www.jianshu.com/p/f6606b27e9de

  5. nginx安装第三方模块echo

    要使用第三方模块ngx_echo的功能,请重新配置添加到nginx插件中 ##下载第三方模块 wget https://github.com/openresty/echo-nginx-module/a ...

  6. 基础Html重点——防健忘

    一.head标签重点 <head> <meta charset="utf-8"> <title>第二天课</title> <! ...

  7. Vue的优缺点

    使用vue.js做开发快两年了,对vue的优缺点有一点自己的见解,跟大神比不了,但是面试基本够用 vue在国内能被广泛使用的首要原因是它是基于mvvm框架做开发的,mvvm是前端开发中一种很有影响力的 ...

  8. 矩阵LU分解的MATLAB与C++实现

    一:矩阵LU分解 矩阵的LU分解目的是将一个非奇异矩阵\(A\)分解成\(A=LU\)的形式,其中\(L\)是一个主对角线为\(1\)的下三角矩阵:\(U\)是一个上三角矩阵. 比如\(A= \beg ...

  9. HTML常用实体字符参考手册

    最常用的字符实体 显示结果 描述 实体名称 实体编号   空格     < 小于号 < < > 大于号 > > & 和号 & & " ...

  10. 抽象工厂模式详解 —— head first 设计模式

    项目实例 假设你有一家 pizza 店,你有很多种 pizza,要在系统中显示你所有 pizza 种类.实现这个功能并不难,使用普通方式实现: public class PizzaStore { Pi ...