PyTorch 是一个开源的机器学习库,广泛应用于计算机视觉和自然语言处理等人工智能领域。由Facebook的人工智能研究团队开发,它基于之前的Torch库。PyTorch以其高度灵活和动态的计算图特性,在科研领域尤其受到青睐。下面是对PyTorch基础知识的一些介绍:

核心特性

  • 动态计算图:PyTorch 使用动态计算图(也称为Define-by-Run方法),这意味着计算图的构建是即时的,并且可以根据运行中的数据进行改变。这为复杂的动态输入和不同长度的输出提供了便利

  • 简洁的接口:PyTorch 提供了简洁直观的API,便于快速实现和调试模型,使得研究人员可以将更多时间投入到实验设计而非代码调试上

  • Python优先:PyTorch 设计为符合Python语言习惯,并且可以无缝集成到Python生态中,与NumPy等库协同工作

基础组件

  • 张量(Tensors):张量是PyTorch中的基础数据结构,它类似于NumPy的ndarrays,但它也可以在GPU上运行以加速计算

  • 自动微分(Autograd):PyTorch 的 autograd 模块提供了自动计算梯度的功能,对于实现神经网络中的反向传播算法至关重要

  • 神经网络(torch.nn)torch.nn 模块包含了构建神经网络所需的所有元素。这些可重用的层(例如卷积层、线性层等)和损失函数可以帮助用户轻松构建复杂的网络结构

  • 优化(torch.optim):PyTorch 提供了常用的优化算法,如SGD、Adam等,用于网络参数的迭代优化

  • 数据加载(torch.utils.data):PyTorch 提供了数据加载和处理工具,方便用户创建数据加载管道,加速数据预处理和模型训练过程

  • 序列化工具(Serialization):PyTorch 模型和张量可以通过 torch.save 轻松地序列化到磁盘,并通过 torch.load 进行反序列化

CUDA集成

  • PyTorch 提供了与NVIDIA CUDA的深度集成,允许张量和模型被无缝地在GPU上运行,大幅提升了计算速度

社区和生态

  • PyTorch 拥有活跃的社区,提供了大量预训练模型和开箱即用的工具。同时,它也是一些高级API(如FastAI)和框架(如Hugging Face的Transformers)的基础

PyTorch 不仅适合于研究原型的开发,还能用于生产环境的部署

它提供了一系列工具来支持模型的量化、蒸馏和优化,使其在不牺牲性能的情况下运行更快、占用资源更少。随着其持续发展和完善,PyTorch 已经成为了机器学习研究者和开发者的首选工具之一

基本操作

torch — PyTorch 2.2 documentation

pytorch中文文档

以下是一些常用的方法

torch.is_tensor: 如果obj是一个pytorch张量,则返回True

1
2
3
4
x=torch.tensor([1,2,3])
torch.is_tensor(x)

Out[0]: True

torch.is_storage: 如何obj是一个pytorch storage对象,则返回True

1
2
3
4
x=torch.tensor([1,2,3])
torch.is_storage(x)

Out[0]: False

torch.numel: 返回input 张量中的元素个数

1
2
3
4
5
6
7
a = torch.randn(1,2,3,4,5)
torch.numel(a)
Out[0]: 120

a = torch.zeros(4,4)
torch.numel(a)
Out[1]: 16

torch.set_printoptions: 设置打印选项

参数:

  • precision – 浮点数输出的精度位数 (默认为8 )
  • threshold – 阈值,触发汇总显示而不是完全显示(repr)的数组元素的总数 (默认为1000)
  • edgeitems – 汇总显示中,每维(轴)两端显示的项数(默认值为3)
  • linewidth – 用于插入行间隔的每行字符数(默认为80)。Thresholded matricies will ignore this parameter.
  • profile – pretty打印的完全默认值。 可以覆盖上述所有选项 (默认为short, full)

创建操作

张量创建函数

  • torch.tensor(): 通过复制数据创建一个具有自动求导历史的张量(如果数据是一个张量)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    >>> torch.tensor([[0.1, 1.2], [2.2, 3.1], [4.9, 5.2]])
    tensor([[ 0.1000, 1.2000],
    [ 2.2000, 3.1000],
    [ 4.9000, 5.2000]])

    >>> torch.tensor([0, 1]) # Type inference on data
    tensor([ 0, 1])

    >>> torch.tensor([[0.11111, 0.222222, 0.3333333]],
    ... dtype=torch.float64,
    ... device=torch.device('cuda:0')) # creates a double tensor on a CUDA device
    tensor([[ 0.1111, 0.2222, 0.3333]], dtype=torch.float64, device='cuda:0')

    >>> torch.tensor(3.14159) # Create a zero-dimensional (scalar) tensor
    tensor(3.1416)

    >>> torch.tensor([]) # Create an empty tensor (of size (0,))
    tensor([])
  • torch.sparse_coo_tensor(): 通过坐标格式的索引和值构建稀疏张量

    使用稀疏矩阵的一个主要优点是,在存储和计算上更加高效,特别是对于非常大的数据集。例如,在矩阵乘法或其他线性代数运算中,利用稀疏性可以显著减少不必要的乘法和加法计算,因为零元素与任何数相乘都是零,并且不会影响加法运算的结果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # 假设我们有2个非零元素分别在(0, 2)和(1, 0)的位置
    indices = torch.tensor([[0, 1], [2, 0]]) # 表示非零元素的坐标
    values = torch.tensor([3, 4]) # 这些非零元素的值
    # 创建COO格式的稀疏张量
    sparse_coo = torch.sparse_coo_tensor(indices, values, (2, 3))

    print(sparse_coo)
    tensor(indices=tensor([[0, 1],
    [2, 0]]),
    values=tensor([3, 4]),
    size=(2, 3), nnz=2, layout=torch.sparse_coo)
  • torch.sparse_csr_tensor(): 通过压缩稀疏行格式的索引和值构建稀疏张量

    torch.sparse_csc_tensor(): 通过压缩稀疏列格式的索引和值构建稀疏张量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # 定义CSR格式的三个组件:行索引、列索引和值
    crow_indices = torch.tensor([0, 1, 2])
    col_indices = torch.tensor([0, 1])
    values = torch.tensor([1, 2])
    # 创建CSR格式的稀疏张量
    sparse_csr = torch.sparse_csr_tensor(crow_indices, col_indices, values)

    print(sparse_csr)
    tensor(crow_indices=tensor([0, 1, 2]),
    col_indices=tensor([0, 1]),
    values=tensor([1, 2]), size=(2, 2), nnz=2, layout=torch.sparse_csr)
  • torch.sparse_bsr_tensor(): 通过块压缩稀疏行格式的索引和2维块构建稀疏张量

    torch.sparse_bsc_tensor(): 通过块压缩稀疏列格式的索引和2维块构建稀疏张量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    >>> crow_indices = [0, 1, 2]
    >>> col_indices = [0, 1]
    >>> values = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
    >>> torch.sparse_bsr_tensor(torch.tensor(crow_indices, dtype=torch.int64),
    ... torch.tensor(col_indices, dtype=torch.int64),
    ... torch.tensor(values), dtype=torch.double)
    tensor(crow_indices=tensor([0, 1, 2]),
    col_indices=tensor([0, 1]),
    values=tensor([[[1., 2.],
    [3., 4.]],
    [[5., 6.],
    [7., 8.]]]), size=(2, 2), nnz=2, dtype=torch.float64,
    layout=torch.sparse_bsr)

数据类型转换函数

  • torch.asarray(): 将对象转换为张量

    torch.as_tensor(): 将数据转换为张量,共享数据并尽可能保留自动求导历史

    torch.as_strided(): 创建一个具有指定大小、步长和存储偏移的现有张量的视图(不好理解)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    # 将对象转换为张量
    >>> a = torch.tensor([1, 2, 3])
    >>> # Shares memory with tensor 'a'
    >>> b = torch.asarray(a)
    >>> a.data_ptr() == b.data_ptr()
    True
    >>> # Forces memory copy
    >>> c = torch.asarray(a, copy=True)
    >>> a.data_ptr() == c.data_ptr()
    False

    # 将数据转换为张量,共享数据并尽可能保留自动求导历史
    >>> a = numpy.array([1, 2, 3])
    >>> t = torch.as_tensor(a)
    >>> t
    tensor([ 1, 2, 3])
    >>> t[0] = -1
    >>> a
    array([-1, 2, 3])
    >>> a = numpy.array([1, 2, 3])
    >>> t = torch.as_tensor(a, device=torch.device('cuda'))
    >>> t
    tensor([ 1, 2, 3])
    >>> t[0] = -1
    >>> a
    array([1, 2, 3])

    # 创建一个具有指定大小、步长和存储偏移的现有张量的视图
    >>> x = torch.randn(3, 3)
    >>> x
    tensor([[ 0.9039, 0.6291, 1.0795],
    [ 0.1586, 2.1939, -0.4900],
    [-0.1909, -0.7503, 1.9355]])
    >>> t = torch.as_strided(x, (2, 2), (1, 2))
    >>> t
    tensor([[0.9039, 1.0795],
    [0.6291, 0.1586]])
    >>> t = torch.as_strided(input=x, size=(2, 2), stride=(1, 2), storage_offset=1)
    tensor([[0.6291, 0.1586],
    [1.0795, 2.1939]])
  • torch.from_file(): 从内存映射文件创建CPU张量

    torch.from_numpy(): 将numpy数组转换为张量

    torch.from_dlpack(): 将来自外部库的张量转换为PyTorch张量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # 从内存映射文件创建CPU张量
    >>> t = torch.randn(2, 5, dtype=torch.float64)
    >>> t.numpy().tofile('storage.pt')
    >>> t_mapped = torch.from_file('storage.pt', shared=False, size=10, dtype=torch.float64)

    # 将numpy数组转换为张量
    >>> a = numpy.array([1, 2, 3])
    >>> t = torch.from_numpy(a)
    >>> t
    tensor([ 1, 2, 3])
    >>> t[0] = -1
    >>> a
    array([-1, 2, 3])

初始化填充函数

  • torch.zeros(): 返回一个指定形状且用0填充的张量

    torch.zeros_like(): 返回一个与给定张量形状相同且用0填充的张量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >>> torch.zeros(2, 3)
    tensor([[ 0., 0., 0.],
    [ 0., 0., 0.]])
    >>> torch.zeros(5)
    tensor([ 0., 0., 0., 0., 0.])

    >>> input = torch.empty(2, 3)
    >>> torch.zeros_like(input)
    tensor([[ 0., 0., 0.],
    [ 0., 0., 0.]])
  • torch.ones(): 返回一个指定形状且用1填充的张量

    torch.ones_like(): 返回一个与给定张量形状相同且用1填充的张量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >>> torch.ones(2, 3)
    tensor([[ 1., 1., 1.],
    [ 1., 1., 1.]])
    >>> torch.ones(5)
    tensor([ 1., 1., 1., 1., 1.])

    >>> input = torch.empty(2, 3)
    >>> torch.ones_like(input)
    tensor([[ 1., 1., 1.],
    [ 1., 1., 1.]])
  • torch.arange(): 返回一个从startend(不包含end)且步长为step的1维张量

    torch.range(): (未来版本弃用)返回一个从startend(包含end)且步长为step的1维张量

    1
    2
    3
    4
    5
    6
    >>> torch.arange(5)
    tensor([ 0, 1, 2, 3, 4])
    >>> torch.arange(1, 4)
    tensor([ 1, 2, 3])
    >>> torch.arange(1, 2.5, 0.5)
    tensor([ 1.0000, 1.5000, 2.0000])

特定区间填充函数

  • torch.linspace(): 返回一个从startend(包括end)且在其中均匀分布的指定大小的1维张量

    torch.logspace(): 返回一个在对数刻度上从(包括end)且均匀分布的指定大小的1维张量

    这两个函数生成的张量常常用于数据预处理、数学模拟、绘图等需要生成规则数列的场景

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    >>> torch.linspace(start=3, end=10, steps=5)
    tensor([ 3.0000, 4.7500, 6.5000, 8.2500, 10.0000])
    >>> torch.linspace(-10, 10, steps=5)
    tensor([-10., -5., 0., 5., 10.])
    >>> torch.linspace(start=-10, end=10, steps=5)
    tensor([-10., -5., 0., 5., 10.])
    >>> torch.linspace(start=-10, end=10, steps=1)
    tensor([-10.])

    >>> torch.logspace(start=-10, end=10, steps=5)
    tensor([ 1.0000e-10, 1.0000e-05, 1.0000e+00, 1.0000e+05, 1.0000e+10])
    >>> torch.logspace(start=0.1, end=1.0, steps=5)
    tensor([ 1.2589, 2.1135, 3.5481, 5.9566, 10.0000])
    >>> torch.logspace(start=0.1, end=1.0, steps=1)
    tensor([1.2589])
    >>> torch.logspace(start=2, end=2, steps=1, base=2)
    tensor([4.0])

其他辅助函数

  • torch.eye(): 返回一个二维张量,对角线上为1,其他地方为0

    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>> torch.eye(3)
    tensor([[ 1., 0., 0.],
    [ 0., 1., 0.],
    [ 0., 0., 1.]])

    >>> torch.eye(n=3, m=2)
    tensor([[1., 0.],
    [0., 1.],
    [0., 0.]])
  • torch.empty(): 返回一个指定形状且未初始化的张量

    torch.empty_like(): 返回一个与给定张量形状相同且未初始化的张量

    torch.empty_strided(): 创建一个具有指定大小和跨度且未初始化的张量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    >>> torch.empty((2,3), dtype=torch.int64)
    tensor([[ 9.4064e+13, 2.8000e+01, 9.3493e+13],
    [ 7.5751e+18, 7.1428e+18, 7.5955e+18]])

    >>> a=torch.empty((2,3), dtype=torch.int32, device = 'cuda')
    >>> torch.empty_like(a)
    tensor([[0, 0, 0],
    [0, 0, 0]], device='cuda:0', dtype=torch.int32)

    >>> a = torch.empty_strided((2, 3), (1, 2))
    >>> a
    tensor([[8.9683e-44, 4.4842e-44, 5.1239e+07],
    [0.0000e+00, 0.0000e+00, 3.0705e-41]])
    >>> a.stride()
    (1, 2)
    >>> a.size()
    torch.Size([2, 3])
  • torch.full(): 返回一个指定形状且用给定值填充的张量

    torch.full_like(): 返回一个与给定张量形状相同且用给定值填充的张量

    1
    2
    3
    4
    5
    6
    7
    >>> torch.full((2, 3), fill_value=3.141592)
    tensor([[ 3.1416, 3.1416, 3.1416],
    [ 3.1416, 3.1416, 3.1416]])

    >>> torch.full_like(torch.empty((2,3)), fill_value=9)
    tensor([[9., 9., 9.],
    [9., 9., 9.]])

量化函数

  • torch.quantize_per_tensor(): 将浮点张量转换为给定比例和零点的量化张量

    torch.quantize_per_channel(): 将浮点张量转换为按通道给定比例和零点的量化张量

  • torch.dequantize(): 通过去量化量化张量来返回一个fp32张量

复数和其他特殊类型函数

  • torch.complex(): 构造一个其实部等于real、虚部等于imag的复数张量

    1
    2
    3
    4
    5
    6
    7
    >>> real = torch.tensor([1, 2], dtype=torch.float32)
    >>> imag = torch.tensor([3, 4], dtype=torch.float32)
    >>> z = torch.complex(real, imag)
    >>> z
    tensor([(1.+3.j), (2.+4.j)])
    >>> z.dtype
    torch.complex64
  • torch.polar(): 根据极坐标的绝对值abs和角度angle构造复数张量的笛卡尔坐标

    1
    2
    3
    4
    5
    6
    >>> import numpy as np
    >>> abs = torch.tensor([1, 2], dtype=torch.float64)
    >>> angle = torch.tensor([np.pi / 2, 5 * np.pi / 4], dtype=torch.float64)
    >>> z = torch.polar(abs, angle)
    >>> z
    tensor([(0.0000+1.0000j), (-1.4142-1.4142j)], dtype=torch.complex128)
  • torch.heaviside(): 计算输入张量每个元素的Heaviside阶跃函数

    1
    2
    3
    4
    5
    6
    7
    8
    >>> input = torch.tensor([-1.5, 0, 2.0])
    >>> values = torch.tensor([0.5])
    >>> torch.heaviside(input, values)
    tensor([0.0000, 0.5000, 1.0000])

    >>> values = torch.tensor([1.2, -2.0, 3.5])
    >>> torch.heaviside(input, values)
    tensor([0., -2., 1.])

这些函数在数据预处理、模型初始化和其他计算任务中非常有用。通过这些函数,你可以创建大小、形状、种类各异的张量来满足不同的需求

索引|切片|连接|换位

这部分主要分为索引和切片、合并和拼接、变换和重塑、元素添加与替换、搜索和条件操作、扩展与重复操作

索引和切片

  • argwhere: 返回非零元素的索引

    nonzero: 返回非零元素的索引

    argwherenonzero 函数都用于查找非零元素的索引,但它们返回的格式略有不同。在某些编程库中,argwhere 通常返回一个二维数组,其中每一行都是输入中非零元素的索引坐标;而 nonzero 返回的是一个元组,每个元素是一个一维数组,表示非零元素在各个维度上的位置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    # argwhere
    >>> t = torch.tensor([1, 0, 1])
    >>> torch.argwhere(t)
    tensor([[0],
    [2]])
    >>> t = torch.tensor([[1, 0, 1], [0, 1, 1]])
    >>> torch.argwhere(t)
    tensor([[0, 0],
    [0, 2],
    [1, 1],
    [1, 2]])

    # nonzero
    >>> torch.nonzero(torch.tensor([1, 1, 1, 0, 1]))
    tensor([[ 0],
    [ 1],
    [ 2],
    [ 4]])
    >>> torch.nonzero(torch.tensor([[0.6, 0.0, 0.0, 0.0],
    ... [0.0, 0.4, 0.0, 0.0],
    ... [0.0, 0.0, 1.2, 0.0],
    ... [0.0, 0.0, 0.0,-0.4]]))
    tensor([[ 0, 0],
    [ 1, 1],
    [ 2, 2],
    [ 3, 3]])
    >>> torch.nonzero(torch.tensor([1, 1, 1, 0, 1]), as_tuple=True)
    (tensor([0, 1, 2, 4]),)
    >>> torch.nonzero(torch.tensor([[0.6, 0.0, 0.0, 0.0],
    ... [0.0, 0.4, 0.0, 0.0],
    ... [0.0, 0.0, 1.2, 0.0],
    ... [0.0, 0.0, 0.0,-0.4]]), as_tuple=True)
    (tensor([0, 1, 2, 3]), tensor([0, 1, 2, 3]))
    >>> torch.nonzero(torch.tensor(5), as_tuple=True)
    (tensor([0]),)
  • select: 在特定维度进行索引

    index_select: 根据索引选择数据

    • input (Tensor) – the input tensor.
    • dim (int) – the dimension in which we index
    • index (IntTensor or LongTensor) – the 1-D tensor containing the indices to index

    masked_select: 根据布尔掩码选择数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    # 在特定维度进行索引
    tensor = [[1, 2], [3, 4], [5, 6]]
    selected_row = select(tensor, dim=0, index=1)
    print(selected_row) # 输出: [3, 4]

    # 根据索引选择数据
    >>> x = torch.randn(3, 4)
    >>> x
    tensor([[ 0.1427, 0.0231, -0.5414, -1.0009],
    [-0.4664, 0.2647, -0.1228, -1.1068],
    [-1.1734, -0.6571, 0.7230, -0.6004]])
    >>> indices = torch.tensor([0, 2])
    >>> torch.index_select(x, 0, indices)
    tensor([[ 0.1427, 0.0231, -0.5414, -1.0009],
    [-1.1734, -0.6571, 0.7230, -0.6004]])
    >>> torch.index_select(x, 1, indices)
    tensor([[ 0.1427, -0.5414],
    [-0.4664, -0.1228],
    [-1.1734, 0.7230]])

    # 根据布尔掩码选择数据
    >>> x = torch.randn(3, 4)
    >>> x
    tensor([[ 0.3552, -2.3825, -0.8297, 0.3477],
    [-1.2035, 1.2252, 0.5002, 0.6248],
    [ 0.1307, -2.0608, 0.1244, 2.0139]])
    >>> mask = x.ge(0.5)
    >>> mask
    tensor([[False, False, False, False],
    [False, True, True, True],
    [False, False, False, True]])
    >>> torch.masked_select(x, mask)
    tensor([ 1.2252, 0.5002, 0.6248, 2.0139])
  • narrow: 缩小张量的一个维度

    • input (Tensor) – the tensor to narrow
    • dim (int) – the dimension along which to narrow
    • start (int or Tensor) – index of the element to start the narrowed dimension from. Can be negative, which means indexing from the end of dim. If Tensor, it must be an 0-dim integral Tensor (bools not allowed)
    • length (int) – length of the narrowed dimension, must be weakly positive
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    >>> x = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    >>> torch.narrow(x, 0, 0, 2)
    tensor([[ 1, 2, 3],
    [ 4, 5, 6]])
    >>> torch.narrow(x, 1, 1, 2)
    tensor([[ 2, 3],
    [ 5, 6],
    [ 8, 9]])
    >>> torch.narrow(x, -1, torch.tensor(-1), 1)
    tensor([[3],
    [6],
    [9]])
  • narrow_copy: narrow操作的复制版本

  • take: 根据索引从输入张量中取元素

    take_along_dim: 沿指定维度根据索引取元素

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    # 根据索引从输入张量中取元素
    >>> src = torch.tensor([[4, 3, 5],
    ... [6, 7, 8]])
    >>> torch.take(src, torch.tensor([0, 2, 5]))
    tensor([ 4, 5, 8])

    # 沿指定维度根据索引取元素
    >>> t = torch.tensor([[10, 30, 20], [60, 40, 50]])
    >>> max_idx = torch.argmax(t)
    >>> torch.take_along_dim(t, max_idx)
    tensor([60])
    >>> sorted_idx = torch.argsort(t, dim=1)
    >>> torch.take_along_dim(t, sorted_idx, dim=1)
    tensor([[10, 20, 30],
    [40, 50, 60]])
  • unbind: 按维度解绑张量

    1
    2
    3
    4
    >>> torch.unbind(torch.tensor([[1, 2, 3],
    >>> [4, 5, 6],
    >>> [7, 8, 9]]))
    (tensor([1, 2, 3]), tensor([4, 5, 6]), tensor([7, 8, 9]))
  • unravel_index: 将平面索引转换为坐标索引

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    >>> import torch
    >>> torch.unravel_index(torch.tensor(4), (3, 2))
    (tensor(2),
    tensor(0))

    >>> torch.unravel_index(torch.tensor([4, 1]), (3, 2))
    (tensor([2, 0]),
    tensor([0, 1]))

    >>> torch.unravel_index(torch.tensor([0, 1, 2, 3, 4, 5]), (3, 2))
    (tensor([0, 0, 1, 1, 2, 2]),
    tensor([0, 1, 0, 1, 0, 1]))

    >>> torch.unravel_index(torch.tensor([1234, 5678]), (10, 10, 10, 10))
    (tensor([1, 5]),
    tensor([2, 6]),
    tensor([3, 7]),
    tensor([4, 8]))

    >>> torch.unravel_index(torch.tensor([[1234], [5678]]), (10, 10, 10, 10))
    (tensor([[1], [5]]),
    tensor([[2], [6]]),
    tensor([[3], [7]]),
    tensor([[4], [8]]))

    >>> torch.unravel_index(torch.tensor([[1234], [5678]]), (100, 100))
    (tensor([[12], [56]]),
    tensor([[34], [78]]))
  • squeeze: 去除大小为1的维度

    unsqueeze: 在指定位置添加大小为1的维度

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    # 压缩维度
    >>> x = torch.zeros(2, 1, 2, 1, 2)
    >>> x.size()
    torch.Size([2, 1, 2, 1, 2])
    >>> y = torch.squeeze(x)
    >>> y.size()
    torch.Size([2, 2, 2])
    >>> y = torch.squeeze(x, 0)
    >>> y.size()
    torch.Size([2, 1, 2, 1, 2])
    >>> y = torch.squeeze(x, 1)
    >>> y.size()
    torch.Size([2, 2, 1, 2])
    >>> y = torch.squeeze(x, (1, 2, 3))
    torch.Size([2, 2, 2])

    # 增加维度
    >>> x = torch.tensor([1, 2, 3, 4])
    >>> torch.unsqueeze(x, 0)
    tensor([[ 1, 2, 3, 4]])
    >>> torch.unsqueeze(x, 1)
    tensor([[ 1],
    [ 2],
    [ 3],
    [ 4]])

合并和拼接

numpy中的hstack()、vstack()、stack()、concatenate()函数详解

  • cat, concat, concatenate: 将序列的张量在指定维度连接(concatconcatenatecat的别名)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    >>> x = torch.randn(2, 3)
    >>> x
    tensor([[ 0.6580, -1.0969, -0.4614],
    [-0.1034, -0.5790, 0.1497]])
    >>> torch.cat((x, x, x), 0)
    tensor([[ 0.6580, -1.0969, -0.4614],
    [-0.1034, -0.5790, 0.1497],
    [ 0.6580, -1.0969, -0.4614],
    [-0.1034, -0.5790, 0.1497],
    [ 0.6580, -1.0969, -0.4614],
    [-0.1034, -0.5790, 0.1497]])
    >>> torch.cat((x, x, x), 1)
    tensor([[ 0.6580, -1.0969, -0.4614, 0.6580, -1.0969, -0.4614, 0.6580,
    -1.0969, -0.4614],
    [-0.1034, -0.5790, 0.1497, -0.1034, -0.5790, 0.1497, -0.1034,
    -0.5790, 0.1497]])
  • chunk: 把张量分成指定数量的块

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    >>> torch.arange(11).chunk(6)
    (tensor([0, 1]),
    tensor([2, 3]),
    tensor([4, 5]),
    tensor([6, 7]),
    tensor([8, 9]),
    tensor([10]))

    # 创建一个张量
    x = torch.tensor([1, 2, 3, 4, 5])
    # 将这个张量分割成3个块
    chunks = torch.chunk(x, chunks=3, dim=0)
    # 输出分割后的块
    for i, chunk in enumerate(chunks):
    print(f"Chunk {i}: {chunk}")

    Chunk 0: tensor([1, 2])
    Chunk 1: tensor([3, 4])
    Chunk 2: tensor([5])
  • column_stack: 按列堆叠张量创建新张量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    >>> a = torch.tensor([1, 2, 3])
    >>> b = torch.tensor([4, 5, 6])
    >>> torch.column_stack((a, b))
    tensor([[1, 4],
    [2, 5],
    [3, 6]])

    >>> a = torch.arange(5)
    >>> b = torch.arange(10).reshape(5, 2)
    >>> torch.column_stack((a, b, b))
    tensor([[0, 0, 1, 0, 1],
    [1, 2, 3, 2, 3],
    [2, 4, 5, 4, 5],
    [3, 6, 7, 6, 7],
    [4, 8, 9, 8, 9]])
  • hstack: 水平方向堆叠张量

    vstack(别名row_stack): 垂直方向堆叠张量

    dstack: 深度方向堆叠张量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    # 水平方向堆叠张量
    >>> a = torch.tensor([1, 2, 3])
    >>> b = torch.tensor([4, 5, 6])
    >>> torch.hstack((a,b))
    tensor([1, 2, 3, 4, 5, 6])
    >>> a = torch.tensor([[1],[2],[3]])
    >>> b = torch.tensor([[4],[5],[6]])
    >>> torch.hstack((a,b))
    tensor([[1, 4],
    [2, 5],
    [3, 6]])

    # 垂直方向堆叠张量
    >>> a = torch.tensor([1, 2, 3])
    >>> b = torch.tensor([4, 5, 6])
    >>> torch.vstack((a,b))
    tensor([[1, 2, 3],
    [4, 5, 6]])
    >>> a = torch.tensor([[1],[2],[3]])
    >>> b = torch.tensor([[4],[5],[6]])
    >>> torch.vstack((a,b))
    tensor([[1],
    [2],
    [3],
    [4],
    [5],
    [6]])

    # 深度方向堆叠张量
    >>> a = torch.tensor([1, 2, 3])
    >>> b = torch.tensor([4, 5, 6])
    >>> torch.dstack((a,b))
    tensor([[[1, 4],
    [2, 5],
    [3, 6]]])
    >>> a = torch.tensor([[1],[2],[3]])
    >>> b = torch.tensor([[4],[5],[6]])
    >>> torch.dstack((a,b))
    tensor([[[1, 4]],
    [[2, 5]],
    [[3, 6]]])

    torch.dstacktorch.column_stack 函数都是用于堆叠张量的函数,但它们在堆叠的细节上有所不同

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    A = torch.tensor([[1, 2, 3],
    [4, 5, 6]])
    B = torch.tensor([[7, 8, 9],
    [10, 11, 12]])
    A.shape
    Out[27]: torch.Size([2, 3])

    # dstack是一整个对象堆叠
    dstack_result = torch.dstack((A, B))
    dstack_result
    Out[30]:
    tensor([[[ 1, 7],
    [ 2, 8],
    [ 3, 9]],
    [[ 4, 10],
    [ 5, 11],
    [ 6, 12]]])
    dstack_result.shape
    Out[31]: torch.Size([2, 3, 2])

    # column_stack专门用于二维张量(矩阵),它会将这些矩阵堆叠成一个更宽的矩阵(即增加列)
    column_stack_result = torch.column_stack((A, B))
    column_stack_result
    Out[33]:
    tensor([[ 1, 2, 3, 7, 8, 9],
    [ 4, 5, 6, 10, 11, 12]])
    column_stack_result.shape
    Out[34]: torch.Size([2, 6])
  • stack: 在新维度上连接张量序列

    pytorch的hstack、vstack、dstack、column_stack以及stack函数之间的区别和联系

    这些堆叠函数之间的联系在于它们的核心目的:将多个张量组合成一个新的、更大的张量

    不同的函数根据堆叠的方向(尺寸或维度)和具体的操作细节来区分,下面是它们之间联系的一个概览:

    维度方向的联系

    • hstack(水平堆叠)通常用于增加列数,适用于1D和2D张量,对于1D张量会先将其视作列向量
    • vstack(垂直堆叠)常用于增加行数,也适用于1D和2D张量,对于1D张量会先将其视作行向量
    • dstack(深度堆叠)是在第三个维度上进行堆叠,适用于创建或扩展为3D张量的情况
    • column_stackhstack相似,但它是专门设计来处理1D张量,将它们作为列向量来堆叠成2D张量的;对于2D张量,它的行为与hstack相同
    • stack是一个更通用的函数,可以在指定的任何维度上进行堆叠,而不局限于特定的堆叠方向。它总是增加一个新的维度来堆叠张量

    操作联系

    • 所有这些函数都是用来组合张量的,但是stack函数会创建一个新的维度,而其他函数(hstack, vstack, dstack, column_stack)则在现有的维度上进行操作
    • hstack, vstack, dstack, column_stack可以看作是stack的特例,它们在指定的一个特定的现有维度上进行操作(hstack在最后一个维度,vstack在第一个维度,dstack在第三个维度,column_stack针对1D张量在第二个新建维度,对2D张量在最后一个维度)

    使用场景联系

    • 当你想要在特定的轴方向上组合数据,而不想增加新的维度时,你会选择使用hstack, vstack, dstack, 或 column_stack
    • 当你需要在新的维度上堆叠张量时(例如,在时间序列数据或不同样本之间),你会选择使用stack

    在实际使用中,选择哪一个函数取决于你的具体需求以及你要操作的张量的维度。这些函数提供了方便的方式来对数据进行重构和整合,这是在准备数据集、构建深度学习模型等场景中非常常见的需求

  • hsplit: 水平方向分割张量

    vsplit: 垂直方向分割张量

    dsplit: 深度方向分割张量

    split: 分割张量成多个块,函数将张量分割成特定大小的块。你可以指定每个块的大小,或者传递一个包含每个块大小的列表。如果张量不能均匀分割,最后一块的大小将小于前面的块

    tensor_split: 沿特定维度分割张量,基于索引来分割张量的。你可以指定一个分割点的索引列表,函数会在这些索引处分割张量。这些索引指的是分割后每个新张量的第一个元素的索引

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    >>> t = torch.arange(16.0).reshape(4,4)
    >>> t
    tensor([[ 0., 1., 2., 3.],
    [ 4., 5., 6., 7.],
    [ 8., 9., 10., 11.],
    [12., 13., 14., 15.]])

    # 水平方向分割张量
    >>> torch.hsplit(t, 2)
    (tensor([[ 0., 1.],
    [ 4., 5.],
    [ 8., 9.],
    [12., 13.]]),
    tensor([[ 2., 3.],
    [ 6., 7.],
    [10., 11.],
    [14., 15.]]))
    >>> torch.hsplit(t, [3, 6])
    (tensor([[ 0., 1., 2.],
    [ 4., 5., 6.],
    [ 8., 9., 10.],
    [12., 13., 14.]]),
    tensor([[ 3.],
    [ 7.],
    [11.],
    [15.]]),
    tensor([], size=(4, 0)))

    # 垂直方向分割张量
    >>> torch.vsplit(t, 2)
    (tensor([[0., 1., 2., 3.],
    [4., 5., 6., 7.]]),
    tensor([[ 8., 9., 10., 11.],
    [12., 13., 14., 15.]]))
    >>> torch.vsplit(t, [3, 6])
    (tensor([[ 0., 1., 2., 3.],
    [ 4., 5., 6., 7.],
    [ 8., 9., 10., 11.]]),
    tensor([[12., 13., 14., 15.]]),
    tensor([], size=(0, 4)))

    # 深度方向分割张量
    >>> t = torch.arange(16.0).reshape(2, 2, 4)
    >>> t
    tensor([[[ 0., 1., 2., 3.],
    [ 4., 5., 6., 7.]],
    [[ 8., 9., 10., 11.],
    [12., 13., 14., 15.]]])
    >>> torch.dsplit(t, 2)
    (tensor([[[ 0., 1.],
    [ 4., 5.]],
    [[ 8., 9.],
    [12., 13.]]]),
    tensor([[[ 2., 3.],
    [ 6., 7.]],
    [[10., 11.],
    [14., 15.]]]))
    >>> torch.dsplit(t, [3, 6])
    (tensor([[[ 0., 1., 2.],
    [ 4., 5., 6.]],
    [[ 8., 9., 10.],
    [12., 13., 14.]]]),
    tensor([[[ 3.],
    [ 7.]],
    [[11.],
    [15.]]]),
    tensor([], size=(2, 2, 0)))

    # 分割张量成多个块
    >>> torch.split(t, 2, dim=0)
    (tensor([[0., 1., 2., 3.],
    [4., 5., 6., 7.]]),
    tensor([[ 8., 9., 10., 11.],
    [12., 13., 14., 15.]]))
    >>> torch.split(t, [1, 3], dim=0)
    (tensor([[0., 1., 2., 3.]]),
    tensor([[ 4., 5., 6., 7.],
    [ 8., 9., 10., 11.],
    [12., 13., 14., 15.]]))

    # 沿特定维度分割张量
    >>> torch.tensor_split(t, [1, 2], dim=0)
    (tensor([[0., 1., 2., 3.]]),
    tensor([[4., 5., 6., 7.]]),
    tensor([[ 8., 9., 10., 11.],
    [12., 13., 14., 15.]]))

变换和重塑

  • adjoint: 返回共轭的张量,并交换最后两维

  • conj: 返回共轭位翻转的张量视图

  • gather: 沿指定维度聚集值

    1
    torch.gather(input, dim, index, *, sparse_grad=False) -> Tensor

    其中参数的意义如下:

    • input 是要从中提取数据的张量
    • dim 是要沿着哪个维度进行提取
    • index 是与 input 张量在除了 dim 指定的维度外具有相同大小的张量,包含了要提取的元素的索引
    • sparse_grad 是布尔值,用于指示是否进行稀疏梯度的计算;通常用于高级用途
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    # 创建一个 3x3 的矩阵
    input_tensor = torch.tensor([[1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]])

    # 创建一个索引,用于选择每一行的第二个元素
    index = torch.tensor([[1], [1], [1]])

    # 使用 gather 来提取元素,dim=1 表示沿着列的方向进行操作
    torch.gather(input_tensor, 1, index)
    # 输出:[[2], [5], [8]]

    >>> t = torch.tensor([[1, 2], [3, 4]])
    >>> torch.gather(t, 1, torch.tensor([[0, 0], [1, 0]]))
    tensor([[ 1, 1],
    [ 4, 3]])
  • movedim(别名moveaxis): 移动张量维度位置的函数,这个操作可以让你指定某个维度(或多个维度)从它的原始位置移动到一个新的位置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    >>> t = torch.randn(3,2,1)
    >>> t
    tensor([[[-0.3362],
    [-0.8437]],

    [[-0.9627],
    [ 0.1727]],

    [[ 0.5173],
    [-0.1398]]])
    >>> torch.moveaxis(t, 1, 0).shape
    torch.Size([2, 3, 1])
    >>> torch.moveaxis(t, 1, 0)
    tensor([[[-0.3362],
    [-0.9627],
    [ 0.5173]],

    [[-0.8437],
    [ 0.1727],
    [-0.1398]]])
    >>> torch.moveaxis(t, (1, 2), (0, 1)).shape
    torch.Size([2, 1, 3])
    >>> torch.moveaxis(t, (1, 2), (0, 1))
    tensor([[[-0.3362, -0.9627, 0.5173]],
    [[-0.8437, 0.1727, -0.1398]]])


    tensor = torch.randn(10, 3, 5)
    torch.movedim(tensor, 1, 0).size()
    Out[78]: torch.Size([3, 10, 5])
  • permute: 重新排列张量的维度,重组tensor维度,支持高维操作,tensor.permute(dim0, dim1, … dimn),表示原本的dim0放在第0维度,dim1放在第1维度,…, dimn放在第n维度,必须将所有维度写上

    reshape: 改变张量的形状,需要指定最终的形状

    transpose(等价于swapaxesswapdims): 转置张量的维度

    捋清pytorch的transpose、permute、view、reshape、contiguous

    permute可以完全替代transpose,transpose不能替代permute

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    # permute重新排列张量的维度
    >>> x = torch.randn(2, 3, 5)
    >>> x.size()
    torch.Size([2, 3, 5])
    >>> torch.permute(x, (2, 0, 1)).size()
    torch.Size([5, 2, 3])

    # reshape改变张量的形状
    >>> a = torch.arange(4.)
    >>> torch.reshape(a, (2, 2))
    tensor([[ 0., 1.],
    [ 2., 3.]])
    >>> b = torch.tensor([[0, 1], [2, 3]])
    >>> torch.reshape(b, (-1,))
    tensor([ 0, 1, 2, 3])

    # transpose转置张量的维度
    >>> x = torch.randn(2, 3)
    >>> x
    tensor([[ 1.0028, -0.9893, 0.5809],
    [-0.1669, 0.7299, 0.4942]])
    >>> torch.transpose(x, dim0=0, dim1=1)
    tensor([[ 1.0028, -0.1669],
    [-0.9893, 0.7299],
    [ 0.5809, 0.4942]])
  • t: 转置二维张量的维度

    期望输入是一个二维或二维以下的张量,并交换维度0和1

    当输入是一个零维或一维张量时,返回的张量保持不变。当输入是一个二维张量时,这相当于 transpose(input, 0, 1)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    >>> x = torch.randn(())
    >>> x
    tensor(0.1995)
    >>> torch.t(x)
    tensor(0.1995)
    >>> x = torch.randn(3)
    >>> x
    tensor([ 2.4320, -0.4608, 0.7702])
    >>> torch.t(x)
    tensor([ 2.4320, -0.4608, 0.7702])
    >>> x = torch.randn(2, 3)
    >>> x
    tensor([[ 0.4875, 0.9158, -0.5872],
    [ 0.3938, -0.6929, 0.6932]])
    >>> torch.t(x)
    tensor([[ 0.4875, 0.3938],
    [ 0.9158, -0.6929],
    [-0.5872, 0.6932]])

元素添加与替换

  • index_add: 根据索引向张量添加元素

    index_copy: 根据索引复制元素到张量

    index_reduce: 在指定维度上,根据索引减少元素

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    >>> x = torch.ones(5, 3)
    >>> t = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=torch.float)
    >>> index = torch.tensor([0, 4, 2])
    >>> x.index_add(0, index=index, source=t)
    tensor([[ 2., 3., 4.],
    [ 1., 1., 1.],
    [ 8., 9., 10.],
    [ 1., 1., 1.],
    [ 5., 6., 7.]])
    >>> x.index_add(0, index, t, alpha=-1)
    tensor([[ 0., -1., -2.],
    [ 1., 1., 1.],
    [-6., -7., -8.],
    [ 1., 1., 1.],
    [-3., -4., -5.]])

  • scatter, scatter_add, scatter_reduce: 根据索引分散和添加元素

    1
    scatter(output, dim, index, src) 

    catter函数就是把src数组中的数据重新分配到output数组当中,index数组中表示了要把src数组中的数据分配到output数组中的位置,若未指定,则填充0

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    >>> input = torch.randn(2, 4)
    >>> print(input)
    tensor([[ 1.4782, -1.1345, -1.1457, -0.6050],
    [-0.4183, -0.0229, 1.2361, -1.7747]])

    >>> output = torch.zeros(2, 5)
    >>> index = torch.tensor([[3, 1, 2, 0], [1, 2, 0, 3]])
    >>> output = output.scatter(dim=1, index=index, src=input)
    >>> print(output)
    tensor([[-0.6050, -1.1345, -1.1457, 1.4782, 0.0000],
    [ 1.2361, -0.4183, -0.0229, -1.7747, 0.0000]])

    一般scatter用于生成onehot向量,如下所示

    1
    2
    3
    4
    5
    6
    7
    8
    >>> index = torch.tensor([[1], [2], [0], [3]])
    >>> onehot = torch.zeros(4, 4)
    >>> onehot.scatter_(1, index, 1)
    >>> print(onehot)
    tensor([[0., 1., 0., 0.],
    [0., 0., 1., 0.],
    [1., 0., 0., 0.],
    [0., 0., 0., 1.]])
  • diagonal_scatter: 沿对角线分散元素

  • select_scatter: 在给定索引处分散元素

  • slice_scatter: 在给定维度上分散元素

搜索和条件操作

  • where: 根据条件从两个张量中选择元素

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    >>> x = torch.randn(3, 2)
    >>> y = torch.ones(3, 2)
    >>> x
    tensor([[-0.4620, 0.3139],
    [ 0.3898, -0.7197],
    [ 0.0478, -0.1657]])

    >>> torch.where(condition=x > 0, input=1.0, other=0.0)
    tensor([[0., 1.],
    [1., 0.],
    [1., 0.]])

    >>> torch.where(condition=x > 0, input=x, other=y)
    tensor([[ 1.0000, 0.3139],
    [ 0.3898, 1.0000],
    [ 0.0478, 1.0000]])

    >>> x = torch.randn(2, 2, dtype=torch.double)
    >>> x
    tensor([[ 1.0779, 0.0383],
    [-0.8785, -1.1089]], dtype=torch.float64)
    >>> torch.where(condition=x > 0, input=x, other=0.)
    tensor([[1.0779, 0.0383],
    [0.0000, 0.0000]], dtype=torch.float64)

扩展与重复操作

  • tile: 通过重复张量的元素来构建新张量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >>> x = torch.tensor([1, 2, 3])
    >>> x.tile((2,))
    tensor([1, 2, 3, 1, 2, 3])

    >>> y = torch.tensor([[1, 2], [3, 4]])
    >>> torch.tile(y, (2, 2))
    tensor([[1, 2, 1, 2],
    [3, 4, 3, 4],
    [1, 2, 1, 2],
    [3, 4, 3, 4]])

随机抽样

随机种子

  • torch.seed: 设置torch cpu随机数种子

    torch.manual_seed: 设置torch cpu随机数种子,torch.manual_seed(seed)

    torch.cuda.manual_seed: 设置torch cuda随机数种子

    torch.initial_seed: 查看设置的种子值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    torch.seed()
    Out[112]: 2362131181677400
    torch.initial_seed()
    Out[113]: 2362131181677400

    torch.manual_seed(101)
    Out[114]: <torch._C.Generator at 0x137cd248b10>
    torch.initial_seed()
    Out[115]: 101
    torch.cuda.manual_seed(0)
    torch.initial_seed()
    Out[116]: 0
  • get_rng_state(): 返回当前随机数生成器的状态。这个状态是一个torch.ByteTensor,它包含了RNG内部的所有状态信息,使得RNG可以在这个状态下继续生成随机数序列。这允许你在某个特定点“保存”RNG的状态,然后在需要的时候恢复到这个状态

  • set_rng_state(state): 设置随机数生成器的状态。state应该是通过get_rng_state()函数获取的状态张量。这个函数用于恢复RNG到一个特定的状态,这样可以从那个状态开始重新生成相同的随机数序列

随机采样函数

常见的概率分布参考 — 兼一书虫-机器学习概率论(1)

  • torch.rand(): 创建一个具有给定形状的张量,并用区间[0, 1)内的均匀分布的随机数填充

    torch.rand_like(): 返回一个与给定张量形状相同的张量,并用区间[0, 1)内的均匀分布的随机数填充

    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>> torch.rand(4)
    tensor([ 0.5204, 0.2503, 0.3525, 0.5673])
    >>> torch.rand(2, 3)
    tensor([[ 0.8237, 0.5781, 0.6879],
    [ 0.3816, 0.7249, 0.0998]])

    >>> torch.rand_like(torch.rand(2, 3))
    tensor([[0.3885, 0.9888, 0.4838],
    [0.8154, 0.6068, 0.6895]])
  • torch.randn(): 返回一个具有给定形状的张量,并用标准正态分布的随机数填充

    torch.randn_like(): 返回一个与给定张量形状相同的张量,并用标准正态分布的随机数填充

    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>> torch.randn(4)
    tensor([-2.1436, 0.9966, 2.3426, -0.6366])
    >>> torch.randn(2, 3)
    tensor([[ 1.5954, 2.8929, -1.0923],
    [ 1.1719, -0.4709, -0.1996]])

    >>> torch.randn_like(torch.randn(2, 3))
    tensor([[ 0.9979, 0.0471, -1.1305],
    [ 0.7216, -0.0747, 0.0610]])
  • torch.randint(): 返回一个具有给定形状的张量,并用区间[low, high)内的随机整数填充

    torch.randint_like(): 返回一个与给定张量形状相同的张量,并用区间[low, high)内的随机整数填充

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    >>> torch.randint(low=3, high=5, size=(3,))
    tensor([4, 3, 4])
    >>> torch.randint(10, (2, 2))
    tensor([[0, 2],
    [5, 5]])
    >>> torch.randint(3, 10, (2, 2))
    tensor([[4, 5],
    [6, 7]])

    >>> torch.randint_like(input=torch.randint(low=3, high=5, size=(3,)), low=6, high=10)
    tensor([8, 9, 9])
  • torch.randperm(): 返回一个从0到给定参数n - 1的整数的随机排列

    1
    2
    >>> torch.randperm(4)
    tensor([2, 1, 0, 3])
  • torch.bernoulli: 从伯努利分布中提取二进制随机数(0或1),输入张量应为包含用于绘制二进制随机数的概率的张量

    因此,输入中的所有值都必须在以下范围内(0,1)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    >>> a = torch.empty(3, 3).uniform_(0, 1)  # generate a uniform random matrix with range [0, 1]
    >>> a
    tensor([[ 0.1737, 0.0950, 0.3609],
    [ 0.7148, 0.0289, 0.2676],
    [ 0.9456, 0.8937, 0.7202]])
    >>> torch.bernoulli(a)
    tensor([[ 1., 0., 0.],
    [ 0., 0., 0.],
    [ 1., 1., 1.]])

    >>> a = torch.ones(3, 3) # probability of drawing "1" is 1
    >>> torch.bernoulli(a)
    tensor([[ 1., 1., 1.],
    [ 1., 1., 1.],
    [ 1., 1., 1.]])
    >>> a = torch.zeros(3, 3) # probability of drawing "1" is 0
    >>> torch.bernoulli(a)
    tensor([[ 0., 0., 0.],
    [ 0., 0., 0.],
    [ 0., 0., 0.]])
  • torch.poisson: 泊松分布用于计算一个事件在平均价值率(时间)的一定时间内发生的可能性。泊松分布是一个离散的概率分布

    1
    2
    3
    4
    5
    6
    >>> rates = torch.rand(4, 4) * 5  # rate parameter between 0 and 5
    >>> torch.poisson(rates)
    tensor([[9., 1., 3., 5.],
    [8., 6., 6., 0.],
    [0., 4., 5., 3.],
    [2., 1., 4., 2.]])
  • torch.multinomial: 对input的每一行做n_samples次取值,输出的张量是每一次取值时input张量对应行的下标

    • input (Tensor) – 包含概率值的张量
    • num_samples (int) – 抽取的样本数
    • replacement (bool, optional) – 布尔值,决定是否能重复抽取
    • out (Tensor, optional) – 结果张量
    1
    2
    3
    4
    5
    6
    7
    8
    weights = torch.Tensor([0, 10, 3, 0])

    torch.multinomial(weights, 4)
    Out[0]: tensor([2, 1, 0, 3])

    # replacement=True时 概率为0的没机会被取到
    torch.multinomial(weights, 4, replacement=True)
    Out[1]: tensor([2, 1, 1, 1])
  • torch.normal: 返回一个张量,包含从给定参数means,std的离散正态分布中抽取随机数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    torch.normal(mean=torch.arange(1., 11.), std=torch.arange(1, 0, -0.1))
    Out[0]:
    tensor([ 0.9732, 2.0833, 2.5282, 4.3588, 5.4837, 5.1150, 7.0366, 7.9774,
    9.1679, 10.0248])

    torch.normal(mean=0.5, std=torch.arange(1., 6.))
    Out[1]: tensor([ 0.7067, 2.4856, -2.1957, -4.3114, 16.2506])

    torch.normal(mean=torch.arange(1., 6.))
    Out[2]: tensor([0.7835, 4.6096, 2.7244, 5.2810, 4.8413])

序列化

  • torch.save: 保存一个对象到一个硬盘文件上 参考: Recommended approach for saving a model

    torch.save(obj, f, pickle_module=pickle, pickle_protocol=DEFAULT_PROTOCOL, _use_new_zipfile_serialization=True)

    • obj – 保存对象
    • f - 类文件对象 (返回文件描述符)或一个保存文件名的字符串
    • pickle_module – 用于pickling元数据和对象的模块
    • pickle_protocol – 指定pickle protocal 可以覆盖默认参数
    1
    2
    3
    4
    5
    6
    7
    8
    x = torch.tensor([0, 1, 2, 3, 4])

    # Save to file
    torch.save(x, 'tensor.pt')

    # Save to io.BytesIO buffer
    buffer = io.BytesIO()
    torch.save(x, buffer)
  • torch.load: 从磁盘文件中读取一个通过torch.save()保存的对象

    torch.load(f, map_location=None, pickle_module=pickle, , weights_only=False, pickle_load_args*)

    1
    2
    3
    4
    5
    6
    7
    8
    torch.load('tensors.pt', encoding='ascii')
    torch.load('tensors.pt', map_location=torch.device('cpu'))
    torch.load('tensors.pt', map_location={'cuda:1':'cuda:0'})

    # Load from io.BytesIO buffer
    with open('tensor.pt', 'rb') as f:
    buffer = io.BytesIO(f.read())
    torch.load(buffer)

并行化

在PyTorch中,CPU操作可以通过多线程来并行化,以此提高性能。这里涉及到两种形式的并行化:intra-op并行和inter-op并行。下面是关于这些函数的解释:

  1. get_num_threads(): 这个函数返回用于在CPU上并行执行操作(即intra-op并行)的线程数。Intra-op并行是指单个操作(如矩阵乘法)内部的并行执行。PyTorch会尝试使用所有可用的CPU核心来加速这些操作

  2. set_num_threads(int): 这个函数用来设置在CPU上进行intra-op并行操作时使用的线程数。如果你想限制PyTorch使用的CPU核心数量,可以调用这个函数

  3. get_num_interop_threads(): 这个函数返回用于CPU上的inter-op并行的线程数。Inter-op并行是指不同操作之间的并行执行。例如,如果你有多个不依赖于彼此的操作,PyTorch可以同时执行它们以提高效率

  4. set_num_interop_threads(int): 这个函数用来设置用于inter-op并行的线程数。通过设定线程数,可以控制同时进行的不同操作的数量

在多核CPU上,适当地设置这些值可以帮助你更好地利用系统资源,提高程序的运行效率。然而,如果设置的线程数太多,可能会导致线程竞争和上下文切换的开销,反而降低性能

通常默认设置是已经针对性能进行了优化,但是在特定的系统和应用场景下,手动调整这些值可以获得更佳的性能表现

梯度管理

在PyTorch中,梯度计算对于训练神经网络是必要的,因为它们用于优化模型的参数。然而,在某些情况下,比如在模型评估或应用阶段,你可能不需要计算梯度。梯度计算会占用额外的内存和计算资源,禁用它们可以提高效率。为了方便地开启和关闭梯度计算,PyTorch提供了几个上下文管理器:

  1. torch.no_grad():

    1
    2
    3
    with torch.no_grad():
    # 在这个代码块中,所有的操作都不会跟踪梯度
    predictions = model(inputs)

    在这个例子中,model(inputs) 的执行不会计算梯度,这对于模型推断(inference)阶段非常有用,因为它减少了内存消耗并提高了计算速度

  2. torch.enable_grad():

    1
    2
    3
    4
    5
    with torch.enable_grad():
    # 在这个代码块中,梯度计算是启用的
    predictions = model(inputs)
    loss = loss_fn(predictions, targets)
    loss.backward()

    这里,即使全局梯度计算被禁用,torch.enable_grad() 仍可以在其作用域内启用梯度计算,以便计算损失函数的梯度

  3. torch.set_grad_enabled():

    1
    2
    3
    4
    5
    6
    torch.set_grad_enabled(mode=True) # 启用梯度计算
    # 后续操作将会跟踪梯度
    predictions = model(inputs)
    loss = loss_fn(predictions, targets)
    loss.backward()
    torch.set_grad_enabled(mode=False) # 禁用梯度计算

    在这里,使用torch.set_grad_enabled()函数来全局地控制是否计算梯度。传递TrueFalse可以分别开启或关闭梯度计算

  4. torch.is_grad_enabled():

    1
    print(torch.is_grad_enabled()) # 打印当前是否启用了梯度计算

    这个函数用来检查当前是否启用了梯度计算

  5. torch.inference_mode():

    1
    2
    3
    with torch.inference_mode():
    # 在这个代码块中,所有的操作都不会跟踪梯度,且某些优化会被应用以加速推断
    predictions = model(inputs)

    torch.inference_mode() 更适合用在推断阶段,相比torch.no_grad(),它会启用额外的优化,比如禁用自动求导引擎和解除对操作immutable的限制,从而实现更高效的模型推断

  6. torch.is_inference_mode_enabled():

    1
    2
    3
    with torch.inference_mode():
    print(torch.is_inference_mode_enabled()) # 在 inference mode 中,这将输出 True
    print(torch.is_inference_mode_enabled()) # 在 inference mode 外部,这将输出 False

    这个函数用来检查当前是否启用了推断模式。在torch.inference_mode()上下文管理器的内部,它会返回True

每个上下文管理器和函数都有其用途,根据需要进行梯度计算的控制,可以优化您的PyTorch 程序的性能

数学操作

torch — PyTorch 2.2 documentation-数学操作

基础操作

  • torch.add: 对输入张量input逐元素加上标量值value,并返回结果到一个新的张量

    torch.addcdiv: 用tensor2tensor1逐元素相除,然后乘以标量值value 并加到tensor,张量的形状不需要匹配,但元素数量必须一致

    • tensor (Tensor) – 张量,对 tensor1 ./ tensor 进行相加
    • value (Number, optional) – 标量,对 tensor1 ./ tensor2 进行相乘
    • tensor1 (Tensor) – 张量,作为被除数(分子)
    • tensor2 (Tensor) –张量,作为除数(分母)
    • out (Tensor, optional) – 输出张量

    torch.addcmul: 用tensor2tensor1逐元素相乘,并对结果乘以标量值value然后加到tensor

    • tensor (Tensor) – 张量,对tensor1 ./ tensor 进行相加
    • value (Number, optional) – 标量,对 tensor1 . tensor2 进行相乘
    • tensor1 (Tensor) – 张量,作为乘子1
    • tensor2 (Tensor) –张量,作为乘子2
    • out (Tensor, optional) – 输出张量

    以上两个可以用于正则化操作

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    # 对输入张量`input`逐元素加上标量值`value`,并返回结果到一个新的张量
    a = torch.randn(4)
    Out[0]: tensor([ 0.3510, -0.2226, -0.7971, -0.2564])
    torch.add(a, 20)
    Out[1]: tensor([20.3510, 19.7774, 19.2029, 19.7436])

    # 用`tensor2`对`tensor1`逐元素相除,然后乘以标量值`value` 并加到`tensor`
    t = torch.randn(1, 3)
    t1 = torch.randn(3, 1)
    t2 = torch.randn(1, 3)
    t, t1, t2
    Out[0]:
    (tensor([[-1.2863, 1.1267, -1.7120]]),
    tensor([[-0.4294],
    [-0.5328],
    [-0.5373]]),
    tensor([[-0.0876, 0.4398, 1.3583]]))

    torch.addcdiv(t, t1, t2, value=0.1)
    Out[1]:
    tensor([[-0.7958, 1.0291, -1.7436],
    [-0.6778, 1.0056, -1.7512],
    [-0.6727, 1.0046, -1.7515]])

    # 用`tensor2`对`tensor1`逐元素相乘,并对结果乘以标量值`value`然后加到`tensor`
    t = torch.randn(1, 3)
    t1 = torch.randn(3, 1)
    t2 = torch.randn(1, 3)
    t, t1, t2
    Out[0]:
    (tensor([[-1.2863, 1.1267, -1.7120]]),
    tensor([[-0.4294],
    [-0.5328],
    [-0.5373]]),
    tensor([[-0.0876, 0.4398, 1.3583]]))

    torch.addcmul(t, t1, t2, value=0.1)
    Out[1]:
    tensor([[-1.2825, 1.1078, -1.7703],
    [-1.2816, 1.1033, -1.7844],
    [-1.2816, 1.1031, -1.7850]])
  • torch.ceil: 对输入input张量每个元素向上取整, 即取不小于每个元素的最小整数

    torch.clamp(别名torch.clip): 将输入input张量每个元素的夹紧到区间,并返回结果到一个新张量

    torch.floor: 返回一个新张量,包含输入input张量每个元素的floor,即不小于元素的最大整数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    # torch.ceil
    a = torch.randn(4)
    Out[0]: tensor([-0.9105, -0.7277, 0.9516, -0.1081])
    torch.ceil(a)
    Out[1]: tensor([-0., -0., 1., -0.])

    # torch.floor
    a = torch.randn(4)
    Out[0]: tensor([-0.5661, -0.9135, 1.1018, -0.2633])
    torch.floor(a)
    Out[1]: tensor([-1., -1., 1., -1.])

    # torch.clamp
    a = torch.randn(4)
    Out[0]: tensor([-0.9105, -0.7277, 0.9516, -0.1081])
    torch.clamp(a, min=-0.5, max=0.5)
    Out[1]: tensor([-0.5000, -0.5000, 0.5000, -0.1081])
  • torch.div(别名torch.divide): 将input逐元素除以标量值value,并返回结果到输出张量out,torch.div(input, value, out=None)

    两张量inputother逐元素相除,并将结果返回到输出,torch.div(input, other, **, rounding_mode=None, out=None*) → Tensor

    torch.mul(别米torch.multiply): 用标量值value乘以输入input的每个元素,并返回一个新的结果张量,torch.mul(input, value, out=None)

    两个张量input,other按元素进行相乘,并返回到输出张量,torch.mul(input, other, out=None)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    # 元素除
    a = torch.randn(4)
    Out[0]: tensor([-0.9105, -0.7277, 0.9516, -0.1081])
    torch.div(a, 0.5)
    Out[1]: tensor([-1.8210, -1.4554, 1.9032, -0.2162])
    a = torch.tensor([[-0.3711, -1.9353, -0.4605, -0.2917],
    [ 0.1815, -1.0111, 0.9805, -1.5923]])
    b = torch.tensor([ 0.8032, 0.2930, -0.8113, -0.2308])
    torch.div(a, b, rounding_mode='trunc')
    Out[2]:
    tensor([[-0., -6., 0., 1.],
    [ 0., -3., -1., 6.]])
    torch.div(a, b, rounding_mode='floor')
    Out[3]:
    tensor([[-1., -7., 0., 1.],
    [ 0., -4., -2., 6.]])

    # 元素乘
    a = torch.randn(3)
    Out[0]: tensor([ 0.0603, -0.5258, -0.3810])
    b = torch.randn(3)
    Out[1]: tensor([ 1.2408, -1.3506, 0.9296])
    torch.mul(a, 100)
    Out[2]: tensor([ 6.0299, -52.5785, -38.0989])
    torch.mul(a, b)
    Out[3]: tensor([ 0.0748, 0.7101, -0.3542])
  • torch.exp: 返回一个新张量,包含输入input张量每个元素的指数

    torch.frac: 返回每个元素的分数部分

    torch.log: 计算input 的自然对数

    torch.log1p: 计算的自然对数,对值比较小的输入,此函数比torch.log()更准确

    torch.neg(别名torch.negative): 返回一个新张量,包含输入input 张量按元素取负

    torch.pow: 对输入input的按元素求exponent次幂值,并返回结果张量,幂值exponent 可以为单一 float 数或者与input相同元素数的张量

    torch.round: (四舍五入)返回一个新张量,将输入input张量每个元素舍入到最近的整数

    torch.trunc: (四舍五入(去尾法))返回一个新张量,包含输入input张量每个元素的截断值(标量x的截断值是最接近其的整数),简而言之,有符号数的小数部分被舍弃

    torch.rsqrt: 返回一个新张量,包含输入input张量每个元素的平方根倒数

    torch.fmod: 计算逐元素余数,保留正负号

    torch.remainder: 计算逐元素余数, 相当于python中的%操作符,不保留正负号

    torch.reciprocal: 返回一个新张量,包含输入input张量每个元素的倒数,即 1.0/x

    torch.sqrt: 返回一个新张量,包含输入input张量每个元素的平方根

    torch.abs(别名为torch.absolute): 计算输入张量的每个元素绝对值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    # 返回一个新张量,包含输入`input`张量每个元素的指数
    torch.exp(torch.Tensor([0, math.log(2)]))
    Out[0]: tensor([1., 2.])

    # 返回每个元素的分数部分
    torch.frac(torch.Tensor([1, 2.5, -3.2]))
    Out[0]: tensor([ 0.0000, 0.5000, -0.2000])

    # 计算`input` 的自然对数
    a = torch.randn(5)
    Out[0]: tensor([-0.3466, 2.3803, -0.0423, -0.9744, 0.4976])
    torch.log(a)
    Out[1]: tensor([ nan, 0.8672, nan, nan, -0.6980])
    # 计算input + 1的自然对数
    torch.log1p(a)
    Out[2]: tensor([-0.4256, 1.2180, -0.0432, -3.6633, 0.4039])

    # 返回一个新张量,包含输入`input` 张量按元素取负
    a = torch.randn(3)
    Out[0]: tensor([ 0.0603, -0.5258, -0.3810])
    torch.neg(a)
    Out[1]: tensor([-0.0603, 0.5258, 0.3810])

    # 求指数
    a = torch.arange(1, 5)
    Out[0]: tensor([1, 2, 3, 4])
    exp = torch.arange(1, 5)
    Out[1]: tensor([1, 2, 3, 4])
    torch.pow(a, 2)
    Out[2]: tensor([ 1, 4, 9, 16])
    torch.pow(a, exp)
    Out[3]: tensor([ 1, 4, 27, 256])
    torch.pow(2, exp)
    Out[4]: tensor([ 2, 4, 8, 16])

    # 四舍五入
    a = torch.randn(4)
    Out[0]: tensor([ 0.7995, -2.0975, 0.7273, 0.7539])
    torch.round(a)
    Out[1]: tensor([ 1., -2., 1., 1.])

    # 四舍五入(去尾法)
    a = torch.randn(4)
    Out[0]: tensor([-2.1647, -0.2294, 0.4943, 1.5146])
    torch.trunc(a)
    Out[1]: tensor([-2., -0., 0., 1.])

    # 求平方根倒数
    a = torch.Tensor([1, 2, 3, 4])
    Out[0]: tensor([1., 2., 3., 4.])
    torch.rsqrt(a)
    Out[1]: tensor([1.0000, 0.7071, 0.5774, 0.5000])

    # 计算逐元素余数, 保留正负号
    t = torch.tensor([10, -22, 31, -47])
    torch.fmod(t, 5)
    Out[0]: tensor([ 0, -2, 1, -2])

    # 计算逐元素余数, 相当于python中的%操作符
    torch.remainder(t, 5)
    Out[1]: tensor([0, 3, 1, 3])
    np.mod(np.array([10, -22, 31, -47]), 5)
    Out[2]: array([0, 3, 1, 3], dtype=int32)

    # 求1/x
    a = torch.Tensor([1, 2, 3, 4])
    Out[0]: tensor([1., 2., 3., 4.])
    torch.reciprocal(a)
    Out[1]: tensor([1.0000, 0.5000, 0.3333, 0.2500])

    # 求平方根
    a = torch.Tensor([1, 2, 3, 4])
    Out[0]: tensor([1., 2., 3., 4.])
    torch.sqrt(a)
    Out[1]: tensor([1.0000, 1.4142, 1.7321, 2.0000])

    # 求绝对值
    torch.abs(torch.FloatTensor([-1, -2, 3]))
    Out[0]: tensor([1., 2., 3.])

三角函数

  • torch.asin(别名torch.arcsin): 返回一个新张量,包含输入input张量每个元素的反正弦函数

    torch.atan: 返回一个新张量,包含输入input张量每个元素的反正切函数

    torch.atan2: 返回一个新张量,包含两个输入张量input1input2反正切函数

    torch.cos: 返回一个新张量,包含输入input张量每个元素的余弦

    torch.acos(别名torch.arccos): 返回一个新张量,包含输入张量每个元素的反余弦

    torch.cosh: 返回一个新张量,包含输入input张量每个元素的双曲余弦

    torch.sin: 返回一个新张量,包含输入input张量每个元素的正弦

    torch.sinh: 返回一个新张量,包含输入input张量每个元素的双曲正弦

    torch.tan: 返回一个新张量,包含输入input张量每个元素的正切

    torch.tanh: 返回一个新张量,包含输入input张量每个元素的双曲正切

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    # 反正弦函数
    a = torch.randn(4)
    Out[0]: tensor([ 0.2583, -0.5285, 0.8979, 1.0104])
    torch.asin(a)
    Out[1]: tensor([ 0.2613, -0.5569, 1.1149, nan])

    # 反正切函数
    a = torch.randn(4)
    Out[0]: tensor([ 0.2583, -0.5285, 0.8979, 1.0104])
    b = torch.randn(4)
    Out[2]: tensor([0.1100, 1.4311, 1.9536, 0.7652])
    torch.atan(a)
    Out[1]: tensor([ 0.2528, -0.4862, 0.7316, 0.7906])
    torch.atan2(a, b)
    Out[3]: tensor([ 1.1681, -0.3538, 0.4308, 0.9226])

    # 余弦
    a = torch.randn(4)
    Out[0]: tensor([-0.9105, -0.7277, 0.9516, -0.1081])
    torch.cos(a)
    Out[1]: tensor([0.6133, 0.7467, 0.5804, 0.9942])
    # 反余弦
    torch.acos(torch.FloatTensor([-1, 1, 0]))
    Out[1]: tensor([3.1416, 0.0000, 1.5708])
    # 双曲余弦
    torch.cosh(a)
    Out[2]: tensor([1.4439, 1.2766, 1.4880, 1.0058])

    # 正弦
    a = torch.randn(4)
    torch.sin(a)
    Out[0]: tensor([-0.9215, 0.2650, 0.8285, 0.5914])
    # 双曲正弦
    torch.sinh(a)
    Out[1]: tensor([-1.4591, 0.2714, 1.1392, 0.6759])

    # 正切
    a = torch.Tensor([1, 2, 3, 4])
    Out[0]: tensor([1., 2., 3., 4.])
    torch.tan(a)
    Out[1]: tensor([ 1.5574, -2.1850, -0.1425, 1.1578])
    # 双曲正切
    torch.tanh(a)
    Out[2]: tensor([0.7616, 0.9640, 0.9951, 0.9993])

位操作

  • bitwise_not – 按位非: 计算给定输入张量的按位非,这个操作会将输入张量中的每个位反转,即将所有的1变成0,将所有的0变成1。在整数数据类型中,这通常意味着进行二进制补码的运算

    bitwise_and – 按位与: 计算两个输入张量的按位与,只有当两个张量在同一位置的位都是1时,结果张量在该位置的位才是1,否则是0

    bitwise_or – 按位或: 计算两个输入张量的按位或,只要两个张量在同一位置的位中有一个是1,结果张量在该位置的位就是1。如果都是0,结果就是0

    bitwise_xor – 按位异或: 计算两个输入张量的按位异或,这个操作在两个张量在同一位置的位不同的时候返回1,相同的时候返回0

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    # 按位非
    >>> torch.bitwise_not(torch.tensor([-1, -2, 3], dtype=torch.int8))
    tensor([ 0, 1, -4], dtype=torch.int8)

    # 按位与
    >>> torch.bitwise_and(torch.tensor([-1, -2, 3], dtype=torch.int8), torch.tensor([1, 0, 3], dtype=torch.int8))
    tensor([1, 0, 3], dtype=torch.int8)
    >>> torch.bitwise_and(torch.tensor([True, True, False]), torch.tensor([False, True, False]))
    tensor([ False, True, False])

    # 按位或
    >>> torch.bitwise_or(torch.tensor([-1, -2, 3], dtype=torch.int8), torch.tensor([1, 0, 3], dtype=torch.int8))
    tensor([-1, -2, 3], dtype=torch.int8)
    >>> torch.bitwise_or(torch.tensor([True, True, False]), torch.tensor([False, True, False]))
    tensor([ True, True, False])

    # 按位异或
    >>> torch.bitwise_xor(torch.tensor([-1, -2, 3], dtype=torch.int8), torch.tensor([1, 0, 3], dtype=torch.int8))
    tensor([-2, -2, 0], dtype=torch.int8)
    >>> torch.bitwise_xor(torch.tensor([True, True, False]), torch.tensor([False, True, False]))
    tensor([ True, False, False])
  • bitwise_left_shift – 按位左移: 计算给定输入张量与另一张量(表示位移数量)的按位左移。这个操作将输入张量的每个位向左移动other指定的位数,左边溢出的位被丢弃,而右边则填充0

    bitwise_right_shift – 按位右移: 计算给定输入张量与另一张量(表示位移数量)的按位右移。这个操作将输入张量的每个位向右移动other指定的位数,右边溢出的位被丢弃,对于无符号数据类型,左边填充0;对于有符号数据类型,一般会进行算术右移,填充的是最高位的值,即符号位

    1
    2
    3
    4
    5
    6
    7
    # 按位左移
    >>> torch.bitwise_left_shift(torch.tensor([-1, -2, 3], dtype=torch.int8), torch.tensor([1, 0, 3], dtype=torch.int8))
    tensor([-2, -2, 24], dtype=torch.int8)

    # 按位右移
    >>> torch.bitwise_right_shift(torch.tensor([-2, -7, 31], dtype=torch.int8), torch.tensor([1, 0, 3], dtype=torch.int8))
    tensor([-1, -7, 3], dtype=torch.int8)

其他操作

  • torch.sigmoid: 返回一个新张量,包含输入input张量每个元素的sigmoid值

    torch.sign: 符号函数,返回一个新张量,包含输入input张量每个元素的正负

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # 求sigmoid值
    a = torch.Tensor([1, 2, 3, 4])
    Out[0]: tensor([1., 2., 3., 4.])
    torch.sigmoid(a)
    Out[1]: tensor([0.7311, 0.8808, 0.9526, 0.9820])

    # 符号函数
    a = torch.Tensor([1, 2, 3, 4])
    Out[0]: tensor([1., 2., 3., 4.])
    torch.sign(a)
    Out[1]: tensor([1., 1., 1., 1.])
  • torch.lerp: 对两个张量以startend做线性插值, 将结果返回到输出张量

    • start (Tensor) – 起始点张量
    • end (Tensor) – 终止点张量
    • weight (float) – 插值公式的weight
    • out (Tensor, optional) – 结果张量
    1
    2
    3
    4
    5
    6
    7
    8
    9
    start = torch.arange(1., 5.)
    end = torch.empty(4).fill_(10)
    start, end
    Out[0]: (tensor([1., 2., 3., 4.]), tensor([10., 10., 10., 10.]))

    torch.lerp(start, end, 0.5)
    Out[1]: tensor([5.5000, 6.0000, 6.5000, 7.0000])
    torch.lerp(start, end, torch.full_like(start, 0.5))
    Out[2]: tensor([5.5000, 6.0000, 6.5000, 7.0000])

归约操作

极值操作

  • argmax: 返回张量中最大值的索引

    argmin: 返回张量中最小值的索引

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    # 返回张量中最大值的索引
    >>> a = torch.randn(4, 4)
    >>> a
    tensor([[ 1.3398, 0.2663, -0.2686, 0.2450],
    [-0.7401, -0.8805, -0.3402, -1.1936],
    [ 0.4907, -1.3948, -1.0691, -0.3132],
    [-1.6092, 0.5419, -0.2993, 0.3195]])
    >>> torch.argmax(a, dim=1)
    tensor([ 0, 2, 0, 1])

    # 返回张量中最小值的索引
    >>> a = torch.randn(4, 4)
    >>> a
    tensor([[ 0.1139, 0.2254, -0.1381, 0.3687],
    [ 1.0100, -1.1975, -0.0102, -0.4732],
    [-0.9240, 0.1207, -0.7506, -1.0213],
    [ 1.7809, -1.2960, 0.9384, 0.1438]])
    >>> torch.argmin(a)
    tensor(13)
    >>> torch.argmin(a, dim=1)
    tensor([ 2, 1, 3, 1])
    >>> torch.argmin(a, dim=1, keepdim=True)
    tensor([[2],
    [1],
    [3],
    [1]])
  • amax: 返回指定维度上每个切片的最大值

    amin: 返回指定维度上每个切片的最小值

    max: 返回张量中所有元素的最大值

    min: 返回张量中所有元素的最小值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    # 返回指定维度上每个切片的最大值
    >>> a = torch.randn(4, 4)
    >>> a
    tensor([[ 0.8177, 1.4878, -0.2491, 0.9130],
    [-0.7158, 1.1775, 2.0992, 0.4817],
    [-0.0053, 0.0164, -1.3738, -0.0507],
    [ 1.9700, 1.1106, -1.0318, -1.0816]])
    >>> torch.amax(a, dim=1)
    tensor([1.4878, 2.0992, 0.0164, 1.9700])

    # 返回指定维度上每个切片的最小值
    >>> a = torch.randn(4, 4)
    >>> a
    tensor([[ 0.6451, -0.4866, 0.2987, -1.3312],
    [-0.5744, 1.2980, 1.8397, -0.2713],
    [ 0.9128, 0.9214, -1.7268, -0.2995],
    [ 0.9023, 0.4853, 0.9075, -1.6165]])
    >>> torch.amin(a, dim=1)
    tensor([-1.3312, -0.5744, -1.7268, -1.6165])

    # 返回张量中所有元素的最大值
    >>> a = torch.randn(4, 4)
    >>> a
    tensor([[-1.2360, -0.2942, -0.1222, 0.8475],
    [ 1.1949, -1.1127, -2.2379, -0.6702],
    [ 1.5717, -0.9207, 0.1297, -1.8768],
    [-0.6172, 1.0036, -0.6060, -0.2432]])
    >>> torch.max(a, 1)
    torch.return_types.max(values=tensor([0.8475, 1.1949, 1.5717, 1.0036]), indices=tensor([3, 0, 0, 1]))

    # 返回张量中所有元素的最小值
    >>> a = torch.randn(4, 4)
    >>> a
    tensor([[-0.6248, 1.1334, -1.1899, -0.2803],
    [-1.4644, -0.2635, -0.3651, 0.6134],
    [ 0.2457, 0.0384, 1.0128, 0.7015],
    [-0.1153, 2.9849, 2.1458, 0.5788]])
    >>> torch.min(a, 1)
    torch.return_types.min(values=tensor([-1.1899, -1.4644, 0.0384, -0.1153]), indices=tensor([2, 0, 1, 0]))
  • aminmax: 同时计算最小值和最大值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    >>> torch.aminmax(torch.tensor([1, -3, 5]))
    torch.return_types.aminmax(min=tensor(-3), max=tensor(5))

    >>> # aminmax propagates NaNs
    >>> torch.aminmax(torch.tensor([1, -3, 5, torch.nan]))
    torch.return_types.aminmax(min=tensor(nan),max=tensor(nan))

    >>> t = torch.arange(10).view(2, 5)
    >>> t
    tensor([[0, 1, 2, 3, 4],
    [5, 6, 7, 8, 9]])
    >>> t.aminmax(dim=0, keepdim=True)
    torch.return_types.aminmax(min=tensor([[0, 1, 2, 3, 4]]), max=tensor([[5, 6, 7, 8, 9]]))

统计操作

  • mean: 返回张量中所有元素的均值

    nanmean: 返回张量中所有非NaN元素的均值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    # 返回张量中所有元素的均值
    >>> a = torch.randn(4, 4)
    >>> a
    tensor([[-0.3841, 0.6320, 0.4254, -0.7384],
    [-0.9644, 1.0131, -0.6549, -1.4279],
    [-0.2951, -1.3350, -0.7694, 0.5600],
    [ 1.0842, -0.9580, 0.3623, 0.2343]])
    >>> torch.mean(a, 1)
    tensor([-0.0163, -0.5085, -0.4599, 0.1807])
    >>> torch.mean(a, dim=1, keepdim=True)
    tensor([[-0.0163],
    [-0.5085],
    [-0.4599],
    [ 0.1807]])

    # 返回张量中所有非NaN元素的均值
    >>> x = torch.tensor([[torch.nan, 1, 2], [1, 2, 3]])
    >>> x.mean()
    tensor(nan)
    >>> x.nanmean()
    tensor(1.8000)
    >>> x.mean(dim=0)
    tensor([ nan, 1.5000, 2.5000])
    >>> x.nanmean(dim=0)
    tensor([1.0000, 1.5000, 2.5000])
    # If all elements in the reduced dimensions are NaN then the result is NaN
    >>> torch.tensor([torch.nan]).nanmean()
    tensor(nan)
  • median: 返回张量中所有元素的中值

    nanmedian: 返回张量中所有非NaN元素的中值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    # 返回张量中所有元素的中值
    >>> a = torch.randn(4, 5)
    >>> a
    tensor([[ 0.2505, -0.3982, -0.9948, 0.3518, -1.3131],
    [ 0.3180, -0.6993, 1.0436, 0.0438, 0.2270],
    [-0.2751, 0.7303, 0.2192, 0.3321, 0.2488],
    [ 1.0778, -1.9510, 0.7048, 0.4742, -0.7125]])
    >>> torch.median(a, 1)
    torch.return_types.median(values=tensor([-0.3982, 0.2270, 0.2488, 0.4742]), indices=tensor([1, 4, 4, 3]))

    # 返回张量中所有非NaN元素的中值
    >>> a = torch.tensor([[2, 3, 1], [float('nan'), 1, float('nan')]])
    >>> a
    tensor([[2., 3., 1.],
    [nan, 1., nan]])
    >>> a.median(0)
    torch.return_types.median(values=tensor([nan, 1., nan]), indices=tensor([1, 1, 1]))
    >>> a.nanmedian(0)
    torch.return_types.nanmedian(values=tensor([2., 1., 1.]), indices=tensor([0, 1, 0]))
  • mode: 返回张量在指定维度上每行的众数及其索引

    1
    2
    3
    4
    5
    6
    >>> a = torch.randint(10, (5,))
    >>> a
    tensor([6, 5, 1, 0, 2])
    >>> b = a + (torch.randn(50, 1) * 5).long()
    >>> torch.mode(b, 0)
    torch.return_types.mode(values=tensor([6, 5, 1, 0, 2]), indices=tensor([2, 2, 2, 2, 2]))
  • sum: 返回张量中所有元素的总和

    nansum: 返回张量中所有元素的和,将NaN视为零

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    # 返回张量中所有元素的总和
    >>> a = torch.randn(4, 4)
    >>> a
    tensor([[ 0.0569, -0.2475, 0.0737, -0.3429],
    [-0.2993, 0.9138, 0.9337, -1.6864],
    [ 0.1132, 0.7892, -0.1003, 0.5688],
    [ 0.3637, -0.9906, -0.4752, -1.5197]])
    >>> torch.sum(a, 1)
    tensor([-0.4598, -0.1381, 1.3708, -2.6217])
    >>> b = torch.arange(4 * 5 * 6).view(4, 5, 6)
    >>> torch.sum(b, dim=(2, 1))
    tensor([ 435., 1335., 2235., 3135.])

    # 返回张量中所有元素的和,将NaN视为零
    >>> torch.nansum(torch.tensor([1., float("nan")]))
    1.0
    >>> a = torch.tensor([[1, 2], [3., float("nan")]])
    >>> torch.nansum(a)
    tensor(6.)
    >>> torch.nansum(a, dim=0)
    tensor([4., 2.])
    >>> torch.nansum(a, dim=1)
    tensor([3., 3.])
  • prod: 返回张量中所有元素的乘积

    1
    2
    3
    4
    5
    6
    7
    8
    >>> a = torch.randn(4, 2)
    >>> a
    tensor([[ 0.5261, -0.3837],
    [ 1.1857, -0.2498],
    [-1.1646, 0.0705],
    [ 1.1131, -1.0629]])
    >>> torch.prod(a, dim=1)
    tensor([-0.2018, -0.2962, -0.0821, -1.1831])
  • quantile: 计算张量在指定维度上每行的第q个百分位数

    nanquantile: 类似于quantile,但在计算百分位数时忽略NaN值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    # 计算张量在指定维度上每行的第q个百分位数
    >>> a = torch.randn(2, 3)
    >>> a
    tensor([[ 0.0795, -1.2117, 0.9765],
    [ 1.1707, 0.6706, 0.4884]])
    >>> q = torch.tensor([0.25, 0.5, 0.75])
    >>> torch.quantile(a, q, dim=1, keepdim=True)
    tensor([[[-0.5661],
    [ 0.5795]],

    [[ 0.0795],
    [ 0.6706]],

    [[ 0.5280],
    [ 0.9206]]])
    >>> torch.quantile(a, q, dim=1, keepdim=True).shape
    torch.Size([3, 2, 1])
    >>> a = torch.arange(4.)
    >>> a
    tensor([0., 1., 2., 3.])
    >>> torch.quantile(a, 0.6, interpolation='linear')
    tensor(1.8000)
    >>> torch.quantile(a, 0.6, interpolation='lower')
    tensor(1.)
    >>> torch.quantile(a, 0.6, interpolation='higher')
    tensor(2.)
    >>> torch.quantile(a, 0.6, interpolation='midpoint')
    tensor(1.5000)
    >>> torch.quantile(a, 0.6, interpolation='nearest')
    tensor(2.)
    >>> torch.quantile(a, 0.4, interpolation='nearest')
    tensor(1.)

    # 类似于quantile,但在计算百分位数时忽略NaN值
    >>> t = torch.tensor([float('nan'), 1, 2])
    >>> t.quantile(0.5)
    tensor(nan)
    >>> t.nanquantile(0.5)
    tensor(1.5000)
    >>> t = torch.tensor([[float('nan'), float('nan')], [1, 2]])
    >>> t
    tensor([[nan, nan],
    [1., 2.]])
    >>> t.nanquantile(0.5, dim=0)
    tensor([1., 2.])
    >>> t.nanquantile(0.5, dim=1)
    tensor([ nan, 1.5000])

距离范数

  • norm: 返回给定张量的矩阵范数或向量范数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    >>> import torch
    >>> a = torch.arange(9, dtype= torch.float) - 4
    >>> b = a.reshape((3, 3))
    >>> torch.norm(a)
    tensor(7.7460)
    >>> torch.norm(b)
    tensor(7.7460)
    >>> torch.norm(a, float('inf'))
    tensor(4.)
    >>> torch.norm(b, float('inf'))
    tensor(4.)
    >>> c = torch.tensor([[ 1, 2, 3], [-1, 1, 4]] , dtype=torch.float)
    >>> torch.norm(c, dim=0)
    tensor([1.4142, 2.2361, 5.0000])
    >>> torch.norm(c, dim=1)
    tensor([3.7417, 4.2426])
    >>> torch.norm(c, p=1, dim=1)
    tensor([6., 6.])
    >>> d = torch.arange(8, dtype=torch.float).reshape(2, 2, 2)
    >>> torch.norm(d, dim=(1, 2))
    tensor([ 3.7417, 11.2250])
    >>> torch.norm(d[0, :, :]), torch.norm(d[1, :, :])
    (tensor(3.7417), tensor(11.2250))
  • dist: 返回两个张量差的p-范数

    p-范数(p-norm)是向量空间中的一种度量,它用于衡量向量的大小或长度

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    >>> x = torch.randn(4)
    >>> x
    tensor([-1.5393, -0.8675, 0.5916, 1.6321])
    >>> y = torch.randn(4)
    >>> y
    tensor([ 0.0967, -1.0511, 0.6295, 0.8360])
    >>> torch.dist(x, other=y, p=3.5)
    tensor(1.6727)
    >>> torch.dist(x, y, 3)
    tensor(1.6973)
    >>> torch.dist(x, y, 0)
    tensor(4.)
    >>> torch.dist(x, y, 1)
    tensor(2.6537)

均值与方差

  • std: 计算指定维度上的标准差

    var: 计算指定维度上的方差

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    # 计算指定维度上的标准差
    >>> a = torch.tensor(
    ... [[ 0.2035, 1.2959, 1.8101, -0.4644],
    ... [ 1.5027, -0.3270, 0.5905, 0.6538],
    ... [-1.5745, 1.3330, -0.5596, -0.6548],
    ... [ 0.1264, -0.5080, 1.6420, 0.1992]])
    >>> torch.std(a, dim=1, keepdim=True)
    tensor([[1.0311],
    [0.7477],
    [1.2204],
    [0.9087]])

    # 计算指定维度上的方差
    >>> a = torch.tensor(
    ... [[ 0.2035, 1.2959, 1.8101, -0.4644],
    ... [ 1.5027, -0.3270, 0.5905, 0.6538],
    ... [-1.5745, 1.3330, -0.5596, -0.6548],
    ... [ 0.1264, -0.5080, 1.6420, 0.1992]])
    >>> torch.std_mean(a, dim=0, keepdim=True)
    (tensor([[1.2620, 1.0028, 1.0957, 0.6038]]),
    tensor([[ 0.0645, 0.4485, 0.8707, -0.0665]]))
  • std_mean: 同时计算指定维度上的标准差和均值

    var_mean: 同时计算指定维度上的方差和均值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    # 同时计算指定维度上的标准差和均值
    >>> a = torch.tensor(
    ... [[ 0.2035, 1.2959, 1.8101, -0.4644],
    ... [ 1.5027, -0.3270, 0.5905, 0.6538],
    ... [-1.5745, 1.3330, -0.5596, -0.6548],
    ... [ 0.1264, -0.5080, 1.6420, 0.1992]])
    >>> torch.var(a, dim=1, keepdim=True)
    tensor([[1.0631],
    [0.5590],
    [1.4893],
    [0.8258]])

    # 同时计算指定维度上的方差和均值
    >>> a = torch.tensor(
    ... [[ 0.2035, 1.2959, 1.8101, -0.4644],
    ... [ 1.5027, -0.3270, 0.5905, 0.6538],
    ... [-1.5745, 1.3330, -0.5596, -0.6548],
    ... [ 0.1264, -0.5080, 1.6420, 0.1992]])
    >>> torch.var_mean(a, dim=0, keepdim=True)
    (tensor([[1.5926, 1.0056, 1.2005, 0.3646]]),
    tensor([[ 0.0645, 0.4485, 0.8707, -0.0665]]))

逻辑操作

  • all: 检查张量中的所有元素是否都满足某个条件(例如是否都为True)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >>> a = torch.rand(4, 2).bool()
    >>> a
    tensor([[True, True],
    [True, False],
    [True, True],
    [True, True]], dtype=torch.bool)
    >>> torch.all(a, dim=1)
    tensor([ True, False, True, True], dtype=torch.bool)
    >>> torch.all(a, dim=0)
    tensor([ True, False], dtype=torch.bool)
  • any: 检查张量中是否有任何元素满足某个条件(例如是否为True)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >>> a = torch.randn(4, 2) < 0
    >>> a
    tensor([[ True, True],
    [False, True],
    [ True, True],
    [False, False]])
    >>> torch.any(a, 1)
    tensor([ True, True, True, False])
    >>> torch.any(a, 0)
    tensor([True, True])

特殊操作

  • unique: 返回张量中的唯一元素

    unique_consecutive: 在每组连续相等的元素中只保留第一个元素

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    # 返回张量中的唯一元素
    >>> output = torch.unique(torch.tensor([1, 3, 2, 3], dtype=torch.long))
    >>> output
    tensor([1, 2, 3])
    >>> output, inverse_indices = torch.unique(
    ... torch.tensor([1, 3, 2, 3], dtype=torch.long), sorted=True, return_inverse=True)
    >>> output
    tensor([1, 2, 3])
    >>> inverse_indices
    tensor([0, 2, 1, 2])
    >>> output, inverse_indices = torch.unique(
    ... torch.tensor([[1, 3], [2, 3]], dtype=torch.long), sorted=True, return_inverse=True)
    >>> output
    tensor([1, 2, 3])
    >>> inverse_indices
    tensor([[0, 2],
    [1, 2]])

    # 在每组连续相等的元素中只保留第一个元素
    >>> x = torch.tensor([1, 1, 2, 2, 3, 1, 1, 2])
    >>> output = torch.unique_consecutive(x)
    >>> output
    tensor([1, 2, 3, 1, 2])
    >>> output, inverse_indices = torch.unique_consecutive(x, return_inverse=True)
    >>> output
    tensor([1, 2, 3, 1, 2])
    >>> inverse_indices
    tensor([0, 0, 1, 1, 2, 3, 3, 4])
    >>> output, counts = torch.unique_consecutive(x, return_counts=True)
    >>> output
    tensor([1, 2, 3, 1, 2])
    >>> counts
    tensor([2, 2, 1, 2, 1])
  • count_nonzero: 计算给定维度上非零元素的数量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >>> x = torch.zeros(3,3)
    >>> x[torch.randn(3,3) > 0.5] = 1
    >>> x
    tensor([[0., 1., 1.],
    [0., 0., 0.],
    [0., 0., 1.]])
    >>> torch.count_nonzero(x)
    tensor(3)
    >>> torch.count_nonzero(x, dim=0)
    tensor([0, 1, 2])
  • logsumexp: 返回在指定维度上,张量所有元素指数的对数和

    1
    2
    3
    4
    5
    >>> a = torch.randn(3, 3)
    >>> torch.logsumexp(a, 1)
    tensor([1.4907, 1.0593, 1.5696])
    >>> torch.dist(torch.logsumexp(a, 1), torch.log(torch.sum(torch.exp(a), 1)))
    tensor(1.6859e-07)

比较操作

torch.eq: torch.eq(input, other, out=None) → Tensor

比较元素相等性。第二个参数可为一个数或与第一个参数同类型形状的张量

torch.ge: torch.ge(input, other, out=None) → Tensor

逐元素比较inputother,即是否 input>=other

torch.gt: torch.gt(input, other, out=None) → Tensor

逐元素比较inputother , 即是否input>otherinput>other

torch.le: torch.le(input, other, out=None) → Tensor

逐元素比较inputother , 即是否input<=other

torch.lt: torch.lt(input, other, out=None) → Tensor

逐元素比较inputother , 即是否 input<other

torch.ne: torch.ne(input, other, out=None) → Tensor

逐元素比较inputother,即是否 input!=other

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
torch.eq(torch.Tensor([[1, 2], [3, 4]]), torch.Tensor([[1, 1], [4, 4]]))
Out[0]:
tensor([[ True, False],
[False, True]])

torch.ge(torch.Tensor([[1, 2], [3, 4]]), torch.Tensor([[1, 1], [4, 4]]))
Out[1]:
tensor([[ True, True],
[False, True]])

torch.gt(torch.Tensor([[1, 2], [3, 4]]), torch.Tensor([[1, 1], [4, 4]]))
Out[2]:
tensor([[False, True],
[False, False]])

torch.le(torch.Tensor([[1, 2], [3, 4]]), torch.Tensor([[1, 1], [4, 4]]))
Out[3]:
tensor([[ True, False],
[ True, True]])

torch.lt(torch.Tensor([[1, 2], [3, 4]]), torch.Tensor([[1, 1], [4, 4]]))
Out[4]:
tensor([[False, False],
[ True, False]])

torch.ne(torch.Tensor([[1, 2], [3, 4]]), torch.Tensor([[1, 1], [4, 4]]))
Out[5]:
tensor([[False, True],
[ True, False]])

torch.equal: torch.equal(tensor1, tensor2) → bool

如果两个张量有相同的形状和元素值,则返回True ,否则 False

1
2
torch.equal(torch.Tensor([1, 2]), torch.Tensor([1, 2]))
Out[0]: True

torch.kthvalue: torch.kthvalue(input, k, dim=None, out=None) -> (Tensor, LongTensor)

取输入张量input指定维上第k 个最小值。如果不指定dim,则默认为input的最后一维

torch.topk: 沿给定dim维度返回输入张量inputk 个最大值。 如果不指定dim,则默认为input的最后一维。 如果为largestFalse ,则返回最小的 k 个值

返回一个元组 (values,indices),其中indices是原始输入张量input中测元素下标。 如果设定布尔值sortedTrue,将会确保返回的 k 个值被排序

torch.topk(input, k, dim=None, largest=True, sorted=True, out=None) -> (Tensor, LongTensor)

参数:

  • input (Tensor) – 输入张量
  • k (int) – “top-k”中的k
  • dim (int, optional) – 排序的维
  • largest (bool, optional) – 布尔值,控制返回最大或最小值
  • sorted (bool, optional) – 布尔值,控制返回值是否排序
  • out (tuple, optional) – 可选输出张量 (Tensor, LongTensor) output buffers
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
x = torch.arange(1, 6)

# torch.kthvalue
torch.kthvalue(x, 4)
Out[0]:
torch.return_types.kthvalue(
values=tensor(4),
indices=tensor(3))

# torch.topk
x = torch.arange(1, 6)
Out[1]: tensor([1, 2, 3, 4, 5])

torch.topk(x, 3)
Out[2]:
torch.return_types.topk(
values=tensor([5, 4, 3]),
indices=tensor([4, 3, 2]))

torch.topk(x, 3, 0, largest=False)
Out[3]:
torch.return_types.topk(
values=tensor([1, 2, 3]),
indices=tensor([0, 1, 2]))

torch.max: 返回输入张量所有元素的最大值

torch.max()

返回输入张量给定维度上每行的最大值,并同时返回每个最大值的位置索引

torch.max(input, dim, max=None, max_indices=None) -> (Tensor, LongTensor)

input逐元素other相应位置的元素对比,返回最大值到输出张量

torch.max(input, other, out=None) → Tensor

torch.min: 返回输入张量所有元素的最小值

torch.min(input) → float

返回输入张量给定维度上每行的最小值,并同时返回每个最小值的位置索引

torch.min(input, dim, min=None, min_indices=None) -> (Tensor, LongTensor)

input逐元素other相应位置的元素对比,返回最小值到输出张量

torch.min(input, other, out=None) → Tensor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
a = torch.randn(2, 2)
Out[0]:
tensor([[-0.1204, -0.5016],
[ 1.2717, 0.7351]])
b = torch.randn(2, 2)
Out[1]:
tensor([[-1.4497, 0.7534],
[ 0.5994, -0.1490]])

# 最大值
torch.max(torch.arange(1, 5))
Out[2]: tensor(4)
torch.max(a, 1)
Out[3]:
torch.return_types.max(
values=tensor([-0.1204, 1.2717]),
indices=tensor([0, 0]))
torch.max(a, b)
Out[4]:
tensor([[-0.1204, 0.7534],
[ 1.2717, 0.7351]])

# 最小值
torch.min(torch.arange(1, 5))
Out[5]: tensor(1)
torch.min(a, 1)
Out[6]:
torch.return_types.min(
values=tensor([-0.5016, 0.7351]),
indices=tensor([1, 1]))
torch.min(a, b)
Out[7]:
tensor([[-1.4497, -0.5016],
[ 0.5994, -0.1490]])

torch.sort: torch.sort(input, dim=None, descending=False, out=None) -> (Tensor, LongTensor)

对输入张量input沿着指定维按升序排序。如果不给定dim,则默认为输入的最后一维。如果指定参数descendingTrue,则按降序排序

返回元组 (sorted_tensor, sorted_indices) , sorted_indices 为原始输入中的下标

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
x = torch.randn(3, 4)
Out[0]:
tensor([[-2.3460, 1.3734, 1.1444, -0.4736],
[-1.1785, 0.8436, -1.4403, -0.1073],
[-0.1198, 0.7067, -0.0734, -1.6181]])

sorted, indices = torch.sort(x)
sorted, indices
Out[1]:
(tensor([[-2.3460, -0.4736, 1.1444, 1.3734],
[-1.4403, -1.1785, -0.1073, 0.8436],
[-1.6181, -0.1198, -0.0734, 0.7067]]),
tensor([[0, 3, 2, 1],
[2, 0, 3, 1],
[3, 0, 2, 1]]))

其它操作

torch.cross: 返回沿着维度dim上,两个张量inputother的向量积(叉积)。 inputother 必须有相同的形状,且指定的dim维上size必须为3

如果不指定dim,则默认为第一个尺度为3的维

torch.cross(input, other, dim=-1, out=None) → Tensor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
a = torch.randint(1, 6, (2, 3))
Out[0]:
tensor([[5, 4, 5],
[4, 2, 3]])
b = torch.randint(1, 6, (2, 3))
Out[1]:
tensor([[1, 1, 2],
[3, 4, 2]])

torch.cross(a, a)
Out[2]:
tensor([[0, 0, 0],
[0, 0, 0]])

torch.cross(a, b)
Out[3]:
tensor([[ 3, -5, 1],
[-8, 1, 10]])

torch.diag: torch.diag(input, diagonal=0, out=None) → Tensor

  • 如果输入是一个向量(1D 张量),则返回一个以input为对角线元素的2D方阵
  • 如果输入是一个矩阵(2D 张量),则返回一个包含input对角线元素的1D张量

参数diagonal指定对角线:

  • diagonal = 0, 主对角线
  • diagonal > 0, 主对角线之上
  • diagonal < 0, 主对角线之下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 如果输入是一个向量(1D 张量),则返回一个以`input`为对角线元素的2D方阵
a = torch.randn(3)
Out[0]: tensor([-0.3509, 0.6176, -1.4976])
torch.diag(a)
Out[1]:
tensor([[-0.3509, 0.0000, 0.0000],
[ 0.0000, 0.6176, 0.0000],
[ 0.0000, 0.0000, -1.4976]])
torch.diag(a, 1)
Out[2]:
tensor([[ 0.0000, -0.3509, 0.0000, 0.0000],
[ 0.0000, 0.0000, 0.6176, 0.0000],
[ 0.0000, 0.0000, 0.0000, -1.4976],
[ 0.0000, 0.0000, 0.0000, 0.0000]])

# 如果输入是一个矩阵(2D 张量),则返回一个包含`input`对角线元素的1D张量
# 取得给定矩阵第k个对角线:
a = torch.randn(3, 3)
Out[3]:
tensor([[ 0.8224, 0.7792, 0.2605],
[-0.8646, 0.2568, -0.8189],
[ 1.1693, 0.8108, -1.9662]])
torch.diag(a, 0)
Out[4]: tensor([ 0.8224, 0.2568, -1.9662])
torch.diag(a, 1)
Out[5]: tensor([ 0.7792, -0.8189])

torch.histc: torch.histc(input, bins=100, min=0, max=0, out=None) → Tensor

计算输入张量的直方图。以minmax为range边界,将其均分成bins个直条,然后将排序好的数据划分到各个直条(bins)中

参数:

  • input (Tensor) – 输入张量
  • bins (int) – 直方图 bins(直条)的个数(默认100个)
  • min (int) – range的下边界(包含)
  • max (int) – range的上边界(包含)
  • out (Tensor, optional) – 结果张量
1
2
3
4
5
torch.histc(torch.FloatTensor([1, 2, 1]), bins=4, min=0, max=3)
Out[0]: tensor([0., 2., 1., 0.])

torch.histc(torch.FloatTensor([1, 1, 2, 1]), bins=4, min=0, max=3)
Out[1]: tensor([0., 3., 1., 0.])

torch.renorm: torch.renorm(input, p, dim, maxnorm, out=None) → Tensor

返回一个张量,包含规范化后的各个子张量,使得沿着dim维划分的各子张量的p范数小于maxnorm

如果p范数的值小于maxnorm,则当前子张量不需要修改

参数:

  • input (Tensor) – 输入张量
  • p (float) – 范数的p
  • dim (int) – 沿着此维切片,得到张量子集
  • maxnorm (float) – 每个子张量的范数的最大值
  • out (Tensor, optional) – 结果张量
1
2
3
4
5
6
7
8
9
10
11
12
13
x = torch.ones(3, 3)
x[1].fill_(2)
x[2].fill_(3)
Out[0]:
tensor([[1., 1., 1.],
[2., 2., 2.],
[3., 3., 3.]])

torch.renorm(x, p=1, dim=0, maxnorm=5)
Out[1]:
tensor([[1.0000, 1.0000, 1.0000],
[1.6667, 1.6667, 1.6667],
[1.6667, 1.6667, 1.6667]])

torch.trace: 返回输入2维矩阵对角线元素的和(迹)

1
2
3
4
5
6
7
8
x = torch.arange(1, 10).view(3, 3)
Out[0]:
tensor([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])

torch.trace(x)
Out[1]: tensor(15)

torch.tril: torch.tril(input, diagonal=0, out=None) → Tensor

返回一个张量out,包含输入矩阵(2D张量)的下三角部分,out其余部分被设为0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
x = torch.arange(1, 10).view(3, 3)
Out[0]:
tensor([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])

torch.tril(x)
Out[1]:
tensor([[1, 0, 0],
[4, 5, 0],
[7, 8, 9]])

torch.tril(x, diagonal=1)
Out[2]:
tensor([[1, 2, 0],
[4, 5, 6],
[7, 8, 9]])

torch.triu: torch.triu(input, k=0, out=None) → Tensor

返回一个张量,包含输入矩阵(2D张量)的上三角部分,其余部分被设为0。这里所说的上三角部分为矩阵指定对角线diagonal之上的元素。

参数k控制对角线: - k = 0, 主对角线 - k > 0, 主对角线之上 - k < 0, 主对角线之下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
x = torch.arange(1, 10).view(3, 3)
Out[0]:
tensor([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])

torch.triu(x)
Out[1]:
tensor([[1, 2, 3],
[0, 5, 6],
[0, 0, 9]])

torch.triu(x, diagonal=1)
Out[2]:
tensor([[0, 2, 3],
[0, 0, 6],
[0, 0, 0]])

torch.cumprod: torch.cumprod(input, dim, out=None) → Tensor

返回输入沿指定维度的累积,例如,如果输入是一个N 元向量,则结果也是一个N 元向量,

1
2
3
4
5
a = torch.Tensor([1, 2, 3, 4])
Out[0]: tensor([1., 2., 3., 4.])

torch.cumprod(a, dim=0)
Out[1]: tensor([ 1., 2., 6., 24.])

torch.cumsum: torch.cumsum(input, dim, out=None) → Tensor

返回输入沿指定维度的累加,例如,如果输入是一个N 元向量,则结果也是一个N 元向量,

1
2
3
4
5
a = torch.Tensor([1, 2, 3, 4])
Out[0]: tensor([1., 2., 3., 4.])

torch.cumsum(a, dim=0)
Out[1]: tensor([ 1., 3., 6., 10.])

BLAS和LAPACK操作

BLAS(Basic Linear Algebra Subprograms)和LAPACK(Linear Algebra Package)是两个广泛使用的数学库,它们提供了一系列的数学运算,这些运算是高性能线性代数计算的基础

  • BLAS 提供了基本的线性代数运算,它主要关注向量与向量之间(Level 1 BLAS)、矩阵与向量之间(Level 2 BLAS)以及矩阵与矩阵之间(Level 3 BLAS)的运算。BLAS 的这些操作是高度优化的,旨在提供高效率的计算,这对于任何需要大量线性代数计算的程序都是非常重要的。例如,BLAS 提供了矩阵乘法、向量加法、标量与向量的乘法等基础操作
  • LAPACK 构建于 BLAS 之上,提供了更复杂的线性代数运算,如求解线性方程组、计算矩阵特征值和特征向量、奇异值分解、LU分解、QR分解等。LAPACK 是为了解决更大规模的线性代数问题而设计的,它能够利用 BLAS 提供的基础操作来实现更高级的数学运算

在很多现代的数值计算环境或科学计算库中,例如 NumPy、SciPy、MATLAB 和 R,底层都直接或间接地使用了 BLAS 和 LAPACK 的实现。这些库通常会链接到特定硬件优化版本的 BLAS 和 LAPACK,如 MKL(Intel Math Kernel Library)或 OpenBLAS,以获得更好的性能

BLAS 和 LAPACK 是高性能数值计算领域的标准构件,它们为复杂的线性代数运算提供了强大的支持

torch.addbmm

torch.addmm

torch.addmv

torch.addr

torch.baddbmm

torch.bmm

torch.btrifact

torch.btrisolve

torch.dot: 计算两个张量的点乘(内乘),两个张量都为1-D 向量

torch.dot(tensor1, tensor2) → float

1
2
torch.dot(torch.Tensor([2, 3]), torch.Tensor([2, 1]))
Out[0]: tensor(7.)

torch.linalg.eig: 计算实方阵a 的特征值和特征向量

torch.linalg.eig(A, * , out=None)

1
2
3
4
5
6
7
8
9
10
A = torch.randn(2, 2, dtype=torch.complex128)
Out[0]:
tensor([[-0.2029-0.0673j, -0.5188-0.6723j],
[-1.1984+0.0585j, 0.5786-0.1849j]], dtype=torch.complex128)

L, V = torch.linalg.eig(A)
Out[1]:
(tensor([-0.7870-0.5003j, 1.1626+0.2481j], dtype=torch.complex128),
tensor([[ 0.7596+0.0000j, -0.4008-0.3285j],
[ 0.6258-0.1770j, 0.8552+0.0000j]], dtype=torch.complex128))