前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PyTorch2:张量的运算

PyTorch2:张量的运算

作者头像
小胡胡说
修改2020-08-06 17:33:37
2.5K0
修改2020-08-06 17:33:37
举报
文章被收录于专栏:小胡学编程小胡学编程

1.Creation操作


1.1 转化一个已有数组


把一个已有数组转化成Tensor,通常有四种方法:

  • torch.Tensor()
代码语言:javascript
复制
array = np.arange(5)
# 方法 1
>>> tensor1 = torch.Tensor(array)
>>> print(tensor1)
tensor([0., 1., 2., 3., 4.])
>>> print(tensor1.dtype)
torch.float32
  • torch.tensor(data, dtype=None, device=None, requires_grad=False, pin_memory=False)
代码语言:javascript
复制
array = np.arange(5)
# 方法 2
>>> tensor2 = torch.tensor(array)
>>> print(tensor2)
tensor([0, 1, 2, 3, 4])
>>> print(tensor2.dtype)
torch.int64
  • torch.from_numpy(ndarray)
代码语言:javascript
复制
array = np.arange(5)
# 方法 3
>>> tensor3 = torch.from_numpy(array)
>>> print(tensor3)
tensor([0, 1, 2, 3, 4])
>>> print(tensor3.dtype)
torch.int64
  • torch.as_tensor(data, dtype=None, device=None)
代码语言:javascript
复制
array = np.arange(5)
# 方法 4
>>> tensor4 = torch.as_tensor(array)
>>> print(tensor4)
tensor([0, 1, 2, 3, 4])
>>> print(tensor14.dtype)
torch.int64

可以看出,torch.Tensor()没有保留数值类型,其它三个都保留了。这是因为torch.Tensor()实际上是一个类,传入的数据需要“初始化”;其它三个都是函数,而通过torch.Tensor()生成的张量的数据类型是由一个环境变量决定的,这个环境变量可以通过torch.set_default_tensor_type(t)这个函数来设定。

那么新的张量与原来的数组是什么关系呢?

代码语言:javascript
复制
>>> tensor1[0] = 100
>>> print(array)
[0 1 2 3 4]
>>> tensor2[1] = 100
>>> print(array)
[0 1 2 3 4]
>>> tensor3[2] = 100
>>> print(array
[  0   1 100   3   4]
>>> tensor4[3] = 100
>>> print(array)
[  0   1 100 100   4]

torch.Tensor()torch.tensor() 复制了原数组的数据,

torch.from_numpy()torch.as_tensor() 直接与原数组共享数据。

综上所述,

需要创建新张量时,推荐使用 torch.tensor()

需要避免复制时,推荐使用 torch.as_tensor()

理由如下:

  1. torch.tensor()torch.as_tensor() 的 API 更丰富,可控制的属性更多;
  2. torch.Tensor() 会改变数据类型,torch.from_numpy() 可接受的变量有限。

1.2 其他创建张量的方法


1.2.1 创建全部值为定值的函数


torch.zeros(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) # 全为 0

torch.ones(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) # 全为 1

torch.empty(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False, pin_memory=False) # 全为一个随机小数

torch.full(size, fill_value, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) # 全为一个定值

参数说明:

  • *size:新张量的形状
  • out:输出的已有张量名称
  • dtype:数据类型
  • layout:内存里的存储方式
  • device:存储设备
  • require_grad:是否追踪导数

最后一个函数 torch.empty 生成的所谓“小数”真的是是非常小的、接近 0 的数:

代码语言:javascript
复制
>>> torch.empty(1)
tensor([2.0890e+20])

还可以根据已有的张量,按照该张量的形状生成相同形状的新张量:

代码语言:javascript
复制
torch.zeros_like(input, dtype=None, layout=None, device=None, requires_grad=False, memory_format=torch.preserve_format)

torch.ones_like(input, dtype=None, layout=None, device=None, requires_grad=False, memory_format=torch.preserve_format)

torch.empty_like(input, dtype=None, layout=None, device=None, requires_grad=False, memory_format=torch.preserve_format)

torch.full_like(input, dtype=None, layout=None, device=None, requires_grad=False, memory_format=torch.preserve_format)

举个例子,假设 a 是一个 (2, 2) 的矩阵张量:

代码语言:javascript
复制
>>> a = torch.ones(2, 2)
>>> b = torch.zeros_like(a)
>>> print(a, b)
tensor([[1., 1.],
        [1., 1.]]) 
tensor([[0., 0.],
        [0., 0.]])

1.2.2 创建一个元素间隔为常量的函数


torch.arange(start=0, end, step=1, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)

创建一个 1 维张量,范围为 [start, end)步进step

代码语言:javascript
复制
>>> torch.arange(4)
tensor([0, 1, 2, 3])

torch.linspace(start, end, steps=100, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)

创建一个 1 维张量,范围为 [start, end]步数step

代码语言:javascript
复制
>>> torch.linspace(0, 5, 6)
tensor([0., 1., 2., 3., 4., 5.])

torch.logspace(start, end, steps=100, base=10.0, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)

创建一个 1 维张量,范围为 ,步数step

代码语言:javascript
复制
>>> torch.logspace(-10, 10, 5, 10)
tensor([1.0000e-10, 1.0000e-05, 1.0000e+00, 1.0000e+05, 1.0000e+10])

1.2.3 创建一个对角张量


torch.eye(n, m=None, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)

对角张量指张量的对角线上的元素为 1,其余值为 0 的张量。

代码语言:javascript
复制
>>> torch.eye(3)
tensor([[ 1.,  0.,  0.],
        [ 0.,  1.,  0.],
        [ 0.,  0.,  1.]])

2. indexing,slicing,joining 及 mutating 操作


2.1 indexing操作


pytorch支持python式的索引操作

代码语言:javascript
复制
>>> a = torch.tensor([[1, 2, 3], [4, 5, 6]])
>>> a[0][1]
tensor(2)

torch.index_select(input, dim, index, out=None) 根据指定索引在指定轴上索引。

代码语言:javascript
复制
>>> a = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> indices = torch.tensor([0, 2])
>>> torch.index_select(a, 0, indices) # 选取第 0 轴上第 0,2 个元素
tensor([[1, 2, 3],
        [7, 8, 9]])

torch.masked_select(input, mask, out=None) 在 1 位张量上以布尔值进行索引。

代码语言:javascript
复制
>>> a = torch.tensor([0, 1, 2, 3])
>>> mask = a.lt(2) # 以“小于 2”为条件创建布尔值
>>> torch.masked_select(a, mask)
tensor([0, 1])

2.2 slicing 操作


Python 原生 slicing 操作

代码语言:javascript
复制
>>> a = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> a[0:2, :]
tensor([[1, 2, 3],
        [4, 5, 6]])

torch.split(tensor, split_size_or_sections, dim=0)

按照给定维度进行切片。

如果 split_size_or_sections 是一个整数,则以该数字为单位进行切片。如果张量在该维的长度不能被整除,最后一片的尺寸会小。

如果 split_size_or_sections 是一个列表,张量会按每个元素值切片。

代码语言:javascript
复制
>>> a = torch.arange(10)
>>> torch.split(a, 2, 0)
(tensor([0, 1]),
 tensor([2, 3]),
 tensor([4, 5]),
 tensor([6, 7]),
 tensor([8, 9]))
>>> torch.split(a, [3, 7], 0)
(tensor([0, 1, 2]), tensor([3, 4, 5, 6, 7, 8, 9]))

torch.chunk(input, chunks, dim=0)

在给定维度上将张量切成 chunk 份。若张量长度不能整除,则最后一份的长度会小。

代码语言:javascript
复制
>>> torch.chunk(a, 3, 0)
(tensor([0, 1, 2, 3]), tensor([4, 5, 6, 7]), tensor([8, 9]))

2.3 joining 操作


torch.cat(tensors, dim=0, out=None)

在不增加维度的情况下聚合若干个张量。

代码语言:javascript
复制
>>> x = torch.arange(6).reshape(2, 3)
>>> torch.cat([x, x], dim=0) # 在第 0 轴聚合
tensor([[0, 1, 2],
        [3, 4, 5],
        [0, 1, 2],
        [3, 4, 5]])
>>> torch.cat([x, x], dim=1) # 在第 1 轴聚合
tensor([[0, 1, 2, 0, 1, 2],
        [3, 4, 5, 3, 4, 5]])

torch.stack(tensors, dim=0, out=None)

将两个张量叠加到一起,这会产生一个新的轴。

代码语言:javascript
复制
>>> torch.stack([x, x], dim=0)
tensor([[[0,1,2],
         [3,4,5]],
        [[0,1,2],
         [3,4,5]]])
       
>>> torch.stack([x, x], dim=1)
tensor([[[0,1,2],[0,1,2]],
        [[3,4,5],[3,4,5]]])

3.math操作


3.1 pointwize 操作


pointwise 指的是元素对元素。比如

代码语言:javascript
复制
A = torch.Tensor([a1, a2])
A + 2. = torch.Tensor([a1+2., a2+2.])

3.1.1 张量的四则运算


代码语言:javascript
复制
torch.add(input, other, *, alpha=1, out=None) # 相加
torch.sub(input, other, out=None) # 相减
torch.mul(input, other, out=None) # 相乘
torch.div(input, other, out=None) # 相除

torch.add()比较特殊,它遵循如下公式:

out=input+alpha*other

例如:torch.add(torch.tensor(1), torch.tensor(2), torch.tensor(3))的运算实际上是1+2*3=7。

还有特殊的运算:

torch.addcdiv(input, tensor1, tensor2, *, value=1, out=None),对应的运算规则为:

out=input+value*tensor1/tensor2

torch.addcmul(input, tensor1, tensor2, *, value=1, out=None),对应的运算规则为:

out=input+value*tensor1*tensor2

3.1.2 指数、对数、幂函数的运算


两个指数函数

  • torch.exp(input, out=None) 自然指数运算:
  • torch.pow(input, exponent, out=None) 任意指数运算:

四个对数函数

  • torch.log(input, out=None) 自然对数运算:
  • torch.log1p(input, out=None) 自然对数运算:
  • torch.log2(input, out=None) 以 2 为底的对数运算:
  • torch.log10(input, out=None) 以 10 为底的对数运算:

3.1.3 变换函数


  • torch.abs(input, out=None):返回张量的绝对值。
  • torch.ceil(input, out=None):对张量向上取整。
  • torch.floor(input, out=None):对张量向下取整。
  • torch.floor_divide(input, other, out=None):张量相除后向下取整。
  • torch.fmod(input, other, out=None):对张量取余。
  • torch.neg(input, out=None):取张量的相反数。
  • torch.round(input, out=None):对张量取整。
  • torch.sigmoid(input, out=None):对张量进行 sigmoid 计算。
  • torch.sqrt(input, out=None):对张量取平方根。
  • torch.square(input, out=None):对张量平方。
  • torch.sort(input, dim=-1, descending=False, out=None):返回张量的排序结果。

3.1.4 三角函数


  • torch.sin(input, out=None):正弦
  • torch.cos(input, out=None):余弦
  • torch.tan(input, out=None):正切

3.2 降维函数


所谓降维,就是某个维度经过运算后返回值是一个张量。

如果下述函数中的 dim 变量没有显式赋值,则对整个张量进行计算,返回一个值;若 dim 被显性赋值,则对该 dim 内的每组数据分别进行运算。

keepdim 若为 True,每个运算结果为一个一维张量,实际上没有降维。

  • torch.argmax(input, dim, keepdim=False):返回张量内最大元素的索引。
  • torch.argmin(input, dim, keepdim=False, out=None):返回张量内最小元素的索引。

例子:

代码语言:javascript
复制
>>> a = torch.tensor([[1, 3, 2, 4], [9, 8, 7, 6]])
>>> torch.argmax(a, dim=1)
tensor([3, 0])
  • torch.max(input, dim, keepdim=False, out=None):返回在指定维度内进行比较后的最大值。
  • torch.min(input, dim, keepdim=False, out=None):返回在指定维度内进行比较后的最小值。
  • torch.mean(input, dim, keepdim=False, out=None):返回张量内张量的平均数。
  • torch.median(input, dim=-1, keepdim=False, out=None):返回张量内张量的中位数。
  • torch.prod(input, dim, keepdim=False, dtype=None):返回张量内元素的乘积。
  • torch.std(input, dim, unbiased=True, keepdim=False, out=None):返回张量内的标准差。
  • torch.sum(input, dim, keepdim=False, dtype=None):返回张量内元素的和。
  • torch.var(input, dim, keepdim=False, unbiased=True, out=None):返回张量内元素的方差。 例子:
代码语言:javascript
复制
>>> a = torch.ones((4, 3)) # 4 x 3 的全 1 矩阵
>>> torch.sum(a) # 没有维度,对所有元素求和
tensor(12.)
>>> torch.sum(a, dim=1)
tensor([3., 3., 3., 3.])
>>> torch.sum(a, dim=1, keepdim=True)
tensor([[3.],
        [3.],
        [3.],
        [3.]])

3.3 比较函数


返回索引的函数:

  • torch.argsort(input, dim=-1, descending=False) 返回在指定维度中第几大/小索引的张量,默认升序比较最后一维:
代码语言:javascript
复制
>>> a = torch.tensor([[1, 3, 2, 4], [9, 8, 7, 6]])
>>> torch.argsort(a)
tensor([[0, 2, 1, 3],
        [3, 2, 1, 0]])

既返回值,又返回索引的函数:

  • torch.sort(input, dim=-1, descending=False, out=None):对张量进行排序。
代码语言:javascript
复制
>>> x = torch.randn(3, 4)
>>> sorted, indices = torch.sort(x)
>>> sorted
tensor([[-0.2162,  0.0608,  0.6719,  2.3332],
        [-0.5793,  0.0061,  0.6058,  0.9497],
        [-0.5071,  0.3343,  0.9553,  1.0960]])
>>> indices
tensor([[ 1,  0,  2,  3],
        [ 3,  1,  0,  2],
        [ 0,  3,  1,  2]])
  • torch.topk(input, k, dim=None, largest=True, sorted=True, out=None):返回最大/最小的 k 个值和它们的索引。
代码语言:javascript
复制
>>> x = torch.arange(1., 6.)
>>> x
tensor([ 1.,  2.,  3.,  4.,  5.])
>>> torch.topk(x, 3)
torch.return_types.topk(values=tensor([5., 4., 3.]), indices=tensor([4, 3, 2]))
  • torch.cummax(input, dim, out=None):值与索引为当前位置以前的最大值和最大值的索引。
  • torch.cummin(input, dim, out=None):值与索引为当前位置以前的最小值和最小值的索引。
代码语言:javascript
复制
>>> a = torch.randn(10)
>>> a
tensor([-0.3449, -1.5447,  0.0685, -1.5104, -1.1706,  0.2259,  1.4696, -1.3284,
     1.9946, -0.8209])
>>> torch.cummax(a, dim=0)
torch.return_types.cummax(
    values=tensor([-0.3449, -0.3449,  0.0685,  0.0685,  0.0685,  0.2259,  1.4696,  1.4696,
     1.9946,  1.9946]),
    indices=tensor([0, 0, 2, 2, 2, 5, 6, 6, 8, 8]))
    
>>> a = torch.randn(10)
>>> a
tensor([-0.2284, -0.6628,  0.0975,  0.2680, -1.3298, -0.4220, -0.3885,  1.1762,
     0.9165,  1.6684])
>>> torch.cummin(a, dim=0)
torch.return_types.cummin(
    values=tensor([-0.2284, -0.6628, -0.6628, -0.6628, -1.3298, -1.3298, -1.3298, -1.3298,
    -1.3298, -1.3298]),
    indices=tensor([0, 1, 1, 1, 4, 4, 4, 4, 4, 4]))

比较两个张量的元素,返回包含每个元素间比较的最大/小值:

  • torch.max(input, other, out=None)
  • torch.min(input, other, out=None)

这两个函数与上面的降维函数中的同名函数的区别在于上面的两个函数的输入是一个张量,这里是两个。

代码语言:javascript
复制
>>> a = torch.tensor([[1, 3, 96, 97], [98, 99, 7, 6]])
>>> b = torch.tensor([[100, 101, -1, -2], [-3, -4, 102, 103]])

>>> torch.max(a, b)
tensor([[100, 101,  96,  97],
        [ 98,  99, 102, 103]])
>>> torch.min(a, b)
tensor([[ 1,  3, -1, -2],
        [-3, -4,  7,  6]])

两个张量比较是否相同,返回一个布尔值:torch.equal(input, other)

代码语言:javascript
复制
>>> torch.equal(torch.tensor([1, 2]), torch.tensor([1, 2]))
True

两个张量的元素之间互相比较,每个比较返回一个布尔值,最终返回一个与被比较元素形状相同的张量:

  • torch.eq(input, other, out=None):如果 input 中的元素等于 output 中的对应元素,返回 True
  • torch.ge(input, other, out=None):如果 input 中的元素大于等于 output 中的对应元素,返回 True
  • torch.gt(input, other, out=None):如果 input 中的元素大于 output 中的对应元素,返回 True
  • torch.le(input, other, out=None):如果 input 中的元素小于等于 output 中的对应元素,返回 True
  • torch.lt(input, other, out=None):如果 input 中的元素小于 output 中的对应元素,返回 True
代码语言:javascript
复制
>>> a = torch.tensor([[1, 3, 96, 97], [98, 99, 7, 6]])
>>> c = torch.tensor([[1, 3, 5, 7], [98, 99, 100, 101]])
>>> torch.eq(a, c)
tensor([[ True,  True, False, False],
        [ True,  True, False, False]])

4. 随机函数


所有随机函数都有一个 generator 变量用于指定随机种子。

  • torch.manual_seed(seed):设置随机种子。
  • torch.bernoulli(input, *, generator=None, out=None):生成服从伯努利分布(二项式分布)的张量。
代码语言:javascript
复制
>>> a = torch.empty(2, 2).uniform_(0, 1)
>>> a
tensor([[0.0117, 0.2281],
        [0.8750, 0.9974]])
>>> torch.bernoulli(a)
tensor([[0., 0.],
        [1., 1.]])
  • torch.multinomial(input, num_samples, replacement=False, *, generator=None, out=None):生成符合多项式分布的张量。input 为多项式分布的权重,当 replacementFalse 时,num_samples 的长度必须小于 input
代码语言:javascript
复制
>>> weights = torch.tensor([1., 2., 3., 4.])
>>> torch.multinomial(weights, 10, replacement=True)
tensor([1, 2, 2, 2, 3, 2, 2, 3, 0, 2])
  • torch.normal(mean, std, size, *, out=None):生成服从均值为 mean,方差为 std 的正态分布张量。meanstd 可以省略一个,若想同时省略请使用 torch.randn 函数。
代码语言:javascript
复制
>>> torch.normal(2, 1, [2, 2])
tensor([[1.7697, 2.2627],
        [2.0743, 2.1683]])
  • torch.poisson(input *, generator=None):生成一个形状与 input 相同,服从泊松分布[1]的张量。
代码语言:javascript
复制
>>> torch.poisson(torch.tensor([2., 2.]))
tensor([1., 4.])
  • torch.rand(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False):生成一个范围为 的均匀分布的张量。
代码语言:javascript
复制
>>> torch.rand((2, 2))
tensor([[0.2255, 0.5614],
        [0.7037, 0.2410]])
  • torch.randn(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False):生成一个均值为 0,方差为 1 的标准正态分布的张量。
代码语言:javascript
复制
>>> torch.randn((2, 2))
tensor([[ 1.2622, -1.3420],
        [-0.2331,  0.6151]])
  • torch.randint(low=0, high, size, *, generator=None, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False):生成一个范围为 内取整数的均匀分布的张量。
代码语言:javascript
复制
>>> torch.randint(10, (2, 2))
tensor([[6, 2],
        [2, 3]])
  • torch.randperm(n, out=None, dtype=torch.int64, layout=torch.strided, device=None, requires_grad=False):返回一个经过随机打乱顺序的张量。
代码语言:javascript
复制
>>> torch.randperm(10)
tensor([8, 9, 5, 3, 2, 1, 0, 7, 4, 6])

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.Creation操作
    • 1.1 转化一个已有数组
      • 1.2 其他创建张量的方法
        • 1.2.1 创建全部值为定值的函数
        • 1.2.2 创建一个元素间隔为常量的函数
        • 1.2.3 创建一个对角张量
    • 2. indexing,slicing,joining 及 mutating 操作
      • 2.1 indexing操作
        • 2.2 slicing 操作
          • 2.3 joining 操作
          • 3.math操作
            • 3.1 pointwize 操作
              • 3.1.1 张量的四则运算
              • 3.1.2 指数、对数、幂函数的运算
              • 3.1.3 变换函数
              • 3.1.4 三角函数
            • 3.2 降维函数
              • 3.3 比较函数
                • 既返回值,又返回索引的函数:
                • 比较两个张量的元素,返回包含每个元素间比较的最大/小值:
                • 两个张量比较是否相同,返回一个布尔值:torch.equal(input, other)
            • 4. 随机函数
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档