1、拼接:
torch.cat():维度dim上的张量拼接
torch.stack():在新创建的维度dim上的拼接(拓展维度)
import torch
t=torch.ones((2,3))
t_stack=torch.stack([t,t],dim=0)
print(t)
print(t_stack)
输出
`tensor([[1., 1., 1.],`
`[1., 1., 1.]])`
`tensor([[[1., 1., 1.],`
`[1., 1., 1.]],`
`[[1., 1., 1.],`
`[1., 1., 1.]]])`
2、切分:
a. torch.chunk()
示例
torch.chunk()
方法将张量在指定维度上均匀切分成指定数量的块。如果不能均匀切分,最后一个块的大小会小于其他块。
import torch
# 创建一个 2x5 的张量
tensor = torch.arange(1, 11).view(2, 5)
print("原始张量:")
print(tensor)
# 在第一维度(列方向)上进行切分,chunks 设置为 2
chunks = torch.chunk(tensor, chunks=2, dim=1)
print("\n使用 torch.chunk() 切分后:")
for i, chunk in enumerate(chunks):
print(f"第 {i+1} 个张量: 形状为 {chunk.shape}")
print(chunk)
输出:
原始张量:
tensor([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10]])
使用 torch.chunk() 切分后:
第 1 个张量: 形状为 torch.Size([2, 3])
tensor([[1, 2, 3],
[6, 7, 8]])
第 2 个张量: 形状为 torch.Size([2, 2])
tensor([[4, 5],
[9, 10]])
b. torch.split()
示例
torch.split()
方法可以根据指定的大小或列表将张量切分成多个块。
整数模式
特点:
- 固定大小:每一块的大小是固定的,由
split_size_or_sections
指定。 - 自动处理剩余部分:如果张量在指定维度上的长度不能被
split_size_or_sections
整除,最后一个块的大小会小于指定的大小。 - 简单直观:适用于需要均匀切分的情况,但不需要精确控制每一块的大小。
在整数模式下,torch.split()
将张量在指定维度上按照指定的大小进行切分,最后一个块的大小可能小于指定大小。
# 在第一维度(列方向)上进行切分,每份长度为 2
splits = torch.split(tensor, split_size_or_sections=2, dim=1)
print("\n使用 torch.split()(整数模式)切分后:")
for i, split in enumerate(splits):
print(f"第 {i+1} 个张量: 形状为 {split.shape}")
print(split)
输出:
使用 torch.split()(整数模式)切分后:
第 1 个张量: 形状为 torch.Size([2, 2])
tensor([[1, 2],
[6, 7]])
第 2 个张量: 形状为 torch.Size([2, 2])
tensor([[3, 4],
[8, 9]])
第 3 个张量: 形状为 torch.Size([2, 1])
tensor([[5],
[10]])
列表模式
特点:
- 精确控制:可以精确指定每一块的大小,适用于需要特定大小切分的情况。
- 严格匹配:列表中所有元素的和必须等于张量在指定维度上的长度。如果列表元素之和不等于指定维度的长度,会报错。
- 灵活性更高:可以实现更复杂的切分需求,例如切分大小不一致的情况。
在列表模式下,torch.split()
将张量在指定维度上按照列表中的大小进行切分。如果列表元素之和不等于指定维度的长度,会报错。
# 使用列表模式,[2, 1, 2]
try:
splits = torch.split(tensor, split_size_or_sections=[2, 1, 2], dim=1)
print("\n使用 torch.split()(列表模式)切分后:")
for i, split in enumerate(splits):
print(f"第 {i+1} 个张量: 形状为 {split.shape}")
print(split)
except RuntimeError as e:
print(f"发生错误:{e}")
输出:
使用 torch.split()(列表模式)切分后:
第 1 个张量: 形状为 torch.Size([2, 2])
tensor([[1, 2],
[6, 7]])
第 2 个张量: 形状为 torch.Size([2, 1])
tensor([[3],
[8]])
第 3 个张量: 形状为 torch.Size([2, 2])
tensor([[4, 5],
[9, 10]])
列表元素之和不等于指定维度长度
如果列表元素之和不等于指定维度的长度,torch.split()
会报错。
# 使用列表模式,[2, 1, 3],但第一维度长度为 5,2+1+3=6,不等于 5
try:
splits = torch.split(tensor, split_size_or_sections=[2, 1, 3], dim=1)
except RuntimeError as e:
print(f"发生错误:{e}")
输出:
发生错误:split_size_or_sections must sum to size of dimension 1, but got 6 for a tensor of size [2, 5]`
3、索引:
a、torch.index_select()
**函数的定义:**torch.index_select(input,dim,index,out =None)
- input:要索引的张量。
- dim:索引的维度。
- index:索引数据的序号。
示例:
假设我们有一个形状为 [3, 4]
的二维张量 input
,我们想要在第 0 维(行)上根据索引选择元素。
import torch
# 创建一个形状为 [3, 4] 的二维张量
input = torch.tensor([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
# 创建一个索引张量,指定在第 0 维上选择哪些行
index = torch.tensor([0, 2])
# 在第 0 维上进行索引选择
selected = torch.index_select(input, dim=0, index=index)
print("选择后的张量:")
print(selected)
输出:
选择后的张量:
tensor([[ 1, 2, 3, 4],
[ 9, 10, 11, 12]])
在这个例子中,我们在第 0 维(行)上选择了索引为 0 和 2 的行。结果是一个新的张量,只包含原始张量的第 0 行和第 2 行。
b、torch.masked_select()
函数定义:torch.masked_select(input,mask,out=None)
- input: 要索引的张量。
- mask: 与input同形状的布尔类型张量。(相当于作为条件在input中检索为True的元素)
返回值:一维张量,包含mask中为True的元素。
示例:
import torch
# 创建一个二维张量(矩阵)
input_tensor = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# 创建一个布尔掩码(mask),其中掩码为 True 的位置表示我们想要选择的元素
mask = torch.tensor([[False, True, False],
[False, False, True],
[True, False, False]])
# 使用 torch.masked_select 根据掩码选择元素
selected_elements = torch.masked_select(input_tensor, mask)
print("原始张量:")
print(input_tensor)
print("掩码:")
print(mask)
print("选择后的元素:", selected_elements)
输出:
原始张量:
tensor([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
掩码:
tensor([[False, True, False],
[False, False, True],
[ True, False, False]])
选择后的元素: tensor([2, 6, 7])
4.变换
a、torch.reshape()
功能: 改变张量的形状而不改变其数据。
- input: 要变换的张量。
- shape: 新张量的形状。
注意事项:
当张量在内存中是连续时,新张量与input共享数据内存。如果改变新张量,原始张量也会被改变。
避免的方式:
①:.contiguous()
方法会创建一个新的连续张量。
②:可以在重塑操作后使用 .clone()
方法创建一个副本,这样原始张量和新张量将拥有独立的内存空间。
示例:
import torch
# 创建一个一维张量
x = torch.arange(6)
# 重塑张量为 2 行 3 列的二维张量
y = torch.reshape(x, (2, 3))
print("原始张量:", x)
print("重塑后的张量:\n", y)
输出:
原始张量: tensor([0, 1, 2, 3, 4, 5])
重塑后的张量:
tensor([[0, 1, 2],
[3, 4, 5]])
b、torch.transpose()
示例
①. 2D 矩阵的转置
import torch
x = torch.tensor([[1, 2, 3],
[4, 5, 6]]) # shape (2, 3)
y = torch.transpose(x, 0, 1) # 交换第0维和第1维
# 等价于 y = x.t() 或 y = x.T
print("原张量:\n", x)
print("转置后的张量:\n", y)
输出:
原张量:
tensor([[1, 2, 3],
[4, 5, 6]])
转置后的张量:
tensor([[1, 4],
[2, 5],
[3, 6]])
②. 3D 张量的维度交换
z = torch.randn(2, 3, 4) # shape (2, 3, 4)
w = z.transpose(0, 2) # 交换第0维和第2维
print("原张量形状:", z.shape)
print("交换后的形状:", w.shape)
输出:
原张量形状:torch.Size([2, 3, 4])
交换后的形状:torch.Size([4, 3, 2])
说明: (2, 3, 4)
→ (4, 3, 2)
c、torch.t()
d、torch.squeeze()
- 功能: 压缩长度为1的维度(轴)。
- 参数:
- input: 要变换的张量。
- dim: 若为None,移除所有长度为1的轴;若指定维度,当且仅当该轴长度为1时,可以被移除。.
示例:
①. 默认移除所有长度为1的维度
import torch
x = torch.randn(1, 3, 1, 2) # shape (1, 3, 1, 2)
y = x.squeeze() # 移除所有长度为1的维度
print("原张量形状:", x.shape)
print("压缩后形状:", y.shape)
输出:
原张量形状:torch.Size([1, 3, 1, 2])
压缩后形状:torch.Size([3, 2])
②. 指定移除某个维度
x = torch.randn(1, 3, 1, 2) # shape (1, 3, 1, 2)
y = x.squeeze(dim=0) # 只移除第0维(长度为1)
print("压缩后形状:", y.shape) # torch.Size([3, 1, 2])
③. 如果指定维度长度不为1,则无变化
x = torch.randn(2, 3, 4) # shape (2, 3, 4)
y = x.squeeze(dim=1) # dim=1的长度是3(不为1),y 不变
print("压缩后形状:", y.shape) # torch.Size([2, 3, 4])
5)torch.unsqueeze()
- 功能: 依据dim扩展维度,新维度的长度为1。
- 参数:
- input: 要变换的张量。
- dim: 要扩展的维度。
- 说明: 使用过程简单,指定维度上拓展一个长度为1的维度。
示例:
import torch
# 创建一个一维张量(使用 arange 替代 range)
x = torch.arange(2, 21, 2) # 从2开始到20(不包括21),步长为2
y = x.unsqueeze(1) # 在第1维(列维度)增加一个维度
print("原始张量 x:")
print(x)
print("形状:", x.shape) # 输出: torch.Size([10])
print("\n扩展后的张量 y:")
print(y)
print("形状:", y.shape) # 输出: torch.Size([10, 1])
输出示例:
原始张量 x:
tensor([ 2, 4, 6, 8, 10, 12, 14, 16, 18, 20])
形状: torch.Size([10])
扩展后的张量 y:
tensor([[ 2],
[ 4],
[ 6],
[ 8],
[10],
[12],
[14],
[16],
[18],
[20]])
形状: torch.Size([10, 1])