《Pytorch学习指南》- 基础API(3)

《Pytorch学习指南》- 基础API(3)

Scroll Down

1. Pytorch的统计学函数

import torch

for module in torch,:
    print(module.__name__, module.__version__)
torch 1.9.1+cpu

1.1 均值与最大最小值

  • torch.mean() 返回平均值
  • torch.sum() 返回总和
  • torch.prod() 计算所有元素的积
  • torch.max() 返回最大值
  • torch.min() 返回最小值
  • torch.argmax() 返回最大值排序的索引值
  • torch.argmin() 返回最小值排序的索引值
  • 注意 :
    1. dim=0, 表示列, dim=1 表示行
    2. 返回每一列中最大值的索引
    3. 比如 : 第一列是 4, 5 , 最大值5的索引是0
    4. 第二列是 3, 6 , 最大值6的索引是1
import torch

a = torch.tensor([[4, 3],
                  [5, 6]], dtype=torch.float32)
print(a)
print(torch.mean(a, dim=0))
print(torch.sum(a, dim=0))
print(torch.prod(a, dim=0))

# dim=0, 表示列, dim=1 表示行
# 返回每一列中最大值的索引
# 比如 : 第一列是 4, 5 , 最大值5的索引是0
# 第二列是 3, 6 , 最大值6的索引是1
print(torch.argmax(a, dim=0))
print(torch.argmin(a, dim=0))

# 以行为单位, 行内最大最小元素的索引
print(torch.argmax(a, dim=1))
print(torch.argmin(a, dim=1))
tensor([[4., 3.],
        [5., 6.]])
tensor([4.5000, 4.5000])
tensor([9., 9.])
tensor([20., 18.])
tensor([1, 1])
tensor([0, 0])
tensor([0, 1])
tensor([1, 0])

1.2 方差与众数

  • torch.std() 返回标准差
  • torch.var() 返回方差
  • torch.median() 返回中间值
  • torch.mode() 返回众数值
  • torch.histc() 计算input的直方图
    1. histc(a, bins = 6, min=0, max=0)
    2. bins : 统计多少个区间
    3. max/min : 定义最大值和最小值, 默认值取值为0,0 表示取tensor中的最大值和最小值
  • torch.bincount() 返回每个值出现的次数
    1. 返回 0 ~ 最大值(tensor中的最大值) 出现的频次
import torch

a = torch.rand(2, 2)

print(torch.std(a))
print(torch.var(a))
print(torch.median(a))
print(torch.mode(a))
tensor(0.2323)
tensor(0.0539)
tensor(0.4822)
torch.return_types.mode(
values=tensor([0.3132, 0.7638]),
indices=tensor([1, 1]))
a = torch.rand(2, 2) * 10
print(a)
#
print(torch.histc(a, bins=6, min=0, max=0))

a = torch.tensor([1, 1, 2, 2, 3, 6])
print(a)
# 返回 0 ~ 最大值 出现的频次
print(torch.bincount(a))
tensor([[7.6349, 0.9091],
        [5.2806, 0.3580]])
tensor([2., 0., 0., 0., 1., 1.])
tensor([1, 1, 2, 2, 3, 6])
tensor([0, 2, 2, 1, 0, 0, 1])

2. Pytorch与分布函数

  • Tensor的torch.distributions
    1. distributions 包含可参数化的概率分布和采样函数得分函数
    2. 强化学习中策略梯度方法的基础pathwise derivative估计器
    3. 变分自动编码器中的重新参数化技巧

3. Pytorch与随机抽样

  • torch.manual_seed(seed) 定义随机种子
  • torch.normal() 定义随机数满足的分布
import torch

# 定义随机数种子
torch.manual_seed(1)
mean = torch.rand(1, 2)  # 均值
std = torch.rand(1, 2)  # 方差
print(torch.normal(mean, std))
tensor([[0.7825, 0.7358]])

4. Pytorch的范数运算

  • 在泛函分析中,它定义在赋范线性空间中,并满足一定的条件,即
    1. 非负性;
    2. 齐次性;
    3. 三角不等式。
  • 常被用来度量某个向量空间(或矩阵)中的每个向量的长度或大小。
  • 0范数/1范数/2范数/p范数/核范数
    1. torch.dist(input, other,p=2) 计算p范数
    2. torch.norm() 计算2范数
import torch

a = torch.rand(2, 1)
b = torch.rand(2, 1)
print(a, b)
# 计算L1距离
print(torch.dist(a, b, p=1))
# L2
print(torch.dist(a, b, p=2))
# L3
print(torch.dist(a, b, p=3))

# a 的2范数
print(torch.norm(a))
print(torch.norm(a, p=3))
print(torch.norm(a, p='fro'))
tensor([[0.5695],
        [0.4388]]) tensor([[0.6387],
        [0.5247]])
tensor(0.1551)
tensor(0.1103)
tensor(0.0988)
tensor(0.7189)
tensor(0.6457)
tensor(0.7189)

5. Tensor的矩阵分解

  • LU分解:将矩阵A分解成L(下三角矩阵和U(上三角)矩阵的乘积
  • QR分解:将原矩阵分解成一个正交矩阵Q和一个上三角矩阵R的乘积
  • EVD分解:特征值分解
  • SVD分解:奇异值分解
  • 特征值分解
    1. 将矩阵分解为由其特征值和特征向量表示的矩阵之积的方法
    2. 特征值VS特征向量
  • PCA与特征值分解
    1. PCA:将n维特征映射到k维上,这k维是全新的正交特征也被称为主成分,是在原有n维特征的基础上重新构造出来的k维特征
    2. PCA算法的优化目标就是:
      • 降维后同一纬度的方差最大
      • 不同维度之间的相关性为0
      • 协方差矩阵

6. Tensor的张量裁剪

  • 对Tensor中的元素进行范围过滤
  • 常用于梯度裁剪(gradient clipping), 即在发生梯度离散或者梯度爆炸时对梯度的处理
  • a.clamp(min,max) 将张量裁剪到 (min, max) 的范围
import torch

a = torch.rand(2, 2) * 10

print(a)
# 将
a = a.clamp(2, 4)

print(a)
tensor([[6.8261, 3.0515],
        [4.6355, 4.5499]])
tensor([[4.0000, 3.0515],
        [4.0000, 4.0000]])

7. Tensor的索引与数据筛选

  • torch.where(condition, x, y)
    1. 按照条件从x和y中选出满足条件的元素组成新tensor
  • torch.gather(input, dim, index, out=None)
    1. 在指定维度上按照索引赋值输出tensor
  • torch.index_select(input, dim, index, out=None)
    1. 按照指定索引输出tensor
  • torch.masked_select(input,mask, out=None)
    1. 按照mask输出tensor, 输出为向量
  • torch.take(input, indices)
    1. 将输入看成1D-tensor,按照索引得到输出tensor
  • torch.nonzero(input, out=None)
    1. 输出非0元素的坐标

7.1 torch.where

  • torch.where(condition, x, y)
    1. 按照条件从x和y中选出满足条件的元素组成新tensor
    2. 例如 : condition = x > 5, 如果a有满足条件的数据, 就取a的数据, 否则取b对应位置的数据
import torch

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

print(a)
print(b)

out = torch.where(a > 3, a, b)

print(out)

c = torch.tensor([[1, 2, 3],
                  [4, 5, 6],
                  [7, 8, 9]])
print(torch.where(a > 3))
tensor([[1, 2, 3],
        [4, 5, 6],
        [7, 8, 9]])
tensor([[7, 2, 3],
        [4, 3, 6],
        [7, 8, 2]])
tensor([[7, 2, 3],
        [4, 5, 6],
        [7, 8, 9]])
(tensor([1, 1, 1, 2, 2, 2]), tensor([0, 1, 2, 0, 1, 2]))

7.2 torch.index_select

  • torch.index_select(input, dim, index, out=None)
    1. 按照指定索引输出tensor
    2. dim = 0, 指定以列为单位, 根据索引查询数据也是以列为单位
    3. 比如 : dim=0 , index=[0, 1, 2] 表示第一列中, 索引为 [0,1,2]的数据, 第二列的[0,1,2]的数据 ...
a = torch.rand(4, 4)
print(a)
# dim = 0, 指定以列为单位, 根据索引查询数据也是以列为单位
out = torch.index_select(a, dim=0,
                         index=torch.tensor([0, 1, 2]))

print(out, out.shape)
tensor([[0.5725, 0.4980, 0.9371, 0.6556],
        [0.3138, 0.1980, 0.4162, 0.2843],
        [0.3398, 0.5239, 0.7981, 0.7718],
        [0.0112, 0.8100, 0.6397, 0.9743]])
tensor([[0.5725, 0.4980, 0.9371, 0.6556],
        [0.3138, 0.1980, 0.4162, 0.2843],
        [0.3398, 0.5239, 0.7981, 0.7718]]) torch.Size([3, 4])

7.3 torch.gather

  • torch.gather(input, dim, index, out=None)
    1. 在指定维度上按照索引赋值输出tensor
  • tensor.view()
    1. 可以修改tensor的shape
# 生成范围在1到16之间16个间隔相同的数据
a = torch.linspace(1, 16, 16).view(4, 4)

print(a)

# 索引的计算方式
# dim = 0, 以列为单位
# index = [[0, 1, 0, 1],
#          [0, 1, 2, 2]]]
# 如上, 第一个 [0, 1, 0, 1] 分别对应 第一列到第四列的索引为 [0, 1, 0, 1]的数据
#
out = torch.gather(a, dim=0,
                   index=torch.tensor([[0, 1, 0, 1],
                                       [0, 1, 2, 2],
                                       [0, 1, 3, 3]]))
print(out)
print(out.shape)
tensor([[ 1.,  2.,  3.,  4.],
        [ 5.,  6.,  7.,  8.],
        [ 9., 10., 11., 12.],
        [13., 14., 15., 16.]])
tensor([[ 1.,  6.,  3.,  8.],
        [ 1.,  6., 11., 12.],
        [ 1.,  6., 15., 16.]])
torch.Size([3, 4])
b = torch.tensor([
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
])
print(b)
out = torch.gather(a, dim=0,
                   index=torch.tensor([
                       [1, 2],
                       [1, 2]
                   ]))
print(out)
tensor([[1, 2, 3],
        [4, 5, 6],
        [7, 8, 9]])
tensor([[ 5., 10.],
        [ 5., 10.]])

7.4 torch.masked_index

  • torch.masked_select(input,mask, out=None)
    1. 按照mask输出tensor, 输出为向量
    2. mask 相当于是一个条件, 返回结果是一个布尔类型的矩阵, 满足mask条件的返回True,
      否则返回False
a = torch.linspace(1, 16, 16).view(4, 4)
# 设置条件
mask = torch.gt(a, 8)
print(a)
print(mask)
out = torch.masked_select(a, mask)
print(out)
tensor([[ 1.,  2.,  3.,  4.],
        [ 5.,  6.,  7.,  8.],
        [ 9., 10., 11., 12.],
        [13., 14., 15., 16.]])
tensor([[False, False, False, False],
        [False, False, False, False],
        [ True,  True,  True,  True],
        [ True,  True,  True,  True]])
tensor([ 9., 10., 11., 12., 13., 14., 15., 16.])

7.5 torch.take

  • torch.take(input, indices)
    1. 将输入看成1D-tensor,按照索引得到输出tensor
a = torch.linspace(1, 16, 16).view(4, 4)
b = torch.take(a, index=torch.tensor([0, 15, 13, 10]))
print(b)
tensor([ 1., 16., 14., 11.])

7.6 torch.nonzero

  • torch.nonzero(input, out=None)
    1. 输出非0元素的坐标
a = torch.tensor([[0, 1, 2, 0], [2, 3, 0, 1]])
out = torch.nonzero(a)
print(out)
tensor([[0, 1],
        [0, 2],
        [1, 0],
        [1, 1],
        [1, 3]])

8. 张量的组合与拼接

  • torch.cat(seq, dim=O, out=None)
    1. 按照已经存在的维度进行拼接
  • torch.stack(seq, dim=0, out=None)
    1. 按照新的维度进行拼接
  • torch.gather(input, dim, index, out=None)
    1. 在指定维度上按照索赋值输出tensor

8.1 torch.cat

  • torch.cat(seq, dim=O, out=None)
    1. 按照已经存在的维度进行拼接
a = torch.zeros((2, 4))
b = torch.ones((2, 4))

# 上下拼接
out = torch.cat((a, b), dim=0)
print(out)

# 左右拼接
out = torch.cat((a, b), dim=1)
print(out)
tensor([[0., 0., 0., 0.],
        [0., 0., 0., 0.],
        [1., 1., 1., 1.],
        [1., 1., 1., 1.]])
tensor([[0., 0., 0., 0., 1., 1., 1., 1.],
        [0., 0., 0., 0., 1., 1., 1., 1.]])

8.1 torch.stack

  • torch.stack(seq, dim=0, out=None)
    1. 按照新的维度进行拼接
a = torch.linspace(1, 6, 6).view(2, 3)
b = torch.linspace(7, 12, 6).view(2, 3)
print(a)
print(b)

out = torch.stack((a, b), dim=0)
print(out)
# torch.Size([2, 2, 3])
print(out.shape)

out = torch.stack((a, b), dim=1)
print(out)
# torch.Size([2, 2, 3])
print(out.shape)

out = torch.stack((a, b), dim=2)
print(out)
# torch.Size([2, 3, 2])
print(out.shape)

print(out[:, :, 0])
print(out[:, :, 1])
tensor([[1., 2., 3.],
        [4., 5., 6.]])
tensor([[ 7.,  8.,  9.],
        [10., 11., 12.]])
tensor([[[ 1.,  2.,  3.],
         [ 4.,  5.,  6.]],

        [[ 7.,  8.,  9.],
         [10., 11., 12.]]])
torch.Size([2, 2, 3])
tensor([[[ 1.,  2.,  3.],
         [ 7.,  8.,  9.]],

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

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

9. 张量的切片

  • torch.chunk(tensor, chunks, dim=0)
    1. 按照某个维度平均分块(最后一个可能小于平均值)
  • torch.split(tensor, split_size_or_sections, dim=0)
    1. 按照某个维度依照第二个参数给出的list或者int进行分割tensor

9.1 torch.chunk

  • torch.chunk(tensor, chunks, dim=0)
    1. 按照某个维度平均分块(最后一个可能小于平均值)
import torch

a = torch.rand((3, 4))
print(a)
# 返回类型是tuple

# 以第一个维度为划分, 分成两个 tensor
out = torch.chunk(a, chunks=2, dim=0)
print(out[0], out[0].shape)
print(out[1], out[1].shape)

out = torch.chunk(a, 2, dim=1)
print(out[0], out[0].shape)
print(out[1], out[1].shape)
tensor([[0.1484, 0.1227, 0.5304, 0.4148],
        [0.7937, 0.2104, 0.0555, 0.8639],
        [0.4259, 0.7812, 0.6607, 0.1251]])
tensor([[0.1484, 0.1227, 0.5304, 0.4148],
        [0.7937, 0.2104, 0.0555, 0.8639]]) torch.Size([2, 4])
tensor([[0.4259, 0.7812, 0.6607, 0.1251]]) torch.Size([1, 4])
tensor([[0.1484, 0.1227],
        [0.7937, 0.2104],
        [0.4259, 0.7812]]) torch.Size([3, 2])
tensor([[0.5304, 0.4148],
        [0.0555, 0.8639],
        [0.6607, 0.1251]]) torch.Size([3, 2])

9.2 torch.split

  • torch.split(tensor, split_size_or_sections, dim=0)
    1. 按照某个维度依照第二个参数给出的list或者int进行分割tensor
a = torch.rand((10, 4))
print(a)
# 分隔成3个tensor
out = torch.split(a, 3, dim=0)
print(len(out))
# 分隔成3个[3, 4], 剩下一个为[1, 4]
for t in out:
    print(t, t.shape)

# 在第一维度上分割成, 1, 3, 6 三个大小的tensor
# 分别是 : [1,4] [3,4] [6, 4]
out = torch.split(a, [1, 3, 6], dim=0)
for t in out:
    print(t, t.shape)
tensor([[0.6004, 0.6201, 0.1652, 0.2628],
        [0.6705, 0.5896, 0.2873, 0.3486],
        [0.9579, 0.4075, 0.7819, 0.7165],
        [0.1768, 0.0748, 0.9799, 0.5261],
        [0.8427, 0.6036, 0.6608, 0.8735],
        [0.9741, 0.1682, 0.5625, 0.8731],
        [0.8622, 0.8106, 0.1381, 0.1399],
        [0.1976, 0.5628, 0.9983, 0.1842],
        [0.7664, 0.2233, 0.0299, 0.3937],
        [0.7881, 0.9642, 0.1895, 0.6085]])
4
tensor([[0.6004, 0.6201, 0.1652, 0.2628],
        [0.6705, 0.5896, 0.2873, 0.3486],
        [0.9579, 0.4075, 0.7819, 0.7165]]) torch.Size([3, 4])
tensor([[0.1768, 0.0748, 0.9799, 0.5261],
        [0.8427, 0.6036, 0.6608, 0.8735],
        [0.9741, 0.1682, 0.5625, 0.8731]]) torch.Size([3, 4])
tensor([[0.8622, 0.8106, 0.1381, 0.1399],
        [0.1976, 0.5628, 0.9983, 0.1842],
        [0.7664, 0.2233, 0.0299, 0.3937]]) torch.Size([3, 4])
tensor([[0.7881, 0.9642, 0.1895, 0.6085]]) torch.Size([1, 4])
tensor([[0.6004, 0.6201, 0.1652, 0.2628]]) torch.Size([1, 4])
tensor([[0.6705, 0.5896, 0.2873, 0.3486],
        [0.9579, 0.4075, 0.7819, 0.7165],
        [0.1768, 0.0748, 0.9799, 0.5261]]) torch.Size([3, 4])
tensor([[0.8427, 0.6036, 0.6608, 0.8735],
        [0.9741, 0.1682, 0.5625, 0.8731],
        [0.8622, 0.8106, 0.1381, 0.1399],
        [0.1976, 0.5628, 0.9983, 0.1842],
        [0.7664, 0.2233, 0.0299, 0.3937],
        [0.7881, 0.9642, 0.1895, 0.6085]]) torch.Size([6, 4])

10. Tensor的变形操作

  • torch.reshape(input, shape)
  • torch.t(input)
    1. 只针对2D tensor转置
  • torch.transpose(input, dim0, dim1)
    1. 交换两个维度
  • torch.squeeze(input, dim= None, out= None)
    1. 去除那些维度大小为1的维度
  • torch.unbind(tensor, dim=0)
    1. 去除某个维度
  • torch.unsqueeze(input, dim, out=None)
    1. 在指定位置添加维度
  • torch.flip(input, dims)
    1. 按照给定维度翻转张量
  • torch.rot90(input, k, dims)
    1. 按照指定维度和旋转次数进行张量旋转

10.1 torch.reshape

a = torch.rand(2, 3)
print(a)
out = torch.reshape(a, (3, 2))
print(out.shape)
tensor([[0.1581, 0.0801, 0.2709],
        [0.4418, 0.1935, 0.6829]])
torch.Size([3, 2])

10.2 torch.transpose

  • torch.t(out) : 针对二维向量转置
  • torch.transpose(out, dim0 = 0, dim1 = 1)
    1. 作用是指定维度进行转置
    2. dim0, dim1 是需要交换的维度, 0 是第一个维度, 1 是第二个维度
a = torch.rand(2, 3)

print(a)

out = torch.reshape(a, (3, 2))
print(out)
print(torch.t(out))
# 指定要交换的维度 , dim0 = 0 , dim=1
print(torch.transpose(out, 0, 1))
tensor([[0.3307, 0.9885, 0.4422],
        [0.4828, 0.0281, 0.1782]])
tensor([[0.3307, 0.9885],
        [0.4422, 0.4828],
        [0.0281, 0.1782]])
tensor([[0.3307, 0.4422, 0.0281],
        [0.9885, 0.4828, 0.1782]])
tensor([[0.3307, 0.4422, 0.0281],
        [0.9885, 0.4828, 0.1782]])

10.3 torch.squeeze

  • torch.squeeze(input, dim= None, out= None)
    1. 去除那些维度大小为1的维度
# 根据括号[] 判断维度
a = torch.rand(1, 2, 3)
print(a)
out = torch.squeeze(a)
print(out)
print(out.shape)
tensor([[[0.6601, 0.8238, 0.2413],
         [0.6084, 0.3180, 0.3877]]])
tensor([[0.6601, 0.8238, 0.2413],
        [0.6084, 0.3180, 0.3877]])
torch.Size([2, 3])

10.4 torch.unsqueeze

  • torch.unsqueeze(input, dim, out=None)
    1. 在指定位置添加维度
a = torch.rand(2, 3)
out = torch.unsqueeze(a, dim=0)
print(out.shape)

out = torch.unsqueeze(a, dim=1)
print(out.shape)

out = torch.unsqueeze(a, dim=-1)
print(out.shape)
torch.Size([1, 2, 3])
torch.Size([2, 1, 3])
torch.Size([2, 3, 1])

10.5 torch.unbind

  • torch.unbind(tensor, dim=0)
    1. 去除某个维度
    2. 去除某个维度后会得到一个 tuple
a = torch.rand(1, 2, 3)

print(a)
out = torch.unbind(a, dim=0)
print(out)

out = torch.unbind(a, dim=1)
print(out)

out = torch.unbind(a, dim=2)
print(out)
tensor([[[0.9891, 0.1500, 0.6211],
         [0.1303, 0.9269, 0.3060]]])
(tensor([[0.9891, 0.1500, 0.6211],
        [0.1303, 0.9269, 0.3060]]),)
(tensor([[0.9891, 0.1500, 0.6211]]), tensor([[0.1303, 0.9269, 0.3060]]))
(tensor([[0.9891, 0.1303]]), tensor([[0.1500, 0.9269]]), tensor([[0.6211, 0.3060]]))

10.6 torch.flip

  • torch.flip(input, dims)
    1. 按照给定维度翻转张量
    2. dims=[1,2] 对1和2维度上的数据进行翻转
a = torch.rand(1, 2, 3)
print(a)
# 对 1, 2维的数据进行翻转
print(torch.flip(a, dims=[1, 2]))
tensor([[[0.5802, 0.6525, 0.0502],
         [0.8643, 0.9359, 0.9133]]])
tensor([[[0.9133, 0.9359, 0.8643],
         [0.0502, 0.6525, 0.5802]]])

10.7 torch.rot90

  • torch.rot90(input, k, dims)
    1. 按照指定维度和旋转次数进行张量旋转
print(a)
out = torch.rot90(a, -1, dims=[0, 2])
print(out)
print(out.shape)
tensor([[[0.5802, 0.6525, 0.0502],
         [0.8643, 0.9359, 0.9133]]])
tensor([[[0.5802],
         [0.8643]],

        [[0.6525],
         [0.9359]],

        [[0.0502],
         [0.9133]]])
torch.Size([3, 2, 1])

11. 张量填充

  • 定义tensor并填充指定的值

11.1 torch.full

  • torch.full(size=(2, 3), fill_value=3.14)
    1. 填充指定的值
a = torch.full(size=(2, 3), fill_value=3.14)
print(a)
tensor([[3.1400, 3.1400, 3.1400],
        [3.1400, 3.1400, 3.1400]])

12. Tensor的频谱操作

  • torch.fft(input, signal ndim, normalized= False)
  • torch.ifft(input, signal ndim, normalized=False)
  • torch.rfft(input, signal_ ndim, normalized= False, onesided= True)
  • torch.irfft(input, signal_ ndim, normalized= False, onesided=True)
  • torch.stft(signa, frame_ length, hop, ..)