PyTorch基础——张量(Tensor)

发布于:2025-07-30 ⋅ 阅读:(15) ⋅ 点赞:(0)

PyTorch基础——张量(Tensor)

一、张量基础:概念与核心特性

1.1 张量的数学定义与计算机表示

在数学中,张量是向量空间中的多线性映射,而在PyTorch中,张量是多维数组的泛化表示:

  • 0维张量(标量):表示单个数值,维度为0
  • 1维张量(向量):表示一组有序数值,维度为1
  • 2维张量(矩阵):表示行列结构的数据,维度为2
  • n维张量:表示更高维度的数据结构,如3维可表示图像(通道×高度×宽度)

张量的核心属性

  • shape:张量的维度信息,返回一个元组(如(3,4)表示3行4列)
  • dtype:张量的数据类型,决定了存储精度和范围
  • device:张量所在的计算设备(CPU/GPU)
  • requires_grad:是否需要追踪梯度,用于自动求导

1.2 张量的数据类型系统

PyTorch支持丰富的数据类型,主要分为以下几类:

数据类型类别 具体类型 描述 占用字节
浮点类型 torch.float16 半精度浮点数,范围±65504 2
torch.float32 单精度浮点数(默认) 4
torch.float64 双精度浮点数 8
torch.bfloat16 脑浮点格式,适合深度学习 2
整数类型 torch.uint8 无符号8位整数(0-255) 1
torch.int8 有符号8位整数(-128-127) 1
torch.int16 有符号16位整数 2
torch.int32 有符号32位整数 4
torch.int64 有符号64位整数(默认整数类型) 8
布尔类型 torch.bool 布尔值(True/False) 1
复数类型 torch.complex64 复数(实部和虚部为float32) 8
torch.complex128 复数(实部和虚部为float64) 16

选择合适数据类型的原则

  1. 深度学习模型通常使用float32作为默认浮点类型
  2. 内存有限时可考虑float16bfloat16(需GPU支持)
  3. 整数类型用于表示索引或分类标签(如torch.long
  4. 布尔类型用于掩码操作(如torch.bool

二、张量的创建方法详解

2.1 使用torch.tensor()创建张量

标准型:

torch.tensor(data, dtype=None, device=None, requires_grad=False, pin_memory=False)

参数详解:

  • data:必需参数,表示输入数据(可以是列表、元组、NumPy数组等)
  • dtype:可选参数,指定张量的数据类型(如torch.float32
  • device:可选参数,指定张量存储的设备(如"cuda:0"
  • requires_grad:可选参数,是否需要计算梯度(默认为False)
  • pin_memory:可选参数,是否分配页锁定内存(用于加速GPU数据传输)

代码示例:

import torch
import numpy as np

# 从列表创建张量,指定数据类型和设备
tensor1 = torch.tensor(
    [1, 2, 3], 
    dtype=torch.float32, 
    device="cuda" if torch.cuda.is_available() else "cpu"
)
print("tensor1:", tensor1)

# 从NumPy数组创建张量,保留梯度
np_array = np.array([[4, 5], [6, 7]])
tensor2 = torch.tensor(np_array, requires_grad=True)
print("\ntensor2:", tensor2)
print("是否需要梯度:", tensor2.requires_grad)

运行效果:

tensor1: tensor([1., 2., 3.], device='cuda:0')

tensor2: tensor([[4, 5],
        [6, 7]], dtype=torch.int64, requires_grad=True)
是否需要梯度: True

2.2 使用torch.Tensor()创建张量(类构造器)

torch.Tensor是张量类的构造器,与torch.tensor()有区别:

  • torch.Tensor():是类的构造函数,默认使用torch.float32数据类型
  • torch.tensor():是工厂函数,会根据输入数据自动推断类型

标准型:

torch.Tensor(*size)  # 创建指定形状的未初始化张量
torch.Tensor(data)   # 从数据创建张量(等价于torch.tensor())

使用场景:

  1. 创建未初始化张量(需谨慎使用):

    empty_tensor = torch.Tensor(2, 3)  # 创建2x3未初始化张量
    
  2. 从已有数据创建张量(与torch.tensor()类似):

    data_tensor = torch.Tensor([1, 2, 3])  # 从列表创建张量
    

代码示例:

# 使用torch.Tensor()创建张量
tensor1 = torch.Tensor([1, 2, 3])  # 注意:输入为Python列表
print("使用Tensor()创建的张量:", tensor1)
print("数据类型:", tensor1.dtype)  # 默认float32

# 创建指定形状的未初始化张量(危险操作)
empty_tensor = torch.Tensor(2, 3)  # 创建2x3的未初始化张量
print("\n未初始化的张量:\n", empty_tensor)  # 可能包含随机值

运行效果:

使用Tensor()创建的张量: tensor([1., 2., 3.])
数据类型: torch.float32

未初始化的张量:
 tensor([[4.5824e-41, 0.0000e+00, 4.5824e-41],
        [0.0000e+00, 0.0000e+00, 0.0000e+00]])

核心讲解:

  1. torch.Tensor()默认使用float32,即使输入是整数列表
  2. 当传入多个整数参数(如torch.Tensor(2,3))时,会创建指定形状的未初始化张量
  3. 未初始化张量包含内存中的随机值,直接使用可能导致不可预测的结果
  4. 推荐使用torch.empty()替代这种危险用法

torch.tensor()的关键区别

  • torch.Tensor()默认使用float32数据类型
  • torch.Tensor(*size)创建的是未初始化内存,内容是随机的
  • torch.tensor()总是复制输入数据,而torch.Tensor(data)可能共享内存(取决于实现)

安全替代方案

  • torch.empty(shape)替代torch.Tensor(shape)创建未初始化张量
  • torch.tensor(data)替代torch.Tensor(data)从已有数据创建张量

2.3 torch.Tensor()torch.tensor()的区别

特性 torch.tensor() torch.Tensor()
函数类型 工厂函数(推荐使用) 类构造器
数据处理方式 复制输入数据 可能创建未初始化的内存空间
默认数据类型 自动推断(整数默认为int64) 固定为float32
安全风险 安全(始终复制数据) 不安全(可能包含随机值)
推荐场景 从已有数据创建张量 创建指定形状的空张量(需后续初始化)

危险示例

# 使用torch.Tensor()创建未初始化张量(不建议)
dangerous_tensor = torch.Tensor(2, 2)  # 创建2x2未初始化张量
print("未初始化张量内容:\n", dangerous_tensor)

运行效果

未初始化张量内容:
 tensor([[4.5824e-41, 0.0000e+00],
        [4.5824e-41, 0.0000e+00]])
安全建议:
1. 避免直接使用torch.Tensor(shape)创建张量
2. 推荐使用torch.empty(shape)创建未初始化张量,或使用torch.zeros/ones等函数
3. 只有在明确需要float32类型且输入为None时,才考虑使用torch.Tensor()

三、张量的常用创建函数详解

3.1 创建特定值的张量

函数名 标准型 功能描述
torch.zeros() torch.zeros(size, dtype=None, layout=torch.strided, device=None, requires_grad=False) 创建全零张量
torch.ones() torch.ones(size, dtype=None, layout=torch.strided, device=None, requires_grad=False) 创建全一张量
torch.full() torch.full(size, fill_value, dtype=None, layout=torch.strided, device=None, requires_grad=False) 创建填充特定值的张量
torch.eye() torch.eye(n, m=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) 创建单位矩阵(对角线为 1,其余为 0)
torch.arange() torch.arange(start=0, end, step=1, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) 创建等差数列张量
torch.linspace() torch.linspace(start, end, steps=100, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) 创建等比数列张量

参数说明:

参数 说明
size 定义张量形状(维度和各维度大小),如(2,3)或[4,5]。
dtype 指定数据类型(默认自动推断),如torch.float32、torch.int64。
layout 内存布局(默认torch.strided),如torch.strided(密集)、torch.sparse_coo(稀疏)。
device 存储设备,如"cpu"、“cuda:0”(GPU)。
requires_grad 是否追踪梯度(用于自动求导),True/False。
fill_value(torch.full()) 填充的具体值,如5、3.14。
n(torch.eye()) 方阵行数(若m未指定则为n×n),如3(3×3 矩阵)。
m(torch.eye()) 可选列数(默认等于n),如4(n×4矩阵)。
start(torch.arange()/torch.linspace()) 序列起始值,如0、1.5。
end(torch.arange()/torch.linspace()) 序列结束值(arange不含,linspace含),如10、5.0。
step(torch.arange()) 相邻元素差值(步长),如2、0.5(非零)。
steps(torch.linspace()) 元素总数(含start和end),如5(生成 5 个元素)。
out 指定输出张量(复用内存),需与结果形状匹配。

代码示例:

# torch.zeros()标准型
torch.zeros(size, dtype=None, device=None, requires_grad=False)

# 示例:创建3x4的全零浮点张量
zeros_tensor = torch.zeros((3, 4), dtype=torch.float32)
print("zeros_tensor:\n", zeros_tensor)

# torch.arange()标准型
torch.arange(start=0, end, step=1, dtype=None)

# 示例:创建从0到9的整数张量
arange_tensor = torch.arange(0, 10)
print("\narange_tensor:", arange_tensor)

运行效果:

zeros_tensor:
 tensor([[0., 0., 0., 0.],
        [0., 0., 0., 0.],
        [0., 0., 0., 0.]])

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

3.2 创建随机分布张量

函数名 标准型 分布类型 部分参数说明
torch.rand() torch.rand(size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) 均匀分布 [0,1) size(形状元组)
torch.randn() torch.randn(size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) 标准正态分布 N (0,1) size,dtype,device
torch.randint() torch.randint(low=0, high, size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) 整数均匀分布 low(下界),high(上界),size(形状),dtype
torch.normal() torch.normal(mean, std, size=None, out=None) 自定义正态分布 mean(均值),std(标准差),size(可选,若提供则覆盖 mean/std 形状)
torch.bernoulli() torch.bernoulli(input, generator=None, out=None) 伯努利分布 input(概率值张量),generator(随机数生成器)

代码示例:

# 创建2x3的均匀分布随机张量
uniform_tensor = torch.rand(2, 3)
print("均匀分布随机张量:\n", uniform_tensor)

# 创建均值为2,标准差为0.5的正态分布随机张量
normal_tensor = torch.normal(mean=2.0, std=0.5, size=(2, 2))
print("\n正态分布随机张量:\n", normal_tensor)

# 创建伯努利分布随机张量(二值0/1)
prob_tensor = torch.tensor([0.1, 0.9, 0.5])
bernoulli_tensor = torch.bernoulli(prob_tensor)
print("\n伯努利分布随机张量:", bernoulli_tensor)

运行效果:

均匀分布随机张量:
 tensor([[0.7231, 0.3456, 0.6829],
        [0.0478, 0.8537, 0.2749]])

正态分布随机张量:
 tensor([[2.3425, 1.9127],
        [2.0578, 2.3250]])

伯努利分布随机张量: tensor([0., 1., 1.])

四、张量的核心操作详解

4.1 形状操作:reshape、view、squeeze与unsqueeze

函数名 标准型 功能描述
reshape() torch.reshape(input, shape)tensor.reshape(shape) 改变张量形状,允许非连续内存
view() tensor.view(*shape) 改变张量形状,要求内存连续
squeeze() torch.squeeze(input, dim=None, out=None)tensor.squeeze(dim=None) 移除所有维度为 1 的维度(如 [1,3,1] 变为 [3])
unsqueeze() torch.unsqueeze(input, dim)tensor.unsqueeze(dim) 在指定位置插入维度为 1 的维度(如 [3] 变为 [1,3,1])
transpose() torch.transpose(input, dim0, dim1)tensor.transpose(dim0, dim1) 交换两个维度的位置
permute() tensor.permute(*dims) 重新排列所有维度的顺序

参数说明:

参数 说明
input(torch.reshape()、torch.squeeze()、torch.unsqueeze()、torch.transpose()) 输入张量(需处理的原始张量),任意维度。
shape(torch.reshape()、tensor.reshape()) 目标形状(元素总数与原张量相同),如(3,4)、-1(自动计算维度)。
*shape(tensor.view()) 目标形状的可变参数(同shape,写法不同),如3,4(3×4 形状)。
dim(torch.squeeze()torch.unsqueeze()torch.transpose()) 操作的维度索引(squeeze移除、unsqueeze插入、transpose交换),如0、1(从 0 开始)。
dim0(torch.transpose()) 需交换的第一个维度,非负整数(小于张量维度数)。
dim1(torch.transpose()) 需交换的第二个维度,非负整数(小于维度数且≠dim0)。
*dims(tensor.permute()) 维度重排顺序(新维度顺序),如2,0,1(原维度 0→1、1→2、2→0)。
out 指定输出张量(复用内存),需与目标形状匹配。

关键区别:

  • reshape():更灵活,会在需要时复制数据以确保连续性
  • view():更高效,直接使用原内存,但要求内存连续
  • 如果不确定内存是否连续,优先使用reshape()

代码示例:

# 创建基础张量
x = torch.arange(12)
print("原始张量:", x)
print("形状:", x.shape)  # torch.Size([12])

# 使用reshape()
reshaped = x.reshape(3, 4)
print("\nreshape后的张量:\n", reshaped)
print("形状:", reshaped.shape)  # torch.Size([3, 4])

# 使用view()
viewed = x.view(2, 6)
print("\nview后的张量:\n", viewed)
print("形状:", viewed.shape)  # torch.Size([2, 6])

# 使用transpose()交换维度
transposed = reshaped.transpose(0, 1)  # 交换行和列
print("\ntranspose后的张量:\n", transposed)
print("形状:", transposed.shape)  # torch.Size([4, 3])

# 使用permute()重新排列维度
permuted = reshaped.permute(1, 0)  # 等价于transpose(0,1)
print("\npermute后的张量:\n", permuted)
print("形状:", permuted.shape)  # torch.Size([4, 3])

# 使用squeeze()和unsqueeze()
unsqueezed = x.unsqueeze(0)  # 在第0维插入维度
print("\nunsqueeze后的形状:", unsqueezed.shape)  # torch.Size([1, 12])
squeezed = unsqueezed.squeeze(0)  # 移除第0维
print("squeeze后的形状:", squeezed.shape)  # torch.Size([12])

运行效果:

原始张量: tensor([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
形状: torch.Size([12])

reshape后的张量:
 tensor([[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]])
形状: torch.Size([3, 4])

view后的张量:
 tensor([[ 0,  1,  2,  3,  4,  5],
        [ 6,  7,  8,  9, 10, 11]])
形状: torch.Size([2, 6])

transpose后的张量:
 tensor([[ 0,  4,  8],
        [ 1,  5,  9],
        [ 2,  6, 10],
        [ 3,  7, 11]])
形状: torch.Size([4, 3])

permute后的张量:
 tensor([[ 0,  4,  8],
        [ 1,  5,  9],
        [ 2,  6, 10],
        [ 3,  7, 11]])
形状: torch.Size([4, 3])

unsqueeze后的形状: torch.Size([1, 12])
squeeze后的形状: torch.Size([12])

运行效果说明:

  1. 原始张量创建torch.arange(12)生成包含0到11的1维张量,共12个元素,形状为(12)。这是后续形状操作的基础,所有操作都基于这12个元素的重新排列。

  2. reshape操作x.reshape(3, 4)将1维张量重构为3行4列的2维张量。原理是保持元素总数不变(3×4=12),通过改变维度组合实现形状转换。reshape支持非连续内存的张量,此处因原始张量连续,直接完成维度重排。

  3. view操作x.view(2, 6)将1维张量转为2行6列的2维张量(2×6=12)。view要求张量内存连续,由于原始张量是连续的,可直接通过改变视图实现,无需复制数据,效率高于reshape(在连续内存场景下)。

  4. transpose交换维度reshaped.transpose(0, 1)交换2维张量的0维和1维(行和列),3行4列变为4行3列。transpose仅能交换两个指定维度,适用于简单维度互换场景。

  5. permute重排维度reshaped.permute(1, 0)通过指定新维度顺序(原1维→新0维,原0维→新1维),实现与transpose相同的效果。permute支持任意维度的重排,比transpose更灵活,尤其适合高维张量。

  6. unsqueeze与squeeze操作x.unsqueeze(0)在第0维插入一个维度,将1维张量(12)变为2维张量(1, 12)squeezed.squeeze(0)则移除第0维(因该维度大小为1),恢复为(12)。两者配合实现维度的动态增减,常用于适配不同操作对张量维度的要求。

4.2 数学运算:逐元素运算与矩阵运算

逐元素运算

  • 加法:+torch.add()
  • 减法:-torch.sub()
  • 乘法:*torch.mul()
  • 除法:/torch.div()
  • 指数:torch.pow()**
  • 对数:torch.log()torch.log2()torch.log10()

矩阵运算

  • 矩阵乘法:torch.matmul()@
  • 点积(向量内积):torch.dot()
  • 矩阵转置:torch.t()tensor.T
  • 矩阵求逆:torch.inverse()
  • 矩阵行列式:torch.det()

代码示例

a = torch.tensor([[1, 2], [3, 4]])
b = torch.tensor([[5, 6], [7, 8]])

# 逐元素乘法
elementwise_mul = a * b
print("逐元素乘法:\n", elementwise_mul)

# 矩阵乘法
matrix_mul = torch.matmul(a, b)  # 等价于 a @ b
print("\n矩阵乘法:\n", matrix_mul)

# 广播机制示例
c = torch.tensor([10, 20])
broadcast_result = a + c  # c自动扩展为[[10,20],[10,20]]
print("\n广播加法:\n", broadcast_result)

# 复杂运算示例
d = torch.tensor([1.0, 2.0, 3.0])
exp_result = torch.exp(d)  # 计算e的幂
sqrt_result = torch.sqrt(d)  # 计算平方根
print("\n指数运算:", exp_result)
print("平方根运算:", sqrt_result)

运行效果

逐元素乘法:
 tensor([[ 5, 12],
        [21, 32]])

矩阵乘法:
 tensor([[19, 22],
        [43, 50]])

广播加法:
 tensor([[11, 22],
        [13, 24]])

指数运算: tensor([ 2.7183,  7.3891, 20.0855])
平方根运算: tensor([1.0000, 1.4142, 1.7321])
广播机制规则:
1. 从右向左比较两个张量的维度
2. 如果维度值相等或其中一个为1,则可以广播
3. 广播时会自动扩展维度为1的张量
4. 示例:
   - [3,1] 与 [3,3] 可以广播(右维度1 vs 3,左维度3 vs 3)
   - [1,4] 与 [3,4] 可以广播(右维度4 vs 4,左维度1 vs 3)
   - [2,3] 与 [3,2] 不可广播(右维度3 vs 2不匹配)

五、张量与NumPy的交互详解

5.1 内存共享机制

PyTorch张量与NumPy数组之间的转换有两种模式:

  1. 内存共享模式:使用torch.from_numpy()tensor.numpy(),修改一方会影响另一方
  2. 内存复制模式:使用torch.tensor()tensor.clone().numpy(),修改互不影响

代码示例

import numpy as np
import torch

# 创建NumPy数组
np_array = np.array([1, 2, 3])

# 内存共享方式转换为张量
shared_tensor = torch.from_numpy(np_array)

# 内存复制方式转换为张量
copied_tensor = torch.tensor(np_array)

# 修改NumPy数组
np_array[0] = 100

print("共享内存的张量:", shared_tensor)  # 输出: tensor([100,   2,   3])
print("复制内存的张量:", copied_tensor)  # 输出: tensor([1, 2, 3])

# 修改共享内存的张量
shared_tensor[1] = 200
print("修改后的NumPy数组:", np_array)  # 输出: [100 200   3]

5.2 数据类型转换规则

NumPy数据类型 自动转换为PyTorch数据类型
np.float32 torch.float32
np.float64 torch.float64
np.int32 torch.int32
np.int64 torch.int64
np.bool_ torch.bool

注意事项

  1. NumPy默认浮点类型是float64,而PyTorch是float32
  2. 转换时应显式指定数据类型,避免意外的精度损失
  3. 对于GPU张量,需先调用.cpu()方法再转换为NumPy数组

六、设备迁移与性能优化

6.1 设备管理API

函数/方法 功能描述
torch.cuda.is_available() 检查CUDA是否可用
torch.device() 创建设备对象(如torch.device("cuda:0")
tensor.to(device) 将张量迁移到指定设备
tensor.cuda() 将张量迁移到GPU(等价于.to("cuda")
tensor.cpu() 将张量迁移到CPU(等价于.to("cpu")
torch.cuda.device_count() 获取可用GPU数量

代码示例

# 检查CUDA可用性
print("CUDA可用:", torch.cuda.is_available())

# 创建CPU和GPU张量
cpu_tensor = torch.tensor([1, 2, 3])
if torch.cuda.is_available():
    gpu_tensor = cpu_tensor.to("cuda")
    print("GPU张量设备:", gpu_tensor.device)
    
    # 在GPU上执行计算
    result = gpu_tensor * 2
    
    # 将结果移回CPU并转换为NumPy
    numpy_result = result.cpu().numpy()
    print("NumPy结果:", numpy_result)
else:
    print("CUDA不可用,使用CPU计算")

6.2 性能优化技巧

  1. 批量操作:利用GPU并行计算能力,优先使用批量操作(如矩阵乘法)
  2. 内存预分配:避免在训练循环中频繁创建新张量,尽量复用内存
  3. 减少设备间传输:最小化CPU与GPU之间的数据传输次数
  4. 混合精度训练:使用torch.cuda.amp模块实现混合精度训练(float16+float32)
  5. 使用in-place操作:如x.add_(1)替代x = x + 1(注意:可能影响梯度计算)

七、自动求导机制

7.1 计算图与反向传播

PyTorch的自动求导基于动态计算图(Dynamic Computational Graph):

  1. 前向传播:构建计算图,记录所有操作
  2. 反向传播:根据计算图反向计算梯度
  3. 梯度累积:梯度存储在.grad属性中,多次反向传播会累积梯度

关键API

  • requires_grad=True:开启张量的梯度追踪
  • backward():执行反向传播
  • grad:访问计算得到的梯度
  • detach():从计算图中分离张量,停止梯度追踪
  • with torch.no_grad():上下文管理器,临时关闭梯度计算(用于推理)

代码示例

# 创建需要求导的张量
x = torch.tensor([2.0], requires_grad=True)
print("x:", x)

# 定义计算过程:y = x² + 3x + 1
y = x**2 + 3*x + 1
print("y:", y)  # y会记录计算图信息

# 执行反向传播(计算dy/dx)
y.backward()

# 查看梯度(dy/dx = 2x + 3 = 2*2 + 3 = 7)
print("x的梯度:", x.grad)

# 复杂计算图示例
a = torch.tensor([3.0], requires_grad=True)
b = torch.tensor([4.0], requires_grad=True)
c = a * b  # c = a*b
d = 2 * c  # d = 2*c
d.backward()  # 计算d关于a和b的梯度

print("\na的梯度:", a.grad)  # dd/da = 2*b = 2*4 = 8
print("b的梯度:", b.grad)  # dd/db = 2*a = 2*3 = 6

7.2 梯度计算注意事项

  1. 梯度累积

    • 默认情况下,多次调用backward()会累积梯度
    • 通常在每个优化步骤后需要调用optimizer.zero_grad()清除梯度
  2. 非标量输出的backward()

    • 当输出是标量时,backward()无需参数
    • 当输出是张量时,需要传入与输出形状相同的gradient参数
    x = torch.tensor([1.0, 2.0], requires_grad=True)
    y = x * 2
    y.backward(torch.tensor([1.0, 1.0]))  # 传入梯度权重
    
  3. 停止梯度追踪

    • 使用tensor.detach()创建不追踪梯度的副本
    • 使用with torch.no_grad()上下文管理器临时关闭梯度计算

requires_grad=True)
c = a * b # c = ab
d = 2 * c # d = 2
c
d.backward() # 计算d关于a和b的梯度

print(“\na的梯度:”, a.grad) # dd/da = 2b = 24 = 8
print(“b的梯度:”, b.grad) # dd/db = 2a = 23 = 6


### 7.2 梯度计算注意事项

1. **梯度累积**:
   - 默认情况下,多次调用`backward()`会累积梯度
   - 通常在每个优化步骤后需要调用`optimizer.zero_grad()`清除梯度

2. **非标量输出的backward()**:
   - 当输出是标量时,`backward()`无需参数
   - 当输出是张量时,需要传入与输出形状相同的`gradient`参数
   ```python
   x = torch.tensor([1.0, 2.0], requires_grad=True)
   y = x * 2
   y.backward(torch.tensor([1.0, 1.0]))  # 传入梯度权重
  1. 停止梯度追踪
    • 使用tensor.detach()创建不追踪梯度的副本
    • 使用with torch.no_grad()上下文管理器临时关闭梯度计算

网站公告

今日签到

点亮在社区的每一天
去签到