03-张量

张量是PyTorch中的核心数据抽象

  • PyTorch中的张量就是元素为同一种数据类型的多维矩阵,与NumPy数组类似。
  • PyTorch中,张量以"类"的形式封装起来,对张量的一些运算、处理的方法(数值计算、矩阵操作、自动求导)被封装在类中。

数据类型

张量中默认的数据类型是float32(torch.FloatTensor)

API

1. 基本创建方式

代码 贴合代码解释 补充要点
torch.tensor([1,2,3], requires_grad=True, dtype=torch.float) 基于列表[1,2,3]创建张量;开启梯度追踪;指定数据类型为浮点型。推荐优先使用 支持自定义requires_graddtype, 要想设定requires_grad=True,必须dtype=True(PyTorch仅浮点类型张量支持自动微分 ;自动推断数据类型;可接收列表、numpy 数组。
torch.Tensor([1,2]) 构造函数创建张量,传入列表[1,2],默认生成浮点张量。 大写 Tensor 是类构造器,无法直接设置 requires_grad;旧写法,不推荐用于创建张量。
torch.IntTensor([1,2]) 创建整型张量,数据来源于列表[1,2] 固定数据类型为 int32;不能直接配置梯度参数。
torch.FloatTensor([1.,2.]) 创建浮点型张量,数据来源于列表[1.,2.] 固定数据类型为 float32;不能直接配置梯度参数。
  1. PyTorch仅浮点类型张量支持自动微分
  2. PyTorch 中 Python 原生浮点数列表自动推断为 32 位浮点型,dtype=torch.float32
  3. PyTorch 中 Python 原生整数列表自动推断为 64 位整型,不是 int32
  4. 查看张量属性:.shape, .dtype, .size(), .requires_grad

2. 线性序列张量

代码 贴合代码解释 补充要点
torch.arange(0, 10, 2) 生成起始值 0、终止值 10(左闭右开 ,不包含 10)、步长为 2 的序列张量;结果:[0,2,4,6,8] 默认生成整型张量;控制步长,无法直接指定元素总个数
torch.linspace(0, 1, 5) 生成起始值 0、终止值 1(包含两端 )、一共 5 个均匀分布数值的序列张量;结果:[0.0, 0.25, 0.5, 0.75, 1.0] 默认浮点张量;控制元素总数,自动计算间隔大小

3. 随机张量

代码 贴合代码解释 补充要点
torch.rand(2, 3) 生成形状为[2,3]的张量,数值服从均匀分布 ,取值区间[0,1) 浮点型随机数;常用于权重初始化、简单随机采样。
torch.randn(4) 生成形状为[4]的一维张量,数值服从标准正态分布(均值 0,方差 1) 深度学习最常用的初始化方式;可生成正负随机值。
torch.randint(0, 10, (2, 2)) 生成形状为[2,2]的整型张量,随机整数区间[0,10),左闭右开。 专门生成随机整数;适合随机索引、离散采样场景。

随机种子:

代码 贴合代码解释 补充要点
torch.manual_seed(42) 设置 CPU 随机数种子为 42;固定随机生成序列,保证每次运行随机结果保持一致,实现实验可复现。 只作用于 CPU;若使用 GPU 还需要额外设置 cuda 种子;种子数字 42 无特殊含义,仅约定俗成。
torch.initial_seed() 获取当前 CPU 上正在使用的随机种子数值。 可用于查看当前种子、保存种子方便后续复现实验。

4. 固定值张量

代码 贴合代码解释 补充要点
torch.zeros((2, 3)) 创建形状为[2,3]的张量,所有元素填充数值 0。 需要手动指定尺寸;默认浮点型。
torch.zeros_like(data) 参照张量data,创建同形状、同数据类型的张量,所有元素填充数值 0。 自动继承data的 shape 与 dtype,无需手动填写维度。
torch.ones(4) 创建形状为[4]的一维张量,所有元素填充数值 1。 手动定义目标形状。
torch.ones_like(data) 参照张量data,创建同形状、同数据类型的张量,所有元素填充数值 1。 常用于生成和 data 规格一致的掩码矩阵。
torch.full((2, 3), fill_value=5) 创建形状为[2,3]的张量,全部元素统一填充数值 5。 手动指定形状与填充值。
torch.full_like(data, fill_value=-2) 参照张量data,创建同形状、同数据类型的张量,全部元素统一填充数值 - 2。 填充值自由自定义,通用性最强。
  1. 第一个参数为shape,推荐元组形式
  2. _like系列函数默认继承原张量 dtype,如果dtype不是浮点型,不能进行自动微分

5. 指定元素类型张量

所有类型转换操作不会原地修改原张量,需要接收返回值

代码 贴合代码解释 补充要点
data.type('torch.FloatTensor') 将张量data转换为 FloatTensor 类型,返回转换后的新张量。 通过传入字符串形式指定目标张量类型;属于旧版 API 写法,推荐使用.to()或者.float()这类简写接口。
data.half() 将张量data转换为**半精度浮点(float16)**张量,返回新张量。 常用于混合精度训练,减小显存占用。
data.float() 将张量data转换为**单精度浮点(float32)**张量,返回新张量。 深度学习最常用默认浮点类型。
data.double() 将张量data转换为**双精度浮点(float64)**张量,返回新张量。 精度高、占用显存大,一般很少使用。
data.int() 将张量data转换为**32 位整型(int32)**张量,返回新张量。 用于普通整数标签、索引。
data.long() 将张量data转换为**64 位长整型(int64)**张量,返回新张量。 分类任务标签、索引取值必须使用 long 类型

6. 张量的类型转换

代码 贴合代码解释 补充要点
tensor.numpy().copy() 先将 tensor 转为 numpy 数组,再执行 copy () 生成独立副本。原 tensor 与 numpy 数组不再共享内存。 不带 copy 时,tensor.numpy()与张量共享内存;带梯度张量直接调用.numpy()会报错,需要先.detach()
torch.from_numpy(arr).copy() 由 numpy 数组arr创建张量,并且复制数据,新张量和原 numpy 数组解除内存共享。 torch.from_numpy(arr)默认共享内存;加上.copy()切断共享,一方修改不会影响另一方。
torch.tensor(arr) 接收 numpy 数组arr,创建全新张量,默认自动拷贝数据,不与原数组共享内存。 对比 from_numpy:天生复制,不存在共享内存问题。
scalar.item() 从标量张量 scalar 中取出普通 Python 数值(int/float)。 仅能用于只有单个元素的标量张量;常用于取出 loss 数值打印。

7. 张量的数值运算

7.1 基本运算

代码 贴合代码解释 补充要点
a.add(b) 张量a与张量b逐元素相加,返回新张量,不修改原始 a 。等价运算符 a + b 支持广播机制。
a.add_(b) 原地逐元素相加,计算结果直接覆盖存入a,修改原张量。 带下划线_代表原地操作;训练时尽量避免对需要求导的张量使用原地运算,易引发梯度报错。
a.sub(b) 张量a与张量b逐元素相减,返回新张量。等价运算符 a - b 支持广播机制。
a.sub_(b) 原地逐元素相减,直接覆盖修改张量a 原地操作。
a.mul(b) 张量a与张量b逐元素相乘(哈达玛积),返回新张量。等价运算符 a * b ⚠️ 不是矩阵乘法,矩阵乘法使用matmul / @
a.mul_(b) 原地逐元素相乘,直接覆盖修改张量a 原地操作。
a.div(b) 张量a与张量b逐元素相除,返回新张量。等价运算符 a / b 除数不能包含 0,否则产生 inf。
a.div_(b) 原地逐元素相除,直接覆盖修改张量a 原地操作。
a.neg() 将张量a所有元素取相反数,返回新张量,不修改原张量。等价 -a 逐元素符号翻转。
a.neg_() 原地对张量a所有元素取相反数,直接修改自身。 原地操作。

7.2 点乘运算

  • 要求:两个张量维度一致,对应元素直接相乘(或其他运算)
代码 贴合代码解释 补充要点
t1.mul(t2) t1t2执行逐元素相乘(哈达玛积) ,返回新张量;不修改原始t1 等价运算符 t1 * t2;要求两个张量形状满足广播规则;不是矩阵乘法
t1.mul_(t2) 带下划线代表原地操作 ,将t1t2逐元素相乘,结果直接覆盖保存到t1自身,无返回值。 原地运算会直接修改原张量;若t1开启requires_grad=True,尽量避免使用原地操作,容易引发自动微分报错。

7.3 矩阵乘法运算

  • 要求:第一个矩阵 shape: (n, m),第二个矩阵 shape: (m, p), 两个矩阵点积运算 shape 为: (n, p)。
代码 贴合代码解释 补充要点
t1.matmul(t2) 执行张量矩阵乘法,将张量t1t2做矩阵相乘运算。等价于 t1 @ t2 遵循矩阵乘法规则:t1最后一维大小 = t2倒数第二维大小;支持高维张量(批量矩阵乘法)。

8. 张量的运算函数

代码 贴合代码解释 补充要点
data.mean(dim=0) 在第 0 维(按列)求平均值,压缩第 0 维。 dim 指定要压缩、归约的维度;输出维度减少一维。
data.mean(dim=1) 在第 1 维(按行)求平均值,压缩第 1 维。 若需要保留被压缩的维度,可添加参数keepdim=True
data.mean() 不指定维度,对张量全部元素求全局平均值,输出标量张量。 等价于把所有元素摊平后求均值。
data.sum(dim=1) 在第 1 维上求和,压缩第 1 维。 深度学习常用于损失求和、特征聚合。
data.min(dim=1) 在第 1 维求取最小值;返回**(最小值张量,最小值索引张量)**。 返回两个值,和 mean/sum 行为不同。
data.max(dim=1) 在第 1 维求取最大值;返回**(最大值张量,最大值索引张量)**。 常用于分类任务获取预测类别。
data.pow(2) 逐元素进行幂运算 data.pow(2)等价于data**2
data.sqrt() 逐元素计算平方根(等价于 .pow (0.5) 或 data ** 0.5)。 输入负数会产生 nan。
data.exp() 逐元素计算自然指数 ex。 激活函数、概率转换常用。
data.log() 逐元素计算自然对数 ln(x)。 输入必须大于 0;负数值会产生 nan。

9. 张量的索引操作

  • 索引取出的数据,如果是切片 / 基础下标,和原张量共享内存;原地修改会互相影响。

9.1 简单行列索引

data行索引, 列索引

代码(data 为张量) 解释
data[0] 选取第 0 行,取出一整行数据
data[:, 0] 选取全部行、第 0 列,取出一整列数据

9.2 列表索引

代码(data 为张量) 解释
data[[0, 1], [1, 2]] 多维配对索引。行索引列表[0,1]与列索引列表[1,2]一一对应,依次取出坐标(0,1)(1,2)两个元素。
data[[[0],[1]], [1, 2]] 广播机制下的多维索引。行维度[[0],[1]]、列维度[1,2]广播配对,取出坐标(0,1),(0,2),(1,1),(1,2),最终结果形状为[2,2]

9.3 范围索引

代码(data 为张量) 解释
data[:3, :2] 范围切片索引;选取前 3 行(0、1、2 行)前 2 列(0、1 列),左闭右开区间
data[2:, :2] 范围切片索引;选取第 2 行及之后所有行前 2 列(0、1 列)

9.4 布尔索引

代码(data 为张量) 解释
data[data[:, 2] > 5] 布尔索引;先取出全部行第 2 列构成一维张量,筛选其中数值大于 5 对应的整行数据。
data[:, data[1] > 5] 布尔索引;先取出第 1 行构成一维张量,筛选其中数值大于 5 对应的整列数据。

9.5 多维索引

代码(data 为三维张量) 解释
data[0, :, :] 选取第 0 维度下标为 0 的全部数据,取出第 0 个切片
data[:, 0, :] 选取全部第 0 维度、第 1 维度下标为 0 的全部数据,取出每个切片的第 0 行
data[:, :, 0] 选取全部第 0 维度、全部第 1 维度、第 2 维度下标为 0 的数据,取出每个切片的第 0 列

10. 张量的形状操作

  • 张量形状操作是指对张量的维度进行变换的一系列操作。
  • 张量的形状则描述了每个维度上的元素数量。
代码(data 为张量) 解释 补充要点
data.shape 获取当前张量各个维度的尺寸大小 等价data.size()data.shape[0]读取第 0 维长度
data.reshape(1, 6) 将张量重塑为[1,6]的二维形状,元素总数量不变 可使用-1自动计算维度;不强制要求张量内存连续
data.unsqueeze(0) 第 0 维插入一个长度为 1 的新维度,实现升维 unsqueeze(-1)代表在最后一维新增维度
data.squeeze() 自动移除张量中所有长度等于 1的维度;若传入维度编号,则只移除指定维度上 size=1 的轴 不会删除长度大于 1 的维度
data.transpose(0, -1) 交换第 0 维最后一维两个维度的位置,仅支持两个维度互换 适合二维转置;仅允许传入两个维度参数
data.permute(2, 0, 1) 把原维度顺序(0,1,2)重排为(2,0,1),一次性完成多维度调换 支持任意多个维度重排,常用于[B,C,H,W]通道变换
data.view(3, 2) 将张量重塑为[3,2]形状,元素总数保持不变 要求张量内存连续 ,非连续张量直接调用会报错,支持-1推导维度
data.contiguous() 复制数据,生成一份内存连续排布的新张量 transpose、permute 操作后张量常不连续,view 前常用
data.is_contiguous() 检测张量在内存中是否连续存储,返回True/False 用来判断是否需要调用 contiguous

11. 张量的拼接操作

代码 贴合代码解释 补充要点
torch.cat([data1, data2], dim=1) 将张量data1data2沿着第 1 维 拼接;不新增维度,只扩展该维度长度。 参与拼接的张量,除 dim 指定维度外,其余维度尺寸必须完全一致
torch.stack([data1, data2], dim=1) 将张量data1data2沿着第 1 维 堆叠;会新增一个维度,把两个张量嵌入新维度中。 参与堆叠的所有张量形状必须完全相同

12. 自动微分模块

自动微分=自动求导(梯度)。

  • 梯度 = 函数求导
    • 对函数求导得到的值就是梯度 (在数值上的理解)
    • 梯度就是上山下山最快的方向 (在方向上理解)
    • 在平面内,梯度就是某一点上的斜率
    • **反向传播传播的是梯度:**反向传播利用链式法则不断的从后向前求导,求出来的值就是梯度,所以大家都经常说反向传播传播的是梯度
    • 链式法则中,梯度相乘,就是传说中的梯度传播
  • 梯度下降法:是一种求最优梯度值的方法,使得损失函数的值最小

训练神经网络时,最常用的算法就是反向传播。在该算法中,参数(模型权重)会根据损失函数关于对应参数的梯度进行调整。为了计算这些梯度,PyTorch内置了名为 torch.autograd 的微分模块。它支持任意计算图的自动梯度计算:

代码 贴合代码解释 补充要点
loss.sum().backward() 先对 loss 张量求和转为标量,再启动反向传播,自动计算计算图中所有可求导参数的梯度并存入.grad backward () 只能对标量直接调用;多维损失需要先聚合为标量
w.grad 读取标量张量w反向传播后计算得到的梯度张量;未执行反向传播时为 None 梯度会累加,多次 backward 不清除会叠加结果
w.grad.zero_() 原地清零参数w已存储的梯度,避免多次迭代梯度持续累积 带下划线_代表原地操作;训练循环每轮一般都需要执行
data.requires_grad 布尔属性,查看张量data是否开启梯度追踪、参与构建计算图 True参与求导;False不计算梯度,节省显存
data.detach().numpy() detach()切断张量与计算图的梯度关联,再转为 numpy 数组;脱离梯度图后才能顺利转 numpy 直接对带梯度张量调用.numpy()会报错,必须先 detach

模拟权重更新过程:

python 复制代码
"""
循环更新梯度:模拟梯度下降过程
"""

import torch

# 1. 准备w
w = torch.tensor(10, requires_grad=True, dtype=torch.float)

# 2. 准备loss
loss = w ** 2 + 40

# 3. 梯度下降,循环100次,求最优解
print(f'初始权重为:{w}, 权重更新公式:w = w - 0.01 * w.grad, 初始梯度:无, 初始loss为:{loss}\n')
for i in range(100):
    # 3.1 正向计算(前向转播)
    loss = w ** 2 + 40

    # 3.2 梯度清零,否则会累加
    # 第1次的时候,w.grad = None,所以会报错
    if w.grad is not None:
        w.grad.zero_()

    # 3.3 反向传播
    loss.sum().backward()

    # 3.4 更新权重
    w.data = w.data - 0.01 * w.grad

    # 3.5 打印结果
    print(f'第{i + 1}次迭代,权重为:{w:.2f}, 梯度为:{w.grad:.2f}, loss为:{loss:.2f}')

# 4. 输出结果
print(f'\n最终结果 权重为:{w}, loss为:{loss}')
相关推荐
后端小肥肠1 小时前
做个人 IP 不用真人出镜,我做了个一键生成 IP 动画视频的 Skill
人工智能·aigc·agent
墨舟的AI笔记1 小时前
大模型游戏剧情评测:用自动化指标抑制幻觉与 OOC 出戏
人工智能
武子康1 小时前
从世界状态到可执行控制:Cosmos 3 Edge 与机器人控制器之间应建立什么合同
人工智能·agent·nvidia
37.2℃9951 小时前
Claude Design哪个公司技术好
python·设计模式
我是大卫2 小时前
【图】解LLM:用图理解大语言模型
人工智能
157092511342 小时前
【无标题】
开发语言·python·算法
勇叔2 小时前
从 LangChain SQLAgent 天生缺陷到五把安全锁落地 — 牧场 AI 查询实战踩坑指南
人工智能
Kel2 小时前
GQA 与 KV 缓存(Grouped-Query Attention & KV Cache)
人工智能
DogDaoDao2 小时前
OpenBrowser 深度解析:让 AI 真正「用上」浏览器的自主代理框架
人工智能·程序员·大模型·github·web·ai工具·openbrowser