Pytorch常用函数汇总【持续更新】
- [`torch.arange(start=0, end, step=1)`](#
torch.arange(start=0, end, step=1)
) - `torch.zeros(size)`
- `torch.ones(size)`
- `torch.randn(size)`
- `torch.tensor(data)`
- 张量形状与属性
-
- [`x.shape / x.size()`](#
x.shape / x.size()
) - `x.numel()`
- `x.reshape(shape)`
- `len(x)`
- [`x.shape / x.size()`](#
- 张量运算
-
- [`x + y, x - y, x * y, x / y`](#
x + y, x - y, x * y, x / y
) - `torch.exp(x)`
- [`torch.cat((X, Y), dim=0)`](#
torch.cat((X, Y), dim=0)
) - [`torch.dot(x, y)`](#
torch.dot(x, y)
) - [`torch.mv(A, x)`](#
torch.mv(A, x)
) - [`torch.mm(A, B)`](#
torch.mm(A, B)
) - `torch.norm(u)`
- `torch.abs(u).sum()`
- [`x + y, x - y, x * y, x / y`](#
- 索引和切片
- `torch.sum`
- `torch.view`
- `torch.unsqueeze`
- `torch.matmul`
- `torch.stack`
- `torch.cat`
- `torch.no_grad()`
- `torch.repeat`
- `torch.meshgrid`
- `torch.nn.functional.grid_sample`
- `torch.unbind`
在PyTorch中,张量是基本的数据结构,类似于NumPy的ndarray,但它还可以在GPU上运行,以加速计算。以下是您提到的几个用于生成张量的函数的详细解释及示例:
torch.arange(start=0, end, step=1)
-
用法 :生成从
start
到end
(不包括end
),步长为step
的1维张量。 -
参数 :
start
(int):起始值,默认是0。end
(int):结束值(不包括)。step
(int):步长,默认是1。
-
示例 :
pythonimport torch x = torch.arange(start=0, end=10, step=2) print(x) # 输出:tensor([0, 2, 4, 6, 8])
torch.zeros(size)
-
用法:生成全为0的张量。
-
参数 :
size
(tuple):张量的形状,例如(2, 3)
表示2行3列的2D张量。
-
示例 :
pythonx = torch.zeros((2, 3)) print(x) # 输出: # tensor([[0., 0., 0.], # [0., 0., 0.]])
torch.ones(size)
-
用法:生成全为1的张量。
-
参数 :
size
(tuple):张量的形状。
-
示例 :
pythonx = torch.ones((2, 3)) print(x) # 输出: # tensor([[1., 1., 1.], # [1., 1., 1.]])
torch.randn(size)
-
用法:生成服从高斯分布(也称为正态分布)的随机值张量。
-
参数 :
size
(tuple):张量的形状。
-
示例 :
pythonx = torch.randn((2, 3)) print(x) # 输出随机值,例如: # tensor([[ 0.5234, -0.2345, 1.2345], # [-0.5678, 0.9876, -0.1234]])
torch.tensor(data)
-
用法:从给定的数据(如列表、NumPy数组等)生成张量。
-
参数 :
data
(list、NumPy ndarray等):要转换为张量的数据。
-
示例 :
pythondata = [[1, 2], [3, 4]] x = torch.tensor(data) print(x) # 输出: # tensor([[1, 2], # [3, 4]])
这些函数是PyTorch中生成张量的基础,通过它们可以创建各种形状和内容的张量,以供后续的计算和模型训练使用。
张量形状与属性
x.shape / x.size()
这两个函数都用于显示张量的形状。x.shape
返回一个tuple,表示张量的维度和大小,而x.size()
返回一个torch.Size对象,但实质上两者提供的信息是相同的。
-
实例:
pythonimport torch x = torch.tensor([[1, 2, 3], [4, 5, 6]]) print(x.shape) # 输出:torch.Size([2, 3]) print(x.size()) # 输出:torch.Size([2, 3])
x.numel()
此函数用于输出张量中元素的总数。
-
实例:
pythonx = torch.tensor([[1, 2, 3], [4, 5, 6]]) print(x.numel()) # 输出:6
x.reshape(shape)
此函数用于改变张量的形状,但不改变其数据的顺序和总数。shape
参数是一个tuple,表示新的形状。
-
实例:
pythonx = torch.tensor([1, 2, 3, 4, 5, 6]) y = x.reshape((2, 3)) print(y) # 输出:tensor([[1, 2, 3], [4, 5, 6]])
len(x)
此函数用于显示张量的列数(对于1维张量)或第一维的大小(对于多维张量)。注意,它并不总是返回列数,而是返回张量形状的第一个元素。
-
实例:
pythonx = torch.tensor([1, 2, 3, 4, 5, 6]) print(len(x)) # 输出:6(1维张量的长度) y = torch.tensor([[1, 2, 3], [4, 5, 6]]) print(len(y)) # 输出:2(2维张量的第一维大小)
张量运算
x + y, x - y, x * y, x / y
这些是基于元素的算术运算,要求x
和y
的形状相同或可广播到相同形状。
-
实例:
pythonx = torch.tensor([1, 2, 3]) y = torch.tensor([4, 5, 6]) print(x + y) # 输出:tensor([5, 7, 9])
torch.exp(x)
此函数计算e
的x
次方,其中e
是自然对数的底数。
-
实例:
pythonx = torch.tensor([1, 2, 3]) print(torch.exp(x)) # 输出:tensor([ 2.7183, 7.3891, 20.0855])
torch.cat((X, Y), dim=0)
此函数在指定维度上拼接张量X
和Y
。dim
参数指定拼接的维度。
-
实例:
pythonx = torch.tensor([[1, 2], [3, 4]]) y = torch.tensor([[5, 6], [7, 8]]) print(torch.cat((x, y), dim=0)) # 输出:tensor([[1, 2], [3, 4], [5, 6], [7, 8]])
torch.dot(x, y)
此函数计算两个1维张量x
和y
的点积。
-
实例:
pythonx = torch.tensor([1, 2, 3]) y = torch.tensor([4, 5, 6]) print(torch.dot(x, y)) # 输出:32
torch.mv(A, x)
此函数计算矩阵A
与向量x
的向量积。A
必须是2维的,x
必须是1维的。
-
实例:
pythonA = torch.tensor([[1, 2], [3, 4]]) x = torch.tensor([5, 6]) print(torch.mv(A, x)) # 输出:tensor([17, 39])
torch.mm(A, B)
此函数计算矩阵A
与矩阵B
的矩阵乘法。A
和B
都必须是2维的,且A
的列数必须等于B
的行数。
-
实例:
pythonA = torch.tensor([[1, 2], [3, 4]]) B = torch.tensor([[5, 6], [7, 8]]) print(torch.mm(A, B)) # 输出:tensor([[19, 22], [43, 50]])
torch.norm(u)
此函数计算向量u
的范数(或长度),即其元素的平方和的平方根。
-
实例:
pythonu = torch.tensor([1, 2, 3]) print(torch.norm(u)) # 输出:tensor(3.7417)
torch.abs(u).sum()
此函数先计算向量u
中每个元素的绝对值,然后求和。
-
实例:
pythonu = torch.tensor([-1, -2, 3]) print(torch.abs(u).sum()) # 输出:tensor(6)
索引和切片
X[-1]
此操作取张量X
的最后一行(对于2维张量)或最后一个元素(对于1维张量)。
-
实例:
pythonX = torch.tensor([[1, 2, 3], [4, 5, 6]]) print(X[-1]) # 输出:tensor([4, 5, 6])
X[1:3]
此操作取张量X
的第2到第3行(不包括第3行,对于2维张量)或第2到第3个元素(不包括第3个,对于1维张量)。注意,这里的索引是从0开始的。
-
实例:
pythonX = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) print(X[1:3]) # 输出:tensor([[4, 5, 6], [7, 8, 9]])
torch.sum
torch.sum
是 PyTorch 中的一个函数,用于计算张量(tensor)中所有元素的和。它可以对整个张量进行求和,也可以只对指定的维度进行求和。这个函数在深度学习、机器学习以及许多其他数学和计算任务中都非常有用。
使用方式
基本的使用方式如下:
python
torch.sum(input, *, dtype=None, out=None, dim=None, keepdim=False)
input
是要求和的张量。dtype
是一个可选参数,用于指定返回张量的数据类型(如果未指定,则与输入张量相同)。out
是一个可选参数,用于指定输出张量(如果不指定,则返回一个新的张量)。dim
是一个可选参数,用于指定在哪个维度上进行求和。如果未指定,则对整个张量进行求和。keepdim
是一个布尔值,如果设置为True
,则在求和后保持原始张量的维度(通过添加大小为1的维度来替代被求和的维度)。
示例
- 对整个张量求和:
python
import torch
x = torch.tensor([[1, 2, 3], [4, 5, 6]])
sum_x = torch.sum(x)
print(sum_x) # 输出: tensor(21)
- 对指定维度求和:
python
sum_x_dim0 = torch.sum(x, dim=0)
print(sum_x_dim0) # 输出: tensor([5, 7, 9])
sum_x_dim1 = torch.sum(x, dim=1)
print(sum_x_dim1) # 输出: tensor([ 6, 15])
- 使用
keepdim
参数保持维度:
python
sum_x_dim1_keepdim = torch.sum(x, dim=1, keepdim=True)
print(sum_x_dim1_keepdim) # 输出: tensor([[ 6],
# [15]])
在这个例子中,x
是一个形状为 (2, 3)
的二维张量。当我们对整个张量求和时,得到的是一个标量(即所有元素的和)。当我们对 dim=0
求和时,得到的是一个形状为 (3,)
的一维张量,它包含了每一列的和。当我们对 dim=1
求和时,得到的是一个形状为 (2,)
的一维张量,它包含了每一行的和。如果我们在对 dim=1
求和时使用 keepdim=True
参数,则得到的是一个形状为 (2, 1)
的二维张量,其中原始的行维度被保留了下来(尽管它的大小现在为1)。
torch.sum
函数是 PyTorch 中处理张量求和的基本工具之一,它在许多计算任务中都有广泛的应用。
torch.view
torch.view
是 PyTorch 中的一个方法,用于重新调整张量的形状而不改变其数据。这个方法非常有用,特别是在需要匹配特定形状要求的情况下,比如在神经网络层之间传递数据时。
使用方式
基本的使用方式如下:
python
tensor.view(new_shape)
这里,tensor
是你想要改变形状的原始张量,而 new_shape
是一个元组,指定了新张量的维度。重要的是,new_shape
中的元素乘积必须等于原始张量元素的数量,否则这个方法会抛出一个错误,因为不能在不改变总元素数的情况下改变张量的形状。
示例
假设你有一个形状为 (2, 3)
的张量:
python
import torch
# 创建一个形状为(2, 3)的张量
x = torch.tensor([[1, 2, 3], [4, 5, 6]])
print(x)
# 输出:
# tensor([[1, 2, 3],
# [4, 5, 6]])
你可以使用 view
方法来改变它的形状,比如变成形状为 (3, 2)
的张量:
python
y = x.view(3, 2)
print(y)
# 输出:
# tensor([[1, 2],
# [3, 4],
# [5, 6]])
或者变成形状为 (1, 6)
的张量:
python
z = x.view(1, 6)
print(z)
# 输出:
# tensor([[1, 2, 3, 4, 5, 6]])
注意事项
torch.view
返回的是一个新的张量,它与原始张量共享相同的数据。所以,如果你修改了新张量的值,原始张量的对应值也会被改变。- 如果你的张量是在 CUDA(GPU)上的,使用
view
后新张量也会自动在相同的设备上。 - 如果要改变的形状与原始数据的总元素数不匹配,
view
会抛出RuntimeError
。 - 对于一些特定操作,如果你想要的形状在某一维度上是未知的(比如你只想指定某些维度的大小,而其他维度由PyTorch自动推断),可以使用
-1
作为该维度的大小。PyTorch会根据其他维度的大小和总元素数自动计算这一维度的大小。
torch.view
是处理张量形状的一个非常强大的工具,能让你更灵活地操作你的数据,以适应不同的计算需求。
torch.unsqueeze
torch.unsqueeze
是 PyTorch 中的一个方法,用于给指定位置加上维数为一的维度。这个方法非常有用,特别是在需要匹配特定维度要求的操作或函数时,比如在一些神经网络层中传递数据时。
使用方式
基本的使用方式如下:
python
tensor.unsqueeze(dim)
这里,tensor
是你想要增加维度的原始张量,而 dim
是一个整数,指定了在哪里添加新的维度。dim
的值可以是从 -tensor.dim()-1
(包括)到 tensor.dim()
(不包括)的任何一个整数,其中 tensor.dim()
是原始张量的维度数。如果 dim
是负的,则它表示从张量维度的末尾开始计数的位置。
示例
假设你有一个形状为 (2, 3)
的张量:
python
import torch
# 创建一个形状为(2, 3)的张量
x = torch.tensor([[1, 2, 3], [4, 5, 6]])
print(x)
# 输出:
# tensor([[1, 2, 3],
# [4, 5, 6]])
你可以使用 unsqueeze
方法在第0维(最外层)增加一个新的维度:
python
y = x.unsqueeze(0)
print(y)
# 输出:
# tensor([[[1, 2, 3],
# [4, 5, 6]]])
# 形状为 (1, 2, 3)
或者在第2维(最内层之后)增加一个新的维度:
python
z = x.unsqueeze(2)
print(z)
# 输出:
# tensor([[[1],
# [2],
# [3]],
#
# [[4],
# [5],
# [6]]])
# 形状为 (2, 3, 1)
如果你使用负的 dim
值,比如 -1
,它会在张量的最后一个维度之后添加一个新的维度:
python
w = x.unsqueeze(-1)
print(w)
# 输出与 z 相同,因为对于形状为 (2, 3) 的张量来说,-1 指的是第2维之后的位置:
# tensor([[[1],
# [2],
# [3]],
#
# [[4],
# [5],
# [6]]])
# 形状为 (2, 3, 1)
注意事项
unsqueeze
返回的是一个新的张量,它与原始张量不共享内存空间(除非你使用了out
参数指定了输出张量,这是一个不常见的用法)。- 增加的维度大小总是1。
- 如果你的张量是在 CUDA(GPU)上的,使用
unsqueeze
后新张量也会自动在相同的设备上。
torch.unsqueeze
是调整张量形状的一个非常有用的工具,特别是在需要增加维度以满足某些操作或函数的输入要求时。
torch.matmul
torch.matmul
是 PyTorch 中的一个函数,用于执行矩阵乘法。它计算两个张量(通常是矩阵)的点积,并返回结果张量。这个函数对于线性代数运算、神经网络中的权重更新以及许多其他数学和计算任务都是至关重要的。
使用方式
基本的使用方式如下:
python
torch.matmul(input, other, *, out=None)
input
是第一个输入张量。other
是第二个输入张量。out
是一个可选参数,用于指定输出张量(如果不指定,则返回一个新的张量)。*
表示out
参数是关键字参数,必须以其关键字形式传递。
示例
假设你有两个矩阵 A
和 B
:
python
import torch
# 创建矩阵 A 和 B
A = torch.tensor([[1, 2], [3, 4]])
B = torch.tensor([[5, 6], [7, 8]])
# 使用 torch.matmul 进行矩阵乘法
C = torch.matmul(A, B)
print(C)
# 输出:
# tensor([[19, 22],
# [43, 50]])
在这个例子中,A
和 B
都是形状为 (2, 2)
的矩阵。torch.matmul
计算了它们的点积,结果是一个新的形状为 (2, 2)
的矩阵 C
。
注意事项
torch.matmul
支持广播机制,但这要求输入张量的某些维度是兼容的。- 如果输入张量是一维的(即向量),则它们将被当作列向量处理(除非它们被明确地重新整形为二维张量)。
- 对于高维张量,
torch.matmul
会在最后两个维度上执行矩阵乘法,其他维度保持不变。 - 如果你的张量是在 CUDA(GPU)上的,使用
torch.matmul
后新张量也会自动在相同的设备上。 torch.matmul
与@
运算符是等价的,所以你也可以使用A @ B
来代替torch.matmul(A, B)
。
与其他函数的比较
torch.mm
:这个函数也是用来执行矩阵乘法的,但它只适用于二维张量。torch.matmul
更加通用,可以处理任意维度的张量。torch.bmm
:这个函数用于执行批量矩阵乘法,它要求输入张量的形状为(b, n, m)
和(b, m, p)
,其中b
是批次大小。torch.mul
和*
运算符:它们执行的是元素级乘法,而不是矩阵乘法。
torch.matmul
是 PyTorch 中执行矩阵乘法的核心函数,对于任何涉及线性代数运算的任务都是必不可少的。
torch.stack
torch.stack
是 PyTorch 中的一个函数,用于沿着一个新的维度将一系列的张量(tensors)堆叠起来。这个函数非常有用,特别是当你想要将多个相同形状的张量组合成一个更高维度的张量时。
使用方式
基本的使用方式如下:
python
torch.stack(sequence, dim=0, *, out=None)
sequence
是一个张量的序列(比如列表、元组等),这些张量需要具有相同的形状。dim
是要插入的新维度,默认为0(意味着在序列的最外层添加一个新维度)。这个参数可以是负的,此时它表示从张量维度的末尾开始计数的位置。out
(可选)是一个输出张量,如果提供,则堆叠的结果将存储在这个张量中。
示例
假设你有三个形状为 (2, 3)
的张量:
python
import torch
# 创建三个形状为(2, 3)的张量
tensor1 = torch.tensor([[1, 2, 3], [4, 5, 6]])
tensor2 = torch.tensor([[7, 8, 9], [10, 11, 12]])
tensor3 = torch.tensor([[13, 14, 15], [16, 17, 18]])
你可以使用 torch.stack
将它们沿着一个新的维度堆叠起来:
python
# 沿着第0维(默认)堆叠
stacked_tensors = torch.stack((tensor1, tensor2, tensor3))
print(stacked_tensors)
# 输出:
# tensor([[[ 1, 2, 3],
# [ 4, 5, 6]],
#
# [[ 7, 8, 9],
# [10, 11, 12]],
#
# [[13, 14, 15],
# [16, 17, 18]]])
# 形状为 (3, 2, 3)
或者你可以指定一个不同的维度来堆叠,比如沿着第1维:
python
# 沿着第1维堆叠
stacked_tensors_dim1 = torch.stack((tensor1, tensor2, tensor3), dim=1)
print(stacked_tensors_dim1)
# 输出:
# tensor([[[ 1, 2, 3], [ 7, 8, 9], [13, 14, 15]],
# [[ 4, 5, 6], [10, 11, 12], [16, 17, 18]]])
# 形状为 (2, 3, 3)
注意事项
- 所有输入张量必须具有完全相同的形状,否则
torch.stack
会抛出一个RuntimeError
。 - 输出的张量将具有一个新的维度,其大小等于输入张量的数量,其他维度的大小与输入张量相同。
- 如果你的张量是在 CUDA(GPU)上的,使用
torch.stack
后新张量也会自动在相同的设备上。
torch.stack
是处理张量序列的一个非常有用的工具,能让你轻松地将多个张量组合成一个更高维度的张量,以便在后续的计算中使用。
torch.cat
在 PyTorch 中,torch.cat
是一个用于按指定维度拼接(连接)一系列张量的函数。这个函数非常有用,当你需要将多个张量合并成一个更大的张量时,比如在处理批处理数据或者将多个特征向量拼接成一个更大的特征向量时。
使用方式
torch.cat
的基本使用方式如下:
python
torch.cat((tensor1, tensor2, ...), dim=0)
tensor1, tensor2, ...
是要拼接的张量。你需要将它们放在一个元组(tuple)或列表(list)中传递给torch.cat
。dim
是要拼接的维度。这是一个整数,指定了沿着哪个维度拼接张量。默认值是 0,表示沿着第一个维度(通常是批次维度)拼接。
示例
python
import torch
# 创建两个形状为 (2, 3) 的张量
tensor1 = torch.tensor([[1, 2, 3], [4, 5, 6]])
tensor2 = torch.tensor([[7, 8, 9], [10, 11, 12]])
# 沿着第一个维度拼接张量
result = torch.cat((tensor1, tensor2), dim=0)
print(result)
# 输出:
# tensor([[ 1, 2, 3],
# [ 4, 5, 6],
# [ 7, 8, 9],
# [10, 11, 12]])
# 沿着第二个维度拼接张量
result_dim1 = torch.cat((tensor1, tensor2), dim=1)
print(result_dim1)
# 输出:
# tensor([[ 1, 2, 3, 7, 8, 9],
# [ 4, 5, 6, 10, 11, 12]])
在这个例子中,我们创建了两个形状为 (2, 3)
的二维张量,并分别沿着第一个维度和第二个维度将它们拼接起来。沿着第一个维度拼接时,我们得到了一个形状为 (4, 3)
的张量;沿着第二个维度拼接时,我们得到了一个形状为 (2, 6)
的张量。
需要注意的是,所有要拼接的张量在非拼接维度上的形状必须相同。在上面的例子中,当我们沿着第一个维度拼接时,两个张量的第二个维度(即特征维度)的形状都是 3;当我们沿着第二个维度拼接时,两个张量的第一个维度(即批次维度)的形状都是 2。如果形状不匹配,PyTorch 将抛出一个运行时错误。
torch.no_grad()
torch.no_grad()
是 PyTorch 中的一个上下文管理器(context manager),用于在代码块内部禁用梯度计算。这在进行模型推理(inference)或评估(evaluation)时非常有用,因为在这些情况下,我们不需要计算梯度,从而可以节省内存和加速计算。
使用方式
基本的使用方式如下:
python
import torch
with torch.no_grad():
# 在这个代码块内,所有的张量操作都不会计算梯度
# 进行模型推理或评估的代码
当进入 torch.no_grad()
上下文时,PyTorch 会自动将 requires_grad
标志设置为 False
对所有新创建的张量。这意味着在这些张量上进行的任何操作都不会记录梯度信息。此外,如果这个上下文管理器内部对已经存在的、requires_grad=True
的张量进行操作,这些操作同样不会计算或记录梯度。
示例
python
import torch
import torch.nn as nn
import torch.optim as optim
# 创建一个简单的模型
model = nn.Linear(10, 1)
# 创建一个优化器
optimizer = optim.SGD(model.parameters(), lr=0.01)
# 创建一个输入张量,并启用梯度(通常用于训练)
input_tensor = torch.randn(5, 10, requires_grad=True)
# 在 no_grad 上下文内进行推理
with torch.no_grad():
output = model(input_tensor)
# 在这里,output 张量的 requires_grad 属性将是 False
# 因此,不会计算或记录任何关于 input_tensor 的梯度信息
# 输出结果
print(output)
在这个例子中,我们创建了一个简单的线性模型和一个输入张量。然后,在 torch.no_grad()
上下文内,我们将输入张量传递给模型进行推理。由于在这个上下文内禁用了梯度计算,所以不会记录任何关于输入张量的梯度信息,这可以节省内存并加速计算。
需要注意的是,torch.no_grad()
只会影响在其上下文内部创建的张量或进行的操作。如果你在这个上下文之外创建了一个张量,并且设置了 requires_grad=True
,然后在 torch.no_grad()
内部对这个张量进行操作,这些操作仍然不会计算梯度,但是张量本身的 requires_grad
属性不会改变。当你退出 torch.no_grad()
上下文时,新创建的张量将默认恢复为 requires_grad=False
(除非你明确指定了其他值),但是已经存在的张量的 requires_grad
属性将保持不变。
torch.repeat
torch.repeat
是 PyTorch 中的一个方法,用于重复张量的元素。你可以指定每个维度上重复的次数,从而得到一个新的张量。
使用方式
基本的使用方式如下:
python
torch.repeat(input, repeats)
input
是你想要重复元素的原始张量。repeats
是一个元组,指定了每个维度上重复的次数。元组的长度必须与原始张量的维度数相匹配。
示例
假设你有一个形状为 (2, 1)
的张量:
python
import torch
# 创建一个形状为(2, 1)的张量
x = torch.tensor([[1], [2]])
print(x)
# 输出:
# tensor([[1],
# [2]])
你可以使用 torch.repeat
来重复这个张量的元素。比如,你想要在第一维上重复2次,在第二维上重复3次:
python
# 重复张量,第一维重复2次,第二维重复3次
y = x.repeat(2, 3)
print(y)
# 输出:
# tensor([[1, 1, 1],
# [2, 2, 2],
# [1, 1, 1],
# [2, 2, 2]])
# 形状为 (4, 3)
在这个例子中,原始张量 x
的第一维(即行数)从1增加到了2(因为重复了2次),第二维(即列数)从1增加到了3(因为重复了3次)。
注意事项
torch.repeat
返回的是一个新的张量,它与原始张量不共享内存空间。- 重复的次数必须是非负的整数。
- 如果你的张量是在 CUDA(GPU)上的,使用
torch.repeat
后新张量也会自动在相同的设备上。 - 如果原始张量的形状是
(d1, d2, ..., dn)
,且repeats
是(r1, r2, ..., rn)
,那么输出张量的形状将是(d1*r1, d2*r2, ..., dn*rn)
。
torch.repeat
是扩展张量大小的一个非常有用的工具,特别是在需要特定形状的数据输入到神经网络层或其他操作时。
torch.meshgrid
torch.meshgrid
是 PyTorch 中的一个函数,用于生成多维坐标网格。它接受两个或多个一维张量,并返回一组多维张量,这些张量表示输入张量所有可能组合的坐标点。这个函数在绘制图形、生成坐标数据以及某些数学计算中非常有用。
使用方式
基本的使用方式如下:
python
torch.meshgrid(*tensors, **kwargs)
*tensors
是你想要生成网格的一维张量列表。**kwargs
是可选参数,其中indexing
参数(取值为'xy'
或'ij'
)决定了输出网格的坐标顺序。'xy'
表示第一个维度是x
坐标,第二个维度是y
坐标(这与 MATLAB 和 NumPy 的默认行为相符)。'ij'
表示第一个维度是行索引(i),第二个维度是列索引(j)(这与常规的二维数组索引相符)。
示例
假设你有两个一维张量 x
和 y
:
python
import torch
# 创建一维张量 x 和 y
x = torch.tensor([1, 2, 3])
y = torch.tensor([4, 5, 6])
你可以使用 torch.meshgrid
来生成一个二维网格:
python
# 使用 'xy' 索引生成网格
grid_x, grid_y = torch.meshgrid(x, y, indexing='xy')
print(grid_x)
# 输出:
# tensor([[1, 2, 3],
# [1, 2, 3],
# [1, 2, 3]])
print(grid_y)
# 输出:
# tensor([[4, 4, 4],
# [5, 5, 5],
# [6, 6, 6]])
在这个例子中,grid_x
和 grid_y
都是形状为 (3, 3)
的二维张量,它们表示了 x
和 y
所有可能的组合。
如果你使用 'ij'
索引:
python
# 使用 'ij' 索引生成网格
grid_i, grid_j = torch.meshgrid(x, y, indexing='ij')
print(grid_i)
# 输出:
# tensor([[1, 2, 3],
# [1, 2, 3],
# [1, 2, 3]])
# (注意:这与 'xy' 索引时的 grid_x 相同,因为 x 是一维的,所以它的值没有变化)
print(grid_j)
# 输出:
# tensor([[4, 4, 4],
# [5, 5, 5],
# [6, 6, 6]])
# (同样,这与 'xy' 索引时的 grid_y 相同)
在 'ij'
索引模式下,结果看起来与 'xy'
模式相同,这是因为我们的输入张量是一维的。然而,在多维情况下,或者当处理更复杂的坐标变换时,这两种索引方式会导致不同的结果。
注意事项
torch.meshgrid
返回的是一组张量,这些张量的形状是根据输入张量的长度和indexing
参数确定的。- 输出的张量与输入张量不共享内存空间。
- 如果你的张量是在 CUDA(GPU)上的,使用
torch.meshgrid
后新张量也会自动在相同的设备上。
torch.meshgrid
是生成坐标网格的一个非常有用的工具,特别是在需要处理多维数据或进行图形绘制时。
torch.nn.functional.grid_sample
torch.nn.functional.grid_sample
是 PyTorch 中的一个函数,用于对输入张量(通常是图像或特征图)进行空间变换。它根据给定的网格坐标,从输入张量中采样出对应的值,生成一个新的输出张量。这个函数在图像处理、目标检测、图像分割等领域有广泛的应用,比如实现仿射变换、透视变换、或者根据任意形状的点云生成图像。
使用方式
基本的使用方式如下:
python
torch.nn.functional.grid_sample(input, grid, mode='bilinear', padding_mode='zeros', align_corners=True)
input
是输入张量,形状通常为(N, C, H, W)
,其中N
是批次大小,C
是通道数,H
和W
分别是输入图像的高度和宽度。grid
是一个形状为(N, H_out, W_out, 2)
的张量,它包含了采样点的坐标。这些坐标是归一化到[-1, 1]
范围内的,其中(-1, -1)
表示输入图像的左上角,(1, 1)
表示右下角。H_out
和W_out
是输出图像的高度和宽度。mode
指定了插值模式,可以是'bilinear'
(双线性插值,默认)、'nearest'
(最近邻插值)、'bicubic'
(双三次插值)之一。padding_mode
指定了填充模式,当采样点超出输入图像边界时如何处理。可以是'zeros'
(默认,用零填充)、'border'
(用边界值填充)、'reflection'
(反射填充)之一。align_corners
是一个布尔值,指定了在插值时是否对齐角落。如果为True
(默认),则输入和输出图像的角落像素会对齐;如果为False
,则插值会更加平滑,但角落像素可能不会完全对齐。
示例
下面是一个简单的示例,演示如何使用 grid_sample
函数对图像进行仿射变换:
python
import torch
import torch.nn.functional as F
import matplotlib.pyplot as plt
# 创建一个简单的图像张量(单通道,高度和宽度都为4)
input_image = torch.tensor([[[[1., 2., 3., 4.],
[5., 6., 7., 8.],
[9., 10., 11., 12.],
[13., 14., 15., 16.]]]], dtype=torch.float32)
# 创建一个仿射变换的网格(这里只是一个简单的例子,实际使用时需要根据具体情况计算网格坐标)
# 这个网格会将图像进行旋转和缩放
grid = torch.tensor([[[[ 0.5, -0.5], # 左上角
[ 1.5, -0.5], # 右上角
[ 0.5, 0.5], # 左下角
[ 1.5, 0.5]]]], # 右下角
dtype=torch.float32)
# 注意:grid_sample函数要求grid的形状为(N, H_out, W_out, 2)
# 并且坐标要归一化到[-1, 1]范围内,所以我们需要对grid进行调整
grid = grid * 2 - 1 # 将坐标归一化
grid = grid.unsqueeze(0).expand(1, -1, -1, -1) # 增加批次维度
# 使用grid_sample函数进行采样
output_image = F.grid_sample(input_image, grid, mode='bilinear', align_corners=True)
# 输出采样后的图像张量
print(output_image)
# 可视化输入和输出图像(这里只展示了单通道图像,所以直接用imshow可能效果不佳)
plt.subplot(1, 2, 1)
plt.imshow(input_image[0, 0], cmap='gray')
plt.title('Input Image')
plt.subplot(1, 2, 2)
plt.imshow(output_image[0, 0, 0], cmap='gray') # 注意这里输出图像多了一个维度,需要去掉
plt.title('Output Image')
plt.show()
请注意,上面的示例只是为了演示 grid_sample
的基本用法,并且创建了一个非常简单的仿射变换网格。在实际应用中,你可能需要根据具体的变换需求来计算网格坐标。此外,由于 grid_sample
函数返回的是浮点数张量,所以在可视化或保存图像时可能需要进行适当的处理(比如四舍五入、类型转换等)。
torch.unbind
torch.unbind
是 PyTorch 中的一个函数,用于将张量(tensor)拆分成多个张量,这些张量是原始张量在指定维度上的切片。这个函数对于需要单独处理张量中每个切片的情况非常有用,比如在循环中处理序列数据,或者将批处理的数据分开处理。
使用方式
基本的使用方式如下:
python
torch.unbind(tensor, dim=0)
tensor
是要拆分的张量。dim
是要拆分的维度。默认值为0,表示拆分第一个维度(通常是批次维度)。
torch.unbind
返回一个包含拆分后张量的元组(tuple)。
示例
python
import torch
# 创建一个形状为 (3, 2) 的张量
x = torch.tensor([[1, 2], [3, 4], [5, 6]])
# 沿着第一个维度(dim=0)拆分张量
tensors = torch.unbind(x, dim=0)
# 打印拆分后的张量
for i, t in enumerate(tensors):
print(f"Tensor {i}: {t}")
# 输出:
# Tensor 0: tensor([1, 2])
# Tensor 1: tensor([3, 4])
# Tensor 2: tensor([5, 6])
在这个例子中,我们创建了一个形状为 (3, 2)
的二维张量,并使用 torch.unbind
函数沿着第一个维度将其拆分成三个形状为 (2,)
的一维张量。拆分后的张量被存储在一个元组中,并通过循环打印出来。
需要注意的是,torch.unbind
函数返回的是元组,而不是列表。如果你需要一个列表而不是元组,你可以简单地将返回的元组转换为列表:
python
tensors_list = list(torch.unbind(x, dim=0))
此外,如果你想要拆分的是最后一个维度(即 -1
维度),你可以这样做:
python
# 沿着最后一个维度拆分张量
tensors = torch.unbind(x, dim=-1)
# 打印拆分后的张量
for i, t in enumerate(tensors):
# 注意:现在每个张量的形状是 (3,)
print(f"Tensor {i}: {t}")
# 输出:
# Tensor 0: tensor([1, 3, 5])
# Tensor 1: tensor([2, 4, 6])
在这个例子中,我们沿着最后一个维度将张量拆分成两个形状为 (3,)
的一维张量。这在实际应用中可能不太常见,因为通常我们会沿着批次维度或特征维度进行拆分,但了解如何沿任意维度拆分张量是很有用的。