神经网络常用库-torch(基础操作张量)

1.理解张量

从简单到复杂逐步理解张量

  • 标量:可以将标量看作是零维张量,它只有一个数值,比如温度、质量等。例如,今天的气温是 25 摄氏度,这里的 25 就是一个标量。
  • 向量:一维张量就是向量,它由一组有序的数值组成,可以表示具有大小和方向的量。比如在平面直角坐标系中,向量 (3, 4) 表示从原点到点 (3, 4) 的有向线段。
  • 矩阵:二维张量是矩阵,它是一个由行和列组成的二维数组。矩阵在图像处理、线性代数等领域有广泛应用。例如,一个表示图像的矩阵,每个元素可以代表图像中对应像素的灰度值或颜色值。
  • 多维张量:当维度超过二维时,就进入了多维张量的范畴。例如,三维张量可以想象成一个立方体,每个元素都有三个索引来确定其位置。在视频数据中,三维张量可以表示一个视频片段,其中三个维度分别可以是时间、高度和宽度。而四维张量则可以在三维张量的基础上,再增加一个维度,比如颜色通道,这样就可以更全面地表示视频数据的信息。

1.直接创建张量 :使用 torch.tensor() 函数可以直接将 Python 列表转换为 PyTorch 张量。

python 复制代码
import torch

# 创建一个一维张量
tensor_1d = torch.tensor([1, 2, 3, 4, 5])
print("一维张量:")
print(tensor_1d)

# 创建一个二维张量
tensor_2d = torch.tensor([[1, 2, 3], [4, 5, 6]])
print("\n二维张量:")
print(tensor_2d)

# 创建一个三维张量
tensor_3d = torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
print("\n三维张量:")
print(tensor_3d)

2.从 numpy.ndarray 转换为 PyTorch 张量

python 复制代码
import torch
import numpy as np

# 创建一个一维的 numpy 数组
np_array_1d = np.array([1, 2, 3, 4, 5])
# 转换为 PyTorch 张量
tensor_from_np_1d = torch.from_numpy(np_array_1d)
print("从一维 numpy 数组转换的张量:")
print(tensor_from_np_1d)

# 创建一个二维的 numpy 数组
np_array_2d = np.array([[1, 2, 3], [4, 5, 6]])
# 转换为 PyTorch 张量
tensor_from_np_2d = torch.from_numpy(np_array_2d)
print("\n从二维 numpy 数组转换的张量:")
print(tensor_from_np_2d)

# 创建一个三维的 numpy 数组
np_array_3d = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
# 转换为 PyTorch 张量
tensor_from_np_3d = torch.from_numpy(np_array_3d)
print("\n从三维 numpy 数组转换的张量:")
print(tensor_from_np_3d)

3.从 pandas.DataFramepandas.Series 转换为 PyTorch 张量

python 复制代码
import torch
import pandas as pd

# 创建一个 pandas Series
series = pd.Series([1, 2, 3, 4, 5])
# 将 Series 转换为 numpy 数组,再转换为 PyTorch 张量
tensor_from_series = torch.from_numpy(series.values)
print("从 pandas Series 转换的张量:")
print(tensor_from_series)

# 创建一个 pandas DataFrame
data = {'col1': [1, 2, 3], 'col2': [4, 5, 6]}
df = pd.DataFrame(data)
# 将 DataFrame 转换为 numpy 数组,再转换为 PyTorch 张量
tensor_from_df = torch.from_numpy(df.values)
print("\n从 pandas DataFrame 转换的张量:")
print(tensor_from_df)

默认的数据类型是 torch.float32(有很多大佬研究了混合精度训练的训练技巧)

也可以通过指定dtype

python 复制代码
tensor_float64 = torch.tensor([1.0, 2.0, 3.0], dtype=torch.float64)

2.操作张量

2.1shape和size

在 PyTorch 中,shapesize() 都与张量(Tensor)的维度信息相关,但它们在使用形式和表现上存在一些差异,下面为你详细介绍:

相同点

shapesize() 本质上都用于获取张量各维度的大小,返回的结果是一致的,都能反映出张量的维度信息。以下是一个示例代码:

python 复制代码
import torch

# 创建一个二维张量
tensor = torch.tensor([[1, 2, 3], [4, 5, 6]])

# 使用 shape 属性获取张量的形状
print("使用 shape 属性:", tensor.shape)

# 使用 size() 方法获取张量的形状
print("使用 size() 方法:", tensor.size())

不同点

  1. 类型和调用方式

shape:它是张量的一个属性,使用时直接通过点号访问,就像访问对象的普通属性一样。

python 复制代码
import torch
tensor = torch.tensor([1, 2, 3])
print(tensor.shape)

size():这是张量的一个方法,使用时需要在后面加上括号,括号内可以传入参数来获取特定维度的大小。

python 复制代码
import torch
tensor = torch.tensor([1, 2, 3])
print(tensor.size())

2**.关于参数**

  • shape[0]shape 是张量的一个属性,它返回一个 torch.Size 对象,该对象类似于元组,shape[0] 是对这个 torch.Size 对象进行索引操作,获取其第一个元素。
  • size(0)size() 是张量的一个方法,通过传入参数 0 来指定获取第一维的大小
  • shape[0] :只能获取第一维的大小,如果要获取其他维度的大小,需要通过索引 shape[1]shape[2] 等方式。
python 复制代码
import torch
tensor = torch.tensor([[1, 2, 3], [4, 5, 6]])
print("第二维的大小 (使用 shape):", tensor.shape[1])
  • size() :方法更加灵活,它可以不传入参数,直接返回整个张量的形状信息(返回值类型为 torch.Size),也可以传入不同的整数参数来获取指定维度的大小。
python 复制代码
import torch
tensor = torch.tensor([[1, 2, 3], [4, 5, 6]])
h,w=tensor.size()
print(h,w)

2.2 操作维度

1.torch.unsqueeze() 方法

torch.unsqueeze() 函数用于在指定的维度上插入一个新的维度,其语为 torch.unsqueeze(input, dim),其中 input 是输入的张量,dim 是要插入新维度的位置(索引从 0 开始)

python 复制代码
import torch

# 创建一个一维张量
tensor_1d = torch.tensor([1, 2, 3])
print("原一维张量形状:", tensor_1d.shape)

# 在第 0 维插入一个新维度
tensor_2d_0 = torch.unsqueeze(tensor_1d, dim=0)
print("在第 0 维插入新维度后的形状:", tensor_2d_0.shape)

# 在第 1 维插入一个新维度
tensor_2d_1 = torch.unsqueeze(tensor_1d, dim=1)
print("在第 1 维插入新维度后的形状:", tensor_2d_1.shape)
  1. 在 PyTorch 中,可以使用 None 索引来增加维度,这与 torch.unsqueeze() 效果类似。示例如下
python 复制代码
import torch

# 创建一个一维张量
tensor_1d = torch.tensor([1, 2, 3])
print("原一维张量形状:", tensor_1d.shape)

# 在第 0 维插入一个新维度
tensor_2d_0 = tensor_1d[None, :]
print("在第 0 维插入新维度后的形状:", tensor_2d_0.shape)

# 在第 1 维插入一个新维度
tensor_2d_1 = tensor_1d[:, None]
print("在第 1 维插入新维度后的形状:", tensor_2d_1.shape)

3.拼接维度torch.cat(tensors, dim=0, out=None)

python 复制代码
import torch

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

# 在第 0 维上拼接
result_0 = torch.cat((tensor1, tensor2), dim=0)
print("在第 0 维上拼接的结果:")
print(result_0)
print("拼接后张量的形状:", result_0.shape)

4.expand方法

expand() 方法只能对大小为 1 的维度进行扩展,与单个或多个维度大小是否为 1 并无直接关系,关键在于维度的大小是否为 1。

可以拓展

python 复制代码
import torch

# 创建一个形状为 (1, 1, 3) 的张量
tensor = torch.tensor([[[1, 2, 3]]])
print("原张量形状:", tensor.shape)

# 对第 0 维和第 1 维进行扩展
expanded_tensor = tensor.expand(2, 2, 3)
print("扩展后张量形状:", expanded_tensor.shape)

不可拓展

python 复制代码
import torch

# 创建一个形状为 (2, 1, 3) 的张量
tensor = torch.tensor([[[1, 2, 3]], [[4, 5, 6]]])
try:
    # 尝试对第 0 维(大小为 2)进行扩展,会报错
    expanded_tensor = tensor.expand(3, 1, 3)
except RuntimeError as e:
    print("错误信息:", e)

5.squeeze

在 PyTorch 中,squeeze() 方法用于移除张量中维度大小为 1 的维度。这在处理一些维度冗余的数据时非常有用,可以让张量的形状更加简洁,便于后续的计算和处理。下面详细介绍 squeeze() 方法的使用、参数和注意事项。

python 复制代码
# 形式一:不指定维度,移除所有大小为 1 的维度
tensor.squeeze()

# 形式二:指定维度,仅移除指定维度上大小为 1 的维度
tensor.squeeze(dim)

不指定维度移除所有大小为 1 的维度

python 复制代码
import torch

# 创建一个形状为 (1, 3, 1, 2) 的张量
tensor = torch.randn(1, 3, 1, 2)
print("原张量形状:", tensor.shape)

# 不指定维度,移除所有大小为 1 的维度
squeezed_tensor = tensor.squeeze()
print("移除所有大小为 1 的维度后形状:", squeezed_tensor.shape)

指定维度移除大小为 1 的维度

python 复制代码
import torch

tensor = torch.randn(1, 3, 1, 2)
print("原张量形状:", tensor.shape)

# 指定维度 0,移除该维度上大小为 1 的维度
squeezed_tensor_0 = tensor.squeeze(0)
print("移除第 0 维后形状:", squeezed_tensor_0.shape)

# 指定维度 1,由于该维度大小不为 1,不会进行移除操作
squeezed_tensor_1 = tensor.squeeze(1)
print("尝试移除第 1 维后形状:", squeezed_tensor_1.shape)

6.permute

permute 方法用于对张量的维度进行重新排列,也就是改变张量各维度的顺序。这在处理不同维度排列的数据时非常有用,比如在图像处理、深度学习模型的数据输入处理等场景中经常会用到。

permute 方法的基本语法如下:

python 复制代码
import torch

# 创建一个二维张量
tensor_2d = torch.randn(2, 3)
print("原二维张量形状:", tensor_2d.shape)

# 交换第 0 维和第 1 维的顺序
permuted_tensor_2d = tensor_2d.permute(1, 0)
print("维度重排后二维张量形状:", permuted_tensor_2d.shape)

在这个例子中,原二维张量 tensor_2d 的形状是 (2, 3),通过 permute(1, 0) 把第 0 维和第 1 维的顺序进行了交换,重排后的张量形状变为 (3, 2)

7.view方法

view 方法是用于改变张量(Tensor)形状(shape)的重要工具**,不过它不会改变张量中元素的数量和元素本身的值** ,并且要求原张量的存储是连续的。下面为你详细介绍 view 方法的使用、特性及注意事项。

一维张量转换为二维张量:

python 复制代码
import torch

# 创建一个一维张量,包含 6 个元素
tensor_1d = torch.arange(6)
print("原一维张量:", tensor_1d)
print("原一维张量形状:", tensor_1d.shape)

# 使用 view 方法将其转换为形状为 (2, 3) 的二维张量
tensor_2d = tensor_1d.view(2, 3)
print("转换后的二维张量:", tensor_2d)
print("转换后二维张量形状:", tensor_2d.shape)

view 方法里,可以使用 -1 让 PyTorch 自动推断该维度的大小,但 -1 在一次调用中只能出现一次。

python 复制代码
import torch

tensor_1d = torch.arange(6)
# 使用 -1 自动推断维度,将其转换为二维张量
tensor_reshaped = tensor_1d.view(2, -1)
print("使用 -1 自动推断维度后的形状:", tensor_reshaped.shape)

2.3 加乘法

广播机制的规则

广播机制的核心规则是从右向左比较两个张量的形状,对于每一个维度,需要满足以下条件之一:

  1. 维度大小相等:两个张量在该维度上的大小相同。
  2. 其中一个维度大小为 1 :如果一个张量在某一维度上的大小为 1,而另一个张量在该维度上有非 1 的大小,那么大小为 1 的维度会被扩展为与另一个张量该维度大小相同
  3. 其中一个张量缺少该维度如果一个张量在某一维度上不存在(即形状中没有对应位置),则可以将其视为该维度大小为 1,然后按照规则 2 进行扩展。

1.加法

如果两个张量形状不同,但满足广播机制的规则,PyTorch 会自动进行广播操作,使它们的形状匹配后再进行逐元素相加。广播规则是从右向左比较两个张量的维度,要么维度大小相等,要么其中一个维度大小为 1 或缺少该维度。

python 复制代码
import torch

# 创建一个二维张量和一个一维张量
tensor_2d = torch.tensor([[1, 2, 3], [4, 5, 6]])
tensor_1d = torch.tensor([1, 1, 1])

# 利用广播机制相加
result = tensor_2d + tensor_1d
print("广播相加结果:")
print(result)

这里 tensor_1d 形状是 (3,)tensor_2d 形状是 (2, 3)tensor_1d 在第 0 维上会广播,逻辑上扩展为 [[1, 1, 1], [1, 1, 1]],也就是复用原来的数据,然后和 tensor_2d 逐元素相加

2.乘法

矩阵乘法

在 PyTorch 中,使用 torch.matmul() 函数或 @ 运算符进行矩阵乘法。矩阵乘法要求左矩阵的列数等于右矩阵的行数。

python 复制代码
import torch

# 创建两个二维张量用于矩阵乘法
tensor1 = torch.tensor([[1, 2], [3, 4]])
tensor2 = torch.tensor([[5, 6], [7, 8]])

# 矩阵乘法
result = torch.matmul(tensor1, tensor2)
# 或者使用 @ 运算符
# result = tensor1 @ tensor2
print("矩阵乘法结果:")
print(result)
相关推荐
Mintopia1 小时前
OpenClaw 对软件行业产生的影响
人工智能
陈广亮1 小时前
构建具有长期记忆的 AI Agent:从设计模式到生产实践
人工智能
会写代码的柯基犬2 小时前
DeepSeek vs Kimi vs Qwen —— AI 生成俄罗斯方块代码效果横评
人工智能·llm
Mintopia2 小时前
OpenClaw 是什么?为什么节后热度如此之高?
人工智能
爱可生开源社区2 小时前
DBA 的未来?八位行业先锋的年度圆桌讨论
人工智能·dba
叁两5 小时前
用opencode打造全自动公众号写作流水线,AI 代笔太香了!
前端·人工智能·agent
前端付豪5 小时前
LangChain记忆:通过Memory记住上次的对话细节
人工智能·python·langchain
strayCat232555 小时前
Clawdbot 源码解读 7: 扩展机制
人工智能·开源
程序员打怪兽5 小时前
详解Visual Transformer (ViT)网络模型
深度学习