找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2456

积分

0

好友

332

主题
发表于 6 小时前 | 查看: 2| 回复: 0

PyTorch 是当前主流的深度学习框架。掌握其核心数据结构——张量的基本操作,是进行模型构建、数据处理和算法实现的第一步。本文将详细介绍 PyTorch 张量的创建方法、常见数学运算、形状变换以及与 NumPy 数组的互操作性。

环境准备

首先,需要安装 PyTorch。如果你的环境支持 CUDA,可以使用以下命令安装 GPU 版本以加速计算:

pip install torch torchaudio torchvision --index-url https://download.pytorch.org/whl/cu130

安装过程如下图所示,会下载并构建相关的 wheel 包:
PyTorch安装过程示例

安装完成后,可以通过简单的代码验证安装是否成功,以及 CUDA 是否可用:

import torch
print(torch.cuda.is_available())

若输出 True,则说明 PyTorch 已正确安装且 GPU 加速可用。
PyTorch CUDA可用性验证结果

张量基础操作

张量是 PyTorch 的基础,类似于 NumPy 的多维数组,但支持在 GPU 上进行加速计算。

张量的多种创建方式

PyTorch 提供了丰富的函数来创建不同初始状态的张量。

import torch

# 1. 创建一个 5行2列 未初始化的张量
x = torch.empty(5,2)
print("empty tensor:\n", x)

创建未初始化张量的输出示例

# 2. 创建一个 5行3列 随机初始化的张量
# 均匀分布进行随机初始化,区间[0,1),不能指定dtype=torch.long
x = torch.rand(5,3) 
print("random tensor:\n", x)

使用torch.rand创建的均匀分布随机张量

# 3. 创建一个 5行3列 根据标准正太分布随机初始化的张量
x = torch.randn(5,3)
print("random tensor:\n", x)

使用torch.randn创建的正态分布随机张量

# 4. 创建一个全为 0 的张量
x = torch.zeros(5,3)
print("zeros tensor:\n", x)

创建全零张量输出示例

# 5. 创建一个全为 0, 数据类型为 long 的张量
x = torch.zeros(5,3, dtype=torch.long)
print("zeros tensor:\n", x)

创建指定数据类型(long)的全零张量

# 6. 创建一个全为1的张量
x = torch.ones(5,3)
print("ones tensor:\n", x)

创建全一张量输出示例

除了直接指定形状,我们还可以基于现有张量的形状来创建新张量。

# 7. 使用 rand_like 创建一个形状和另一个张量相同的随机张量
x = torch.ones(2,2)
y = torch.randn_like(x)
print("rand like tensor:\n", y)

使用randn_like创建同形状随机张量

# 8. 使用 ones_like 
x = torch.rand(3,3)
y = torch.ones_like(x, dtype=torch.long)
print("ones like tensor:\n", y)

使用ones_like创建同形状全一张量

# 9. 使用zeros_like
x = torch.rand(4,4)
y = torch.zeros_like(x)
print("zeros like tensor:\n", y)

使用zeros_like创建同形状全零张量

# 10. 使用 full_like。
x = torch.rand(2,2)
y = torch.full_like(x, 3) # 创建一个值全为3的 2行2列 的张量
print("full like tensor:\n", y)

使用full_like创建指定值的同形状张量

最直接的方式是从 Python 列表或嵌套列表创建张量,PyTorch 会自动推断数据类型。

# 11. 直接从数据创建张量,tensor的类型会保持一致
x = torch.tensor([
    [1.0, 2],
    [2.5,3]
])
print("data tensor:\n", x)
print(x.type(), x.dtype)

从Python列表直接创建张量

张量运算操作

张量支持丰富的数学运算,包括逐元素运算和矩阵运算。

# 加法,相同位置的数值相加 1+5, 2+6, 3+7, 4+8
a = torch.tensor([
    [1,2],
    [3,4]
])
b = torch.tensor([
    [5,6],
    [7,8]
])
print("张量加法:\n", a+b)

张量逐元素加法运算结果

# 减法, 1-5, 2-6, 3-7, 4-8
print("张量减法:\n", a-b)

张量逐元素减法运算结果

# 乘法,1*5, 2*6, 3*7, 4*8
print("张量乘法:\n", a*b)

张量逐元素乘法运算结果

# 矩阵乘法 1*5+2*7,1*6+2*8,3*5+4*7, 3*6+4*8
print("张量矩阵乘法:\n", a @ b)
print("张量矩阵乘法:\n", torch.matmul(a, b))

张量矩阵乘法运算结果

张量拼接是组合数据的常用操作,dim 参数决定了拼接的维度。

# 拼接, dim=0 按第1个维度行拼接 dim=1按第2个维度列拼接。dim也可以是负数,-1表示最后一个维度,在二维张量中代表列

print("concat tensors:\n", torch.cat((a,b),dim=0)) # 行拼接,所有行按顺序拼接到一起
print("concat tensors:\n", torch.cat((a,b),dim=1)) # 列拼接,相同行号的列拼接到一行中
print("concat tensors:\n", torch.cat((a,b),dim=-1)) # 列拼接
print("concat tensors:\n", torch.cat((a,b),dim=-2)) # 行拼接

不同维度(dim)下的张量拼接结果

张量形状变换

在数据处理和模型层间传递时,经常需要改变张量的形状。

# reshape
x = torch.arange(1,13) # 1~12
print("Original tensor:\n", x)
print("Reshape to 6x2:\n", x.reshape(6,2)) # 6行2列

使用reshape改变张量形状为6x2

view 是另一个常用的变形方法,但它要求操作的张量在内存中是连续的。

# view 与 reshape 类似,但是要求张量是连续的
print("view to 4x3:\n", x.view(4,3))

使用view改变张量形状为4x3

transpose 用于交换张量的两个维度。

# transpose 交换两个维度
x = torch.randn(2,3,4) # 按照正太分布随机生成 三维 张量
print("Original tensor shape:\n", x.shape)
print("Transpose from (2,3,4) to (2,4,3):\n", x.transpose(1,2).shape)

使用transpose交换维度后的形状变化

squeezeunsqueeze 用于删除或增加大小为1的维度。

# squeeze / unsqueeze 删除或增加维度
x = torch.randn(1,3,1,2)
print("Squeeze Tensor:\n", x.squeeze().shape) # 删除所有数值为1的维度
print("Unsqueeze at dim=0:\n", x.unsqueeze(0).shape) # 在第1个位置增加一个维度

squeeze和unsqueeze操作对张量形状的影响

理解张量的连续性(Contiguity)很重要。连续张量的元素在内存中按索引顺序连续存储,某些操作(如 view)需要张量是连续的。

# is_contiguous 判断是否连续张量
a = torch.tensor([
    [1,2,3],
    [4,5,6]
])

print("a是不是连续张量:", a.is_contiguous())

b = a.transpose(0,1) # 转置操作
print("转置后的tensor:\n", b)
print("b是不是连续张量:", b.is_contiguous())

转置操作导致张量变为非连续

对于非连续张量,可以调用 contiguous() 方法将其转换为连续张量,然后进行 view 等操作。

# contiguous 将张量转为连续张量
print("转为连续张量:\n", b.contiguous())
print("转为连续张量后使用view变形:\n", b.contiguous().view(-1))

使用contiguous将非连续张量转为连续并重塑

与 Numpy 互操作

PyTorch 与 NumPy 可以方便地相互转换,便于利用两个生态的优势。

import numpy as np

# 从numpy array 创建张量
np_array = np.array([[1,2,3],[4,5,6],[7,8,9]])
print(np_array, type(np_array))
tensor = torch.from_numpy(np_array)
print(tensor, type(tensor))

从NumPy数组创建PyTorch张量

# tensor 转 numpy
tensor = torch.rand(2,2)
np_array = tensor.numpy()
print("tensor转numpy:\n",np_array, type(np_array))

将PyTorch张量转换为NumPy数组

一个重要特性是:当张量位于 CPU 上时,通过 from_numpy() 创建的张量和 numpy() 方法返回的数组会共享底层内存。这意味着修改其中一个,另一个也会随之改变。

# 如果张量在CPU上, from_numpy() 和 numpy() 会共享内存
print(tensor.device)

tensor.add_(2) # 原地操作,给张量每个元素加2
print("修改后的张量:\n", tensor)
print("对应的NumPy数组:\n", np_array)

可以看到,当张量在 CPU 上时,对张量进行原地修改,对应的 NumPy 数组也同步发生了变化。
共享内存示例:修改张量导致NumPy数组同步变化

以上就是 PyTorch 张量基础操作的全面介绍。从创建、运算到形状变换,这些操作构成了使用 PyTorch 进行深度学习研究和开发的基石。熟练掌握它们,能让你在后续的模型构建和数据处理中更加得心应手。如果想探讨更多深度学习Python相关话题,欢迎来到云栈社区交流分享。




上一篇:基于FreeRTOS的C语言嵌入式日志系统设计与实现
下一篇:AI SDK与OpenAI Responses API实战指南:构建智能体与实现持久化对话
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-26 18:42 , Processed in 0.318252 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表