机器学习是深度学习的地基:从数据到CNN的完整入门

发布时间:2026/9/29 4:56:15
机器学习是深度学习的地基:从数据到CNN的完整入门
我见过太多人学深度学习的路线是这样的先在某个平台上找到一份卷积神经网络的教程跟着敲一遍跑通手写数字识别准确率看着还不错然后就彻底卡住了。换一个数据集准确率掉到随机猜测的水平想改网络结构不知道该动哪一层模型在训练集上表现完美测试集一塌糊涂也说不清问题出在哪。这背后的原因通常不是代码写得不熟而是跳过了机器学习这一层地基直接扑到了深度学习的塔尖上。这篇东西想聊的就是这件被很多人跳过的事机器学习到底是什么它和深度学习是什么关系哪些概念是后面所有模型——从逻辑回归到CNN再到今天各种结构——都必须继承的。无论你是刚接触这一行、准备做第一个项目还是已经能跑通demo但说不清原理我想把这条从数据到结论的完整链条拆开讲一遍。全程说人话尽量把每个为什么都交代清楚而不是甩一堆公式让你自己悟。1. 先把认识猫这件事拆开机器学习到底在解决什么让机器认识猫这句话听起来像个玩具问题但它是理解整个领域的极佳入口。因为它逼着你回答一个根本问题你手里有的到底是什么你想要的到底是什么中间那一步凭什么能成立。把这一步想透后面无论你用CNN还是别的什么结构都只是实现细节。1.1 传统编程和机器学习的分水岭在哪传统编程的思路是人总结规则机器执行规则。比如判断一封邮件是不是垃圾邮件你可以写如果正文出现中奖且包含链接就标记为垃圾邮件。这套逻辑在规则有限、边界清晰的任务上非常好用而且完全可解释出错了直接去改规则就行。可一旦任务变成识别一张图里有没有猫这套思路立刻崩了。你没法写出猫有四条腿、两只耳朵、胡须若干这样的规则——因为照片里的猫可能是背影、可能蜷成一团、可能被遮挡一半光照、角度、品种全都不同。规则写到最后你会发现你写的每一条规则都能被一堆反例打穿。机器学习的思路是把这件事反过来不去总结规则而是给机器一大堆输入—答案的样例让它自己去找出那个映射关系。你给模型几万张标好猫和不是猫的图片它自己调整内部参数最终学到一个函数输入一张图的像素矩阵输出它是猫的概率。这里有个反直觉的点第一次接触的人经常想不明白模型学到的不是猫的本质而是在给定数据分布下能把猫和非猫区分开的统计规律。所以用白猫黑猫训练出来的模型遇到橘猫可能就懵了——这不是模型坏了而是它的经验里没有这一类。理解这一点你就理解了后面所有的数据偏置、泛化、域适应问题。提示判断一个任务该不该用机器学习有个很实用的标准——你能不能轻松写出明确规则能就别用模型规则更快更省。不能且你能拿到大量带答案的样例才轮到机器学习上场。1.2 机器学习的四要素数据、模型、损失、优化不管多复杂的系统落到最底层都是同一个骨架。我把这个骨架拆成四块可以记成一句话用模型去拟合数据用损失衡量差多远用优化把差距调小。数据由一条条样本组成每条样本用一组特征描述还可能有对应的标签。图片任务里特征就是像素值标签就是猫/非猫。模型一个带参数的函数它规定了从特征到预测的计算形式。线性模型是一组权重加偏置神经网络就是一堆线性变换和非线性激活交替堆叠。损失函数一个打分器衡量模型当前预测和真实标签差多少。分类常用交叉熵回归常用均方误差。优化算法一套按什么方向、多大步长去调参数的流程。最主流的就是基于梯度的各种变体。这四块里损失函数的选择往往被新手严重低估。我见过有人做二分类却用均方误差训练也能跑但收敛极慢、概率输出也不校准。分类任务用交叉熵不是习惯问题而是它对应着最大似然估计梯度形式也更干净。选错了你不是调不动而是要走一大段冤枉路。1.3 为什么认识猫这件事离不开标签热词里有个词条是机器学习 认识猫 标签这个组合其实点到了关键。猫和非猫的区分靠的是标签提供的监督信号。没有标签模型没有任何依据知道自己猜对还是猜错参数就没法朝正确方向更新。但标签是有代价的标注图片需要人一张张看贵且慢标注标准还会因人而异——一只模糊的、只露出半张脸的动物算不算猫不同标注者给不同答案模型学到的就是矛盾的信号。这就是为什么数据质量往往比数据数量更决定项目成败。一个我踩过的坑早期做图像分类数据集里混进了一批标注错误的样本比例不到百分之三但模型怎么调都在某个类别上表现异常。把错标样本清出来之后同样的结构和超参准确率直接上了一个台阶。这件事让我彻底改掉了先堆数据再说的习惯先抽样人工过一遍标签质量再谈模型。2. 三条主线监督、无监督、强化学习的边界机器学习不是一种方法而是一大类方法的集合。按监督信号从哪来划分主流分三条线。搞清它们的边界你在面对一个新问题时才能快速判断自己该往哪个方向找工具而不是拿着监督学习的方法硬套一个根本没有标签的场景。2.1 监督学习标签明确但代价也明确监督学习是应用最广的一支特点是每条样本都带标签。它又分两类典型任务任务类型输出形式典型例子常用损失分类离散类别猫/非猫、垃圾邮件识别交叉熵回归连续数值房价预测、销量预测均方误差、绝对误差分类和回归的区别不在模型结构而在输出空间和损失设计。有意思的是同一个网络改一下最后一层和损失就能从分类切到回归这也说明模型和任务是解耦的两件事。监督学习的核心矛盾是标签越精确成本越高。医学影像标注得靠专业医生一小时的标注成本可能是普通图像标注的几十倍。所以实际项目里经常出现折中方案——用少量精标数据加大量弱标数据或者先用规则粗筛再用人工复核。这些做法背后都是在标签成本和模型上限之间找平衡点。2.2 无监督学习没有标签时在做什么无监督学习拿到的只有特征没有答案。它要回答的问题变成了这些数据内部有什么结构。最典型的是聚类把相似的样本归到一起。比如电商里把用户按行为分组你事先并不知道有哪几类人是算法告诉你这批人偏向夜间下单、客单价低你再给这群人起个业务名字。注意这里有个容易混淆的点聚类给出的簇编号本身没有语义第0类是什么含义得靠人去解读算法不负责这件事。另一大类是降维把高维特征压到低维同时尽量保留重要信息。它的价值有两层一是可视化几百维的数据压到二维才能画出来看二是去噪和加速去掉冗余维度后下游模型往往更稳。无监督最容易被高估的地方是评估。监督学习有准确率这种明确指标无监督没有标准答案评估只能靠间接手段——比如把聚类结果拿去跑下游任务看效果是否提升。所以实践中无监督常作为预训练或特征提取的一环很少单打独斗。2.3 强化学习延迟反馈下的决策问题强化学习处理的场景和前两者完全不同没有现成的正确答案只有一个环境智能体做出动作环境给出奖励和新的状态。目标是让长期累积奖励最大化。它的难点在于信用分配——一局棋赢了是哪几步走得好奖励往往在最后才出现中间每一步的贡献都难以直接归因。这也是为什么强化学习训练起来方差极大同样的代码跑两次结果可能差很远随机种子的影响比监督学习里大得多。热词里出现了图强化学习与深度强化学习联邦深度强化学习这些组合词其实反映了一个趋势强化学习本身处理不了高维输入一旦状态是图像或复杂图结构就必须靠深度网络来做函数近似。所以深度强化学习不是两个词的简单拼凑而是用深度学习解决强化学习里的表示问题。把这条依赖关系理顺你就明白为什么这篇要先把机器学习的地基讲清楚。3. 深度学习之前必须吃透的五个经典概念这一节是我认为最不能跳的部分。深度学习的网络可以很深、参数可以上亿但评估和诊断它的那套方法论几乎全部来自经典机器学习。不懂这些你训出来的模型就是个黑箱好坏全靠运气。3.1 泛化误差和经验误差模型到底在背还是在学有两个误差必须分清楚经验误差模型在训练数据上的错误率。泛化误差模型在没见过的数据上的错误率。我们真正关心的是泛化误差但我们能直接算的只有经验误差。这两者之间的差距就是整个机器学习最核心的张力所在。一个能记住所有训练样本的模型经验误差可以是零但泛化误差可能极差——它没有学到规律只是把答案背下来了。这就是过拟合。反过来模型太简单连训练数据都拟合不好叫欠拟合。泛化误差界那套理论热词里提到的泛化误差界想干的事就是用模型复杂度、样本量这些可计算的量去给泛化误差的上界做一个估计。理论本身比较抽象但它给出的直觉非常实用模型容量要和样本量匹配。几万张图配一个上亿参数的网络就需要强正则化或者大量数据增强来兜底否则过拟合几乎是必然的。3.2 偏差与方差诊断模型病根的坐标系偏差和方差是诊断模型问题的两把尺子我把它总结成一张表方便对照症状训练误差验证误差主要问题处理方向欠拟合高高偏差大加容量、加特征、减正则过拟合低高方差大加数据、强正则、早停、简化模型理想低低都小保持这张表的价值在于它把模型效果不好这个模糊判断变成了有方向可查的具体问题。很多新手一看到验证集效果差就狂调学习率但如果训练误差本身就很高那根本是欠拟合调学习率是白费力气。注意判断过拟合不能只看一次训练。至少跑三到五个不同的随机种子看验证指标的波动范围。如果波动比你要优化的提升幅度还大那你调的其实不是模型是噪声。3.3 正则化、交叉验证和数据泄漏正则化的思路是给模型加约束不让它把参数调得过于极端。常见做法有两种一是直接在损失里加参数惩罚项L1、L2二是训练过程中随机丢弃一部分激活Dropout。L2 让权重整体偏小模型更平滑L1 会让部分权重直接变成零自带特征选择效果。交叉验证解决的是数据太少切一次验证集太浪费也不稳定的问题。把数据分成 K 份轮流留一份做验证其余做训练最后取平均。它比单次划分更可靠代价是训练 K 次。数据量充足时没必要用数据紧张时它是救命的。数据泄漏是我认为最隐蔽、危害最大的坑。它的表现是离线指标高得离谱上线后效果断崖式下跌。常见成因包括——在划分训练/验证集之前就做了全局归一化导致验证集的统计信息泄露进训练时序数据随机打乱后划分让模型看到未来特征里混进了标签的衍生字段。这类问题不看指标看不出来只能靠检查数据处理流程。这里要提一下机器学习校准集这个说法。严格讲校准集是在模型训练完之后用来调整输出概率是否与实际频率匹配的一份独立数据。比如模型说80% 概率是猫那在这批样本里就真的应该有约 80% 是猫。如果偏差很大就要做概率校准。它必须和训练集、验证集都独立否则校准结果没有意义。4. 从逻辑回归到CNN深度学习其实没有另起炉灶很多人觉得深度学习是全新的东西和机器学习是两码事。实际上把深度网络拆开看每一层都是经典方法的堆叠。理解这个继承关系你再看各种新结构时就不会觉得它们凭空冒出来。4.1 逻辑回归一个神经元的完整解剖逻辑回归做的是二分类形式上就两步先算线性加权和再过一次非线性函数把结果压到 0 到 1 之间。import numpy as np def sigmoid(z): return 1.0 / (1.0 np.exp(-z)) def forward(x, w, b): z np.dot(x, w) b return sigmoid(z) # 输出可解释为概率这短短几行包含了神经网络里一个完整神经元的全部要素权重、偏置、加权求和、非线性激活。所谓一个神经元就是这套结构的别名。再看它的损失函数——交叉熵def cross_entropy(p, y): eps 1e-12 p np.clip(p, eps, 1 - eps) # 防止log(0) return -(y * np.log(p) (1 - y) * np.log(1 - p))为什么用交叉熵而不是均方误差直观解释是交叉熵对自信地答错惩罚极重。模型说99% 是猫但实际不是猫交叉熵给出的惩罚远大于均方误差梯度信号也更强更干净。如果换成均方误差配合 sigmoid梯度里会多出一个导数因子在输出接近 0 或 1 时会变得极小训练就变得非常慢。4.2 梯度下降与反向传播参数是怎么被调出来的优化的核心思想只有一句话沿着损失下降最快的方向小步移动参数。梯度告诉我们损失对每个参数的敏感程度。学习率决定每一步迈多大。关键细节是学习率比模型结构更能决定训练成败。设太大损失在最低点附近来回跳甚至发散设太小训练慢到你看不出进展。那多层网络里成千上万个参数梯度怎么算答案是反向传播。它本质上是链式法则的高效实现前向计算得到损失然后从输出层往回一层层把梯度传下去。反向传播不是深度学习发明的它只是把微积分的链式法则组织成了一个可复用的计算流程。# 一个最小训练循环的骨架示意 for epoch in range(num_epochs): for xb, yb in dataloader: pred model(xb) # 前向 loss criterion(pred, yb) # 算损失 optimizer.zero_grad() # 清空旧梯度漏了这步梯度会累加 loss.backward() # 反向求梯度 optimizer.step() # 更新参数optimizer.zero_grad()这一步新手最容易漏。PyTorch 默认梯度是累加的不清零的话每步的梯度会越叠越大训练很快失控。这个坑我当年排查了整整一个下午因为损失曲线是慢慢发散而不是直接崩看着特别像学习率的问题。4.3 从全连接到CNN为什么图像任务必须换结构如果用一个全连接网络处理一张 224x224x3 的彩色图输入维度就是 15 万左右。第一层如果有 1000 个神经元光这一层的权重就是 1.5 亿个参数。参数太多直接带来两个后果训练数据远远不够过拟合跑不掉而且完全丢掉了图像的空间结构相邻像素之间的关系被当成独立特征。CNN 用两个巧妙的设计解决这个问题。一是局部连接每个卷积核只看图像的一小块区域二是权重共享同一个卷积核在整张图上滑动。这两点让参数量骤降同时保住了平移不变性——猫在左上角还是右下角卷积核都能识别出来。热词里的深度学习cnn和深度学习算法经常一起出现这里要强调一点CNN 不是卷积这一种操作的集合而是卷积 非线性 池化 全连接的组合模式。理解每一块各自解决了什么问题比记住整体结构更重要。4.4 Epoch、Batch、学习率训练循环里的三个旋钮这三个词被问得最多我用一段话把它们的关系理清Epoch把整个训练集完整过一遍叫一个 epoch。Batch一次前向反向用到的样本数。一个 epoch 里包含的批次数等于总样本数除以批大小。学习率每次参数更新的步长。三者互相牵制。批大小会影响梯度的噪声水平——批太小梯度噪声大可能帮助跳出局部最优但也可能训不稳批太大梯度估计更准但显存吃紧且泛化有时反而变差。常见做法是先固定批大小用学习率预热加衰减的策略比一上来就精调批大小更有效。现象可能原因先动哪个旋钮损失震荡剧烈学习率偏大学习率降到 1/3 再试损失几乎不动学习率偏小或初始化差学习率提一个量级损失平稳但偏高模型容量不足加层或加宽训练好验证差过拟合加增强、加正则、早停5. 把环境搭起来一次可复现的入门实战聊完原理落到实操。热词里深度学习环境配置深度学习环境学校实验室搭建机器学习服务器这些搜索频率很高说明环境这一步确实卡住了大量人。我把流程按依赖顺序梳理一遍重点讲那些文档里不写但实际会卡住你的地方。5.1 环境配置清单与常见坑先说结论一定要用虚拟环境隔离不要往系统 Python 里直接装。# 创建并激活虚拟环境 python -m venv dl-env source dl-env/bin/activate # Windows 用 dl-env\Scripts\activate # 安装核心依赖版本务必对齐 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121 pip install numpy pandas matplotlib scikit-learn三个最容易踩的坑第一驱动、CUDA、框架版本必须三者对齐。很多人装了某个版本的框架后跑起来报CUDA 不可用八成是驱动版本低于框架要求的 CUDA 版本。先用nvidia-smi看驱动支持的版本再去选框架版本顺序不能反。第二不要迷信 pip 装依赖能一次成功。科学计算库之间版本约束很复杂建议固定一个 requirements 文件把版本号写死团队里所有人用同一份。环境不可复现实验就没法对比。第三异构算力环境要留个心眼。如果实验室用的是非主流加速卡先跑一个最小张量运算和一次小规模训练做验证确认基本算子和反向传播都正常再投入正式项目。这类适配问题在正式训练里才暴露的话排查成本会高很多。提示环境配好第一件事写一个五行脚本打印框架版本、是否检测到加速设备、设备名称。把这三行存下来以后任何报错先看它。5.2 数据准备与标签规范模型之外数据准备占了项目里大部分时间。我总结的检查清单标签是否有一致的定义文档同类样本的标注标准要写下来不能靠记忆。类别是否严重不均衡如果某一类只占总量的百分之几准确率这个指标就失去了意义要换成看每一类的召回率。有没有重复样本跨集分布同一张图同时出现在训练集和验证集里指标必然虚高。归一化的均值方差从哪里来只能从训练集统计然后应用到验证集和测试集。关于归一化我再强调一次它的逻辑模型假设输入特征的尺度大致一致否则不同维度的梯度量级差很多优化会偏向尺度大的维度。但统计量绝不能从全量数据算因为那等于把验证集的信息提前告诉模型——这就是典型的数据泄漏。5.3 训练、验证与校准集各自的使用方式数据划分不是随便切三份每份有明确职责数据集用途使用频率训练集更新参数每个 batch验证集选超参、早停、判断过拟合每个 epoch校准集调整输出概率的可靠性训练结束后一次测试集最终评估只能看一次项目收尾验证集和校准集的区别很多人会混。简单说验证集是用来做选择的选哪组超参、什么时候停校准集是用来修概率数值的。两者都必须和训练集独立。还有一个纪律问题测试集只能看一次。如果你反复用测试集调参它实际上就变成了验证集你报出来的最终指标就带了乐观偏差。这个偏差在小数据集上可以大到让你误判方案优劣。6. 从跑通到跑好排查链路与调参经验到这一步模型能跑了但效果平庸。真正区分熟手和新手的是面对效果不行时能不能有条理地定位而不是随机试。我把常用的排查链路整理如下。6.1 损失不下降的五种典型原因按排查顺序排列学习率设置不当。最常见。先做一次学习率扫描从很小的值开始每个 batch 后指数级增大学习率画出损失曲线找下降最快的那一段对应的量级。输入数据没归一化。原始像素值范围 0 到 255直接喂进去梯度会非常不稳定。归一化到 0 到 1 或标准化到零均值。标签编码错误。分类任务里标签必须是 0 到 C-1 的整数索引或正确的独热编码混用了会导致损失从头到尾都是常数。网络结构问题。比如多层线性层之间漏了激活函数整个网络退化成单层线性模型或者初始化方差过大激活值一开始就饱和。梯度消失或爆炸。深层网络常见。检查每层的梯度范数如果接近零就是消失加残差连接或换激活函数如果数值巨大就是爆炸加梯度裁剪。这套顺序是有讲究的从成本最低、最可能的原因查起。学习率和数据归一化检查一遍只要几分钟而改网络结构要重训几小时。6.2 过拟合和欠拟合的现场判断判断的依据是训练误差和验证误差的关系但具体数值要看任务。图像分类里训练准确率百分之九十九、验证百分之七十是明显过拟合两者都在百分之六十是欠拟合。处理过拟合的手段按性价比排序数据增强翻转、裁剪、色彩抖动。几乎零成本效果通常最好。早停验证指标连续若干轮不提升就停并保存最好那一轮的权重。Dropout 和权重衰减常规操作注意 Dropout 只在训练时开启。简化模型前几招都不行再考虑。加数据最有效但最贵。处理欠拟合就比较直接加容量、减少正则强度、训练更久、检查特征是否包含足够信息。如果特征本身没有区分度换再大的模型也没用这时候要回到数据层面找原因。6.3 一些不太写在文档里的经验固定随机种子但不要只信一个种子。调参时固定种子能让对比公平但最终结论要跑三到五个种子取平均否则你优化的可能只是那一次随机初始化的运气。先跑通一个能过拟合的小实验。拿二十张图故意让模型过拟合到接近零损失。如果连这都做不到说明代码有 bug此时调超参毫无意义。这个过拟合小样本测试是我用得最多的调试技巧能快速区分代码问题和参数问题。记录每次实验的完整配置。损失曲线、超参、数据版本、代码提交号。你以为记得住等你做到第三十次实验的时候就完全记不清了最后只能重跑。指标要挑对。类别不均衡看每类召回概率可靠性看校准误差排序任务看排序指标。指标选错优化方向就错而且往往错得不明显。别忽视推理成本。训练时能塞进显存的结构部署时不一定跑得动。如果落地环境算力有限训练阶段就要把模型大小和算子复杂度考虑进去而不是等训练完再压缩。关于深度学习所需要的编程语言我的实际感受是Python 生态最成熟几乎不用犹豫。真正需要投入时间的是数值计算和调试思维语言只是载体。热词里出现机器学习模型可以自己写吗答案是当然可以——上面那段逻辑回归的 numpy 实现就是自己写的。自己实现一遍前向和反向比看十篇博客更能建立直觉但生产环境还是用成熟框架因为要处理数值稳定性、设备调度、分布式这些琐事。最后再分享一个我反复验证过的判断大多数模型效果不行的问题根子在数据和评估而不是模型结构。我遇到过的案例里改数据清洗流程、修正标注标准、补上验证集泄漏带来的提升几乎总是大于换一个更新的网络结构。这个结论在深度学习时代依然成立甚至更成立——模型越大越依赖干净、可靠的数据和评估体系来兜底。如果你正打算入门我的建议顺序是先用手写实现跑通逻辑回归理解损失和梯度再用框架复现一遍把训练循环的每一步对应起来然后找一个小的真实数据集完整走一遍数据清洗、划分、训练、验证的流程最后再去碰 CNN 和各种结构。这条路径看起来慢但每一步都在为后面省时间。