《人工智能概论》实验1 知识点复习提纲
知识点复习
一、PyTorch 张量(Tensor)基础
1. 张量创建方式
| 函数 | 说明 |
|---|---|
torch.ones(rows, cols) |
全1张量 |
torch.zeros(rows, cols) |
全0张量 |
torch.rand(rows, cols) |
均匀分布 [0,1) 随机数 |
torch.randn(rows, cols) |
标准正态分布(均值0,方差1)随机数 |
torch.arange(start, end) |
生成一维整数序列,不包含 end |
tensor.reshape(r, c) |
改变张量形状,元素总数必须一致 |
2. 张量切片与索引
-
格式:
tensor[起始行:结束行, 起始列:结束列] -
遵循 左闭右开 规则,例如
[2:6, 2:6]取行索引2~5,列索引2~5 -
示例:16×16图像的中心4×4区域 →
[6:10, 6:10]
3. 张量拼接:torch.cat()
-
torch.cat([A, B], dim=0)→ 垂直拼接(增加行数),要求列数相同 -
torch.cat([A, B], dim=1)→ 水平拼接(增加列数),要求行数相同
4. 广播机制(Broadcasting)
-
规则:从最后一位维度开始向前对齐,每个对应维度满足以下条件之一即可:
-
相等
-
其中一个为1
-
其中一个缺失(视为1)
-
-
结果形状:取各维度最大值
-
示例:
-
(3,1)+(1,4)→(3,4) -
(5,4)+(5,1)→(5,4) -
(3,4)+(2,4)→ ❌ 不满足(3≠2且都不是1)
-
二、自动微分(Autograd)
1. 基本概念
-
requires_grad=True:张量需要被记录梯度 -
loss.backward():反向传播计算梯度,累积到.grad属性中 -
tensor.grad:存储计算得到的梯度
2. 梯度停止方法
| 方法 | 特点 | 适用场景 |
|---|---|---|
tensor.detach() |
返回共享数据的新张量,requires_grad=False,不影响原张量 |
从计算图中取出数值,但不需要梯度回传(如强化学习目标网络更新) |
torch.no_grad() |
上下文管理器或装饰器,内部所有操作不跟踪梯度 | 测试/评估阶段,或手动更新参数(如梯度下降更新) |
3. 梯度下降优化步骤
x = torch.tensor(3.0, requires_grad=True)
lr = 0.1
for _ in range(steps):
loss = f(x) # 1. 计算损失
loss.backward() # 2. 计算梯度
with torch.no_grad():
x -= lr * x.grad # 3. 更新参数(不记录梯度)
x.grad.zero_() # 4. 梯度清零(防止累积)
简单说:
.grad是“梯度的存放处”,是自动微分和优化之间的关键桥梁。
-
必须清零梯度:否则下次
backward()会在原梯度上累加,导致错误 -
手动更新时使用
with torch.no_grad():避免构建不必要的计算图
.grad是 PyTorch 中张量的一个属性,用于存储该张量的梯度值。具体作用:
-
当您对某个张量设置了
requires_grad=True,并参与运算后调用backward(),PyTorch 会自动计算该张量相对于最终标量结果的梯度,并将其累加到.grad属性中。 -
在梯度下降优化中,通过
x.grad获取梯度,然后手动或通过优化器更新参数(例如x -= learning_rate * x.grad)。 -
每次反向传播后,梯度会累加,因此通常需要在更新参数后调用
x.grad.zero_()将梯度清零,避免下一次累加旧梯度。
三、可视化
-
plt.imshow(tensor.numpy(), cmap='gray'/'viridis'):显示图像或热力图 -
plt.subplots()创建多子图布局
考题:张量操作与自动微分
出题人说明:本套考题基于实验1的知识点,涵盖张量创建、切片拼接、广播机制、自动微分及梯度下降优化等内容。题型包括单选题、填空题、判断题、简答题和代码填空题,总分100分。建议完成时间60分钟。
一、单选题(每题3分,共15分)
-
以下关于
torch.rand(4, 4)和torch.randn(4, 4)的说法,正确的是( )
A. 两者都生成服从标准正态分布的随机数
B.torch.rand生成均匀分布,torch.randn生成标准正态分布
C.torch.rand生成标准正态分布,torch.randn生成均匀分布
D. 两者生成的都是[0,1)均匀分布的随机数 -
有一个形状为
(16, 16)的张量img,想要裁剪出中心4×4的区域,下列切片写法正确的是( )
A.img[4:8, 4:8]
B.img[5:9, 5:9]
C.img[6:10, 6:10]
D.img[7:11, 7:11] -
关于广播机制,下列哪一组形状的两个张量无法进行广播运算?( )
A.(3, 1)和(1, 4)
B.(2, 3, 4)和(4,)
C.(3, 4)和(2, 4)
D.(5, 1, 6)和(1, 5, 1) -
以下代码中,
y.requires_grad的值是( )x = torch.tensor(2.0, requires_grad=True) with torch.no_grad(): y = x ** 2A.
True
B.False
C.None
D. 运行时报错 -
在梯度下降优化中,每次更新参数后必须执行的操作是( )
A.loss.backward()
B.optimizer.step()
C. 梯度清零(如x.grad.zero_())
D. 重新计算损失函数
二、填空题(每空1分,共12分)
-
使用
torch.arange(0, 256).reshape(16, 16)创建渐变图像,arange生成的元素个数是 ______,reshape后张量的形状是 ______。若想改为32×8的图像,应写为torch.arange(0, 256).reshape(______, ______)。 -
将两个形状分别为
(8, 8)的张量A和B进行左右拼接(增加列数),应使用torch.cat([A, B], dim=______),拼接后的形状是 ______。 -
对于形状
(3, 1)的列向量和形状(1, 4)的行向量,广播相加后的结果形状是 ______。 -
在自动微分中,若要计算
f = x**3 + 2*x在x=2.0处的导数,需要设置x.requires_grad=______,然后调用f.______(),最后通过x.______获取导数值。 -
使用
detach()方法会返回一个 ______ (填“共享数据”或“深拷贝”)且 ______ (填“记录”或“不记录”)梯度的新张量。
三、判断题(正确打“√”,错误打“×”,每题2分,共8分)
-
( )
torch.ones(4, 4)与torch.zeros(4, 4)相加得到的结果张量仍然会记录梯度(假设它们原本没有requires_grad=True)。 -
( )形状为
(3, 4)和形状为(4, 3)的两个张量可以进行广播相加。 -
( )在
with torch.no_grad():块内创建的张量,其requires_grad始终为False。 -
( )对于函数
f(x)=x⁴-4x²+5,使用梯度下降法寻找最小值时,学习率越大收敛越快,且不会发散。
四、简答题(共29分)
简答题1(5分,实验2.1节思考题)
(1)torch.rand 和 torch.randn 生成的随机数有什么不同?
(2)torch.arange(0, 256) 生成的序列有多少个元素?为什么刚好能 reshape 成 16×16?
(3)如果想把渐变图像变成 32×8,代码应该怎么改?
简答题2(5分,实验2.2节思考题)
(1)16×16 的图像,中心 4×4 区域的起始索引为什么是 6 和 6?
(2)切片操作 [2:6, 2:6] 取出的是第几行到第几行?第几列到第几列?
(3)dim=0 和 dim=1 在拼接时分别对应什么方向?
(4)如果两个张量形状不匹配,cat 会报什么错?
简答题3(6分,实验2.3节思考题)
判断以下形状对能否进行广播。如果可以,写出广播后的形状;如果不可以,写出理由。
① (5,4) 和 (5,1)
② (3,2) 和 (2,)
③ (2,3,4) 和 (4,)
④ (2,3,4) 和 (3,4)
⑤ (3,4,5) 和 (4,5)
⑥ (3,4) 和 (2,4)
简答题4(5分,实验3.1节思考题)
(1)在自动微分中,如果张量的 requires_grad=False 会发生什么?
(2)对于一元函数 f(x)=x³+2x²+3x+4,若把 x=2.0 改成 x=3.0,x.grad 的值会如何变化?
(3)手动写出函数 f(x,y)=x²y+2xy² 的偏导公式 ∂f/∂x 和 ∂f/∂y,并验证当 x=2, y=3 时程序输出的结果是否正确。
简答题5(4分,实验3.2节思考题)
(1)detach() 和 torch.no_grad() 有什么区别?
(2)请列举至少两个需要停止梯度追踪的典型场景。
简答题6(4分,实验3.3节思考题)
(1)函数 f(x)=x⁴-4x²+5 的最小值点在哪里?(提示:求导解方程)
(2)为什么在梯度下降更新参数时要放在 with torch.no_grad(): 里?
(3)如果注释掉梯度清零的代码(即去掉 x.grad.zero_()),重新运行,会发生什么?为什么?
五、代码填空题(每空3分,共36分)
-
张量操作(补全代码)
import torch # 创建均匀分布随机张量 4×4 rand_tensor = torch.______(4, 4) # 创建正态分布随机张量 4×4 randn_tensor = torch.______(4, 4) # 渐变图像:0~255 并 reshape 为 16×16 gradient = torch.arange(0, 256).reshape(______, ______) # 裁剪左上角 8×8 crop_tl = gradient[______, ______] # 裁剪右下角 8×8(已给出) crop_br = gradient[8:16, 8:16] # 上下拼接(增加行数) concat_v = torch.cat([crop_tl, crop_br], dim=______) # 左右拼接(增加列数) concat_h = torch.cat([crop_tl, crop_br], dim=______) -
自动微分与梯度下降(补全代码)
x = torch.tensor(3.0, requires_grad=______) # 开启梯度 learning_rate = 0.1 steps = 50 for i in range(steps): f = x**4 - 4*x**2 + 5 f.______() # 反向传播计算梯度 with torch.______(): # 不记录梯度上下文 x -= learning_rate * x.grad x.______.______() # 清零梯度(两个点号填空) if i % 10 == 0: print(f"第{i}步: x={x.item():.4f}, f={f.item():.4f}")
参考答案与详细解析
一、单选题
-
答案:B
解析:torch.rand生成[0,1)均匀分布的随机数;torch.randn生成均值为0、方差为1的标准正态分布随机数。 -
答案:C
解析:16×16 图像的中心区域,起始索引 = (16-4)//2 = 6,结束索引 = 6+4 = 10,因此为[6:10, 6:10]。 -
答案:C
解析:广播规则:从后向前对齐维度,要求每个对应维度要么相等,要么其中一个为1,要么缺失。C项(3,4)与(2,4):第一个维度 3 ≠ 2 且均不为1,因此无法广播。 -
答案:B
解析:torch.no_grad()上下文内所有操作都不会追踪梯度,因此y.requires_grad为False。 -
答案:C
解析:梯度下降更新参数后,必须将梯度清零,否则下次反向传播会累加旧梯度。通常使用x.grad.zero_()或优化器的zero_grad()。
二、填空题
-
答案:256;(16, 16);32;8
解析:arange(0,256)生成0~255共256个整数。reshape(32,8)后行数为32,列数为8,32×8=256。 -
答案:1;(8, 16)
解析:左右拼接增加列数,对应dim=1(第二维)。两个(8,8)沿dim=1拼接后为(8, 8+8) = (8,16)。 -
答案:(3, 4)
解析:(3,1)与(1,4)广播:第一维取3,第二维取4,结果为(3,4)。 -
答案:True;backward;grad
解析:标准自动微分流程。 -
答案:共享数据;不记录
解析:detach()返回与原始张量共享内存的新张量,但requires_grad=False,不参与计算图。
三、判断题
-
答案:×
解析:ones和zeros默认requires_grad=False,相加结果也不记录梯度。若要记录梯度需显式设置。 -
答案:×
解析:广播要求从后向前对齐维度,(3,4)与(4,3)最后一维 4≠3 且均不为1,无法广播。 -
答案:√
解析:torch.no_grad()内部所有操作生成的张量requires_grad=False。 -
答案:×
解析:学习率过大可能导致震荡甚至发散,无法收敛到最小值。
四、简答题
简答题1(5分)
(1)torch.rand 生成 [0,1) 均匀分布随机数;torch.randn 生成均值为0、方差为1的标准正态分布随机数。
(2)256个元素;因为 16×16 = 256,元素总数与reshape目标形状一致。
(3)torch.arange(0,256).reshape(32, 8)
简答题2(5分)
(1)中心起始索引 = (16-4)//2 = 6,所以行和列都从6开始。
(2)第2行到第5行(行索引2,3,4,5),第2列到第5列(列索引2,3,4,5)。
(3)dim=0 对应垂直方向(增加行数),dim=1 对应水平方向(增加列数)。
(4)报错:RuntimeError: Sizes of tensors must match except in dimension ...(形状不匹配错误)。
简答题3(6分)
① 能,(5,4)
② 能,(3,2) ((2,) 补为 (1,2))
③ 能,(2,3,4) ((4,) 补为 (1,1,4))
④ 能,(2,3,4) ((3,4) 补为 (1,3,4))
⑤ 能,(3,4,5) ((4,5) 补为 (1,4,5))
⑥ 不能,因为第一维 3 ≠ 2 且均不为1,无法对齐。
简答题4(5分)
(1)该张量不会参与梯度计算,其 .grad 为 None,反向传播时不会对其求导。
(2)x.grad 会从 23 变为 3×3² + 4×3 + 3 = 27+12+3=42(具体值:f'(3)=3*9+4*3+3=27+12+3=42)。
(3)∂f/∂x = 2xy + 2y²,∂f/∂y = x² + 4xy。代入 x=2,y=3:∂f/∂x = 2×2×3 + 2×9 = 12+18=30,∂f/∂y = 4 + 4×2×3 = 4+24=28,与程序输出一致。
简答题5(4分)
(1)区别:
-
detach()是张量方法,返回一个共享数据但requires_grad=False的新张量,不影响原张量的计算图。 -
torch.no_grad()是上下文管理器,块内所有操作均不追踪梯度,退出后恢复。
(2)场景:① 模型评估/测试时,不需要计算梯度以节省内存和计算;② 在强化学习中,从当前网络复制目标网络的值但不希望梯度回传;③ 手动更新参数时(如梯度下降中的x -= lr * x.grad)。
简答题6(4分)
(1)最小值点:令 f'(x)=4x³-8x=4x(x²-2)=0,得 x=0, ±√2。二阶导 f''(x)=12x²-8,在 x=±√2 处 f''=16>0,故为极小值点,最小值 f(±√2)=4-8+5=1;x=0 为极大值点(f''=-8<0)。
(2)因为参数更新操作不需要构建计算图,且如果放在计算图内会导致不必要的内存消耗和梯度追踪错误。
(3)梯度会不断累积(每步梯度累加),导致参数更新幅度越来越大,最终发散或无法收敛到最小值。
五、代码填空题
-
答案:
rand_tensor = torch.rand(4, 4) randn_tensor = torch.randn(4, 4) gradient = torch.arange(0, 256).reshape(16, 16) crop_tl = gradient[0:8, 0:8] concat_v = torch.cat([crop_tl, crop_br], dim=0) concat_h = torch.cat([crop_tl, crop_br], dim=1)解析:
[0:8, 0:8]取左上角8行8列;上下拼接dim=0,左右拼接dim=1。 -
答案:
x = torch.tensor(3.0, requires_grad=True) f = x**2 # 前向计算 f.backward() # 反向传播 print(x.grad) # 输出梯度值 with torch.no_grad(): x.grad.zero_() # 梯度清零解析:
requires_grad=True;backward()计算梯度;no_grad()更新参数;梯度清零使用x.grad.zero_(),注意两个点号:先访问grad属性再调用zero_()方法。
更多推荐




所有评论(0)