Pytorch - 张量转换拼接

88661fd4183f4cb9ac889645a47363fe.gif

😆😆😆感谢大家的观看😆😆😆

张量转换为 numpy 数组

🔎使用 Tensor.numpy 函数可以将张量转换为 ndarray 数组,但是共享内存,可以使用 copy 函数避免共享。

data_tensor = torch.tensor([2, 3, 4])
# 使用张量对象中的 numpy 函数进行转换
data_numpy = data_tensor.numpy()

print(type(data_tensor))
print(type(data_numpy))


# 修改其中的一个,另外一个也会发生改变!
# data_tensor[0] = 100
data_numpy[0] = 100

print(data_tensor)
print(data_numpy)

我们可以通过对象拷贝避免共享内存:

data_tensor = torch.tensor([2, 3, 4])
# 使用张量对象中的 numpy 函数进行转换
data_numpy = data_tensor.numpy().copy()

print(type(data_tensor))
print(type(data_numpy))


# data_tensor[0] = 100
data_numpy[0] = 100
print(data_tensor)
print(data_numpy)

numpy 转换为张量

  1. 使用 from_numpy 可以将 ndarray 数组转换为 Tensor,默认共享内存,使用 copy 函数避免共享。
  2. 使用 torch.tensor 可以将 ndarray 数组转换为 Tensor,默认不共享内存。
def test01():

    data_numpy = np.array([2, 3, 4])
    data_tensor = torch.from_numpy(data_numpy)

    # 共享内存
    # data_numpy[0] = 100
    data_tensor[0] = 100

    print(data_tensor)
    print(data_numpy)


# 使用 torch.tensor 函数
def test02():

    data_numpy = np.array([2, 3, 4])

    data_tensor = torch.tensor(data_numpy)

    # 不共享内存
    # data_numpy[0] = 100
    data_tensor[0] = 100

    print(data_tensor)
    print(data_numpy)

标量张量和数字的转换

🔎对于只有一个元素的张量(shape没有限制,元素只有一个),使用 item 方法将该值从张量中提取出来。 

data = torch.tensor([30,])
print(data.item())

data = torch.tensor(30)
print(data.item())

data = torch.tensor([[30]])
print(data.item())

# 30
# 30
# 30

张量拼接操作

⚔️张量的拼接方式有两种:CAT、STACK

  • CAT方法是将两个张量按照某一维度进行拼接(类似于积木拼接)
  • STACK方法是将两个张量按照顺序垂直堆叠起来。
  • STACK 方法主要用于将多个张量垂直堆叠在一起,形成一个新的、更高维度的张量。这在需要将来自不同来源或具有不同特征集的数据整合到一起时非常有用,例如在处理时间序列数据或多通道图像数据时。而 CAT 方法则是在同一维度上水平拼接张量,适用于需要扩展特征空间宽度的情况~

torch.cat()   该函数接受两个参数:输入张量列表和拼接的维度。以下是一个简单的示例:

import torch

# 创建两个张量
tensor1 = torch.tensor([[1, 2], [3, 4]])
tensor2 = torch.tensor([[5, 6], [7, 8]])

# 沿着第0维(行)拼接张量
result = torch.cat((tensor1, tensor2), dim=0)
print(result)
# 输出:
# tensor([[1, 2],
#         [3, 4],
#         [5, 6],
#         [7, 8]])

# 沿着第1维(列)拼接张量
result = torch.cat((tensor1, tensor2), dim=1)
print(result)
# 输出:
# tensor([[1, 2, 5, 6],
#         [3, 4, 7, 8]])

我们可以打印每个张量的shape,来观察一下拼接所发生的变化:依次类推dim:0,1,2位置

import torch
data1 = torch.randint(0, 10, [3, 5, 4])
data2 = torch.randint(0, 10, [3, 5, 4])
data1.cuda()
data2.cuda()
new_data = torch.cat([data1, data2], dim=0)
print(new_data.shape)
# 结果:torch.Size([6, 5, 4])

torch.stack() 

⚔️torch.stack函数用于将一系列张量堆叠到一个新的维度。(轴)

torch.stack的使用场景通常包括需要增加数据的一个维度时。比如在处理图像数据或者文本数据的时候,我们经常需要把二维的数据转换为三维的,这时候就可以使用torch.stack来完成这个操作。使用torch.stack可以保留两个信息:序列和张量矩阵信息。当我们需要把一系列的二维张量转换为三维的张量时,可以使用torch.stack来实现。例如,如果我们有两个形状为(3, 3)的二维张量A和B,我们可以通过指定dim=0来在它们的最前面增加一个新的维度,结果张量的形状就会变为(2, 3, 3)。这表明在新的维度上,张量的个数是2,其它两个维度的大小保持不变。

torch.cat的区别主要在于,torch.cat是在现有的维度上进行拼接

这意味着使用torch.cat时,输入的张量必须在除了拼接维度外的所有其他维度上具有相同的大小。而torch.stack则要求所有输入张量在所有维度上的大小都相同。此外,torch.cat不会增加张量的总维度数量,它仅仅是在一个指定的维度上扩展了张量的大小。例如,如果我们有两个形状为(2, 2, 3)的张量,当我们对它们应用torch.cat(dim=0)时,结果张量的形状会是(4, 2, 3),这里的4表示在指定的维度上,元素的数量从原来的2个扩展到了4个。

import torch

# 创建两个形状为(3, 3)的张量A和B
A = torch.tensor([[1, 2, 3], 
                  [4, 5, 6], 
                  [7, 8, 9]])
B = torch.tensor([[10, 11, 12],
                  [13, 14, 15], 
                  [16, 17, 18]])

# 使用torch.stack将A和B堆叠成一个新的维度,dim=0表示在最前面增加新的维度
C = torch.stack((A, B), dim=0)
print(C)

tensor([[[ 1,  2,  3],
         [ 4,  5,  6],
         [ 7,  8,  9]],

        [[10, 11, 12],
         [13, 14, 15],
         [16, 17, 18]]])

我们可以再观察dim=1表示在第二个维度上进行堆叠。

import torch

A = torch.tensor([[1, 2, 3],
                  [4, 5, 6]])
B = torch.tensor([[7, 8, 9], 
                  [10, 11, 12]])

C = torch.stack((A, B), dim=1)


tensor([[[ 1,  2,  3],
         [ 7,  8,  9]],

        [[ 4,  5,  6],
         [10, 11, 12]]])

我们可以再观察dim=2表示在第三个维度上进行堆叠。

data1= torch.randint(0, 10, [2, 3])
data2= torch.randint(0, 10, [2, 3])
new_data = torch.stack([data1, data2], dim=2)
print(new_data)



tensor([[[5, 6],
         [6, 0],
         [9, 2]],

        [[5, 1],
         [9, 4],
         [0, 1]]])

💥我们观察一下dim = 0时的cat与stack💥

import torch

data1= torch.randint(0, 10, [2, 3])
data2= torch.randint(0, 10, [2, 3])
print(data1)
print(data2)
print('-'*30)
new_data = torch.stack([data1, data2], dim=0)
print(new_data)
new_data = torch.cat([data1,data2],dim=0)
print(new_data)

tensor([[9, 3, 5],
            [0, 7, 7]])
tensor([[2, 1, 4],
            [9, 0, 1]])
------------------------------
tensor([[[9, 3, 5],
         [0, 7, 7]],

        [[2, 1, 4],
         [9, 0, 1]]])
tensor([[9, 3, 5],
        [0, 7, 7],
        [2, 1, 4],
        [9, 0, 1]])

  • 我们可以看出cat是在现有的维度上进行拼接,原本只有两个维度,所以dim = 0时将两个张量按行拼到一起了~ 💥
  • 而stack是将其增加数据的一个维度,按照原本dim = 0,1,2进行堆叠,即按照第0维度堆叠成了[2,2,3]shape~ 💥

张量索引操作

张量索引操作允许我们对多维数组中的元素进行访问和操作。张量索引操作是处理多维数据的基础,它不仅能够让我们访问和修改数据,还能够帮助我们实现各种复杂的数据操作和算法。

我们来看一下张量索引基本操作:

🏹简单行、列索引

import torch

data = torch.randint(0, 10, [4, 5])
print(data)


tensor([[0, 7, 6, 5, 9],
        [6, 8, 3, 1, 0],
        [6, 3, 8, 7, 3],
        [4, 9, 5, 3, 1]])
  • data[0]    --- tensor([0, 7, 6, 5, 9])
  • data[:, 0] --- tensor([0, 6, 6, 4])
  • data[[0, 1], [1, 2]] :返回 (0, 1)、(1, 2) 两个位置的元素(tensor([7, 3]))
  • data[[[0], [1]], [1, 2]]  : 返回 0、1 行的 1、2 列共4个元素 (tensor([[7, 6], [8, 3]]))

🏹范围索引 

# 前3行的前2列数据
print(data[:3, :2])
# 第2行到最后的前2列数据
print(data[2:, :2])


tensor([[0, 7],
        [6, 8],
        [6, 3]])
tensor([[6, 3],
        [4, 9]])

🏹布尔索引

# 第三列大于5的行数据
print(data[data[:, 2] > 5]) # data[:, 2] > 5返回了按照这个规则的一列布尔值,再套入到data求出来
类似于pandas求所有行的某一维度>5的所有行
# 第二行大于5的列数据
print(data[:, data[1] > 5])



tensor([[0, 7, 6, 5, 9],
        [6, 3, 8, 7, 3]])
tensor([[0, 7],
        [6, 8],
        [6, 3],
        [4, 9]])

🏹多维索引

data = torch.randint(0, 10, [3, 4, 5])
print(data)
print('-' * 50)

print(data[0, :, :])
print(data[:, 0, :])
print(data[:, :, 0])


结果:
tensor([[[2, 4, 1, 2, 3],
         [5, 5, 1, 5, 0],
         [1, 4, 5, 3, 8],
         [7, 1, 1, 9, 9]],

        [[9, 7, 5, 3, 1],
         [8, 8, 6, 0, 1],
         [6, 9, 0, 2, 1],
         [9, 7, 0, 4, 0]],

        [[0, 7, 3, 5, 6],
         [2, 4, 6, 4, 3],
         [2, 0, 3, 7, 9],
         [9, 6, 4, 4, 4]]])
--------------------------------------------------
tensor([[2, 4, 1, 2, 3],
        [5, 5, 1, 5, 0],
        [1, 4, 5, 3, 8],
        [7, 1, 1, 9, 9]])
tensor([[2, 4, 1, 2, 3],
        [9, 7, 5, 3, 1],
        [0, 7, 3, 5, 6]])
tensor([[2, 5, 1, 7],
        [9, 8, 6, 9],
        [0, 2, 2, 9]])

💥我们下期一起学习张量的高阶操作💥

  • 40
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 26
    评论
以下是一个基于PyTorch的全景图像拼接代码示例: ```python import torch import numpy as np from PIL import Image # 定义模型 class PanoramaNet(torch.nn.Module): def __init__(self): super(PanoramaNet, self).__init__() self.conv1 = torch.nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1) self.conv2 = torch.nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1) self.conv3 = torch.nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1) self.conv4 = torch.nn.Conv2d(128, 256, kernel_size=3, stride=1, padding=1) self.conv5 = torch.nn.Conv2d(256, 512, kernel_size=3, stride=1, padding=1) self.conv6 = torch.nn.Conv2d(512, 1024, kernel_size=3, stride=1, padding=1) self.upconv1 = torch.nn.ConvTranspose2d(1024, 512, kernel_size=2, stride=2) self.upconv2 = torch.nn.ConvTranspose2d(512, 256, kernel_size=2, stride=2) self.upconv3 = torch.nn.ConvTranspose2d(256, 128, kernel_size=2, stride=2) self.upconv4 = torch.nn.ConvTranspose2d(128, 64, kernel_size=2, stride=2) self.upconv5 = torch.nn.ConvTranspose2d(64, 32, kernel_size=2, stride=2) self.final_conv = torch.nn.Conv2d(32, 3, kernel_size=3, stride=1, padding=1) def forward(self, x): x = torch.nn.functional.relu(self.conv1(x)) x = torch.nn.functional.relu(self.conv2(x)) x = torch.nn.functional.relu(self.conv3(x)) x = torch.nn.functional.relu(self.conv4(x)) x = torch.nn.functional.relu(self.conv5(x)) x = torch.nn.functional.relu(self.conv6(x)) x = torch.nn.functional.relu(self.upconv1(x)) x = torch.nn.functional.relu(self.upconv2(x)) x = torch.nn.functional.relu(self.upconv3(x)) x = torch.nn.functional.relu(self.upconv4(x)) x = torch.nn.functional.relu(self.upconv5(x)) x = self.final_conv(x) return x # 加载模型 model = PanoramaNet() model.load_state_dict(torch.load('panorama_model.pth')) # 加载输入图片 image1 = Image.open('image1.jpg') image2 = Image.open('image2.jpg') images = [image1, image2] # 将输入图片转换PyTorch张量 images_tensors = [] for image in images: image_tensor = torch.tensor(np.array(image)) image_tensor = image_tensor.permute(2, 0, 1).float().unsqueeze(0) images_tensors.append(image_tensor) # 将输入张量传入模型,生成全景图像 with torch.no_grad(): output = model(torch.cat(images_tensors, dim=0)) output = output.squeeze().permute(1, 2, 0).numpy() # 将全景图像转换为PIL图像,保存结果 output_image = Image.fromarray((output * 255).astype(np.uint8)) output_image.save('panorama_image.jpg') ``` 该代码使用PyTorch实现了一个基于卷积神经网络的全景图像拼接模型,通过加载已经训练好的模型,输入两张图片,并生成拼接之后的全景图像。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小森( ﹡ˆoˆ﹡ )

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值