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 已经成为了机器学习研究者和开发者的首选工具之一
1 基本操作
以下是一些常用的方法
torch.is_tensor: 如果obj是一个pytorch张量,则返回True
x=torch.tensor([1,2,3])
torch.is_tensor(x)
Out[0]: True
torch.is_storage: 如何obj是一个pytorch storage对象,则返回True
x=torch.tensor([1,2,3])
torch.is_storage(x)
Out[0]: False
torch.numel: 返回
input
张量中的元素个数
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)
2 创建操作
2.1 张量创建函数
torch.tensor()
: 通过复制数据创建一个具有自动求导历史的张量(如果数据是一个张量)>>> 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()
: 通过坐标格式的索引和值构建稀疏张量使用稀疏矩阵的一个主要优点是,在存储和计算上更加高效,特别是对于非常大的数据集。例如,在矩阵乘法或其他线性代数运算中,利用稀疏性可以显著减少不必要的乘法和加法计算,因为零元素与任何数相乘都是零,并且不会影响加法运算的结果
# 假设我们有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()
: 通过压缩稀疏列格式的索引和值构建稀疏张量# 定义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维块构建稀疏张量>>> 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)
2.2 数据类型转换函数
torch.asarray()
: 将对象转换为张量torch.as_tensor()
: 将数据转换为张量,共享数据并尽可能保留自动求导历史torch.as_strided()
: 创建一个具有指定大小、步长和存储偏移的现有张量的视图(不好理解
)# 将对象转换为张量 >>> 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张量# 从内存映射文件创建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])
2.3 初始化填充函数
torch.zeros()
: 返回一个指定形状且用0填充的张量torch.zeros_like()
: 返回一个与给定张量形状相同且用0填充的张量>>> 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填充的张量>>> 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()
: 返回一个从start
到end
(不包含end
)且步长为step
的1维张量torch.range()
: (未来版本弃用)返回一个从start
到end
(包含end
)且步长为step
的1维张量>>> 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])
2.4 特定区间填充函数
torch.linspace()
: 返回一个从start
到end
(包括end
)且在其中均匀分布的指定大小的1维张量torch.logspace()
: 返回一个在对数刻度上从到(包括end
)且均匀分布的指定大小的1维张量这两个函数生成的张量常常用于数据预处理、数学模拟、绘图等需要生成规则数列的场景
>>> 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])
2.5 其他辅助函数
torch.eye()
: 返回一个二维张量,对角线上为1,其他地方为0>>> 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()
: 创建一个具有指定大小和跨度且未初始化的张量>>> 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()
: 返回一个与给定张量形状相同且用给定值填充的张量>>> 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.]])
2.6 量化函数
torch.quantize_per_tensor()
: 将浮点张量转换为给定比例和零点的量化张量torch.quantize_per_channel()
: 将浮点张量转换为按通道给定比例和零点的量化张量torch.dequantize()
: 通过去量化量化张量来返回一个fp32张量
2.7 复数和其他特殊类型函数
torch.complex()
: 构造一个其实部等于real
、虚部等于imag
的复数张量>>> 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
构造复数张量的笛卡尔坐标>>> 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阶跃函数>>> 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.])
这些函数在数据预处理、模型初始化和其他计算任务中非常有用。通过这些函数,你可以创建大小、形状、种类各异的张量来满足不同的需求
3 索引|切片|连接|换位
这部分主要分为索引和切片、合并和拼接、变换和重塑、元素添加与替换、搜索和条件操作、扩展与重复操作
3.1 索引和切片
argwhere
: 返回非零元素的索引nonzero
: 返回非零元素的索引argwhere
和nonzero
函数都用于查找非零元素的索引,但它们返回的格式略有不同。在某些编程库中,argwhere
通常返回一个二维数组,其中每一行都是输入中非零元素的索引坐标;而nonzero
返回的是一个元组,每个元素是一个一维数组,表示非零元素在各个维度上的位置# 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
: 根据布尔掩码选择数据# 在特定维度进行索引 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
>>> 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
: 沿指定维度根据索引取元素# 根据索引从输入张量中取元素 >>> 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
: 按维度解绑张量>>> 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
: 将平面索引转换为坐标索引>>> 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的维度# 压缩维度 >>> 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]])
3.2 合并和拼接
cat
,concat
,concatenate
: 将序列的张量在指定维度连接(concat
和concatenate
是cat
的别名)>>> 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
: 把张量分成指定数量的块>>> 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
: 按列堆叠张量创建新张量>>> 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
: 深度方向堆叠张量# 水平方向堆叠张量 >>> 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.dstack
和torch.column_stack
函数都是用于堆叠张量的函数,但它们在堆叠的细节上有所不同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_stack
与hstack
相似,但它是专门设计来处理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
: 沿特定维度分割张量,基于索引来分割张量的。你可以指定一个分割点的索引列表,函数会在这些索引处分割张量。这些索引指的是分割后每个新张量的第一个元素的索引>>> 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.]]))
3.3 变换和重塑
adjoint
: 返回共轭的张量,并交换最后两维conj
: 返回共轭位翻转的张量视图gather
: 沿指定维度聚集值torch.gather(input, dim, index, *, sparse_grad=False) -> Tensor
其中参数的意义如下:
input
是要从中提取数据的张量dim
是要沿着哪个维度进行提取index
是与input
张量在除了dim
指定的维度外具有相同大小的张量,包含了要提取的元素的索引sparse_grad
是布尔值,用于指示是否进行稀疏梯度的计算;通常用于高级用途
# 创建一个 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
): 移动张量维度位置的函数,这个操作可以让你指定某个维度(或多个维度)从它的原始位置移动到一个新的位置```python
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`(等价于`swapaxes`、`swapdims`): 转置张量的维度
> [捋清pytorch的transpose、permute、view、reshape、contiguous](https://blog.csdn.net/nuohuang3371/article/details/113403755)
permute可以完全替代transpose,transpose不能替代permute
```python
# 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)
>>> 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]])
3.4 元素添加与替换
index_add
: 根据索引向张量添加元素index_copy
: 根据索引复制元素到张量index_reduce
: 在指定维度上,根据索引减少元素>>> 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
: 根据索引分散和添加元素scatter(output, dim, index, src)
catter函数就是把src数组中的数据重新分配到output数组当中,index数组中表示了要把src数组中的数据分配到output数组中的位置,若未指定,则填充0
>>> 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向量,如下所示
>>> 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
: 在给定维度上分散元素
3.5 搜索和条件操作
where
: 根据条件从两个张量中选择元素>>> 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)
3.6 扩展与重复操作
tile
: 通过重复张量的元素来构建新张量>>> 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]])
4 随机抽样
4.1 随机种子
torch.seed: 设置torch cpu随机数种子
torch.manual_seed: 设置torch cpu随机数种子,torch.manual_seed(seed)
torch.cuda.manual_seed: 设置torch cuda随机数种子
torch.initial_seed: 查看设置的种子值
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到一个特定的状态,这样可以从那个状态开始重新生成相同的随机数序列
4.2 随机采样函数
常见的概率分布参考 -- 兼一书虫-机器学习概率论(1)
torch.rand()
: 创建一个具有给定形状的张量,并用区间[0, 1)内的均匀分布
的随机数填充torch.rand_like()
: 返回一个与给定张量形状相同的张量,并用区间[0, 1)内的均匀分布
的随机数填充>>> 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()
: 返回一个与给定张量形状相同的张量,并用标准正态分布
的随机数填充>>> 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)内的随机整数填充>>> 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
的整数的随机排列>>> torch.randperm(4) tensor([2, 1, 0, 3])
torch.bernoulli: 从伯努利分布中提取二进制随机数(0或1),输入张量应为包含用于绘制二进制随机数的概率的张量
因此,输入中的所有值都必须在以下范围内(0,1)
>>> 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: 泊松分布用于计算一个事件在平均价值率(时间)的一定时间内发生的可能性。泊松分布是一个离散的概率分布
>>> 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) – 结果张量
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
的离散正态分布中抽取随机数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])
5 序列化
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 可以覆盖默认参数
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*)
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)
6 并行化
在PyTorch中,CPU操作可以通过多线程来并行化,以此提高性能。这里涉及到两种形式的并行化:intra-op并行和inter-op并行。下面是关于这些函数的解释:
get_num_threads()
: 这个函数返回用于在CPU上并行执行操作(即intra-op并行)的线程数。Intra-op并行是指单个操作(如矩阵乘法)内部的并行执行。PyTorch会尝试使用所有可用的CPU核心来加速这些操作set_num_threads(int)
: 这个函数用来设置在CPU上进行intra-op并行操作时使用的线程数。如果你想限制PyTorch使用的CPU核心数量,可以调用这个函数get_num_interop_threads()
: 这个函数返回用于CPU上的inter-op并行的线程数。Inter-op并行是指不同操作之间的并行执行。例如,如果你有多个不依赖于彼此的操作,PyTorch可以同时执行它们以提高效率set_num_interop_threads(int)
: 这个函数用来设置用于inter-op并行的线程数。通过设定线程数,可以控制同时进行的不同操作的数量
在多核CPU上,适当地设置这些值可以帮助你更好地利用系统资源,提高程序的运行效率。然而,如果设置的线程数太多,可能会导致线程竞争和上下文切换的开销,反而降低性能
通常默认设置是已经针对性能进行了优化,但是在特定的系统和应用场景下,手动调整这些值可以获得更佳的性能表现
7 梯度管理
在PyTorch中,梯度计算对于训练神经网络是必要的,因为它们用于优化模型的参数。然而,在某些情况下,比如在模型评估或应用阶段,你可能不需要计算梯度。梯度计算会占用额外的内存和计算资源,禁用它们可以提高效率。为了方便地开启和关闭梯度计算,PyTorch提供了几个上下文管理器:
torch.no_grad()
:with torch.no_grad(): # 在这个代码块中,所有的操作都不会跟踪梯度 predictions = model(inputs)
在这个例子中,
model(inputs)
的执行不会计算梯度,这对于模型推断(inference)阶段非常有用,因为它减少了内存消耗并提高了计算速度torch.enable_grad()
:with torch.enable_grad(): # 在这个代码块中,梯度计算是启用的 predictions = model(inputs) loss = loss_fn(predictions, targets) loss.backward()
这里,即使全局梯度计算被禁用,
torch.enable_grad()
仍可以在其作用域内启用梯度计算,以便计算损失函数的梯度torch.set_grad_enabled()
: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()
函数来全局地控制是否计算梯度。传递True
或False
可以分别开启或关闭梯度计算torch.is_grad_enabled()
:print(torch.is_grad_enabled()) # 打印当前是否启用了梯度计算
这个函数用来检查当前是否启用了梯度计算
torch.inference_mode()
:with torch.inference_mode(): # 在这个代码块中,所有的操作都不会跟踪梯度,且某些优化会被应用以加速推断 predictions = model(inputs)
torch.inference_mode()
更适合用在推断阶段,相比torch.no_grad()
,它会启用额外的优化,比如禁用自动求导引擎和解除对操作immutable的限制,从而实现更高效的模型推断torch.is_inference_mode_enabled()
: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 程序的性能
8 数学操作
8.1 基础操作
torch.add: 对输入张量
input
逐元素加上标量值value
,并返回结果到一个新的张量torch.addcdiv: 用
tensor2
对tensor1
逐元素相除,然后乘以标量值value
并加到tensor
,张量的形状不需要匹配,但元素数量必须一致- tensor (Tensor) – 张量,对 tensor1 ./ tensor 进行相加
- value (Number, optional) – 标量,对 tensor1 ./ tensor2 进行相乘
- tensor1 (Tensor) – 张量,作为被除数(分子)
- tensor2 (Tensor) –张量,作为除数(分母)
- out (Tensor, optional) – 输出张量
torch.addcmul: 用
tensor2
对tensor1
逐元素相乘,并对结果乘以标量值value
然后加到tensor
- tensor (Tensor) – 张量,对tensor1 ./ tensor 进行相加
- value (Number, optional) – 标量,对 tensor1 . tensor2 进行相乘
- tensor1 (Tensor) – 张量,作为乘子1
- tensor2 (Tensor) –张量,作为乘子2
- out (Tensor, optional) – 输出张量
以上两个可以用于正则化操作
# 对输入张量`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,即不小于元素的最大整数# 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)两张量
input
和other
逐元素相除,并将结果返回到输出,torch.div(input, other, **, rounding_mode=None, out=None*) → Tensortorch.mul(别米torch.multiply): 用标量值
value
乘以输入input
的每个元素,并返回一个新的结果张量,torch.mul(input, value, out=None)两个张量
input
,other
按元素进行相乘,并返回到输出张量,torch.mul(input, other, out=None)# 元素除 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/xtorch.sqrt: 返回一个新张量,包含输入
input
张量每个元素的平方根torch.abs(别名为torch.absolute): 计算输入张量的每个元素绝对值
# 返回一个新张量,包含输入`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.])
8.2 三角函数
torch.asin(别名torch.arcsin): 返回一个新张量,包含输入
input
张量每个元素的反正弦函数
torch.atan: 返回一个新张量,包含输入
input
张量每个元素的反正切函数
torch.atan2: 返回一个新张量,包含两个输入张量
input1
和input2
的反正切函数
torch.cos: 返回一个新张量,包含输入
input
张量每个元素的余弦
torch.acos(别名torch.arccos): 返回一个新张量,包含输入张量每个元素的
反余弦
torch.cosh: 返回一个新张量,包含输入
input
张量每个元素的双曲余弦
torch.sin: 返回一个新张量,包含输入
input
张量每个元素的正弦
torch.sinh: 返回一个新张量,包含输入
input
张量每个元素的双曲正弦
torch.tan: 返回一个新张量,包含输入
input
张量每个元素的正切
torch.tanh: 返回一个新张量,包含输入
input
张量每个元素的双曲正切
# 反正弦函数 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])
8.3 位操作
bitwise_not – 按位非: 计算给定输入张量的
按位非
,这个操作会将输入张量中的每个位反转,即将所有的1变成0,将所有的0变成1。在整数数据类型中,这通常意味着进行二进制补码的运算bitwise_and – 按位与: 计算两个输入张量的
按位与
,只有当两个张量在同一位置的位都是1时,结果张量在该位置的位才是1,否则是0bitwise_or – 按位或: 计算两个输入张量的
按位或
,只要两个张量在同一位置的位中有一个是1,结果张量在该位置的位就是1。如果都是0,结果就是0bitwise_xor – 按位异或: 计算两个输入张量的
按位异或
,这个操作在两个张量在同一位置的位不同的时候返回1,相同的时候返回0# 按位非 >>> 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
指定的位数,左边溢出的位被丢弃,而右边则填充0bitwise_right_shift – 按位右移: 计算给定输入张量与另一张量(表示位移数量)的按位右移。这个操作将输入张量的每个位向右移动
other
指定的位数,右边溢出的位被丢弃,对于无符号数据类型,左边填充0;对于有符号数据类型,一般会进行算术右移,填充的是最高位的值,即符号位# 按位左移 >>> 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)
8.4 其他操作
torch.sigmoid: 返回一个新张量,包含输入
input
张量每个元素的sigmoid值torch.sign: 符号函数,返回一个新张量,包含输入
input
张量每个元素的正负# 求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: 对两个张量以
start
,end
做线性插值, 将结果返回到输出张量- start (Tensor) – 起始点张量
- end (Tensor) – 终止点张量
- weight (float) – 插值公式的weight
- out (Tensor, optional) – 结果张量
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])
9 归约操作
9.1 极值操作
argmax
: 返回张量中最大值的索引argmin
: 返回张量中最小值的索引# 返回张量中最大值的索引 >>> 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
: 返回张量中所有元素的最小值# 返回指定维度上每个切片的最大值 >>> 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
: 同时计算最小值和最大值>>> 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]]))
9.2 统计操作
mean
: 返回张量中所有元素的均值nanmean
: 返回张量中所有非NaN元素的均值# 返回张量中所有元素的均值 >>> 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元素的中值# 返回张量中所有元素的中值 >>> 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
: 返回张量在指定维度上每行的众数及其索引>>> 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视为零# 返回张量中所有元素的总和 >>> 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
: 返回张量中所有元素的乘积>>> 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值# 计算张量在指定维度上每行的第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])
9.3 距离范数
norm
: 返回给定张量的矩阵范数或向量范数>>> 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)是向量空间中的一种度量,它用于衡量向量的大小或长度>>> 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)
9.4 均值与方差
std
: 计算指定维度上的标准差var
: 计算指定维度上的方差# 计算指定维度上的标准差 >>> 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
: 同时计算指定维度上的方差和均值# 同时计算指定维度上的标准差和均值 >>> 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]]))
9.5 逻辑操作
all
: 检查张量中的所有元素是否都满足某个条件(例如是否都为True)>>> 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)>>> 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])
9.6 特殊操作
unique
: 返回张量中的唯一元素unique_consecutive
: 在每组连续相等的元素中只保留第一个元素# 返回张量中的唯一元素 >>> 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
: 计算给定维度上非零元素的数量>>> 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
: 返回在指定维度上,张量所有元素指数的对数和>>> 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)
10 比较操作
torch.eq: torch.eq(input, other, out=None) → Tensor
比较元素相等性。第二个参数可为一个数或与第一个参数同类型形状的张量
torch.ge: torch.ge(input, other, out=None) → Tensor
逐元素比较
input
和other
,即是否 input>=othertorch.gt: torch.gt(input, other, out=None) → Tensor
逐元素比较
input
和other
, 即是否input>otherinput>othertorch.le: torch.le(input, other, out=None) → Tensor
逐元素比较
input
和other
, 即是否input<=othertorch.lt: torch.lt(input, other, out=None) → Tensor
逐元素比较
input
和other
, 即是否 input<othertorch.ne: torch.ne(input, other, out=None) → Tensor
逐元素比较
input
和other
,即是否 input!=other
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
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
维度返回输入张量input
中k
个最大值。 如果不指定dim
,则默认为input
的最后一维。 如果为largest
为False
,则返回最小的k
个值返回一个元组 (values,indices),其中
indices
是原始输入张量input
中测元素下标。 如果设定布尔值sorted
为True,将会确保返回的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
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
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
,则默认为输入的最后一维。如果指定参数descending
为True
,则按降序排序返回元组 (sorted_tensor, sorted_indices) ,
sorted_indices
为原始输入中的下标
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]]))
11 其它操作
torch.cross: 返回沿着维度
dim
上,两个张量input
和other
的向量积(叉积)。input
和other
必须有相同的形状,且指定的dim
维上size必须为3
如果不指定
dim
,则默认为第一个尺度为3
的维torch.cross(input, other, dim=-1, out=None) → Tensor
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, 主对角线之下
# 如果输入是一个向量(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
计算输入张量的直方图。以
min
和max
为range边界,将其均分成bins
个直条,然后将排序好的数据划分到各个直条(bins)中参数:
- input (Tensor) – 输入张量
- bins (int) – 直方图 bins(直条)的个数(默认100个)
- min (int) – range的下边界(包含)
- max (int) – range的上边界(包含)
- out (Tensor, optional) – 结果张量
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) – 结果张量
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维矩阵对角线元素的和(迹)
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
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, 主对角线之下
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 元向量,
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 元向量,
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.])
12 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
torch.dot(torch.Tensor([2, 3]), torch.Tensor([2, 1]))
Out[0]: tensor(7.)
torch.linalg.eig: 计算实方阵
a
的特征值和特征向量torch.linalg.eig(A, * , out=None)
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))