文章目录

  • 创建
  • empty、zeros、ones
  • `new_*` : new_ones
  • rand / randn / randperm / randint / randn_like
  • normal
  • uniform_
  • eye
  • 创建列表,类似 numpy 中的 arange
  • 创建等差数列 linspace
  • logspace 返回一维张量
  • 稠密向量
  • Tensor -- Numpy
  • 属性和方法
  • 数据类型转换
  • 判断一个对象是否为 Tensor
  • 判断一个对象是否为 PyTorch Storage 类型
  • item
  • 获取 Tensor 中元素个数 numel
  • 尺寸 shape / size
  • 修改形状 view
  • 转置
  • 将输入张量分割成相同形状的 chunks
  • 增加矩阵维度 unsqueeze
  • 降低纬度(去掉 []) squeeze
  • 获取沿着某个维度切片后 所有的切片 unbind
  • 拼接 cat
  • 按指定维度切分 chunk
  • 聚合 gather
  • 改变尺寸
  • 索引、切片
  • 高级选择函数
  • 按照索引选择目标数据 index_select
  • 选出满足条件的矩阵元素 masked_select
  • 找出矩阵中的非零元素的索引 nonzero
  • 数学计算
  • 加法
  • 乘法
  • 绝对值、向上取整、向下取整、相反数、倒数、平方根、平方根倒数
  • 每个元素加减乘除
  • 指、对、幂
  • 三角函数
  • 线性插值
  • Sigmoid 函数,sign符号函数
  • 规约计算
  • 累积 & 累和
  • 均值、中位数、众数、方差、标准差
  • p-norm 距离
  • 数值比较运算
  • 大于、小于、等于、不等于
  • 最大值、最小值 max、min
  • 排序 sort
  • topk
  • 矩阵运算
  • 对角矩阵
  • 矩阵的迹
  • 上三角矩阵和下三角矩阵
  • 矩阵的乘积 mm
  • 特征值及特征向量
  • 广播机制
  • 其它
  • 设置打印选项
  • 全局设置 Tensor 数据类型
  • 随机抽样
  • 设置随机种子
  • 伯努利分布采样
  • 多项式分布抽样
  • 标准分布抽样
  • 在 gpu/cpu 运行



详见官方文档
https://pytorch.org/docs/stable/tensors.html


创建

可以参考借鉴 numpy

  • Tensor(*sizes), 基础构造函数,指定形状
  • Tensor(data), 使用数据直接初始化,类似np.array的构造函数

  • *_like 创建与已知tensor 形状相同的 tensor。如 zeros_like, ones_like
  • new_* 创建与已知tensor 类型相同的 tensor

定义一个序列

  • empty(*sizes)
  • ones(*sizes), 全 1 Tensor,单位矩阵
  • zeros(*sizes), 全 0 Tensor
  • eye(*sizes), 对角线为1,其他为0

  • arange(s,e,step), 从s到e,步长为step
  • linspace(s,e,steps), 从s到e,均匀切分成steps份
  • rand/randn(*sizes), 均匀分布/标准正态分布
  • normal(mean,std) / uniform(from,to), 正态分布/均匀分布
  • randperm(m), 随机排列

import torch
  
# 创建二两三列的数据
t1 = torch.Tensor(2,3)
# tensor([[1.0000, 1.0000, 1.0000], [1.0000, 1.0000, 1.0000]])

# 根据数组创建
t1 = torch.Tensor([2,3])
# tensor([2., 3.])

t1 = torch.tensor([5.5, 3])  
# tensor([5.5000, 3.0000])

t1 = torch.Tensor([[2,3], [1, 4]])
# tensor([[2., 3.], [1., 4.]])

torch.Tensor & torch.tensor

  • torch.Tensor是主要的tensor类,所有的tensor都是torch.Tensor的实例。
  • 全局默认数据类型是 torch.float32
  • torch.Tensor是torch.FloatTensor的别名。
  • torch.Tensor 传入数字代表形状;
  • torch.Tensor 传入可迭代对象,表示数据。类型为模型的数据类型。
  • torch.tensor 为创建 tensor 的方法。
  • torch.tensor是一个函数,返回的是一个tensor

empty、zeros、ones

# 创建空数组;但内容不为空,有填充。
t1 = torch.empty(2, 3)    
#  tensor([[ 0.0000e+00, -2.5244e-29,  0.0000e+00], [-2.5244e-29,  1.6816e-44,  0.0000e+00]])
 
t1 = torch.zeros(2, 3, dtype=torch.long)    
#  tensor([[0, 0, 0], [0, 0, 0]])

t1 = torch.ones([2, 3])  # 等价于 torch.ones(2, 3)  
# tensor([[1., 1., 1.], [1., 1., 1.]])
  
  
# 相同size,全部元素为 0
t2 = torch.zeros_like(t1) 
# tensor([[0., 0.], [0., 0.]])

new_* : new_ones

创建与已知tensor 类型相同的 tensor

# new_* 得到数据类型相同的 tensor
tensor = torch.tensor((), dtype=torch.int32)
tensor.new_ones((2, 3))
# tensor([[1, 1, 1],
#        [1, 1, 1]], dtype=torch.int32)
  
tensor = torch.tensor((), dtype=torch.float64)
tensor.new_ones((2, 3))
# tensor([[1., 1., 1.],
#        [1., 1., 1.]], dtype=torch.float64)

rand / randn / randperm / randint / randn_like

# 生成 2*3 的随机张量,服从 [0, 1) 标准正态分布
t1 = torch.rand(2, 3) # 等价于 torch.rand([2, 3])    
#  tensor([[0.9694, 0.3158, 0.6500], [0.0295, 0.8634, 0.6159]])

torch.randn(2, 3) 
# tensor([[ 0.8246,  0.7402,  1.5977], [-0.6260,  0.6390, -0.9222]])

# 创建两行三列的随机整数 tensor,随机值区间是 [low, high)
#  torch 中一般使用 size 获取尺寸,而非 numpy 中的shape 
torch.randint(low=1, high=10, size=[2, 3])
# tensor([[8, 9, 4], [8, 4, 5]])

# 值在 [0, 8) 以内,尺寸为 [3, 5]
t1 = torch.randint(8, [3, 5])
# tensor([[1, 7, 7, 6, 7], [3, 1, 2, 1, 1], [4, 0, 5, 5, 2]])
 
np.random.permutation(10)
#  array([1, 8, 2, 6, 5, 9, 3, 7, 4, 0])
 
torch.randperm(10)
#  tensor([1, 9, 6, 3, 7, 2, 4, 5, 0, 8])

# 利用 randn_like 方法得到 相同张量尺寸 的一个新张量, 并且采用随机初始化来对其赋值
t1 = torch.randn_like(t1,  dtype=torch.float)    
# tensor([[ 0.2930,  1.1197,  1.8780], [-1.1264, -1.2930, -0.1120]])


# 指定新的数据类型
t1 = torch.randn_like(t1, dtype=torch.float)  
# tensor([[-0.5377,  0.9886, -1.2924], [ 0.1119, -0.4485,  0.9149]])

normal

normal(mean, std, *, generator=None, out=None)
该函数返回从单独的正态分布中提取的随机数的张量,该正态分布的均值是mean,标准差是std。

# 从一个标准正态分布N~(0,1),提取一个2x2的矩阵
torch.normal(mean=100.,std=1.,size=(2,2))
# tensor([[ 99.8296,  99.3379], [101.4170, 100.2711]])

# 生成平均值为0,标准差为随机的5个张量 
t1 = torch.normal(mean=0.0, std=torch.rand(5))
# tensor([ 0.0401,  0.3874, -0.0811,  0.0051,  0.4429])

# 五组随机的面,五个随机的标准差;得到五组不同的正态分布
t1 = torch.normal(mean=torch.rand(5), std=torch.rand(5))
# tensor([ 1.0911, -0.8740,  0.1921,  0.9249,  0.1547])

uniform_

t1 = torch.Tensor(2, 2) 
# tensor([[2.3694e-38, nan], [2.8026e-45, 0.0000e+00]])

t1.uniform_(-1, 1) 
# tensor([[-0.2414, -0.2573], [-0.5572,  0.4906]])



eye

torch.eye(3, 3)

'''
tensor([[1., 0., 0.],
            [0., 1., 0.],
            [0., 0., 1.]])
'''


torch.eye(3, 4)
'''
tensor([[1., 0., 0., 0.],
            [0., 1., 0., 0.],
            [0., 0., 1., 0.]])
'''

创建列表,类似 numpy 中的 arange

np.arange(1, 10, 3)
# array([1, 4, 7])
 
torch.arange(1, 10, 3)
# tensor([1, 4, 7])

创建等差数列 linspace

# start / end / step
# step : 个数
torch.linspace(1, 9, 3, requires_grad=True)
# tensor([1., 5., 9.], requires_grad=True)

logspace 返回一维张量

和 linspace 相似。包含在区间 制作pytorch数据集 pytorch数据处理_制作pytorch数据集制作pytorch数据集 pytorch数据处理_Tensor_02 中。
以对数刻度均匀间隔的 steps 个点,输出一维张量的长度为 steps。

torch.logspace(1, 5, 5, requires_grad=True) 
# tensor([1.00000e+01, 1.00000e+02, 1.00000e+03, 1.00000e+04, 1.00000e+05], requires_grad=True)

稠密向量

# 将对角线定义为非零元素
i = torch.tensor([[0, 1, 2], [0, 1, 2]])
v = torch.tensor([1, 2, 3])

t1 = torch.sparse_coo_tensor(i, v, [5, 4])
'''
tensor(indices=tensor([[0, 1, 2],
                       [0, 1, 2]]),
       values=tensor([1, 2, 3]),
       size=(5, 4), nnz=3, layout=torch.sparse_coo)
'''

# 转化为稠密张量
t2 = t1.to_dense()
'''
tensor([[1, 0, 0, 0],
        [0, 2, 0, 0],
        [0, 0, 3, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]])
'''

Tensor – Numpy

Torch Tensor 和 Numpy array 之间的相互转换

import numpy as np

arr = np.array([[1, 2, 3], [4, 5, 6]])
# array([[1, 2, 3], [4, 5, 6]])

t1 = torch.tensor(arr) 
# tensor([[1, 2, 3], [4, 5, 6]])

# 方式2,效果同上 
a2 = torch.from_numpy(arr) # tensor([[1, 2, 3], [4, 5, 6]])

# numpy 数组的改变,不会影响 tensor
np.add(arr, 1, out=arr)  

t2 = t1.numpy() # array([[1, 2, 3], [4, 5, 6]])
 
t1.add_(1) # tensor([[2, 3, 4], [5, 6, 7]])

t2 # b同时被改变, 但 arr 不会被改变 
# array([[2, 3, 4], [5, 6, 7]])

属性和方法


数据类型转换

torch 支持的类型:

t1 = torch.Tensor([1., 2.])
t1.dtype  # torch.float32

# 创建时制定数据类型
t2 = torch.ones([2, 3], dtype=torch.float32)
# tensor([[1., 1., 1.], [1., 1., 1.]])

# 强制转换
t2.double() # .int(),  .long(),  
# tensor([[1., 1., 1.], [1., 1., 1.]], dtype=torch.float64)

t3 = torch.LongTensor([2, 3])
# tensor([2, 3])

t3.dtype  # torch.int64

使用 Tensor 创建,不支持 dtype, tensor 支持
在 jupyter 中可以使用 help(torch.tensor) 查看帮助文档

参数值太小,会导致梯度消失。
数值太大,会梯度爆炸。


判断一个对象是否为 Tensor

obj = np.arange(1, 10)
torch.is_tensor(obj) # False 

t1 = torch.Tensor(10)
torch.is_tensor(t1) # True

判断一个对象是否为 PyTorch Storage 类型

s1 = torch.DoubleStorage(5)
s1
'''
     0.0
     0.0
     0.0
     0.0
     0.0
    [torch.DoubleStorage of size 5]
'''
torch.is_storage(s1) #  True

item

当张量中只有一个值,可以使用 item 获取那个值。

t1 = torch.Tensor([[[1]]]) # tensor([[[1.]]])
a.item() # 1.0

# 张量内有两个值时,会报错 
t2 = torch.Tensor([[[1, 2]]])
b.item() # only one element tensors can be converted to Python scalars

获取 Tensor 中元素个数 numel

t1 = torch.Tensor(3, 4)
torch.numel(t1)
12

尺寸 shape / size

  • shape 属性
  • size() 方法,比较常用。可以指定维度。
  • dim(), 获取维数
t1 = torch.tensor([[[1, 2, 3], [4, 5, 6]]])  
a.shape   # torch.Size([1, 2, 3])
a.size()  # torch.Size([1, 2, 3])

a.size(0)  # 1  # 第0维的尺寸
a.size(1)  # 2
a.size(-1) # 3 最后一维的长度

a.dim() # 3

修改形状 view

numpy 中使用 reshape,这里也可以用,但不推荐。建议使用 view。
两者都是浅拷贝,仅仅改变形状

t1 = torch.tensor([[[1, 2, 3], [4, 5, 6]]]) 

t2 = t1.view([3, 2])
# tensor([[1, 2], [3, 4], [5, 6]])

t3 = t1.view([-1])
# tensor([1, 2, 3, 4, 5, 6])

# t1 修改后,t2和 c 中的数值也会修改 
a.add_(1)

转置

Numpy 中使用 T,torch 中使用 t。
二维可以使用 t 转置,高维使用 transpose。

t1 = torch.tensor([[1, 2], [3, 4]])
# tensor([[1, 2],
#        [3, 4]])

t1.t() 
# tensor([[1, 3],
#        [2, 4]])

# 效果同上,且此时 t1 中数据不变
t1.transpose(0, 1)

# 多维
t1 = torch.tensor([[[1, 2, 3],[4, 5, 6]],
                [[7, 8, 9],[10, 11, 12]]])

t2 = torch.transpose(t1, 1, 2)

# 效果同上
t3 = t1.transpose(1, 2)
'''
tensor([[[ 1,  4],
          [ 2,  5],
          [ 3,  6]],
 
         [[ 7, 10],
          [ 8, 11],
          [ 9, 12]]]),
'''

将输入张量分割成相同形状的 chunks

非 truck

t1 = torch.ones(2, 10)
'''
    tensor([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
            [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]])
'''
 
torch.split(t1, 2)
'''
    (tensor([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
             [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]]),)
'''

torch.split(t1, 5, dim=1)
'''
    (tensor([[1., 1., 1., 1., 1.],
             [1., 1., 1., 1., 1.]]), tensor([[1., 1., 1., 1., 1.],
             [1., 1., 1., 1., 1.]]))
'''

# 指定划分列表,依次表示有 1,2,3,4 个长度
torch.split(t1, [1, 2, 3, 4], dim=1)
'''
    (tensor([[1.],
             [1.]]), tensor([[1., 1.],
             [1., 1.]]), tensor([[1., 1., 1.],
             [1., 1., 1.]]), tensor([[1., 1., 1., 1.],
             [1., 1., 1., 1.]]))
'''

增加矩阵维度 unsqueeze

t1 = torch.Tensor([1, 2, 3, 4, 5, 6])
t2 = t1.unsqueeze(dim=0)
# tensor([[1., 2., 3., 4., 5., 6.]])
 
t3 = t1.unsqueeze(dim=1)
'''
    tensor([[1.],
            [2.],
            [3.],
            [4.],
            [5.],
            [6.]])
'''
 
# 另一种调用方式
torch.unsqueeze(t1, dim=0)
# tensor([[1., 2., 3., 4., 5., 6.]])

降低纬度(去掉 []) squeeze

属于 unsqueeze 的逆向操作,删除 dim 指定的维度

t1 = torch.Tensor([[[2, 3, 4], [7, 8, 9]]])
t1.shape # torch.Size([1, 2, 3])
 
t2 = torch.squeeze(t1, dim=0) 
t2, t2.shape
# (tensor([[2., 3., 4.], [7., 8., 9.]]), torch.Size([2, 3]))

t3 = torch.squeeze(t1, dim=1)
t3, t3.shape
# (tensor([[[2., 3., 4.], [7., 8., 9.]]]), torch.Size([1, 2, 3]))
 
t4 = t1.squeeze(dim=0)
t4, t4.shape
# (tensor([[2., 3., 4.], [7., 8., 9.]]), torch.Size([2, 3]))

获取沿着某个维度切片后 所有的切片 unbind

t1 = torch.rand(2, 2, 3)
'''
    tensor([[[0.53095, 0.25374, 0.68720],
             [0.69803, 0.41977, 0.72966]],
    
            [[0.62927, 0.88989, 0.74201],
             [0.49337, 0.88015, 0.29941]]])
''' 

torch.unbind(t1, dim=1)
'''
    (tensor([[0.53095, 0.25374, 0.68720],
             [0.62927, 0.88989, 0.74201]]), tensor([[0.69803, 0.41977, 0.72966],
             [0.49337, 0.88015, 0.29941]]))
'''

torch.unbind(t1, dim=0)
'''
    (tensor([[0.53095, 0.25374, 0.68720],
             [0.69803, 0.41977, 0.72966]]), tensor([[0.62927, 0.88989, 0.74201],
             [0.49337, 0.88015, 0.29941]]))
'''

拼接 cat

t1 = torch.ones(2,3)
torch.cat([t1, t1]) # (4, 3)
'''
    tensor([[1., 1., 1.],
            [1., 1., 1.],
            [1., 1., 1.],
            [1., 1., 1.]])
'''


torch.cat([t1, t1], dim=1) # (2, 6)
'''
tensor([[1., 1., 1., 1., 1., 1.],
            [1., 1., 1., 1., 1., 1.]])
'''

按指定维度切分 chunk

# 按照第二个维度,切分为5个tensor
t1 = torch.ones(2, 10)
torch.chunk(t1, 5, dim=1)
'''
    (tensor([[1., 1.],
             [1., 1.]]), tensor([[1., 1.],
             [1., 1.]]), tensor([[1., 1.],
             [1., 1.]]), tensor([[1., 1.],
             [1., 1.]]), tensor([[1., 1.],
             [1., 1.]]))
'''

聚合 gather

t1 = torch.Tensor([[33, 6, 9], [1, 5, 8]])
# 原tensor:t1, 维度:1, 索引:[[0, 1], [2, 1]]
torch.gather(t1, 1, torch.LongTensor([[0, 1], [2, 1]])) 
#    tensor([[33.,  6.], [ 8.,  5.]])

改变尺寸

  • view
  • reshape
  • transpose 转置
  • permute

1、view

view()返回的新Tensor与源Tensor虽然可能有不同的size,但是是共享data的,也即更改其中的一个,另外一个也会跟着改变。(顾名思义,view仅仅是改变了对这个张量的观察角度,内部数据并未改变)**

t1 = torch.ones(4,5)

# -1代表自动匹配个数
t2 = t1.view(-1, 10)
# tensor([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]])

t3 = t1.view(4, -1) 
# tensor([[1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.]])

t4 = t1.view(5,4)

t5 = t1.view(3,3)
# RuntimeError: shape '[3, 3]' is invalid for input of size 20


t1 += 1
t1, t2 
# t1 : tensor([[2., 2., 2., 2., 2.], [2., 2., 2., 2., 2.], [2., 2., 2., 2., 2.], [2., 2., 2., 2., 2.]]),
# t2 : tensor([[2., 2., 2., 2., 2., 2., 2., 2., 2., 2.], [2., 2., 2., 2., 2., 2., 2., 2., 2., 2.]])

Pytorch还提供了一个reshape()可以改变形状,但是此函数并不能保证返回的是其拷贝,所以不推荐使用。

所以如果我们想返回一个真正新的副本(即不共享data内存),推荐先用clone创造一个副本然后再使用view参考此处 SOF

t1_cp = t1.clone().view(2, -1)
t1 -= 1
# t1 : tensor([[1., 1., 1., 1., 1.],  [1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.], [1., 1., 1., 1., 1.]])
 
# t2 : tensor([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],  [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])

2、reshape

t1 = torch.ones(2,3,5)
'''
tensor([[[1., 1., 1., 1., 1.],
         [1., 1., 1., 1., 1.],
         [1., 1., 1., 1., 1.]],
        [[1., 1., 1., 1., 1.],
         [1., 1., 1., 1., 1.],
         [1., 1., 1., 1., 1.]]])
'''

t2 = torch.reshape(t1,((1,5,6)))
'''
tensor([[[1., 1., 1., 1., 1., 1.],
         [1., 1., 1., 1., 1., 1.],
         [1., 1., 1., 1., 1., 1.],
         [1., 1., 1., 1., 1., 1.],
         [1., 1., 1., 1., 1., 1.]]])
'''

t3 = torch.reshape(t1,((1,-1,6))) # 结果同 t2

索引、切片

我们还可以使用类似NumPy的索引操作来访问Tensor的一部分。
需要注意的是:索引出来的结果 与 原数据共享内存,也即修改一个,另一个会跟着修改。

函数

功能

index_select(input, dim, index)

在指定维度dim上选取,比如选取某些行、某些列

masked_select(input, mask)

例子如上,a[a>0],使用ByteTensor进行选取

nonzero(input)

非0元素的下标

gather(input, dim, index)

根据index,在dim维度上选取数据,输出的size与index一样


t1 = torch.tensor([[1, 2, 3], [4, 5, 6]])   
# t1 : tensor([[1, 2, 3], [4, 5, 6]])

t2 = t1[1,2] # tensor(6) 

t3 = t1[0, :]
# tensor([1, 2, 3])

t3 += 1
# t3 : tensor([2, 3, 4]) 
# t1 tensor([[2, 3, 4], [4, 5, 6]])

t1 = torch.tensor([[[1, 2, 3], [4, 5, 6]],
                 [[7, 8, 9], [10, 11, 12]]])

t1.shape # torch.Size([2, 2, 3])

t1[1, 0, 2] # tensor(9)

t1[:, :, 2]
'''
tensor([[ 3,  6],
        [ 9, 12]])
'''

高级选择函数

  • index_select(input, dim, index), 在指定维度dim上选取,比如选取某些行、某些列
  • masked_select(input, mask), 例子如上,a[a>0],使用ByteTensor进行选取
  • nonzero(input), 非0元素的下标
  • gather(input, dim, index), 根据index,在dim维度上选取数据,输出的size与index一样

按照索引选择目标数据 index_select

t1 = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])  
'''
tensor([[1, 2, 3],
        [4, 5, 6],
        [7, 8, 9]])
'''

t1[1,2]  # tensor(6)

# 0 维度的第0个数据
torch.index_select(t1, 0, torch.LongTensor([0]))  

# 第1列的元素排在 第0列; 0-1, 2-2
torch.index_select(t1, 1, torch.LongTensor([1, 0, 2]))  
'''
tensor([[2, 1, 3],
        [5, 4, 6],
        [8, 7, 9]])
'''
 
torch.index_select(t1, 1, torch.LongTensor([2, 1, 0]))  
'''
tensor([[3, 2, 1],
        [6, 5, 4],
        [9, 8, 7]])
'''

选出满足条件的矩阵元素 masked_select

t1 = torch.rand(2, 4)
t1
'''
    tensor([[0.00894, 0.14170, 0.06343, 0.57149],
            [0.99475, 0.81315, 0.28624, 0.73843]])
'''


mask = t1.ge(0.5)
mask
''' 
    tensor([[False, False, False,  True],
            [ True,  True, False,  True]])
'''
 
torch.masked_select(t1, mask) 
# tensor([0.57149, 0.99475, 0.81315, 0.73843])

找出矩阵中的非零元素的索引 nonzero

t1 = torch.Tensor([[0.48282, 0, 0.45506, 0.48478],
        [0, 0.23411, 0, 0.44914]])

torch.nonzero(t1)
# 返回的行数为原 Tensor 中非零元素的个数,列数为原 Tensor 的维度
# [0,0] 第0维的第 0 个数据非 0
tensor([[0, 0],
        [0, 2],
        [0, 3],
        [1, 1],
        [1, 3]])
t1 = torch.Tensor([[[0.48282, 0], [0.45506, 0.48478]], 
                  [[0, 0.23411], [0, 0.44914]]])

torch.nonzero(t1)
# [0,0] 第0维的索引 [0, 0] 个数据非 0
tensor([[0, 0, 0],
        [0, 1, 0],
        [0, 1, 1],
        [1, 0, 1],
        [1, 1, 1]])

数学计算

t1 = torch.tensor([[[1, 2., 3.], [4, 5, 6]]])  
a.min() # tensor(1)
a.max() # tensor(6)

# 浮点数的 tensor 才能获取标准差;整数无法获取
a.std() # tensor(1.8708)

加法

t1 = torch.randn(2, 3)    
#  tensor([[-0.4300, -0.8063,  1.4317], [ 0.8179,  0.5675, -2.0124]])

t1 + 1
# tensor([[ 0.5700,  0.1937,  2.4317], [ 1.8179,  1.5675, -1.0124]])

t2 = torch.ones(2, 3)    
#  tensor([[1., 1., 1.], [1., 1., 1.]])


# 加法方式 1
t1 + t2   
# tensor([[ 0.5700,  0.1937,  2.4317], [ 1.8179,  1.5675, -1.0124]])


# 加法方式 2
torch.add(t1,  t2)  
# tensor([[ 0.5700,  0.1937,  2.4317], [ 1.8179,  1.5675, -1.0124]])


# 加法方式 3
# 提前设定一个空的张量
result = torch.empty(2, 3)

# 将空的张量作为加法的结果存储张量
torch.add(t1,  t2, out=result)    
# tensor([[ 0.5700,  0.1937,  2.4317], [ 1.8179,  1.5675, -1.0124]])


# 加法方式 4 -  in-place (原地置换)  
# 注意: 所有in-place的操作函数都有一个下划线的后缀.
# 比如 t1.copy_(y), t1.add_(y), 都会直接改变x的值.

y.add_(x)    
# t2 : tensor([[ 0.5700,  0.1937,  2.4317], [ 1.8179,  1.5675, -1.0124]])

t1[:, 1]
tensor([-0.8063,  0.5675])    
#  tensor([[-0.4300, -0.8063,  1.4317], [ 0.8179,  0.5675, -2.0124]])

乘法

t1 = torch.tensor([[1, 2], [3, 4]])
t2 = torch.tensor([[5, 6], [7, 8]])

t1 * 2
# tensor([[2, 4], [6, 8]])

# 对应元素相乘 
t1 * t2  
# tensor([[ 5, 12], 
#        [21, 32]])

torch.mul(t1, t2) # 结果同上


# 矩阵乘法
t3 = torch.mm(t1, t2)
# c  tensor([[19, 22],
#           [43, 50]])


t4 = torch.matmul(t1, t2) # 结果同上


绝对值、向上取整、向下取整、相反数、倒数、平方根、平方根倒数

t1 = torch.Tensor([-1, 0.5, -2.3, 0.99, 0.35])
 
# 绝对值
torch.abs(t1)
# tensor([1.0000, 0.5000, 2.3000, 0.9900, 0.3500])


# 向上取整
torch.ceil(t1)
# tensor([-1.,  1., -2.,  1.,  1.])


# 向下取整
torch.floor(t1)
# tensor([-1.,  0., -3.,  0.,  0.])


# 夹逼函数
# 每个元素限制在给定的区间范围内,小于范围下限的被强制设置为下限值;大于范围上限的被强制设置为上限值。
torch.clamp(t1, -5.5, 5.5)
# tensor([-1.0000,  0.5000, -2.3000,  0.9900,  0.3500])


# 相反数
torch.neg(t1)
# tensor([ 1.0000, -0.5000,  2.3000, -0.9900, -0.3500])


# 倒数
torch.reciprocal(t1)
# tensor([-1.0000,  2.0000, -0.4348,  1.0101,  2.8571])


# 平方根倒数
torch.rsqrt(t1[t1>0])
# tensor([1.4142, 1.0050, 1.6903])


# 平方根
torch.sqrt(t1)
# tensor([   nan, 0.7071,    nan, 0.9950, 0.5916])


  
# 返回浮点数小数部分
torch.frac(t1)
# tensor([ 0.0000,  0.5000, -0.3000,  0.9900,  0.3500])


# 四舍五入
torch.round(t1) 
# tensor([-1.,  0., -2.,  1.,  0.])


# 截断值,标量x的截断值,比x更接近于0。
torch.trunc(torch.Tensor([-1, 0.5, -2.3, 0.99, 0.35]))
# tensor([-1.,  0., -2.,  0.,  0.])

每个元素加减乘除

t1 = torch.Tensor([2, 3, 4])
# tensor([2., 3., 4.])


torch.add(t1, 3)
# tensor([5., 6., 7.])


torch.mul(t1, 2)
# tensor([4., 6., 8.])


torch.div(t1, 3)
# tensor([0.6667, 1.0000, 1.3333])


# 取余 %
torch.fmod(t1, 3)
# tensor([2., 0., 1.])


torch.remainder(t1, 3)
# tensor([2., 0., 1.])


t2 = torch.Tensor([1.4, 2.3, 5.9])
# tensor([1.4000, 2.3000, 5.9000])

指、对、幂

import math
 
# 指数运算
torch.exp(torch.Tensor([0, math.log(2)]))
# tensor([1., 2.])


# 自然对数
t1 = torch.Tensor([math.e, math.e**2])
# tensor([2.7183, 7.3891])


# 平滑对数:对输入加1 平滑后再求对数
torch.log1p(t1)
# tensor([1.3133, 2.1269])


# 以2为底的对数
torch.log2(t1)
# tensor([1.4427, 2.8854])


# 以10为底的对数
torch.log10(t1)
# tensor([0.4343, 0.8686])


# 幂运算
torch.pow(t1, 1), torch.pow(t1, 2)
(tensor([2.7183, 7.3891]), tensor([ 7.3891, 54.5982]))

三角函数

t1 = torch.Tensor([-1, 0.5, -2.3, 0.99, 0.35])
torch.cos(t1)
# tensor([ 0.5403,  0.8776, -0.6663,  0.5487,  0.9394])


torch.sin(t1)
# tensor([-0.8415,  0.4794, -0.7457,  0.8360,  0.3429])


# 反余弦
torch.acos(t1)
# tensor([3.1416, 1.0472,    nan, 0.1415, 1.2132])

线性插值

t1 = torch.zeros(5).fill_(8)
# tensor([8., 8., 8., 8., 8.])


t2 = torch.arange(5).float()
# tensor([0., 1., 2., 3., 4.])


torch.lerp(t1, t2, 0.5) # 4.5 = 8 + (1-8)*0.5
# tensor([4.0000, 4.5000, 5.0000, 5.5000, 6.0000])


torch.lerp(t1, t2, 0.1) # 7.2 = 8 + (8-0) * 0.1; 7.4 = 8 + (2-8) * 0.1
# tensor([7.2000, 7.3000, 7.4000, 7.5000, 7.6000])

Sigmoid 函数,sign符号函数

# Sigmoid 函数
t1 = torch.arange(-5, 5, 1).float()
t1 
# tensor([-5., -4., -3., -2., -1.,  0.,  1.,  2.,  3.,  4.])


torch.sigmoid(t1)
# tensor([0.0067, 0.0180, 0.0474, 0.1192, 0.2689, 0.5000, 0.7311, 0.8808, 0.9526,
            0.9820])


torch.sign(t1)
# tensor([-1., -1., -1., -1., -1.,  0.,  1.,  1.,  1.,  1.])

规约计算

规约计算一般指分组聚合运算,特点是会使用 分组内 或 所有元素 参与计算,得到统计的结果。


累积 & 累和

t1 = torch.Tensor([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
# tensor([[ 1.,  2.,  3.,  4.,  5.],
#         [ 6.,  7.,  8.,  9., 10.]])


# 累积 
torch.cumprod(t1, dim=0) # 从上往下累积相乘
# tensor([[ 1.,  2.,  3.,  4.,  5.],
#         [ 6., 14., 24., 36., 50.]])


torch.cumprod(t1, dim=1) # 从前往后累积相乘
# tensor([[1.0000e+00, 2.0000e+00, 6.0000e+00, 2.4000e+01, 1.2000e+02],
#         [6.0000e+00, 4.2000e+01, 3.3600e+02, 3.0240e+03, 3.0240e+04]])


# 累和
torch.cumsum(t1, dim=0) # 从上往下累加
# tensor([[ 1.,  2.,  3.,  4.,  5.],
#         [ 7.,  9., 11., 13., 15.]])


torch.cumsum(t1, dim=1) # 从前往后累加
# tensor([[ 1.,  3.,  6., 10., 15.],
#         [ 6., 13., 21., 30., 40.]])


# 所有元素的和
torch.sum(t1)
# tensor(55.)


torch.sum(t1, dim=0)
# tensor([ 7.,  9., 11., 13., 15.])


torch.sum(t1, dim=1)
# tensor([15., 40.])

均值、中位数、众数、方差、标准差

t1 = torch.Tensor([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
# 均值
torch.mean(t1)
# tensor(5.5000)


torch.mean(t1, dim=0)
# tensor([3.5000, 4.5000, 5.5000, 6.5000, 7.5000])


torch.mean(t1, dim=1)
# tensor([3., 8.])


# 中位数

torch.median(t1)
# tensor(5.)


# 指定 dim 返回两个Tensor,第一个是中位数,第二个是索引
torch.median(t1, dim=0)
'''
    torch.return_types.median(
    values=tensor([1., 2., 3., 4., 5.]),
    indices=tensor([0, 0, 0, 0, 0]))
'''
 

torch.median(t1, dim=1)
'''
    torch.return_types.median(
    values=tensor([3., 8.]),
    indices=tensor([2, 2]))
'''


# 众数
torch.mode(t1)
'''
    torch.return_types.mode(
    values=tensor([1., 6.]),
    indices=tensor([0, 0]))
'''

# 方差
torch.var(t1)
# tensor(9.1667)


torch.var(t1, dim=0)
# tensor([12.5000, 12.5000, 12.5000, 12.5000, 12.5000])


torch.var(t1, dim=1)
# tensor([2.5000, 2.5000])


# 标准差
torch.std(t1)
# tensor(3.0277)


torch.std(t1, dim=0)
# tensor([3.5355, 3.5355, 3.5355, 3.5355, 3.5355])


torch.std(t1, dim=1)
# tensor([1.5811, 1.5811])

p-norm 距离

距离公式,常用语模型损失值的计算。计算采用 p-norm 范数。
p=1 为曼哈顿距离,p=2为欧氏距离。默认计算欧式距离。

t1 = torch.Tensor([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
t2 = torch.Tensor([[1, 2, 3, 4, 5], [1, 2, 8, 9, 10]])
 
torch.dist(t1, t2, p=0)
# tensor(2.)


torch.dist(t1, t2, p=1)
# tensor(10.)


torch.dist(t1, t2, np.inf)
# tensor(5.)


torch.norm(t1, p=1, dim=0) # 上下相加
# tensor([ 7.,  9., 11., 13., 15.])


torch.norm(t1, p=1, dim=1) # 左右相加
# tensor([15., 40.])


torch.norm(t1, p=2, dim=0) #  
# tensor([ 6.0828,  7.2801,  8.5440,  9.8489, 11.1803])


torch.norm(t1, p=2, dim=1) #  
# tensor([ 7.4162, 18.1659])

数值比较运算


大于、小于、等于、不等于

t1 = torch.Tensor([[1, 2, 3], [4, 5, 6]])
t2 = torch.Tensor([[1, 2, 3], [7, 8, 9]])
t3 = torch.Tensor([[4, 5, 6], [7, 8, 9]])


torch.equal(t1, t2)
# False
 
# 大于,greater than
torch.gt(t1, t2)
# tensor([[False, False, False],
#         [False, False, False]])


# 大于等于 
torch.ge(t1, t2)
# tensor([[ True,  True,  True],
#         [False, False, False]])


# 小于,less than
torch.lt(t1, t2)
# tensor([[False, False, False],
#         [ True,  True,  True]])


# 小于等于
torch.le(t1, t2)
# tensor([[True, True, True],
#         [True, True, True]])


# 是否不相等
torch.ne(t1, t2)
# tensor([[False, False, False],
#         [ True,  True,  True]])

最大值、最小值 max、min

t1 = torch.Tensor([[1, 2, 3], [4, 5, 6]])
 
torch.max(t1), torch.min(t1)
# (tensor(6.), tensor(1.))


torch.max(t1, dim=0)
'''
torch.return_types.max(
    values=tensor([4., 5., 6.]),
    indices=tensor([1, 1, 1]))
'''
 

torch.max(t1, dim=1)
'''
torch.return_types.max(
    values=tensor([3., 6.]),
    indices=tensor([2, 2]))
'''

排序 sort

t1 = torch.Tensor([[11, 2, 23], [4, 15, 61]])
 
torch.sort(t1, dim=0, descending=False) # 升序
'''
torch.return_types.sort(
values=tensor([[ 4.,  2., 23.],
               [11., 15., 61.]]),
indices=tensor([[1, 0, 0],
               [0, 1, 1]]))
'''

torch.sort(t1, dim=1, descending=False)
'''
torch.return_types.sort(
values=tensor([[ 2., 11., 23.],
               [ 4., 15., 61.]]),
indices=tensor([[1, 0, 2],
                [0, 1, 2]]))
'''

topk

选择最大或最小的k个元素作为返回值

t1 = torch.Tensor([[11, 2, 23], [4, 15, 61]])
 
torch.topk(t1, k=2) # 默认选择最大
'''
torch.return_types.topk(
    values=tensor([[23., 11.],
                   [61., 15.]]),
    indices=tensor([[2, 0],
                    [2, 1]]))
'''
 

torch.topk(t1, k=2, largest=False) # 选出最小的两个值
'''
torch.return_types.topk(
    values=tensor([[ 2., 11.],
                   [ 4., 15.]]),
    indices=tensor([[1, 0],
                    [0, 1]]))

'''
 
torch.topk(t1, k=1, dim=0)
'''
    torch.return_types.topk(
    values=tensor([[11., 15., 61.]]),
    indices=tensor([[0, 1, 1]]))
'''

torch.topk(t1, k=1, dim=1)
'''

    torch.return_types.topk(
    values=tensor([[23.],
                  [61.]]),
    indices=tensor([[2],
                   [2]]))
'''

矩阵运算


对角矩阵

t1 = torch.rand(2)
# tensor([0.7190, 0.3232])


# diagonal=0,设置为主对角线
torch.diag(t1, diagonal=0)
# tensor([[0.7190, 0.0000],
#         [0.0000, 0.3232]])


# diagonal>0,设置为主对角线之上 diagonal 对应的位置
torch.diag(t1, diagonal=1)
# tensor([[0.0000, 0.7190, 0.0000],
#         [0.0000, 0.0000, 0.3232],
#         [0.0000, 0.0000, 0.0000]])


torch.diag(t1, diagonal=2)
# tensor([[0.0000, 0.0000, 0.7190, 0.0000],
#         [0.0000, 0.0000, 0.0000, 0.3232],
#         [0.0000, 0.0000, 0.0000, 0.0000],
#         [0.0000, 0.0000, 0.0000, 0.0000]])


# diagonal<0,设置为主对角线之下 diagonal 对应的位置
torch.diag(t1, diagonal=-1)
# tensor([[0.0000, 0.0000, 0.0000],
#         [0.7190, 0.0000, 0.0000],
#         [0.0000, 0.3232, 0.0000]])

矩阵的迹

t1 = torch.randn(2, 4)
# tensor([[-0.8954,  0.6590,  0.0918,  0.5809],
#         [ 0.5339, -0.8087, -0.4212,  2.0023]])


torch.trace(t1)
# tensor(-1.7041)

上三角矩阵和下三角矩阵

# diagonal 控制对角线 偏移的位置

t1 = torch.randn(3, 4)
# tensor([[ 0.2944,  1.0727, -0.5332,  2.2292],
#         [-0.3672,  1.5228, -1.1491,  0.2756],
#         [ 0.4644, -0.1443, -2.5940, -2.1068]])


torch.tril(t1, diagonal=1)
# tensor([[ 0.2944,  1.0727,  0.0000,  0.0000],
#         [-0.3672,  1.5228, -1.1491,  0.0000],
#         [ 0.4644, -0.1443, -2.5940, -2.1068]])


torch.tril(t1, diagonal=-1)
# tensor([[ 0.0000,  0.0000,  0.0000,  0.0000],
#         [-0.3672,  0.0000,  0.0000,  0.0000],
#         [ 0.4644, -0.1443,  0.0000,  0.0000]])

矩阵的乘积 mm

t1 = torch.Tensor([[1, 2, 3], [4, 5, 6]])
t2 = torch.Tensor([[5], [3], [2]])
 
torch.mm(t1, t2) # 17 = 1*5 + 2*3 + 3*2
# tensor([[17.],
#         [47.]])

特征值及特征向量

t1 = torch.Tensor([[1, 2, 3], [6, 5, 4], [9, 5, 1]])

torch.eig(t1)
'''
torch.return_types.eig(
eigenvalues=tensor([[ 1.1262e+01,  0.0000e+00],
        [-4.2621e+00,  0.0000e+00],
        [-6.1734e-07,  0.0000e+00]]),
eigenvectors=tensor([]))
'''
 
torch.eig(t1, eigenvectors=True)
'''
torch.return_types.eig(
eigenvalues=tensor([[ 1.1262e+01,  0.0000e+00],
                    [-4.2621e+00,  0.0000e+00],
                    [-6.1734e-07,  0.0000e+00]]),
eigenvectors=tensor([[ 0.3216,  0.4729,  0.4082],
                    [ 0.7090,  0.0729, -0.8165],
                    [ 0.6275, -0.8781,  0.4082]]))
'''

广播机制

广播机制即不同维度、长度的 Tensor,在满足一定规则的前提下,能够自动进行维度和长度的扩充。

t1 = torch.Tensor([1, 2, 3])
t2 = torch.Tensor([4, 5, 6])
 
t1 + t2 # tensor([5., 7., 9.])
 
t1 * t2 # tensor([ 4., 10., 18.])

其它


设置打印选项

torch.set_printoptions(precision=5, threshold=100, linewidth=80, edgeitems=4)
torch.DoubleTensor(100, 300)
'''
    tensor([[  0.00000e+00,  2.18717e-314,  1.22392e-318,           nan,
              ..., -5.26032e+127, -4.12046e+127, -5.26352e+127,
              3.99349e-237],
            [ 1.31275e+170,  3.03984e-298,  4.43398e+228,   4.66241e+24,
              ...,  1.52293e+256,  9.08365e+223,  1.77568e+248,
              3.43530e+228], 
              ...
            [ 4.03717e-270,  3.19126e-241,  2.31582e-289,  3.95581e+252,
              ...,  8.03757e+165,  8.80067e+199,  2.86524e+161,
              1.66042e+243]])
'''

全局设置 Tensor 数据类型

torch.set_default_tensor_type(torch.DoubleTensor)
t1 = torch.Tensor(2)
# tensor([2.2755e+161, 6.7866e+199])

t1.dtype #  torch.float64

随机抽样


设置随机种子

# 手动设置种子
torch.manual_seed(123)
seed = torch.initial_seed() #  123 

# 返回随机生成器状态
state = torch.get_rng_state()
# tensor([123,   0,   0,   0,  ...,   0,   0,   0,   0], dtype=torch.uint8)

伯努利分布采样

伯努利分布结果只有 0 和 1,第一个参数的概率是p,且 0<=p<=1

torch.manual_seed(123)
t1 = torch.rand(3, 3)
'''
    tensor([[0.36890, 0.01337, 0.59178],
            [0.09264, 0.47245, 0.52203],
            [0.60508, 0.53130, 0.94855]])
''' 
t2 = torch.bernoulli(t1)
'''
    tensor([[1., 0., 1.],
            [0., 1., 1.],
            [1., 0., 1.]])
'''

多项式分布抽样

torch.multinomial 函数参数说明

  • 第一个参数是多项式权重;可以是向量,也可以是矩阵。权重决定了对下标的抽样。
  • 如果是向量,replacement 代表是否有放回的抽样;
  • replacement=True,结果行数为1,列数由 num_samples 决定;
  • replacement=False, 行数为1,列数<=权重长度
w1 = torch.Tensor([20, 10, 3, 2])

torch.multinomial(w1, num_samples=3, replacement=False)
# tensor([1, 0, 2])

torch.multinomial(w1, num_samples=10, replacement=True)
# tensor([1, 0, 0, 0, 3, 0, 0, 0, 1, 0])


w2 = torch.Tensor([[20, 10, 3, 2], [30, 4, 5, 6]])

torch.multinomial(w2, num_samples=4, replacement=False)
'''
    tensor([[1, 0, 2, 3],
            [0, 2, 3, 1]])
'''

torch.multinomial(w2, num_samples=15, replacement=True)
'''
    tensor([[1, 1, 1, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 3],
            [2, 0, 0, 3, 0, 1, 3, 2, 2, 0, 0, 0, 0, 2, 0]])
'''

标准分布抽样

# 均值为0.5,方差为 [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]
torch.normal(mean=0.5, std=torch.arange(0.1, 1, 0.0001))
# tensor([0.48034, 0.44650, 0.56860, 0.57181,  ..., 0.35206, 1.26491, 1.48555, 2.14253])
 
# 均值为 [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9],方差为 0.5 
torch.normal(mean=torch.arange(0.1, 1, 0.1), std=0.5)
# tensor([0.00936, 0.29426, 0.80918, 1.27463, 0.18718, 1.13891, 0.50415, 1.32652, 0.71879])

# 均值为 [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9],方差为 [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9] 
torch.normal(mean=torch.arange(0.1, 1, 0.1), std=torch.arange(0.1, 1, 0.1))
# tensor([ 0.11960,  0.52833, -0.29105,  0.60408,  1.43937,  0.51561,  1.04438, 0.85068,  0.45567])
import matplotlib.pyplot as plt

t1 = torch.normal(mean=0.5, std=torch.arange(0.1, 1, 0.0001))
plt.plot(torch.arange(0.1, 1, 0.0001).data.numpy(), t1.data.numpy() )
plt.show()

在 gpu/cpu 运行

# 实例化 device 
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu" ) 
# device(type='cpu')

# 在 device 上创建 tensor
t1 = torch.ones([2, 3], device=device)

# 将已创建的 tensor 转移到 device
t2 = t2.to(device)

2022-02-01