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



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

API
1. 基本创建方式
| 代码 | 贴合代码解释 | 补充要点 |
|---|---|---|
torch.tensor([1,2,3], requires_grad=True, dtype=torch.float) |
基于列表[1,2,3]创建张量;开启梯度追踪;指定数据类型为浮点型。推荐优先使用。 |
支持自定义requires_grad、dtype, 要想设定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;不能直接配置梯度参数。 |
- PyTorch仅浮点类型张量支持自动微分
- PyTorch 中 Python 原生浮点数列表自动推断为 32 位浮点型,dtype=torch.float32
- PyTorch 中 Python 原生整数列表自动推断为 64 位整型,不是 int32
- 查看张量属性:.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。 |
填充值自由自定义,通用性最强。 |
- 第一个参数为shape,推荐元组形式
- _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) |
对t1与t2执行逐元素相乘(哈达玛积) ,返回新张量;不修改原始t1。 |
等价运算符 t1 * t2;要求两个张量形状满足广播规则;不是矩阵乘法。 |
t1.mul_(t2) |
带下划线代表原地操作 ,将t1与t2逐元素相乘,结果直接覆盖保存到t1自身,无返回值。 |
原地运算会直接修改原张量;若t1开启requires_grad=True,尽量避免使用原地操作,容易引发自动微分报错。 |
7.3 矩阵乘法运算
- 要求:第一个矩阵 shape: (n, m),第二个矩阵 shape: (m, p), 两个矩阵点积运算 shape 为: (n, p)。
| 代码 | 贴合代码解释 | 补充要点 |
|---|---|---|
t1.matmul(t2) |
执行张量矩阵乘法,将张量t1与t2做矩阵相乘运算。等价于 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) |
将张量data1、data2沿着第 1 维 拼接;不新增维度,只扩展该维度长度。 |
参与拼接的张量,除 dim 指定维度外,其余维度尺寸必须完全一致 |
torch.stack([data1, data2], dim=1) |
将张量data1、data2沿着第 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}')