面试八股——机器学习
基础概念
监督学习、半监督学习和无监督学习
1. 监督学习 (Supervised Learning)
- 核心特点:数据既有特征(Features),也有标签(Labels)。即每个 $X$ 都有对应的 $Y$。
- 工作原理:模型通过学习输入 $X$ 到输出 $Y$ 的映射关系,来预测未知数据。
- 经典任务:
- 分类 (Classification):预测离散值(如垃圾邮件分类、多模态暴力行为检测)。
- 回归 (Regression):预测连续值(如股票/期货价格预测)。
2. 无监督学习 (Unsupervised Learning)
- 核心特点:数据只有特征(Features),没有标签(Labels)。只有 $X$,没有 $Y$。
- 工作原理:模型不依赖外界引导,而是依靠算法自身去挖掘数据的内在结构、相似性或潜在模式。
- 经典任务:
- 聚类 (Clustering):把相似的数据聚集在一起(如 K-Means、用户画像分群)。
- 降维 (Dimensionality Reduction):压缩数据特征,去除冗余(如 PCA、t-SNE)。
- 自监督学习 (Self-Supervised Learning):现代大模型(LLM)基座预训练的核心。本质上是从无标签数据中自己构造标签(比如掩码语言模型 Masked LM,抠掉一个词让模型预测,这个词就是标签)。
3. 半监督学习 (Semi-Supervised Learning)
- 核心特点:介于两者之间。通常是极少量的标注数据 + 大量的无标注数据。
- 为什么需要:在实际工程中,标注数据极其昂贵且耗时,而无标注数据极易获取。半监督学习旨在利用海量无标注数据包含的分布信息,来辅助提升小规模标注数据的分类性能。
- 常见方法:
- 伪标签 (Pseudo-Labeling):先用标注数据训练一个基础模型,用它去预测无标签数据,把置信度高的预测结果当做“真标签”喂回模型重新训练。
- 一致性正则 (Consistency Regularization):对同一个无标签输入做不同的数据增强(如加噪声),约束模型的输出保持一致。
机器学习任务
监督学习任务:
- 分类 (Classification):目标变量是离散的标签。
- 二分类:判断邮件是否为垃圾邮件、判断文本是否包含暴力行为。
- 多分类/多标签:图像物体识别、给一篇文章贴多个领域标签。
- 回归 (Regression):目标变量是连续的数值。
- 预测未来走势:如房价预测、股票/期货价格预测。
无监督学习任务:
- 聚类 (Clustering):无监督地将相似样本归为一类(如 K-Means、层次聚类)。
- 降维 (Dimensionality Reduction):在高维特征空间中提炼低维特征(如 PCA、t-SNE),常用于特征降噪和数据可视化。
- 异常检测 (Anomaly Detection):寻找与绝大多数数据显著不同的极少数样本(如信用卡盗刷、工业设备故障检测)。
常见的损失函数
一、 回归任务(Regression Loss)
用于预测连续数值(如房价预测、期货价格走势)。
1. MSE (Mean Squared Error) 均方误差 / $L_2$ 损失
公式:
特点:对异常值(Outliers)极其敏感。因为平方项的存在,如果一个样本预测偏了,误差会被无限放大。
缺点:如果数据集中有很多脏数据(噪声),模型会被异常值带偏。
2. MAE (Mean Absolute Error) 平均绝对误差 / $L_1$ 损失
公式:
特点:对异常值具有很强的鲁棒性(Robust),误差的影响是线性的。
缺点:在 $y = \hat{y}$ 处(即误差为0的点)不可导,在训练后期(接近最优点时)可能会在最小值附近震荡,不易收敛。
3. Huber Loss (平滑的 $L_1$ 损失)
- 核心思想:结合了 MSE 和 MAE 的优点。
- 工作机制:当误差较小时,使用 MSE(保证梯度平滑、快速收敛);当误差较大(遇到异常值)时,自动切换为 MAE(降低敏感度,保护模型)。
二、 分类任务(Classification Loss)
用于预测离散的类别标签。
1. 二分类交叉熵损失 (Binary Cross-Entropy, BCE)
公式:
适用场景:判断题(是/否),或者多标签分类(一个样本可以同时属于多个独立类别)。
搭配激活函数:网络最后一层通常搭配 Sigmoid,将输出映射到 $(0, 1)$ 区间。
2. 多分类交叉熵损失 (Categorical Cross-Entropy, CCE)
公式:
(其中 $C$ 为类别总数)
适用场景:单选多分类(如经典的 MNIST 手写数字识别 0~9,或是判别一段文本是否属于暴力行为)。
搭配激活函数:网络最后一层必须搭配 Softmax,使所有类别的预测概率之和等于 1。
偏差(Bias)与方差(Variance)
欠拟合对应“高偏差,低方差”。模型本身偏离了真实规律,但由于简单,在不同数据集上表现都很稳定的差。
过拟合对应“低偏差,高方差”。模型对训练集拟合得极好(偏差低),但因为对数据太敏感,换一个数据集它的预测结果就会发生剧烈抖动(方差高)。
如何应对过拟合问题?
1. 数据层面 (Data Level)
- 增加训练数据量:这是解决过拟合最直接、最根本的手段。数据量足够大、覆盖面足够广时,模型就很难“死记硬背”噪声。
- 数据增强 (Data Augmentation):如果无法获取新数据,可以通过对现有数据进行变换(如图像旋转、裁剪、NLP中的同义词替换、多模态中引入轻微干扰)来人为制造“新数据”,提高模型的鲁棒性。
2. 模型架构与复杂度层面 (Model Level)
- 降低模型复杂度:减少神经网络的层数(Depth)或隐藏单元数(Width),或者在使用传统机器学习(如决策树)时限制树的深度。
- 引入正则化 (Regularization):
- $L_1$ 正则化 (Lasso):在损失函数中加入权重绝对值之和($\lambda \sum |w|$),会使不重要的参数变为 0,从而产生稀疏解,起到特征选择的作用。
- $L_2$ 正则化 (Ridge / 权重衰减):在损失函数中加入权重平方和($\frac{\lambda}{2} \sum w^2$),惩罚过大的权重值,让模型的参数分布更平滑,防止个别特征权重过大。
- Dropout (深度学习特有):在每次前向传播时,随机让一定比例(如 50%)的神经元失活(输出置零)。强制网络不能依赖某几个特定的神经元组合,从而学习到更具鲁棒性的集成特征。
3. 训练策略层面 (Optimization Level)
- 早停法 (Early Stopping):在训练过程中同时监控验证集的 Loss。当发现训练集 Loss 还在下降,但验证集 Loss 已经开始不降反升时,立即终止训练,保存验证集效果最好的那一代参数。
- 交叉验证 (Cross-Validation):如 K-Fold 交叉验证,确保评估结果不受单一特定划分的测试集影响,让调参和模型选择更准确。
- 集成学习 (Ensemble Learning):将多个基模型的预测结果进行组合(如 Bagging 算法、Random Forest),利用“集体智慧”抵消单个模型可能产生的过拟合风险。
正则化
什么是正则化?
定义:正则化是指在机器学习模型的目标函数(Loss Function)中引入额外约束/惩罚项的技术。
机器学习/深度学习中常见的正则化方法
在面试中,建议将方法划分为传统数学惩罚和现代深度学习策略两部分来作答。
1. 传统数学惩罚项(在原 Loss 后面直接加项)
① $L_1$ 正则化 (Lasso 回归)
做法:在损失函数后面加上所有权重参数的绝对值之和。
作用与特点:会产生稀疏解(Sparse Solution)。它会无情地将很多不重要特征的权重直接削减为 0。
面试金句:“$L_1$ 正则化自带特征选择(Feature Selection)功能。” 因为在几何上,$L_1$ 的等高线是一个带尖角的方形,原 Loss 极值通常会在坐标轴(即某个 $w=0$ 的地方)与它相交。
② $L_2$ 正则化 (Ridge 岭回归 / Weight Decay 权重衰减)
做法:在损失函数后面加上所有权重参数的平方和。
作用与特点:会产生平滑解。它不会把权重减到 0,而是倾向于让所有的 $w$ 都尽可能地接近 0 但不等于 0(惩罚大权重)。
面试金句:“$L_2$ 正则化让模型参数分布更均匀,避免单个特征独大。” 当输入发生轻微扰动时,因为 $w$ 都很小,输出就不会产生剧烈震荡,从而降低了方差。
梯度下降有哪些变体?
1. 批量梯度下降 (Batch Gradient Descent, BGD)
- 工作机制:每次更新参数时,使用整个训练集的所有样本来计算梯度。
- 优点:梯度的计算方向非常准,由于利用了全量数据,曲线下降过程非常平滑,只要学习率合适,一定能收敛到全局最优(凸问题)或局部最优(非凸问题)。
- 缺点:太慢了! 如果数据集有几百万条,每更新一次参数都要把所有数据算一遍,算力和内存/显存根本吃不消。
2. 随机梯度下降 (Stochastic Gradient Descent, SGD)
- 工作机制:每次更新参数时,随机抽取一个样本来计算梯度并更新。
- 优点:计算速度极快,内存占用极小。由于单个样本具有随机性,它的梯度方向总是“晃晃悠悠”的,这种随机噪声反而有助于模型跳出某些局部最优解或鞍点。
- 缺点:准确度低。即使到了山谷底部,它也不会安分停下,而是在最低点附近剧烈震荡,很难达到完美的收敛状态。
3. 小批量梯度下降 (Mini-batch Gradient Descent)
- 工作机制:前两者的折中。每次更新参数时,使用一小批样本(一个 Batch,如 32, 64, 128, 256)来计算梯度。
- 现代深度学习的标准做法:
- 融合了 BGD 的稳定:利用 Batch 数据的平均梯度,方向比纯 SGD 稳定得多,曲线相对平滑。
- 融合了 SGD 的高效:不需要载入全量数据,可以完美利用 GPU 的矩阵并行计算能力。
线性与概率模型
线性回归
1. 建立模型方程
对于一个多特征的样本 $X = [x_1, x_2, …, x_d]^T$,模型通过赋予每个特征不同的权重 $w$,再加上一个偏置 $b$,来计算出预测值 $\hat{y}$:
2. 定义损失函数:最小二乘法 (OLS)
我们如何评价这条“线”画得好不好?标准做法是计算均方误差(MSE)。我们希望所有样本的预测值与真实值之间的平方差之和最小:
注:为什么要用平方?一是为了消去正负号的影响,二是平方项在数学上处处可导,非常方便计算。
3. 参数求解(怎么找到最完美的 $w$ 和 $b$)
在面试中,求解方法一定要答出以下两条完全不同的路径:
路径 A:闭式解(解析解)—— 矩阵直接求导
将一整套数据集写成矩阵形式,对损失函数求偏导并直接令偏导等于 0。在数学上可以一步到位直接推导出最优解公式:
- 面试追问点:只有当 $X^T X$ 满秩且可逆时,才能用这个公式。如果特征之间高度相关(多重共线性),矩阵就会不可逆。此时必须引入 $L_2$ 正则化(岭回归)来强制使其可逆。
路径 B:数值解 —— 梯度下降法
当特征维度或数据量极端庞大时(比如大模型和现代深度学习场景),矩阵求逆的计算复杂度极高($O(d^3)$)。此时我们会转而采用梯度下降法,顺着梯度的反方向一步步更新 $W$ 和 $b$,直到模型收敛。
线性回归(Linear Regression)和逻辑回归(Logistic Regression)
| 维度 | 线性回归 (Linear Regression) | 逻辑回归 (Logistic Regression) |
|---|---|---|
| 任务本质 | 回归(Regression)任务。 | 分类(Classification)任务。 |
| 输出形式 | 连续值。范围为 $(-\infty, +\infty)$(如预测房价、股票价格)。 | 离散值/概率值。范围严格限制在 $(0, 1)$ 之间,表示属于某一类的概率。 |
| 激活函数 | 无(或者说是线性的 $f(x)=x$)。 | Sigmoid 函数(将输出映射到概率区间)。 |
| 损失函数 | 均方误差 (MSE) / 最小二乘法。 | 交叉熵损失 (Cross-Entropy) / 负对数似然。 |
在数学和逻辑上,逻辑回归本质上是在线性回归的基础上套了一层“外壳”。
逻辑回归分别是怎样处理二分类问题和多分类问题的?
直接升级为多项逻辑回归(Softmax 回归)
这是最本质、最优雅的扩展方式。当二分类的逻辑回归遇到多分类时,Sigmoid 函数会直接升级为 Softmax 函数。
机制:
模型不再只有一根线性输出线,而是针对 $K$ 个类别分别拉出 $K$ 根线,计算出 $K$ 个类别的得分:$[z_1, z_2, …, z_K]$。
使用 Softmax 函数 将这 $K$ 个得分进行归一化,转化为一个概率分布:
Softmax 的魔法在于:所有类别算出来的概率之和严格等于 1。模型最终选择概率最大的那个类别作为预测结果。
极大似然估计(MLE)
“简单来说,极大似然估计就是利用已经发生的事实(数据),去反推最有可能导致这个事实发生的一组模型参数(权重 $w$)。”
- 传统概率:已知参数(比如硬币是均匀的),去预测未来的结果(抛 10 次大概有 5 次正面)。
- 极大似然:结果已经摆在桌子上了(抛了 10 次硬币,结果 9 次正面 1 次反面),现在我们要反推参数(这枚硬币大概率被灌铅了,正面概率 $w = 90\%$ 左右最合理)。
准备工作:设定场景与符号
假设我们手头有一个二分类数据集,样本之间是独立同分布 (i.i.d.) 的。
- 每个样本的真实标签 $y_i \in {0, 1}$。
- 模型预测它为 1 的概率为 $p_i$(在逻辑回归中 $p_i = \sigma(w^T x_i)$)。
- 那么,模型预测它为 0 的概率自然就是 $1 - p_i$。
我们可以把这两个情况合并成一个优雅的单一样本概率公式(伯努利分布的概率质量函数):
小思考:验证一下这个公式。如果真实标签 $y_i = 1$,代入后半部分变成 $(1-p_i)^0 = 1$,整体就剩 $p_i^1 = p_i$;同理,若 $y_i = 0$,整体就剩 $1-p_i$。非常完美。
数学推导三步走
现在我们要利用这个单一样本的概率,去反推最完美的权重 $w$。
第一步:构建似然函数 $L(w)$ —— 求总概率
由于所有样本相互独立,这 $n$ 个样本同时发生的“总概率”,就是把所有单一样本的概率全部乘起来:
这个 $L(w)$ 就是似然函数。我们的终极目标是找到一个 $w$,让这个连乘的总概率最大。
第二步:取对数 $\ln$ —— 连乘变连加
直接对连乘求导会触发数学灾难(高阶乘积求导极其复杂),而且计算机会发生浮点数下溢。所以我们两边同时取自然对数 $\ln$:
根据对数的性质 $\ln(a \cdot b) = \ln a + \ln b$ 以及 $\ln(a^b) = b \ln a$,我们可以把连乘的大括号拆开,变成连加:
这就是著名的对数似然函数 (Log-Likelihood)。
第三步:求偏导并令其为 0 —— 寻找极值点
为了让总概率最大,我们需要对权重 $w$ 求偏导。这里需要用到高等数学的链式求导法则(由于 $p_i$ 内部含有 $w$):
在传统的统计学中,我们解出这个方程,得到的 $w$ 就是极大似然估计值。
交叉验证
拆解 K 折交叉验证的工作原理(以 5 折为例)
正如你所说,它的标准执行步骤非常具有仪式感,我们可以通过图解和“轮班制”来理解:
- 第一步(分块):把原始数据集随机打乱,并平均分成 $K$ 个互不重叠的块(Folds)。比如我们选 $K=5$,数据集就被均分为 块1、块2、块3、块4、块5。
- 第二步(轮流站岗):我们要进行 $5$ 轮训练和测试。
- 第 1 轮:拿 块1 作为验证集,剩下的 块2, 3, 4, 5 合并作为训练集。训练模型,得到一个评估得分 $S_1$。
- 第 2 轮:拿 块2 作为验证集,剩下的 块1, 3, 4, 5 作为训练集。得到得分 $S_2$。
- ……
- 第 5 轮:拿 块5 作为验证集,剩下的 块1, 2, 3, 4 作为训练集。得到得分 $S_5$。
- 第三步(大和解):把这 5 轮算出来的得分求一个平均值 $\text{Mean}(S_1, S_2, …, S_5)$。这个平均分,才是我们最终认定的模型真实泛化能力。
1. 分层 K 折交叉验证 (Stratified K-Fold)
- 对应场景:样本极度不均衡。 比如你在做多模态暴力行为检测,1 万条视频里只有 100 条是暴力的(只占 1%)。
- 做法:如果用普通 K 折,随机盲抽可能会导致某些块(Fold)里全是正常视频,一个暴力视频都没有,模型直接学不会。分层 K 折在切块时,会强迫每一个块内部的正负样本比例,都严格保持原数据集的 1:99。
2. 留一法 (Leave-One-Out, LOOCV)
- 对应场景:数据量极其稀少(比如只有几十个样本)。
- 做法:如果总共有 $N$ 个样本,那我们就搞 $N$ 折交叉验证。每次只把 1 个样本扣出来当验证集,剩下的 $N-1$ 个全部用来训练。 这样要重复跑 $N$ 次模型。
- 优缺点:几乎用尽了所有数据去训练,结果最精准;但如果大模型或者数据量稍大一点,算力根本承受不起,计算量爆炸。
Ridge 回归(岭回归)和Lasso 回归
一、 Ridge 回归(岭回归 / $L_2$ 正则化)
Ridge 回归是在标准线性回归的均方误差(MSE)损失函数后面,加上了权重参数的平方和(称为 $L_2$ 范数惩罚项)。
1. 数学公式
- $\lambda$(正则化系数)用来控制惩罚的力度。$\lambda$ 越大,紧箍咒越紧。
2. 工作原理与“性格”
- 整体平滑压制:$L_2$ 惩罚项对极大的权重惩罚非常严厉(因为有平方)。这会逼迫梯度下降在更新参数时,把所有的权重 $w$ 都尽可能地往 0 的方向压,但绝对不会让它们真正等于 0。
- 物理意义:它让模型的参数分布变得非常均匀且平滑,避免了单个特征独大。这样当输入数据有轻微风吹草动(噪声)时,输出不会剧烈晃动,从而降低了方差。
- 经典作用:完美解决多重共线性问题。当特征之间高度相关时,传统的线性回归矩阵求逆会崩溃,而 Ridge 回归在数学上强行保证了逆矩阵必然存在且稳定。
二、 Lasso 回归($L_1$ 正则化)
Lasso 回归则是在 MSE 损失函数后面,加上了权重参数的绝对值之和(称为 $L_1$ 范数惩罚项)。
1. 数学公式
2. 工作原理与“性格”
- 无情裁剪(稀疏解):$L_1$ 惩罚项对大权重和小权重的惩罚力度是恒定的(斜率固定)。在优化过程中,它会表现得非常无情,直接把很多不重要、或者贡献小的特征的权重 $w$ 削减到严格的 0。
- 物理意义:训练完成后,你会得到一个非常“稀疏”的权重矩阵(里面充斥着大量的 0)。
- 经典作用:自带特征选择(Feature Selection)功能。如果你的数据有 1000 个特征,Lasso 跑完可能只有 50 个特征的 $w$ 不为 0,剩下 950 个特征直接被它无视了。这极大提升了模型在大数据场景下的可解释性和运行效率。
贝叶斯定理
- $P(\theta)$ —— 先验概率 (Prior):在没有看到新数据之前,你对这件事情发生可能性的固有认知或主观猜测。
- $P(X\vert{}\theta)$ —— 似然概率 (Likelihood):就是我们刚刚反复聊到的“利用概率反推权重”里的那个概率。如果我的假设 $\theta$ 是对的,那么出现眼前这批数据 $X$ 的可能性有多大?
- $P(X)$ —— 边缘概率/标准化常量 (Evidence):无论你的假设是什么,这批数据 $X$ 自身发生的总概率。在很多时候它只是一个分母,用来把结果缩放到 0~1 之间。
- $P(\theta\vert{}X)$ —— 后验概率 (Posterior):核心目标。在看到了新数据 $X$ 之后,我们更新过后的新认知。
朴素贝叶斯
回到贝叶斯公式,我们要预测一个新样本(比如一封邮件 $X$)属于某个类别(比如垃圾邮件 $C_1$)的概率:
这里的特征 $X$ 通常包含很多个维度,比如一封邮件里包含了词汇 $[x_1=\text{“发票”}, x_2=\text{“中奖”}, x_3=\text{“点击”}]$。
在现实生活中,这些词之间明显是有关联的。但是,如果我们要去计算它们复杂的联合概率 $P(\text{“发票”, “中奖”, “点击”} \vert{} C_1)$,在数学上需要海量的数据才能统计出来,甚至会发生维度灾难。
为了打破这个僵局,朴素贝叶斯提出了一个近乎弱智、极其天真的假设 —— 特征条件独立假设(这也就是“朴素”的由来):
“它假设所有的特征之间是完全独立的、互不影响的。”
有了这个“朴素”的假设,原本极其难算的联合概率,在数学上就可以直接简单粗暴地拆解为各自概率的连乘:
树模型与集成学习
信息增益,信息增益率
信息增益 (Information Gain) —— 初代鼻祖(ID3 标配)
要理解信息增益,必须先了解信息熵(Entropy)。信息熵是香农提出的,用来量化数据的混乱程度。
📊 数学公式
对于一个数据集 $D$,假设里面有 $K$ 个类别,每个类别占的比例是 $p_k$,那么它的信息熵为:
- 当数据全是一类时(纯度最高),$\text{Entropy} = 0$。
- 当数据各类别均匀分布时(最混乱),$\text{Entropy}$ 达到最大值。
信息增益就是:分裂前的总熵,减去分裂后各子节点熵的加权和。
💡 通俗理解
信息增益代表了“得知某个特征后,系统混乱度下降了多少”。增益越大,说明这个特征分得越好,系统越快变整齐。
信息增益率 (Gain Ratio) —— 修复补丁(C4.5 标配)
为了死死卡住 ID3 偏向多取值特征的 Bug,C4.5 引入了信息增益率。
📊 数学公式
信息增益率在信息增益的分子基础上,强行除以了一个分母 —— 特征自身的内在熵(Split Info):
其中分母 $\text{SplitInfo}A(D) = - \sum{v=1}^{V} \frac{\vert{}D^v\vert{}}{\vert{}D\vert{}} \log_2 \frac{\vert{}D^v\vert{}}{\vert{}D\vert{}}$。
💡 通俗理解
特征的取值越多、分出来的枝丫越零碎,这个特征自身的“内在熵(分母)”就会暴涨。
作为分母,它就像一个无情的惩罚项。即使一个特征(比如身份证号)的信息增益很大,但因为它的取值太多导致分母极大,最终算出来的“信息增益率”也会被狠狠地拉低。从而完美抑制了过拟合。
ID3 构造决策树的五步算法流程
步骤 1:准备输入与边界检查(递归基判定)
算法传入当前的数据集 $D$ 和剩余的特征集 $A$。在开始算数学公式前,先做三项“安全检查”,看是否能直接收敛为叶子节点:
- 检查 A:如果 $D$ 中所有样本都属于同一个类别 $C_k$,不用分了,直接把当前节点标记为类别 $C_k$ 的叶子节点,返回。
- 检查 B:如果特征集 $A$ 已经空了(特征用完了),或者 $D$ 中所有样本在剩下特征上的取值都一模一样(无法再分),那就“少数服从多数”,把当前节点标记为 $D$ 中样本数最多的类别的叶子节点,返回。
步骤 2:计算当前数据集的总体混乱度(总信息熵)
如果检查通过,说明需要继续分裂。首先计算当前数据集 $D$ 的信息熵 $H(D)$,作为分裂前的基准混乱度:
(其中 $p_k$ 是第 $k$ 个类别在当前数据集中的样本占比。)
步骤 3:挑选最佳分裂特征(计算信息增益)
遍历当前剩下所有特征。对于每一个特征 $g$:
假设按特征 $g$ 的所有可能取值,把数据集 $D$ 划分成了多个子集 $D^1, D^2, …, D^V$。
计算划分后的条件熵(即所有子集混乱度的加权平均):
算出该特征的信息增益:$\text{Gain}(D, g) = H(D) - H(D\vert{}g)$。
决策判定:对比所有特征,挑出信息增益最大的那一个特征,作为当前节点的核心分裂特征 $A_{best}$。
步骤 4:长出分支,切分数据集
针对挑选出的最佳特征 $A_{best}$,它有多少个可能的取值,就从当前节点向下拉出多少个对应的子分支(多叉树结构)。根据取值将数据集 $D$ 划分到各个子节点中。
步骤 5:递归向下构建
对每一个子节点,把已经用掉的特征 $A_{best}$ 从特征集中剔除,然后将子节点的数据集和缩减后的特征集重新喂回“步骤 1”,直到所有分支都触碰到叶子节点。
决策树算法是如何应对欠拟合和过拟合的
一、 决策树如何应对【过拟合】?
过拟合在决策树上的表现是:树长得太深、太茂盛,方差(Variance)极高,完美拟合训练集噪声,测试集一塌糊涂。
应对过拟合,单棵决策树的核心武器是“剪枝(Pruning)”,分为预剪枝和后剪枝:
1. 预剪枝(Pre-pruning)—— 提前叫停
在树的生长过程中,只要满足某些设定的硬性阈值,就直接强行停止分裂,让其直接退化为叶子节点。
- 限制最大深度(
max_depth):这是最直观的限制,强制树高不能超过指定的层数。 - 限制叶子节点所需最小样本数(
min_samples_leaf):如果某个分支切完后,子节点里的样本数少于 5 个,就不允许再切了。 - 限制分裂所需最小样本数(
min_samples_split):如果一个节点自己包含的样本数已经很少了,直接放弃继续往下分。 - 设置最小信息增益阈值:如果切完这刀,信息熵降低的幅度(信息增益)达不到规定标准,说明这刀不划算,不切了。
- 优点:计算效率极高,省时省算力。
- 缺点:非常盲目,容易带来欠拟合(因为你不知道当前的微小增益,会不会在下一次分裂时带来巨大的纯度飙升,即“视界局限”)。
2. 后剪枝(Post-pruning)—— 斩草除根
先让整棵树憋着一股劲完全长完(直到熵归 0),然后使用验证集,从下往上审视每一个非叶子节点。如果把这个节点的子树全部砍掉、直接退化为叶子节点后,验证集的准确率没有下降甚至上升了,那就果断挥刀把子树砍掉。
典型算法:代价复杂度剪枝(CCP, Cost-Complexity Pruning)。它在损失函数中加入了一个关于叶子节点个数的惩罚项:
通过调节 $\alpha$,在“训练误差 $R(T)$”与“树的复杂程度(叶子数 $\vert{}T_f\vert{}$)”之间找到完美的平衡。
优点:泛化能力极强,保留了真正有效的长远规则,防过拟合效果极佳。
缺点:需要把树完整建好再反向遍历,算力和时间开销非常大。
二、 决策树如何应对【欠拟合】?
欠拟合在决策树上的表现是:树长得太矮、太粗糙,偏差(Bias)极高,模型在训练集和测试集上的准确率都很低。
应对欠拟合的思路非常直接 —— 为模型松绑,增加模型的表达容量:
- 放宽剪枝限制:
- 调大最大深度
max_depth。 - 调小叶子节点或分裂所需的最小样本数(
min_samples_leaf/min_samples_split)。 - 将最小信息增益阈值直接调低或设为 0,允许模型去敏锐地捕捉更加微弱的特征变化。
- 调大最大深度
- 特征工程升级:
- 决策树如果欠拟合,很可能是当前的自变量特征根本不足以划分出正负样本。需要引入更多的交互特征(Interaction Features)、衍生特征,或者对连续特征使用更细致的离散化方案。
- 更换分裂指标:
- 如果你在用初代 ID3 算法,由于它无法处理连续值和缺失值,极易在复杂任务中欠拟合。此时需要无脑升级到支持连续值和二分的 C4.5 或 CART 算法。
Boosting 算法和 Bagging 算法
| 维度 | Bagging (自举汇聚法) | Boosting (提升法) |
|---|---|---|
| 构建方式 | 并行(Parallel)。各个弱学习器之间相互独立,可以同时训练。 | 串行(Sequential)。各个弱学习器必须串行,后一个模型依赖前一个的结果。 |
| 核心使命 | 降低方差(Variance)。通过平均多个过拟合的模型来消灭过拟合。 | 降低偏差(Bias)。通过一轮轮纠错,强行提升模型的拟合能力(消灭欠拟合)。 |
| 数据抽取 | Bootstrap 抽样(有放回的随机抽样),每个模型的样本权重完全一样。 | 每次使用全量数据,但根据上一轮的预测错误率,动态调整样本的权重或拟合残差。 |
| 弱学习器特征 | 倾向于使用强学习器(如长得很深的、容易过拟合的 CART 决策树)。 | 倾向于使用弱学习器(如只切了一刀的、极易欠拟合的“残差小树桩” Stump)。 |
一、 Bagging 算法的算法流程(并行架构)
Bagging(Bootstrap Aggregating)的流程核心是“独立、并行、平均分权”。
假设我们的原始数据集为 $D$,包含 $N$ 个样本,我们要构建一个包含 $T$ 个基模型的 Bagging 集成系统:
核心步骤:
并行抽样(自举汇聚):
启动一个循环,独立重复 $T$ 次。每一轮都对原始数据集 $D$ 进行 Bootstrap 抽样(即有放回的随机抽样),每次抽取 $N$ 个样本。
- 注:因为是有放回的,某些样本会被重复抽到,某些则抽不到。最终会得到 $T$ 个长得互不相同、但规模一样大的子数据集 ${D_1, D_2, …, D_T}$。
并行独立训练:
将这 $T$ 个子数据集同时分发出去。并行地训练 $T$ 个基模型(各个模型之间完全闭关锁国,不知道彼此的存在)。最终得到 $T$ 个训练好的强基模型 ${f_1, f_2, …, f_T}$。
聚合投票/平均(Aggregating):
当来了一个新样本 $x$ 需要预测时:
- 分类任务:让这 $T$ 个基模型同时对 $x$ 进行预测,统计得票数,少数服从多数(Voted),得票最多的类作为最终输出。
- 回归任务:让这 $T$ 个基模型输出各自的连续值,直接取算术平均值(Averaged),作为最终输出。
二、 Boosting 算法的算法流程(串行架构)
Boosting 的流程核心是“接力、串行、动态纠错”。它不搞平行宇宙,它搞的是一代代版本的迭代演进。
同样面对包含 $N$ 个样本的数据集 $D$,我们要迭代 $T$ 轮,训练出 $T$ 个基模型进行接力:
核心步骤:
初始化“新手包”:
- 如果是调整样本权重的流派(如 AdaBoost):给原始数据集里的每个样本都赋予一个相同的初始权重(均为 $\frac{1}{N}$),此时大家是平等的。
- 如果是拟合残差的流派(如 GBDT):先初始化一个最简单的常数预测值(比如全量标签的平均值),计算出初始的预测误差(残差)。
串行接力循环(迭代 $T$ 轮):
进入一个严格的前后依赖循环,从 $t = 1$ 到 $T$:
- 第 $t$ 步训练:根据当前这轮的样本权重分布(或者当前模型留下的残差),训练第 $t$ 个基模型 $f_t$。这个基模型被强强要求:必须拼尽全力去拟合眼前的错题/残差。
- 计算本轮话语权:计算这个基模型 $f_t$ 在训练集上的表现(如错误率)。表现越好的模型,在最终团队里的发言权重 $\alpha_t$ 就会被分配得越大。
- 动态更新,为下一轮铺路:
- 权重流派:把本轮 $f_t$ 做错的样本的权重调高,做对的样本权重调低,重新打包成一份“错题重灾区数据集”喂给下一轮。
- 残差流派:用真实值减去当前总模型的预测值,算出最新的残差,作为下一轮的目标。
加权联合表决:
最终预测新样本 $x$ 时,不是简单的民主投票,而是采取带权重的强力组合。
最终的集成模型 $F(x)$ 是这 $T$ 个基模型的加权求和:
那个话语权 $\alpha_t$ 高的“学霸模型”说了算,话语权低的“偏科模型”只起微调辅助作用。
随机森林算法
随机森林算法核心流程
假设我们的原始数据集为 $D$,包含 $N$ 个样本、共 $M$ 个特征。我们准备构建一个包含 $T$ 棵决策树的随机森林:
步骤 1:引入“双重随机性”并行建树(核心精髓)
启动一个并行循环,独立构建 $T$ 棵 CART 决策树。在构建每棵树的过程中,都要注入以下两层随机性:
第一重随机(样本随机):
利用 Bootstrap 抽样(有放回的随机抽样),从原始的 $N$ 个样本中强行抽取 $N$ 次,形成一个用于训练当前树的子数据集 $D_t$。
- 注:因为是有放回的,大约会有 36.8% 的样本永远抽不到,这部分数据被称为袋外数据(OOB, Out-of-Bag),天然可以用来做不需要交叉验证的泛化评估。
第二重随机(特征随机):
当这棵树在向下分裂节点时,算法不从全部 $M$ 个特征中挑选最优的,而是先随机盲选一部分特征(数量通常为 $m = \sqrt{M}$ 或 $\log_2 M$),然后再从这 $m$ 个随机候选特征中,利用基尼系数(Gini)或平方误差(MSE)选出那个最好的特征进行二叉切分。
步骤 2:树木无限生长(不剪枝)
让这 $T$ 棵树在各自的随机宇宙里完全长完,直到每个叶子节点都达到极高的纯度。
- 底层哲学:因为引入了特征和样本的双重随机性,每棵树各过拟合各的(它们的过拟合噪声是高度不相关的),所以不需要单独对树进行繁琐的剪枝。
步骤 3:多方会审,聚合预测(Aggregating)
当森林构建完毕,来了一个全新的测试样本 $x$ 时,所有树木同时开工:
- 分类任务(民主投票):让 $T$ 棵树对 $x$ 进行分类,统计各个类别的票数,少数服从多数,得票最高的类别即为最终预测结果。
- 回归任务(算术平均):让 $T$ 棵树输出各自的连续值预测,直接计算这 $T$ 个输出值的算术平均值,作为最终的预测结果。
Adaboost
1. 动态调整样本权重(关注错题)
在每一轮训练中,数据集里的每个样本都有一个权重。
- 如果某个样本被当前的弱分类器预测错误,它的权重就会在下一轮中被大幅调高,变成“重灾区错题”;
- 如果样本预测正确,它的权重就会被调低。
- 效果:下一轮的弱分类器被迫把绝大部分精力都放在那些“前人屡屡做错的难题”上。
2. 动态计算模型话语权(学霸权力大)
每个弱分类器训练完后,AdaBoost 会根据它在当前数据集上的分类错误率,为它计算一个发言权重(分类器权重 $\alpha$)。
- 错误率越低(表现越好),这个模型的 $\alpha$ 就越大,在最终决议时的话语权就重;
- 错误率接近 50%(相当于瞎猜),它的 $\alpha$ 就会接近 0,几乎没有话语权。
3. 加权投票表决(精英联合)
最终预测时,不是简单的“少数服从多数”,而是“加权投票”。把所有弱分类器的预测结果乘以它们各自的发言权重 $\alpha$ 进行累加,最后看正负号或者总分决定最终类别。
无监督学习:距离度量与 K-means 聚类
KNN(K-Nearest Neighbors,K近邻)
步骤 1:设定超参数 $K$ 值
在开始之前,我们需要人工指定一个整数 $K$(比如 $K=3$ 或 $K=5$)。这个 $K$ 代表我们最终要参考多少个“最近的邻居”。
- 注:如果是二分类任务,$K$ 通常选奇数,防止投票时出现平局。
步骤 2:计算距离(全量大扫除)
算法会遍历训练集中的每一个样本,计算新样本 $x$ 与训练集中各个样本之间的几何距离。
在连续特征空间中,最常用的是欧氏距离(Euclidean Distance):
在某些高维或特定业务场景下,也会使用曼哈顿距离或闵可夫斯基距离。
步骤 3:挑选出最近的 $K$ 个“邻居”
将计算出的所有距离进行从小到大排序,挑选出距离最近(也就是相似度最高)的 $K$ 个训练集样本。
步骤 4:投票决议,胜者为王(Aggregating)
统计这 $K$ 个最邻居的标签类别。
- 分类任务:采用多数表决制(Majority Voting)。这 $K$ 个邻居里哪种类别最多,新样本就归为哪一类(比如 5 个邻居里有 4 个是“猫”,1 个是“狗”,那新样本判定为“猫”)。
- 回归任务:如果预测的是连续值,则直接计算这 $K$ 个邻居标签值的算术平均值作为最终输出。
K-means(K-均值)聚类
步骤 1:初始化“圈子中心”(随机选种)
在特征空间中,随机挑选 $K$ 个点 作为初始的聚类中心(Centroids),我们把它们记为 ${\mu_1, \mu_2, …, \mu_K}$。
- 注:最原始的做法是直接从训练集里随机盲抽 $K$ 个样本点作为中心。
步骤 2:对样本进行“划分子集”(E 步:分配身份)
遍历数据集中的每一个样本点 $x_i$,计算它到这 $K$ 个聚类中心的欧氏距离:
通过对比,把这个样本点分配给距离它最近的那一个聚类中心所在的簇。
- 通俗理解:每个样本点都在特征空间里找离自己最近的“组织”,并加入进去。这一步结束后台面上会诞生 $K$ 个临时的圈子。
步骤 3:重新计算“圈子中心”(M 步:中心漂移)
对于刚刚诞生的这 $K$ 个圈子,分别计算每个圈子内部所有成员特征的算术平均值(均值):
将算出来的这个“几何重心”,作为全新的聚类中心。此时,这 $K$ 个中心点会发生位置的“漂移”。
步骤 4:循环迭代,直到收敛
将更新后的新中心点重新喂回 “步骤 2”,再次让所有人重新找最近的组织分配身份,接着进 “步骤 3” 重新计算中心。
如此反复循环,直到触发以下终止条件之一:
- 中心点不再动了:新计算出来的均值中心和上一轮的中心完全重合(或变化小于极小阈值)。
- 所有人的身份固化了:连续两轮迭代中,没有任何一个样本点的簇分配发生改变。
- 达到了最大设定的迭代步数(防止死循环)。
SVM 深度探究与贝叶斯优化
降维
解释 PCA 算法的原理和步骤
假设我们的原始数据集为 $X$,包含 $n$ 个样本,每个样本有 $m$ 个特征。即 $X$ 是一个 $n \times m$ 的矩阵。我们希望将其降维到 $k$ 维($k < m$)。
步骤 1:特征去中心化(中心化处理)
为了消除量纲对均值的影响,必须将每个特征的均值归零。计算每个特征(每一列)的平均值 $\mu_j$,然后让每个样本的该特征都减去这个均值:
经过这一步后,数据集的中心点完美平移到了坐标轴的原点 $(0,0)$。
步骤 2:计算协方差矩阵(Covariance Matrix)
协方差矩阵用来衡量特征与特征之间的相关性。计算中心化后的矩阵 $X_{\text{new}}$ 的协方差矩阵 $\Sigma$:
得到的 $\Sigma$ 是一个 $m \times m$ 的对称矩阵。矩阵对角线上的元素是各个特征自己的方差,非对角线上的元素是特征之间的协方差。
步骤 3:特征值分解,求出特征值与特征向量
对协方差矩阵 $\Sigma$ 进行矩阵特征值分解(Eigendecomposition):
- 得到 $m$ 个特征值 $\lambda_1, \lambda_2, …, \lambda_m$(代表了新坐标轴方向上的方差大小)。
- 以及对应的 $m$ 个特征向量 $v_1, v_2, …, v_m$(代表了新坐标轴的空间走向,且彼此正交)。
步骤 4:挑选前 $k$ 个最大特征值对应的特征向量
- 将特征值 $\lambda$ 从大到小进行排序。
- 挑选出最大的前 $k$ 个特征值,并取出它们对应的特征向量 $[v_1, v_2, …, v_k]$。
- 把这 $k$ 个列向量纵向拼接,组合成一个投影矩阵(变换矩阵) $W$,它的维度是 $m \times k$。
步骤 5:矩阵相乘,完成降维投影
将去中心化后的原始数据矩阵 $X_{\text{new}}$ 与投影矩阵 $W$ 进行矩阵乘法,得到降维后的全新数据集 $Y$:
由于 $X_{\text{new}}$ 的维度是 $n \times m$,$W$ 的维度是 $m \times k$,相乘后得到的 $Y$ 维度正是 $n \times k$。降维大功告成!