张量的操作

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()

  • 功能: 交换张量的两个维度。

  • 参数:

    • input: 要变换的张量。
    • dim0: 要交换的第一个维度。
    • dim1: 要交换的第二个维度。

示例

①. 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()

  • 功能: 二维张量转置,对矩阵而言,等价于torch.transpose(input, 0, 1)。
  • 使用场景: 矩阵转置,行变列,列变行。

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])
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值