返回交互课程

第1周 / 静态讲义

从数据到一次可解释的学习

学习安排与内容对照

课次与时间 完整讲解内容 立即练习 需要留下的结果
第1课 1.5小时 样本、特征、标签;回归与分类;标量、向量、矩阵与形状 给一个预测任务设计数据表,指出不能提前知道的信息 一张数据表与形状说明
第2课 1.5小时 模型、参数、超参数;误差、MSE、均值基线 比较三条预测规则,手算每个样本的误差 一张逐样本计算表
第3课 1.5小时 导数、偏导、梯度;求导规则、链式法则、中心差分 手推两个偏导,用差分核对一个数 一份推导与数值核对
第4课 2小时 负梯度与学习率;两次完整更新;公式怎样变成循环 运行参考程序,逐行解释,再改初始参数 参数轨迹与修改前的预测
第5课 2小时 Python/C++函数与容器;填空、调试、求导库的分工 选择一种语言补完三个核心函数 可运行的练习版与自查结果
第6课 1.5小时 训练、验证、测试;泛化与泄漏;迁移自测 读懂80样本参考实验,讲解结果并答题 简短实验记录与8–10分钟讲解

合计10小时,另留0–2小时补学。80样本实验本周要求读懂并运行参考实现;数据生成、文件读写与整套实验的独立重写放到第2周。第二语言、NumPy、SymPy与PyTorch示例按需对照,不全算作本周必做作业。

第1课 把一个问题写成数据

样本 特征 标签

假设要根据房间面积预测租金。一行历史记录是一份样本;预测时能获得的面积是特征;希望预测的租金是标签。真实任务还可能需要地区、房龄等特征,这里只用面积说明数据结构,并不假定面积足以解释所有差异。

样本编号 面积这个特征 x 租金这个标签 y
1 1 3
2 2 5

本周计算使用上面两个抽象数值点,不把它们当作真实租房数据。预测连续数值叫回归;预测“垃圾邮件/正常邮件”这样的离散类别叫分类。两者都可以从带标签样本学习,属于监督学习。

特征必须在实际做预测的时刻能够取得。若预测明天销量,却把明天最终成交金额作为输入,就可能提前泄露答案。能从文件中读到,不等于预测时能够使用。

**停下来想:**预测学生下一次测验成绩,哪些可以作特征:过去成绩、本次测验结束后才统计的答对题数、此前练习时间?说明理由,不只回答“能”或“不能”。

标量 向量 矩阵与形状

标量是一个数,例如一个样本的面积。向量是一组按约定排列的数,例如同一样本的面积与房龄。矩阵可以用来组织多个样本:通常一行一个样本,一列一个特征。

对象 本周单特征写法 一般形状 含义
单个特征值 1.0 标量 一个样本的一项信息
一批单特征数据 [1.0, 2.0] (n,) n个样本的一项特征
特征矩阵 X [[1.0], [2.0]] (n,d) n个样本、d个特征
权重向量 w [0.0] (d,) 每个特征一个权重
标签 y与预测值 [3.0, 5.0] (n,) 每个样本一个值
偏置 b与损失 L 0.0与17.0 标量 一个全局偏置与一个汇总误差

多特征预测可以写成:

意思是每一行特征与权重作点积,再加上同一个偏置。若X是3行2列,权重有2个数,预测就应有3个数。不要只问代码是否能执行,还要问输出是否确实“一行样本对应一个预测”。NumPy中的 (n,) 与 (n,1) 不是同一种形状;混用时可能发生广播,意外产生 (n,n) 误差矩阵,详见编程辅助。

**本课练习:**自己造一个“3个样本、2个特征、1个标签”的数据表。标出X与y,给出形状,并说明列的顺序为什么不能在预测时随意交换。

第2课 从模型到可以比较的损失

模型 参数与超参数

先选择最简单的一种预测规则:

其中i是样本编号,帽子表示预测值;w控制斜率,b控制整体上下平移。x是已经给定的输入,y是用于比较的标签,训练调整的是w和b。选择“用一条直线”是建模决定,并不是程序从所有可能规则中自动发现了直线。

名称 本周例子 怎样确定
参数 w、b 通过训练数据与优化过程调整
超参数 学习率、更新次数 由人设定或使用验证集选择
数据 x、y 来源于观察或明确规定的生成过程
模型形式 一条直线 由任务和建模假设选择

先不训练,手工试三组参数:全零预测、恒定预测4、直线预测2x+1。训练的作用是用有组织的方式寻找参数,代替一直凭感觉猜数字。

为什么定义误差与均方误差

本周统一用“预测减真实值”定义残差:

残差为负表示预测偏低,为正表示偏高。若两个残差是2和−2,直接平均得到0,却不能说完全预测正确。均方误差先平方,再取平均:

这里n是样本数,求和符号表示把每个样本的平方残差加起来。本页采用普通MSE,没有额外除以2。平方避免正负抵消,同时更强调大误差;如果标签单位是元,MSE的单位是元的平方,不能把MSE直接当成平均相差多少元。

预测规则 两个预测 两个残差 MSE
w=0,b=0 0,0 −3,−5 17
w=0,b=4 4,4 1,−1 1
w=2,b=1 3,5 0,0 0

恒定预测训练标签的均值,是一种简单的基线。它回答“如果不利用输入特征,能做到什么程度”。在MSE下,最佳恒定预测是训练标签均值;这条结论依赖于使用平方损失。

**本课练习:**改成w=1、b=0,独立写出预测、残差与MSE。再把一个标签5改成50,观察平方损失如何放大大误差。不要据此宣布MSE“不好”,而应讨论任务是否真的要让大错误付出更高代价。

第3课 求导到底在求什么

从斜率到局部变化率

直线f(t)=3t+2每增加一小段t,输出增加约3倍,导数就是3。曲线的变化速度会随位置改变,例如:

在t=3处导数是6,表示t增加一个很小的量h时,函数值约增加6h。它不是说“t增加任意大小,输出都准确增加6倍”。例如h=0.1时,实际增加0.61,一阶估计是0.6。

学习参数时,我们关心的是参数变化会怎样影响损失。对w求偏导,暂时固定b与所有样本;对b求偏导,暂时固定w与所有样本。把各参数的偏导收集起来,就得到梯度。本例梯度有两个分量,分别对应w与b。

本周真正需要的求导规则

函数 对t求导 应怎样理解
常数c 0 输入变化不影响输出
t 1 输入增加多少,输出增加多少
t的平方 2t 同一曲线在不同位置有不同斜率
c乘f(t) c乘f的导数 整体缩放也缩放变化率
f(t)+g(t) 两个导数相加 总变化来自各部分变化
外层函数作用于内层函数 外层导数乘内层导数 一层变化经过另一层传播,称为链式法则

对一个样本,把计算分成三步:预测z=wx+b,残差e=z−y,平方误差q=e²。q对e的导数是2e,e对z的导数是1,而z对w的导数是x。因此:

同理,z对b的导数是1,所以:

最后对所有样本求和并除以n,就得到真正需要写进程序的两个式子:

请留意:对w求导时多出来的x不是记忆口诀,它来自预测对w的变化率。若把残差定义改成“真实减预测”,整套推导的符号也必须一起调整,不能只改程序的一行残差。

用中心差分核对结果

如果已经有一个能计算损失的函数,就可以轻微改变w,观察两侧损失之差:

这个方法叫数值差分,返回的是近似导数值,不返回解析公式。h表示探测间距,不是训练学习率。本周可先用h=0.00001。h过大可能使局部近似变差,过小又可能使浮点数相减丢失有效数字,不能简单认为越小越准确。

例如f(t)=t³在t=2处,解析导数是12;中心差分的精确表达式为12+h²,h=0.1时得到12.01。本周的线性回归MSE对参数是二次函数,精确算术下中心差分恰好能给出导数;实际程序仍有浮点误差。

**本课练习:**固定w=0、b=0,先手算梯度,再用损失函数差分核对w的偏导。然后改为w=1、b=0重做,不能只验证原点。更多求导工具见编程辅助中的求导方式。

第4课 怎样走出一次学习更新

为什么沿负梯度更新

在当前位置,正偏导表示参数稍微增加会使损失增大,所以可以尝试减小参数;负偏导则相反。更新规则是:

t是更新轮次,alpha是学习率。两个偏导必须使用同一组旧参数计算,然后同时应用更新。不能先更新w,再把新w代入计算b的梯度,却仍把它称为同一次标准梯度下降。

你在第二版笔记中提到的一阶泰勒近似,可以把这个方向解释得更清楚。记g为当前梯度、theta为参数向量;在变化足够小且函数可微的局部范围内:

其中梯度范数的平方就是各个偏导平方的和。当alpha为正、梯度不为零时,右侧比原损失小。但这是局部近似,步子过大时高阶项不能忽略,实际损失可以上升;对于更一般的模型,梯度为零也不自动表示找到全局最优。

两次更新全部算出来

在w=0、b=0处,残差是−3与−5:

学习率取0.1,第一次更新得到w=1.3、b=0.8。再次计算残差−0.9与−1.6,得到新梯度−4.1与−2.5;第二次更新得到w=1.71、b=1.05。

已完成更新次数 w b 对x=1的预测 对x=2的预测 当前MSE
0 0 0 0 0 17
1 1.3 0.8 2.1 3.4 1.685
2 1.71 1.05 2.76 4.47 0.16925

两次更新后的直线与训练样本

图中的横轴是输入x,纵轴是输出y。它展示参数如何改变预测线,不是独立测试的证据。两个点可以被无数其他形状的函数经过,仅拟合它们不能证明现实规律就是一条直线。

把学习率改为1,从零出发一次就得到w=13、b=8,损失升到582.5。梯度方向可以没有算错,更新仍会因步长过大而失败。把损失整体除以2会让梯度也减半;在本例普通梯度下降、没有其他变化时,把学习率乘2才能保留相同的参数更新幅度。

一段可直接运行的最小Python程序

先读懂下面的完整程序。它只依赖Python自身,和数学推导一一对应:

samples = [(1.0, 3.0), (2.0, 5.0)]
w, b = 0.0, 0.0
alpha = 0.1

for step in range(3):
    errors = [w * x + b - y for x, y in samples]
    loss = sum(e * e for e in errors) / len(samples)
    print(f"step={step}, w={w:.6f}, b={b:.6f}, loss={loss:.6f}")
    if step == 2:
        break
    dw = 2.0 * sum(e * x for e, (x, y) in zip(errors, samples)) / len(samples)
    db = 2.0 * sum(errors) / len(samples)
    w, b = w - alpha * dw, b - alpha * db

第一行把每个样本保存为一对数。列表推导式逐个计算残差;sum把各项加起来,len提供样本数;zip把残差与对应样本配对。最后一行的右侧先计算完毕,再把结果赋给w和b,所以使用的是同一组旧参数。

预期输出中的loss依次为17.000000、1.685000、0.169250。分函数的完整版本和C++对应实现见Python参考与C++参考,运行步骤见代码使用说明。

第5课 逐步减少编程帮助

先选一种语言完成

阶段 你做什么 怎样判断完成
跟读 运行参考版本,找到预测、损失、梯度和更新位置 能指着代码说出每个输入与返回值的数学含义
改动 初始参数改为w=1、b=0,运行前先预测 损失6.5,梯度−8与−5;能说明为何不同
填空 在starter里补预测、MSE与解析梯度 两次更新、均值基线与中心差分检查一致
迁移 换成自己设计的3个样本,独立调用这些函数 不依赖旧答案也能核对一轮更新

填空文件:Python练习版、C++练习版。它们含待完成项,未填写前报错是预期行为。卡住时逐层看提示,不必立刻从空文件独立写完整实验框架。

C++的平方写成 e * e,Python可写 e * e 或 e ** 2;两者的 ^ 都不是普通数值平方运算。C++里用 2.0 / n 避免整数除法。检查数组长度、样本对应关系和浮点数类型,往往比先调学习率更有效。

求导函数和库分别帮你做什么

方式 本周怎么用 得到什么
解析求导后手写函数 把上面的两个偏导实现为循环 某组参数处的准确公式计算值,存在浮点舍入
中心差分 对损失函数左右取值 近似导数数值,用来交叉检查
SymPy符号求导 用diff对数学表达式求导 新的符号表达式,再代入数值得到结果
PyTorch自动微分 保留张量计算过程,再反向传播 相对于参数的梯度数值

NumPy负责数组运算,它的 gradient 是对采样数据作数值差分,并不自动追踪任意模型的计算图;SymPy的 diff 才是这里的符号求导。C++标准库没有通用符号或自动求导接口,本周用手写梯度与中心差分就能完成。NumPy官方说明、SymPy求导教程

Python与C++编程辅助提供函数、容器、NumPy形状、SymPy与PyTorch的短示例以及C++库说明。现在先用这些工具核对一个导数;完整神经网络反向传播仍放在第9至10周。

第6课 从训练成功走向有效评估

三份数据回答三个不同问题

训练集用于调整w和b;验证集用于选择学习率、更新轮数或其他方案;测试集用于方案固定后的最终评估。只要看过某份数据上的结果并据此改了方案,它就已经在帮助选择,不能继续假装它完全独立。

第一次更新后的训练损失由17下降到1.685,但仍差于恒定预测4的基线损失1。第二次更新的0.16925虽优于基线,也仅说明训练样本上的比较。泛化关心的是未来相关样本;不仅要有独立评估,还要考虑评估数据是否代表将来的使用情形。

训练损失和验证损失都高,可能是还没训练好、模型太简单、数据或实现有问题;训练很低而验证高,可能是过拟合、划分问题或分布变化。它们是排查线索,不是只看一张图就能确定的诊断。先检查实现和数据,再一次改变一个因素。

80个样本的带教实验

本周先运行已提供的参考实现,并回答它为何这样设计。数据生成规则是:

x在−2至2之间均匀采样。epsilon(ε)代表加在直线输出上的随机噪声;波浪号表示“服从某个分布”,N表示正态分布,括号里的0是均值,0.3²是方差,所以标准差是0.3。均值为0表示噪声总体不偏向正或负,不意味着这一批抽到的噪声均值恰好为0。这里先认识它如何让点偏离直线,概率分布的系统推导留到后续。

使用随机种子42生成80个样本,打乱后固定48个训练、16个验证、16个测试。seed固定的是特定实现的随机过程;Python与C++使用相同seed不保证产生同一份数据,所以配套程序让C++读取Python导出的同一份CSV。

三档学习率0.01、0.1、1.0都从零参数开始,在训练集最多更新100次。参考实现记录训练和验证轨迹,非有限数会被标记;只有完成并产生有限结果的候选参加选择。数值有限也不等于训练有效,损失巨大但有限的候选仍应如实保留。

使用第100步的验证MSE选择方案,选择后只评估这一模型与训练均值基线在测试集上的MSE。不要用三个测试分数来选学习率。16个测试样本带来较大不确定性,这次实验用于学评估流程,不能证明某个学习率对所有数据最优。

**本课练习:**在记录中指出“哪一行拟合参数、哪一步选择学习率、哪一步首次看测试结果”。再提出一个需要分组而不能随意按行划分的例子,例如同一用户多条记录。第2周再独立重写完整流程。

综合自测 先答后看参考

  1. 预测明天销量时,历史销量、天气预报、明天最终成交金额分别能否作特征?需要说明预测时点。
  2. 3个样本、2个特征时,X、权重和预测的形状分别是什么?本周两个样本的损失又是什么形状?
  3. w、b、学习率和训练次数中,哪些是模型参数,哪些是超参数?
  4. 两个残差为2与−2时,平均残差与MSE分别是多少?哪一个会隐藏预测错误?
  5. w=1、b=0时,本周两个点的损失、w偏导和b偏导分别是多少?请写中间过程。
  6. 为什么w偏导中有x,而b偏导中没有?用链式法则解释。
  7. 已经算出dw后立刻修改w,再用新w计算db,是否与文中的同步更新相同?
  8. 损失整体除以2但学习率不变,一次梯度下降的参数变化会怎样?
  9. 学习率改为1导致损失变大,是否必然说明梯度公式写错?
  10. 把所有训练样本完整复制一遍,MSE与一次全量梯度更新是否改变?如果使用损失之和呢?
  11. SymPy diff、NumPy gradient与PyTorch backward返回或计算的对象有什么区别?本周不使用任何第三方求导库能否训练?
  12. 看完测试误差后决定再换学习率,之后得到的同一测试集分数还可以当作首次独立评估吗?

自测参考与过关方式

已作答,展开参考与过关方式
  1. 历史销量通常可用;天气预报需使用预测时已经发布的版本;明天最终成交金额当时未知,不应作为输入。还需检查特征是否隐含标签。
  2. X为(3,2),权重为(2,),预测为(3,);MSE把所有样本误差汇总成一个标量。标签与预测应逐样本一一对应。
  3. w、b是参数;学习率、训练次数是超参数。参数可以通过学习确定,但决定怎样训练也需要独立验证。
  4. 平均残差0,MSE为4;直接平均残差会因为符号抵消而隐藏错误。
  5. 预测1、2,残差−2、−3,损失(4+9)/2=6.5;w偏导−2×1−3×2=−8,b偏导−2−3=−5。
  6. 预测wx+b对w的导数为x,对b的导数为1;外层平方误差的2e通过链式法则与它们相乘。
  7. 不同。它使用了两个不同位置的梯度分量;应在旧w、b处算好两个偏导再更新。
  8. 梯度与参数变化都减半;对本例普通梯度下降,把学习率乘2才恢复原更新幅度。
  9. 不必然。正确的局部下降方向配上过大步长也会增加损失;本例从零更新得到w=13、b=8,MSE=582.5。
  10. 对同一参数的一次全量更新,MSE及其梯度不变;损失之和及其梯度翻倍。按样本逐步更新时,执行次数也可能改变,要另行讨论。
  11. SymPy生成符号导数表达式,NumPy gradient估计采样值的数值导数,PyTorch backward通过计算图把梯度累积到相应张量。解析手写梯度足以完成本周训练。
  12. 不可以。该测试结果已参与方案选择。可以把它转为开发证据,最终评价需要新的独立数据或明确声明评估已受选择影响。

用三条验收线分别评分:讲解、理解、实践各至少6/8且无0分。主讲解用8–10分钟回答“数据到参数更新再到评估怎样连起来”;实践只要求一种语言的三个核心函数与一次变式正确。运行参考程序是起点,独立补完和解释才是过关证据。

本周已讲授与后续内容的边界

规划目标 对应讲解 验收证据
数据概念与预测任务 第1课的数据表与预测时点 自测1,自己造一个任务
向量与矩阵形状 第1课形状表与3×2练习 自测2,解释一个广播错误
模型与参数 第2课三种预测规则 自测3,说明参数与超参数
损失和基线 第2课逐样本计算,第6课比较 自测4,完整误差表
求导和首次更新 第3、4课推导与程序 自测5至10,梯度核对
编程能力 第5课和辅助文档 一种语言的填空版与变式
训练与泛化 第6课的评估流程 自测12,解释一次结果的范围

第2周进一步学习批量矩阵实现、线性回归的完整优化实验和独立编程;概率分类与交叉熵从第3周开始。2026年10月23日已补充第2–24周交互课程,包括教学正文、分步代码、练习、自测与参考答案。项目中的真实训练与评估仍需自己完成并留下记录。

Python与C++机制示例

下面的小程序验证关键机制;完整项目须按本周交付要求另行完成。

Python

"""Two samples: predict, measure, differentiate, and update. No third-party library."""
samples = [(1.0, 3.0), (2.0, 5.0)]

def predict(x, w, b):
    return w * x + b

def mse(data, w, b):
    total = 0.0
    for x, y in data:
        error = predict(x, w, b) - y
        total += error * error
    return total / len(data)

def gradients(data, w, b):
    dw, db = 0.0, 0.0
    for x, y in data:
        error = predict(x, w, b) - y
        dw += error * x
        db += error
    return 2.0 * dw / len(data), 2.0 * db / len(data)

w, b, alpha = 0.0, 0.0, 0.1
for step in range(3):
    print(f"step={step} w={w:.6f} b={b:.6f} mse={mse(samples,w,b):.6f}")
    if step == 2:
        break
    dw, db = gradients(samples, w, b)
    w, b = w - alpha * dw, b - alpha * db

C++

#include <iomanip>
#include <iostream>
#include <utility>
#include <vector>
using Data = std::vector<std::pair<double, double>>;

double predict(double x, double w, double b) {
    return w * x + b;
}
double mse(const Data& data, double w, double b) {
    double total = 0.0;
    for (const auto& p : data) {
        double error = predict(p.first, w, b) - p.second;
        total += error * error;
    }
    return total / data.size();
}
std::pair<double, double> gradients(const Data& data, double w, double b) {
    double dw = 0.0, db = 0.0;
    for (const auto& p : data) {
        double error = predict(p.first, w, b) - p.second;
        dw += error * p.first;
        db += error;
    }
    return {2.0 * dw / data.size(), 2.0 * db / data.size()};
}
int main() {
    const Data data{{1.0, 3.0}, {2.0, 5.0}};
    double w = 0.0, b = 0.0, alpha = 0.1;
    std::cout << std::fixed << std::setprecision(6);
    for (int step = 0; step < 3; ++step) {
        std::cout << "step=" << step << " w=" << w << " b=" << b
                  << " mse=" << mse(data, w, b) << '\n';
        if (step == 2) break;
        auto g = gradients(data, w, b);
        w -= alpha * g.first;
        b -= alpha * g.second;
    }
}

逐步解释

一条样本怎样进入程序

Python的每个元组保存一对(x,y),C++用pair保存同样的两个数。x是输入,y是目标。这里的数字只是教学样本,不是现实数据。predict输入一个x及当前w、b,返回一个预测数值。

自查:predict(2,2,1)应该返回5;参数和数据有什么不同?

从一行残差到平均损失

遍历样本后,先用预测减标签,再平方并累加。除以样本数只在循环完成后进行。total是浮点数;C++的浮点数除以整数size()仍会进行浮点除法。本例没有额外的1/2系数。

自查:w=b=0时,两个平方残差是9和25,平均是17。

公式里的求和变成两个累加器

同一个残差分别贡献error*x和error。w的偏导多乘x,因为预测wx+b对w求导得到x;对b求导得到1。最后统一乘2/n。返回值的先后顺序固定为w梯度、b梯度。

自查:原点的dw=-13,db=-8。请解释负号代表的局部变化方向。

先观察,再同步更新

第0行输出初始状态。先在旧参数上求出两个梯度,然后更新w、b。C++虽然分成两条赋值,但g已经在旧参数处算完,所以仍是同步梯度下降。输出第2行后停止,恰好完成两次更新。

自查:第二次更新后w=1.71、b=1.05,MSE=0.16925。把alpha改成1时会怎样?

参考输出

step=0 w=0.000000 b=0.000000 mse=17.000000
step=1 w=1.300000 b=0.800000 mse=1.685000
step=2 w=1.710000 b=1.050000 mse=0.169250

练习与参考答案

练习1

基础:用普通循环实现mse,并手算w=1、b=0时的输出。

提示:

先分别算两个预测,再算残差。

残差为−2与−3;平方后最后取平均。

参考:

预测为1、2,残差为−2、−3,MSE=(4+9)/2=6.5。循环体累加error*error,循环结束返回total/len(data)。如果得到13,说明漏掉平均;若得到−2.5,说明没有平方。

练习2

改动:仍从w=1、b=0开始,用0.1做一次同步更新。写出参数与新损失。

提示:

先计算dw=−8、db=−5。

新w=1−0.1×(−8),新b=0−0.1×(−5)。

参考:

w=1.8,b=0.5,预测2.3与4.1,残差−0.7与−0.9,MSE=(0.49+0.81)/2=0.65。两个梯度必须来自同一组旧参数。

练习3

迁移:把数据换成(0,1)、(1,3)、(2,5),从原点手算梯度,再用程序核对。

提示:

n现在是3。

dw=2/3×[−1×0−3×1−5×2]。

参考:

原损失(1+9+25)/3=35/3;dw=−26/3,db=−6。学习率0.1更新后w=13/15≈0.866667,b=0.6。不能继续把2/n当成1;样本数发生了改变。

自测

1. 这里的梯度是对谁求导?

  1. 样本编号
  2. 随机种子
  3. 训练次数
  4. 模型参数w与b

参考:D

损失关于参数的变化率用于更新参数。数学上也可对输入求导,但用途不同。

2. 所有样本完整复制一遍,普通MSE的全量梯度会怎样?

  1. 减半
  2. 必定变成零
  3. 翻倍
  4. 不变

参考:D

求和与样本数同时翻倍,平均及梯度不变;损失之和则不同。

3. 正确的梯度配上很大的学习率,可能发生什么?

  1. 测试集变大
  2. 必定更快收敛
  3. 梯度自动变小
  4. 损失上升

参考:D

梯度描述局部方向,大步跨出局部有效范围后损失可能增大。

4. 用测试分数挑选学习率之后,该测试集是什么状态?

  1. 仍是首次独立评估
  2. 只要固定种子就不受影响
  3. 样本多就不会泄漏
  4. 已参与方案选择

参考:D

选择依赖了测试反馈,最终评价需要新的独立数据,或明确声明选择影响。

开放讲解题

不用背术语,解释一轮机器学习发生了什么。

输入数据经当前模型得到预测;损失衡量预测与标签的差异;梯度给出参数的局部影响;沿负梯度做小步更新。随后用未参与拟合的数据评价效果。训练损失下降只是其中一个观察。

手写梯度、差分、SymPy与PyTorch分别帮了什么忙?

手写梯度把自己推导的公式算成数值;差分用函数两侧值近似导数;SymPy生成符号导数表达式;PyTorch按记录的运算依赖执行链式法则。四者一致还需检查共同使用的损失定义是否正确。

交付物

验收标准

来源与延伸