机器学习入门知识骨架与复习清单:从监督学习到神经网络
发布时间:2026/10/30 18:31:37 锦皓数字建站

简介围绕斯坦福大学吴恩达机器学习课程整理的学习包面向希望系统入门并夯实机器学习基础的高校学生、数据科学从业者与自学者。内容覆盖监督与无监督学习、线性回归、逻辑回归、神经网络与反向传播、支持向量机、决策树与随机森林、聚类、降维以及梯度下降、正则化、交叉验证和模型评估等核心主题可用于课程复盘、算法理解与实践准备。压缩包共130个文件约17.21MB以PDF讲义和阅读材料为主辅以JPG/GIF图示、TXT说明、ZIP子包及HTML/CSS页面文件便于按知识点查阅与离线学习。目前已有400人学习下载适合作为课程配套资料帮助读者梳理算法脉络、理解关键概念并积累实践参考。1. 一张图看懂机器学习这门课的知识密度机器学习入门课的第一印象往往是“算法很多、公式很密”真正学完一遍再回头看骨架其实很清楚一条主线、两套评估、三类场景。主线是监督学习从线性回归一路推到逻辑回归和神经网络两套评估是训练误差与泛化误差的区分以及由此长出来的偏差与方差诊断三类场景按数据形态分有标签、无标签、序列决策。几乎所有公式都挂在这根骨架上知道自己在哪个位置推导就不会迷路。适合已经听过一遍课、手里有笔记却串不起来的人也适合正准备复习、想把散点连成面的人。2. 监督学习主线从线性回归到逻辑回归的推导要点监督学习是整个课程的重量所在从最简单的单变量线性回归开始一路推到多分类。这条线上的每一步推导都不是孤立的技术点而是前一步暴露问题后的补丁。复习时如果只背公式很容易出现“每个公式都认识、连起来不知道在干嘛”的状态把每一步的动机记住公式反而不用死记。2.1 假设函数、代价函数与梯度下降三件套任何监督学习模型都可以拆成三件套假设函数描述模型长什么样代价函数描述“错得有多离谱”优化算法描述怎么把错降到最低。线性回归的假设函数是特征的线性组合代价函数是所有样本预测误差的平方和再取平均优化方法是梯度下降。这三件套换个模型就换一套皮但骨架不变后面逻辑回归、神经网络都是在这个框架里换假设函数和代价函数。线性回归的代价函数写成平方误差的均值前面乘 1/2 是为了求导时把平方的 2 消掉让梯度表达式干净。这个 1/2 不影响最优解的位置只影响代价函数的具体数值所以不要拿 J 的绝对大小去比较两个不同定义的模型。import numpy as np def compute_cost(X, y, theta): # X: (m, n1)第一列全是 1对应偏置项 theta[0] # y: (m,)theta: (n1,) m len(y) residual X.dot(theta) - y # 预测值减真实值 J (1.0 / (2 * m)) * residual.dot(residual) return J def gradient_descent(X, y, theta, alpha, iterations): m len(y) J_history [] for _ in range(iterations): residual X.dot(theta) - y # 对 theta_j 求偏导统一写成矩阵形式 gradient (1.0 / m) * X.T.dot(residual) theta theta - alpha * gradient J_history.append(compute_cost(X, y, theta)) return theta, J_history上面两段代码对应课程里最基础的两步算代价、走一步梯度。参数说明上alpha是学习率决定每步迈多大iterations是迭代轮数不是收敛判据真正判断收敛要看J_history是否还在下降。矩阵写法里X.T.dot(residual)一次算出所有参数的偏导比逐参数循环更贴近实际实现也能避免维度写错。梯度下降的更新是同步更新所有参数用同一轮的旧值算完梯度后再一起改不能改完一个立刻用新值算下一个。这个细节在单变量时看不出问题变量一多就会导致结果对不上属于典型的手写实现踩坑点。正规方程是另一条路直接解出解析解不需要选学习率、不需要迭代。代价是要算矩阵逆特征数量大时计算量按三次方增长特征存在线性相关时矩阵不可逆这时要么删冗余特征要么用正则化版本。课程里给的判断是特征数在一万以内可以考虑正规方程再多就老实上梯度下降。2.2 特征缩放与学习率收敛的玄学部分特征尺度差异大是梯度下降收敛慢最常见的原因。一个特征取值在 0 到 1 之间另一个在 0 到 100000 之间代价函数的等高线会被拉成极扁的椭圆梯度下降会在狭长方向来回震荡看起来像不收敛。特征缩放把每个特征拉到大致相同的量级等高线变圆下降路径短很多。常用的做法是均值归一化把特征减均值再除以标准差或极差。目标不是严格落在 0 到 1而是大致落在负一到一附近量级差别不大就行。复习时容易忽略的一点是缩放参数必须只用训练集算出来然后原样应用到验证集和测试集否则会引入数据泄漏验证结果会虚高。学习率的调试有个朴素方法固定迭代次数画代价函数随迭代次数的曲线。曲线持续下降但很缓说明学习率偏小曲线上下震荡甚至上升说明学习率偏大需要往下调。常见的尝试顺序是按三倍或十倍量级跳比如 0.001、0.003、0.01、0.03、0.1找到能稳定下降的最大值附近。代价函数曲线在若干次迭代后变平不等于模型已经训好只说明在当前学习率下参数更新幅度变小了。想确认是否真的收敛要看梯度范数是否接近零而不是只看 J 的绝对值小不小。这个区别在后面判断欠拟合和过拟合时还会用到。2.3 逻辑回归从决策边界到代价函数为什么不能平方逻辑回归虽然名字里带回归做的是分类。假设函数在线性组合外面套一个 sigmoid 函数把输出压到 0 到 1 之间解释成“属于正类的概率”。阈值 0.5 只是默认值不是模型的一部分调整阈值改变的是精确率和召回率的平衡不是模型本身。决策边界是假设函数等于 0.5 时对应的那條线由参数决定和训练数据的分布没有直接关系。数据集里两类点分得开不开决定的是能不能找到好的参数边界画在哪里是参数说了算。复习时把这两件事混在一起就会误以为数据线性不可分时逻辑回归一定失效。逻辑回归的代价函数用对数损失而不是平方损失。原因不是平方损失不能算而是平方损失套上 sigmoid 之后关于参数是非凸的梯度下降容易停在局部极小。对数损失保证了代价函数是凸的梯度下降能走到全局最优。这个动机比公式本身更值得记。def sigmoid(z): # 防止 exp 溢出对极端值做截断是工程上的常规做法 return 1.0 / (1.0 np.exp(-np.clip(z, -500, 500))) def logistic_cost(X, y, theta): m len(y) h sigmoid(X.dot(theta)) # 加极小值避免 log(0) eps 1e-12 J -(1.0 / m) * (y.dot(np.log(h eps)) (1 - y).dot(np.log(1 - h eps))) return J对数损失的梯度形式和线性回归长得几乎一样都是“预测减真实再乘特征”区别只在预测值经过了 sigmoid。这个巧合让很多人误以为两者可以互换实际上代价函数不同最优解的含义也不同。逻辑回归输出的是概率线性回归输出的是连续值混用会让评估指标失去意义。多分类用一对多策略为每个类别训练一个二分类器预测时取输出概率最大的那个类别。这个方法简单、可并行类别数不多时够用。类别之间互斥且数量大时softmax 更合适但它已经不是基础课程的主线内容复习时知道有这个替代方案即可。3. 模型评估与正则化偏差方差、学习曲线怎么读模型训出来能拟合训练集不代表能用。评估这一块解决的就是“怎么知道模型在新数据上还行”以及“效果不好时该往哪个方向调”。这部分内容在课程里篇幅不算最大但对实际项目的影响最大复习时值得单独拎出来过一遍。3.1 训练集/验证集/测试集与诊断流程数据划分的常见比例是 60/20/20数据量大时验证集和测试集的比例可以更小。验证集用来选超参数、选模型结构、选正则化强度测试集只在最后用一次用来估计泛化误差。用测试集反复调参等于把测试集变成了验证集报出来的数字会偏乐观这是最典型的评估污染。诊断流程有个固定顺序先实现一个能跑通的简单版本哪怕效果一般再画学习曲线判断是偏差问题还是方差问题最后按判断结果决定加特征、加数据还是调正则化。跳过第一步直接上复杂模型往往连问题出在哪都说不清。误差分析是另一个容易被跳过的步骤。人工看一遍被分错的样本统计错误类型分布往往能发现某几类样本占了错误的大头针对性补数据比盲目调模型有效得多。课程里给的建议是先做快速实现、再做误差分析、最后才优化顺序反了会浪费大量时间。3.2 偏差与方差学习曲线告诉你的四件事高偏差对应欠拟合训练误差和验证误差都高且两者很接近高方差对应过拟合训练误差低、验证误差明显高两者之间有明显间隙。这两个判断不看绝对数值看的是两条误差曲线的相对位置和随样本量变化的趋势。学习曲线横轴是训练样本数纵轴是误差。高偏差时增加训练样本对验证误差的改善很有限曲线很快变平高方差时增加训练样本能让验证误差持续下降两条曲线逐渐靠近。这个区别直接决定了对策高偏差加样本没用得加特征或换更复杂的模型高方差加样本有用或者减特征、加正则化。症状训练误差验证误差两者差距优先对策高偏差高高小加特征、加多项式项、减小正则化高方差低高大加样本、减特征、增大正则化刚好低低小保持关注数据质量这张表的用法不是对号入座就完事而是先定位症状再选对策。现实里更常见的是两者兼有验证误差高同时训练误差也没低到哪去这时要先降偏差把模型能力提上来再处理方差。顺序搞反会在一个本身欠拟合的模型上拼命加正则化越调越差。提示判断偏差方差之前先确认训练误差的计算方式和验证误差一致比如是否都包含正则化项、是否都做了同样的预处理。口径不一致时两条曲线没有可比性。3.3 正则化与正则化参数的选择正则化的作用是把参数压小降低模型对个别特征的敏感度从而缓解过拟合。线性回归里加参数平方和逻辑回归里同样加神经网络里每一层的权重矩阵都加。正则化项不含偏置项因为偏置只控制整体平移不影响模型的复杂度。正则化强度由参数控制太大时所有参数被压到接近零模型退化成常数预测训练误差和验证误差都高表现成欠拟合太小时起不到约束作用过拟合照旧。选择的方法是在验证集上扫一组候选值取验证误差最低的那个不要用测试集选。def regularized_cost(X, y, theta, lam): m len(y) # theta[0] 是偏置项不参与正则化 reg (lam / (2.0 * m)) * theta[1:].dot(theta[1:]) return compute_cost(X, y, theta) reg def regularized_gradient(X, y, theta, lam): m len(y) residual X.dot(theta) - y grad (1.0 / m) * X.T.dot(residual) # 只对非偏置项加惩罚偏置项梯度保持原样 grad[1:] (lam / m) * theta[1:] return grad代码里两个细节值得注意正则化项除以样本数 m是为了让惩罚强度不随样本量剧烈变化偏置项单独排除是因为把它也压小只会让模型整体偏移不解决过拟合。这两点在手写实现时最容易被漏掉漏了之后表现是“正则化加了但没效果”或者“模型怎么调都欠拟合”。正则化和特征缩放是绑定的。特征量级差异大时同样的正则化强度对不同特征的实际惩罚不一样大尺度特征的参数被压得相对更狠等于给特征加了隐式权重。所以做正则化之前先把特征缩放到同一量级两者要一起做。4. 神经网络与无监督学习从反向传播到 K-means监督学习的主线推到神经网络本质上还是三件套的延伸只是假设函数变成了多层复合代价函数依然是对数损失优化依然靠梯度下降。无监督学习换了问题设定没有标签目标变成找结构。这两块内容在课程里位置靠后但复习时不能只记结论尤其是反向传播的维度关系和 K-means 的初始化出错概率很高。4.1 神经网络结构、前向传播与反向传播的维度对齐神经网络的结构由层数和每层单元数决定。输入层单元数等于特征维度输出层单元数等于类别数隐藏层数量和每层单元数是超参数。前向传播就是逐层做线性组合加激活函数把上一层的输出当作下一层的输入直到输出层给出预测。def forward(X, Thetas): # Thetas: 每层的权重矩阵列表形状 (out_dim, in_dim1) activations [X] a X for i, theta in enumerate(Thetas): a np.hstack([np.ones((a.shape[0], 1)), a]) # 补一列偏置 z a.dot(theta.T) a sigmoid(z) if i len(Thetas) - 1 else sigmoid(z) activations.append(a) return activations前向传播写出来不长但维度是最容易翻车的地方。权重矩阵的形状是“输出单元数 × 输入单元数加一”转置之后才能和补了偏置的激活值相乘。把形状记成“行是输出、列是输入”比记公式更不容易错。反向传播的核心是误差项的递推输出层的误差是预测减真实隐藏层的误差由后一层的误差乘权重再乘激活函数的导数得到。每一层的误差项维度必须和该层激活值维度一致这个一致性检查能在写代码前就抓出大部分维度错误。注意反向传播的公式推导可以慢慢补但维度对齐必须先对。维度不对时很多时候不会报错只会算出看似合理但完全错误的结果属于最难排查的一类问题。4.2 训练神经网络的工程细节初始化、梯度检验、随机失活参数初始化不能全设成零。全零时同一层的所有单元在前向传播中输出相同反向传播中梯度也相同训练多少轮都保持对称等于这一层只起了一个单元的作用。正确做法是随机初始化把权重取成接近零的小随机数打破对称性。梯度检验用来验证反向传播实现是否正确。做法是用数值方法近似计算梯度和解析梯度比较相对误差。相对误差在十的负七次方量级以下说明实现基本正确负五次方以上就要怀疑有 bug。关键是梯度检验只在调试时开正式训练必须关掉否则每一轮都要多算两倍的前向传播慢得没法用。def numerical_gradient(cost_fn, params, eps1e-4): # 只用于调试正式训练关闭 grad np.zeros_like(params) for i in range(len(params)): plus params.copy(); plus[i] eps minus params.copy(); minus[i] - eps grad[i] (cost_fn(plus) - cost_fn(minus)) / (2 * eps) return grad def relative_error(g1, g2): return np.linalg.norm(g1 - g2) / (np.linalg.norm(g1) np.linalg.norm(g2) 1e-12)这段代码的意思是逐参数扰动用中心差分近似偏导。参数多时很慢所以实际只在小型网络上验证或者只抽一部分参数检查。检验之前记得把正则化项也算进代价函数否则数值梯度和解析梯度的口径不一致会误判成实现有错。随机失活在训练时按概率随机把一部分隐藏单元的输出置零相当于每次迭代训练一个不同的子网络推理时用完整网络并做相应缩放。它的效果类似集成学习能缓解过拟合。训练和推理的行为不一致是它的特点不是 bug忘记在推理时关掉失活才是 bug。训练集要打乱。按类别顺序喂数据会让梯度方向在批次之间剧烈摆动收敛变慢甚至震荡。打乱之后每个批次的分布更接近整体分布梯度估计更稳。这个操作成本很低但漏掉的人不少。4.3 无监督学习K-means、PCA 与异常检测的边界K-means 是迭代两步先把每个样本分给最近的簇中心再用每簇样本的均值更新中心。两步交替直到分配不再变化。它对初始化敏感随机选点可能收敛到局部最优常规做法是多次随机初始化取代价函数最小的那次结果。簇数 K 的选择没有标准答案。肘部法看代价函数随 K 变化的拐点拐点不明显时这个方法就失效。更实际的做法是结合业务含义定 K或者用轮廓系数之类的指标辅助。复习时不要把肘部法当成通用解法它只是一个启发式手段。PCA 做的是降维先对数据做均值归一化再求协方差矩阵的特征向量取前若干个主成分做投影。主成分数量可以按保留方差的比例来定常见目标是保留 99% 的方差。PCA 的前提是数据已经缩放否则量级大的特征会主导主成分方向降维结果没有意义。异常检测和高斯分布绑定对每个特征估计均值和方差算样本的概率密度低于阈值判为异常。阈值用验证集上的 F1 分数来选不要拍脑袋定。数据严重偏斜时准确率完全不能反映效果必须看精确率和召回率。4.4 推荐系统与大规模数据的一点常识推荐系统用协同过滤从用户对物品的评分矩阵出发学习用户偏好向量和物品特征向量用两者内积预测缺失评分。冷启动用户没有任何评分时用均值归一化把该用户的预测拉回全局均值附近避免预测出无意义的零分。大规模数据的训练策略是换优化方法。批量梯度下降每轮要扫全部样本数据量大时一轮都跑不完随机梯度下降每次只用一个样本速度快但梯度噪声大小批量梯度下降折中是实际最常用的做法。在线学习进一步把模型做成持续更新适合数据流式到达的场景。提示随机梯度下降的学习率通常要随迭代衰减否则后期会在最优点附近持续震荡。衰减策略没有统一最优解常见做法是按轮数线性或指数衰减。5. 易错点清单五个最容易翻车的地方这一章单独拎出来是因为下面这几条不是知识点不会而是会了也照样错。它们共同的特征是“看起来对、跑起来也不报错”只能靠流程约束避免。5.1 把代价函数收敛当成模型变好易漏点看到代价函数曲线变平就认为训练完成、模型可用。为什么漏代价函数只反映训练集上的拟合程度它在下降说明优化在推进不说明泛化能力在提升。过拟合时训练代价可以降得很低验证误差却在上升。怎么补每次看训练曲线同时看验证误差曲线两条一起判断。训练代价下降而验证误差抬头就是过拟合的信号该停下来调正则化或减特征了。5.2 用测试集调超参数易漏点反复在测试集上试不同配置取测试分数最高的那个。为什么漏这样操作时测试集事实上承担了验证集的角色报出来的分数是对“测试集加调参过程”的乐观估计换一批数据就掉下来。怎么补把数据切成三份调参只看验证集测试集只在最终确定方案后跑一次。如果数据量实在小用交叉验证在训练集内部做选择测试集依然只碰一次。5.3 正则化漏掉偏置项或漏做特征缩放易漏点正则化项把偏置项也算进去或者特征没缩放就直接加正则化。为什么漏代码里直接对整个参数向量求平方和写起来最省事特征缩放和正则化在课程里是两节复习时容易当成两个独立知识点。怎么补正则化只作用于非偏置参数实现时显式排除下标为零的项做正则化之前先完成特征缩放两者绑定执行形成固定顺序。5.4 逻辑回归的阈值和类别不平衡混为一谈易漏点类别比例悬殊时仍然用准确率和 0.5 阈值评估逻辑回归。为什么漏准确率直观、好算默认阈值 0.5 也是课程里最先出现的设定容易形成惯性。怎么补先看类别分布明显不平衡时改用精确率、召回率和 F1阈值根据业务对两类错误的不同容忍度来定用验证集扫一遍候选阈值而不是固定 0.5。5.5 梯度检验只做一次或忘记关闭易漏点训练前跑一次梯度检验通过之后改了网络结构不再检验或者检验开着忘了关。为什么漏检验通过给人“已经验证过”的安全感但结构、激活函数、正则化项任何一处改动都会让之前的结论失效。怎么补每次改动网络结构或代价函数后重新做一次梯度检验把检验写成一个默认关闭的开关训练入口显式关掉避免带着它跑完整训练。6. 复习清单把公式变成可执行的检查表复习到这个阶段公式推导应该已经过了一遍剩下的问题是“上了考场或者上了项目怎么保证不漏”。我的做法是把整门课压缩成一张可勾选的检查表按流程顺序排而不是按章节顺序排。按章节排的清单只能帮你回忆内容按流程排的清单能帮你在动手时定位。阶段检查项判断标准数据准备特征是否缩放各特征量级接近缩放参数只来自训练集数据准备数据划分是否独立验证集调参测试集只评估一次模型建立先跑通简单版本有基线结果能算训练误差和验证误差诊断偏差方差定位两条误差曲线的相对位置和间隙大小调优正则化强度在验证集上扫候选值偏置项不参与调优学习率代价曲线稳定下降不震荡不爬升神经网络初始化随机小值不全零神经网络维度对齐每层误差项维度等于该层激活维度神经网络梯度检验相对误差在负七次方量级训练时关闭评估指标选择类别不平衡时用精确率/召回率/F1这张表里最容易被跳过的是“先跑通简单版本”这一行。很多人一上来就搭复杂模型跑不通时无法判断是数据问题、实现问题还是模型能力问题只能挨个试时间全耗在排查上。先有一个能算误差的基线后面每一步改动都有参照问题定位会快很多。另一个值得单独练的动作是手写一遍梯度下降和反向传播的维度检查。不需要写完整实现只写形状推导拿纸笔把每层的输入维度、输出维度、权重形状、误差项形状列出来对照代码检查。这个动作十分钟能做完但能挡掉大部分运行时才暴露的错误。# 维度自检把每层形状打印出来和手推结果对照 def check_shapes(layer_sizes): # layer_sizes 形如 [输入维度, 隐藏层1, 隐藏层2, 输出维度] for i in range(len(layer_sizes) - 1): in_dim, out_dim layer_sizes[i], layer_sizes[i 1] print(f层 {i}: 权重形状 ({out_dim}, {in_dim 1}), f激活形状 (m, {in_dim}), 误差形状 (m, {out_dim}))这段代码不参与训练只是把维度关系打印出来对照。参数说明上layer_sizes的第一项是特征数最后一项是类别数中间是隐藏层单元数。把这个函数放在网络定义之后、训练之前调用一次维度错误基本当场暴露不用等到反向传播报错或者算出离谱结果才发现。最后说一个我自己的习惯。每次复习完一个模块我会合上笔记在白纸上默写这个模块的“输入、输出、代价函数、更新规则、常见失败模式”五项写不出来的那一项就是没真掌握的地方回去只看那一节。这个方法比从头再读一遍快得多也更能暴露“看着眼熟其实不会”的状态。从那以后我每次准备复习都强制先默写再翻书顺序反了就会产生已经学会的错觉。希望帮到你。这份笔记的完整版整理成了可打印的文档按章节分块、带检查表和代码片段需要的话可以拿去对着自己的进度逐项过一遍。本文还有配套的精品资源点击获取
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。