面试八股——机器学习
基础概念
监督学习、半监督学习和无监督学习
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) 均方误差 / L2 损失
公式:
$$\text{MSE} = \frac{1}{n} \sum_{i=1}^{n} (y_i - \hat{y}_i)^2$$
特点:对异常值(Outliers)极其敏感。因为平方项的存在,如果一个样本预测偏了,误差会被无限放大。
缺点:如果数据集中有很多脏数据(噪声),模型会被异常值带偏。
2. MAE (Mean Absolute Error) 平均绝对误差 / L1 损失
公式:
$$\text{MAE} = \frac{1}{n} \sum_{i=1}^{n} |y_i - \hat{y}_i|$$
特点:对异常值具有很强的鲁棒性(Robust),误差的影响是线性的。
缺点:在 y = ŷ 处(即误差为0的点)不可导,在训练后期(接近最优点时)可能会在最小值附近震荡,不易收敛。
3. Huber Loss (平滑的 L1 损失)
- 核心思想:结合了 MSE 和 MAE 的优点。
- 工作机制:当误差较小时,使用 MSE(保证梯度平滑、快速收敛);当误差较大(遇到异常值)时,自动切换为 MAE(降低敏感度,保护模型)。
二、 分类任务(Classification Loss)
用于预测离散的类别标签。
1. 二分类交叉熵损失 (Binary Cross-Entropy, BCE)
公式:
$$\text{BCE} = -\frac{1}{n} \sum_{i=1}^{n} [y_i \log(\hat{y}_i) + (1 - y_i) \log(1 - \hat{y}_i)]$$
适用场景:判断题(是/否),或者多标签分类(一个样本可以同时属于多个独立类别)。
搭配激活函数:网络最后一层通常搭配 Sigmoid,将输出映射到 (0, 1) 区间。
2. 多分类交叉熵损失 (Categorical Cross-Entropy, CCE)
公式:
$$\text{CCE} = -\sum_{c=1}^{C} y_c \log(\hat{y}_c)$$
(其中 C 为类别总数)
适用场景:单选多分类(如经典的 MNIST 手写数字识别 0~9,或是判别一段文本是否属于暴力行为)。
搭配激活函数:网络最后一层必须搭配 Softmax,使所有类别的预测概率之和等于 1。
偏差(Bias)与方差(Variance)
欠拟合对应“高偏差,低方差”。模型本身偏离了真实规律,但由于简单,在不同数据集上表现都很稳定的差。
过拟合对应“低偏差,高方差”。模型对训练集拟合得极好(偏差低),但因为对数据太敏感,换一个数据集它的预测结果就会发生剧烈抖动(方差高)。
如何应对过拟合问题?
1. 数据层面 (Data Level)
- 增加训练数据量:这是解决过拟合最直接、最根本的手段。数据量足够大、覆盖面足够广时,模型就很难“死记硬背”噪声。
- 数据增强 (Data Augmentation):如果无法获取新数据,可以通过对现有数据进行变换(如图像旋转、裁剪、NLP中的同义词替换、多模态中引入轻微干扰)来人为制造“新数据”,提高模型的鲁棒性。
2. 模型架构与复杂度层面 (Model Level)
- 降低模型复杂度:减少神经网络的层数(Depth)或隐藏单元数(Width),或者在使用传统机器学习(如决策树)时限制树的深度。
- 引入正则化 (Regularization):
- L1 正则化 (Lasso):在损失函数中加入权重绝对值之和(λ∑|w|),会使不重要的参数变为 0,从而产生稀疏解,起到特征选择的作用。
- L2 正则化 (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 后面直接加项)
① L1 正则化 (Lasso 回归)
做法:在损失函数后面加上所有权重参数的绝对值之和。
$$\text{Total Loss} = \text{Original Loss} + \lambda \sum_{j=1}^{d} |w_j|$$
作用与特点:会产生稀疏解(Sparse Solution)。它会无情地将很多不重要特征的权重直接削减为 0。
面试金句:“L1 正则化自带特征选择(Feature Selection)功能。” 因为在几何上,L1 的等高线是一个带尖角的方形,原 Loss 极值通常会在坐标轴(即某个 w = 0 的地方)与它相交。
② L2 正则化 (Ridge 岭回归 / Weight Decay 权重衰减)
做法:在损失函数后面加上所有权重参数的平方和。
$$\text{Total Loss} = \text{Original Loss} + \frac{\lambda}{2} \sum_{j=1}^{d} w_j^2$$
作用与特点:会产生平滑解。它不会把权重减到 0,而是倾向于让所有的 w 都尽可能地接近 0 但不等于 0(惩罚大权重)。
面试金句:“L2 正则化让模型参数分布更均匀,避免单个特征独大。” 当输入发生轻微扰动时,因为 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 = [x1, x2, ..., xd]T,模型通过赋予每个特征不同的权重 w,再加上一个偏置 b,来计算出预测值 ŷ:
ŷ = w1x1 + w2x2 + ... + wdxd + b
2. 定义损失函数:最小二乘法 (OLS)
我们如何评价这条“线”画得好不好?标准做法是计算均方误差(MSE)。我们希望所有样本的预测值与真实值之间的平方差之和最小:
$$L(W, b) = \frac{1}{2n} \sum_{i=1}^{n} (y_i - \hat{y}_i)^2$$
注:为什么要用平方?一是为了消去正负号的影响,二是平方项在数学上处处可导,非常方便计算。
3. 参数求解(怎么找到最完美的 w 和 b)
在面试中,求解方法一定要答出以下两条完全不同的路径:
路径 A:闭式解(解析解)—— 矩阵直接求导
将一整套数据集写成矩阵形式,对损失函数求偏导并直接令偏导等于 0。在数学上可以一步到位直接推导出最优解公式:
W = (XTX)−1XTY
- 面试追问点:只有当 XTX 满秩且可逆时,才能用这个公式。如果特征之间高度相关(多重共线性),矩阵就会不可逆。此时必须引入 L2 正则化(岭回归)来强制使其可逆。
路径 B:数值解 —— 梯度下降法
当特征维度或数据量极端庞大时(比如大模型和现代深度学习场景),矩阵求逆的计算复杂度极高(O(d3))。此时我们会转而采用梯度下降法,顺着梯度的反方向一步步更新 W 和 b,直到模型收敛。
线性回归(Linear Regression)和逻辑回归(Logistic Regression)
| 维度 | 线性回归 (Linear Regression) | 逻辑回归 (Logistic Regression) |
|---|---|---|
| 任务本质 | 回归(Regression)任务。 | 分类(Classification)任务。 |
| 输出形式 | 连续值。范围为 (−∞, +∞)(如预测房价、股票价格)。 | 离散值/概率值。范围严格限制在 (0, 1) 之间,表示属于某一类的概率。 |
| 激活函数 | 无(或者说是线性的 f(x) = x)。 | Sigmoid 函数(将输出映射到概率区间)。 |
| 损失函数 | 均方误差 (MSE) / 最小二乘法。 | 交叉熵损失 (Cross-Entropy) / 负对数似然。 |
在数学和逻辑上,逻辑回归本质上是在线性回归的基础上套了一层“外壳”。
逻辑回归分别是怎样处理二分类问题和多分类问题的?
直接升级为多项逻辑回归(Softmax 回归)
这是最本质、最优雅的扩展方式。当二分类的逻辑回归遇到多分类时,Sigmoid 函数会直接升级为 Softmax 函数。
机制:
模型不再只有一根线性输出线,而是针对 K 个类别分别拉出 K 根线,计算出 K 个类别的得分:[z1, z2, ..., zK]。
使用 Softmax 函数 将这 K 个得分进行归一化,转化为一个概率分布:
$$P(y=c|X) = \frac{e^{z_c}}{\sum_{j=1}^{K} e^{z_j}}$$
Softmax 的魔法在于:所有类别算出来的概率之和严格等于 1。模型最终选择概率最大的那个类别作为预测结果。
极大似然估计(MLE)
“简单来说,极大似然估计就是利用已经发生的事实(数据),去反推最有可能导致这个事实发生的一组模型参数(权重 w)。”
- 传统概率:已知参数(比如硬币是均匀的),去预测未来的结果(抛 10 次大概有 5 次正面)。
- 极大似然:结果已经摆在桌子上了(抛了 10 次硬币,结果 9 次正面 1 次反面),现在我们要反推参数(这枚硬币大概率被灌铅了,正面概率 w = 90% 左右最合理)。
准备工作:设定场景与符号
假设我们手头有一个二分类数据集,样本之间是独立同分布 (i.i.d.) 的。
- 每个样本的真实标签 yi ∈ {0, 1}。
- 模型预测它为 1 的概率为 pi(在逻辑回归中 pi = σ(wTxi))。
- 那么,模型预测它为 0 的概率自然就是 1 − pi。
我们可以把这两个情况合并成一个优雅的单一样本概率公式(伯努利分布的概率质量函数):
P(yi|xi; w) = piyi(1 − pi)1 − yi
小思考:验证一下这个公式。如果真实标签 yi = 1,代入后半部分变成 (1 − pi)0 = 1,整体就剩 pi1 = pi;同理,若 yi = 0,整体就剩 1 − pi。非常完美。
数学推导三步走
现在我们要利用这个单一样本的概率,去反推最完美的权重 w。
第一步:构建似然函数 L(w) —— 求总概率
由于所有样本相互独立,这 n 个样本同时发生的“总概率”,就是把所有单一样本的概率全部乘起来:
$$L(w) = \prod_{i=1}^{n} P(y_i | x_i; w) = \prod_{i=1}^{n} p_i^{y_i} (1 - p_i)^{1 - y_i}$$
这个 L(w) 就是似然函数。我们的终极目标是找到一个 w,让这个连乘的总概率最大。
第二步:取对数 ln —— 连乘变连加
直接对连乘求导会触发数学灾难(高阶乘积求导极其复杂),而且计算机会发生浮点数下溢。所以我们两边同时取自然对数 ln :
$$\ln L(w) = \ln \left( \prod_{i=1}^{n} p_i^{y_i} (1 - p_i)^{1 - y_i} \right)$$
根据对数的性质 ln (a ⋅ b) = ln a + ln b 以及 ln (ab) = bln a,我们可以把连乘的大括号拆开,变成连加:
$$\ln L(w) = \sum_{i=1}^{n} \left[ y_i \ln p_i + (1 - y_i) \ln(1 - p_i) \right]$$
这就是著名的对数似然函数 (Log-Likelihood)。
第三步:求偏导并令其为 0 —— 寻找极值点
为了让总概率最大,我们需要对权重 w 求偏导。这里需要用到高等数学的链式求导法则(由于 pi 内部含有 w):
$$\frac{\partial \ln L(w)}{\partial w} = 0$$
在传统的统计学中,我们解出这个方程,得到的 w 就是极大似然估计值。
交叉验证
拆解 K 折交叉验证的工作原理(以 5 折为例)
正如你所说,它的标准执行步骤非常具有仪式感,我们可以通过图解和“轮班制”来理解:
- 第一步(分块):把原始数据集随机打乱,并平均分成 K 个互不重叠的块(Folds)。比如我们选 K = 5,数据集就被均分为 块1、块2、块3、块4、块5。
- 第二步(轮流站岗):我们要进行 5 轮训练和测试。
- 第 1 轮:拿 块1 作为验证集,剩下的 块2, 3, 4, 5 合并作为训练集。训练模型,得到一个评估得分 S1。
- 第 2 轮:拿 块2 作为验证集,剩下的 块1, 3, 4, 5 作为训练集。得到得分 S2。
- ……
- 第 5 轮:拿 块5 作为验证集,剩下的 块1, 2, 3, 4 作为训练集。得到得分 S5。
- 第三步(大和解):把这 5 轮算出来的得分求一个平均值 Mean(S1, S2, ..., S5)。这个平均分,才是我们最终认定的模型真实泛化能力。
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 回归(岭回归 / L2 正则化)
Ridge 回归是在标准线性回归的均方误差(MSE)损失函数后面,加上了权重参数的平方和(称为 L2 范数惩罚项)。
1. 数学公式
$$\text{Loss}_{\text{Ridge}} = \frac{1}{2n} \sum_{i=1}^{n} (y_i - w^T x_i)^2 + \frac{\lambda}{2} \sum_{j=1}^{d} w_j^2$$
- λ(正则化系数)用来控制惩罚的力度。λ 越大,紧箍咒越紧。
2. 工作原理与“性格”
- 整体平滑压制:L2 惩罚项对极大的权重惩罚非常严厉(因为有平方)。这会逼迫梯度下降在更新参数时,把所有的权重 w 都尽可能地往 0 的方向压,但绝对不会让它们真正等于 0。
- 物理意义:它让模型的参数分布变得非常均匀且平滑,避免了单个特征独大。这样当输入数据有轻微风吹草动(噪声)时,输出不会剧烈晃动,从而降低了方差。
- 经典作用:完美解决多重共线性问题。当特征之间高度相关时,传统的线性回归矩阵求逆会崩溃,而 Ridge 回归在数学上强行保证了逆矩阵必然存在且稳定。
二、 Lasso 回归(L1 正则化)
Lasso 回归则是在 MSE 损失函数后面,加上了权重参数的绝对值之和(称为 L1 范数惩罚项)。
1. 数学公式
$$\text{Loss}_{\text{Lasso}} = \frac{1}{2n} \sum_{i=1}^{n} (y_i - w^T x_i)^2 + \lambda \sum_{j=1}^{d} \vert{}w_j\vert{}$$
2. 工作原理与“性格”
- 无情裁剪(稀疏解):L1 惩罚项对大权重和小权重的惩罚力度是恒定的(斜率固定)。在优化过程中,它会表现得非常无情,直接把很多不重要、或者贡献小的特征的权重 w 削减到严格的 0。
- 物理意义:训练完成后,你会得到一个非常“稀疏”的权重矩阵(里面充斥着大量的 0)。
- 经典作用:自带特征选择(Feature Selection)功能。如果你的数据有 1000 个特征,Lasso 跑完可能只有 50 个特征的 w 不为 0,剩下 950 个特征直接被它无视了。这极大提升了模型在大数据场景下的可解释性和运行效率。
贝叶斯定理
$$P(\theta\vert{}X) = \frac{P(X\vert{}\theta) \cdot P(\theta)}{P(X)}$$
- P(θ) —— 先验概率 (Prior):在没有看到新数据之前,你对这件事情发生可能性的固有认知或主观猜测。
- P(X|θ) —— 似然概率 (Likelihood):就是我们刚刚反复聊到的“利用概率反推权重”里的那个概率。如果我的假设 θ 是对的,那么出现眼前这批数据 X 的可能性有多大?
- P(X) —— 边缘概率/标准化常量 (Evidence):无论你的假设是什么,这批数据 X 自身发生的总概率。在很多时候它只是一个分母,用来把结果缩放到 0~1 之间。
- P(θ|X) —— 后验概率 (Posterior):核心目标。在看到了新数据 X 之后,我们更新过后的新认知。
朴素贝叶斯
回到贝叶斯公式,我们要预测一个新样本(比如一封邮件 X)属于某个类别(比如垃圾邮件 C1)的概率:
$$P(C_1 \vert{} X) = \frac{P(X \vert{} C_1) P(C_1)}{P(X)}$$
这里的特征 X 通常包含很多个维度,比如一封邮件里包含了词汇 [x1 = “发票”, x2 = “中奖”, x3 = “点击”]。
在现实生活中,这些词之间明显是有关联的。但是,如果我们要去计算它们复杂的联合概率 P(“发票”, “中奖”, “点击”|C1),在数学上需要海量的数据才能统计出来,甚至会发生维度灾难。
为了打破这个僵局,朴素贝叶斯提出了一个近乎弱智、极其天真的假设 —— 特征条件独立假设(这也就是“朴素”的由来):
“它假设所有的特征之间是完全独立的、互不影响的。”
有了这个“朴素”的假设,原本极其难算的联合概率,在数学上就可以直接简单粗暴地拆解为各自概率的连乘:
P(X|C1) = P(“发票”|C1) × P(“中奖”|C1) × P(“点击”|C1)
树模型与集成学习
信息增益,信息增益率
信息增益 (Information Gain) —— 初代鼻祖(ID3 标配)
要理解信息增益,必须先了解信息熵(Entropy)。信息熵是香农提出的,用来量化数据的混乱程度。
📊 数学公式
对于一个数据集 D,假设里面有 K 个类别,每个类别占的比例是 pk,那么它的信息熵为:
$$\text{Entropy}(D) = - \sum_{k=1}^{K} p_k \log_2 p_k$$
- 当数据全是一类时(纯度最高),Entropy = 0。
- 当数据各类别均匀分布时(最混乱),Entropy 达到最大值。
信息增益就是:分裂前的总熵,减去分裂后各子节点熵的加权和。
$$\text{Gain}(D, A) = \text{Entropy}(D) - \sum_{v=1}^{V} \frac{\vert{}D^v\vert{}}{\vert{}D\vert{}} \text{Entropy}(D^v)$$
💡 通俗理解
信息增益代表了“得知某个特征后,系统混乱度下降了多少”。增益越大,说明这个特征分得越好,系统越快变整齐。
信息增益率 (Gain Ratio) —— 修复补丁(C4.5 标配)
为了死死卡住 ID3 偏向多取值特征的 Bug,C4.5 引入了信息增益率。
📊 数学公式
信息增益率在信息增益的分子基础上,强行除以了一个分母 —— 特征自身的内在熵(Split Info):
$$\text{Gain\_ratio}(D, A) = \frac{\text{Gain}(D, A)}{\text{SplitInfo}_A(D)}$$
其中分母 $\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 中所有样本都属于同一个类别 Ck,不用分了,直接把当前节点标记为类别 Ck 的叶子节点,返回。
- 检查 B:如果特征集 A 已经空了(特征用完了),或者 D 中所有样本在剩下特征上的取值都一模一样(无法再分),那就“少数服从多数”,把当前节点标记为 D 中样本数最多的类别的叶子节点,返回。
步骤 2:计算当前数据集的总体混乱度(总信息熵)
如果检查通过,说明需要继续分裂。首先计算当前数据集 D 的信息熵 H(D),作为分裂前的基准混乱度:
$$H(D) = - \sum_{k=1}^{K} p_k \log_2 p_k$$
(其中 pk 是第 k 个类别在当前数据集中的样本占比。)
步骤 3:挑选最佳分裂特征(计算信息增益)
遍历当前剩下所有特征。对于每一个特征 g:
假设按特征 g 的所有可能取值,把数据集 D 划分成了多个子集 D1, D2, ..., DV。
计算划分后的条件熵(即所有子集混乱度的加权平均):
$$H(D\vert{}g) = \sum_{v=1}^{V} \frac{\vert{}D^v\vert{}}{\vert{}D\vert{}} H(D^v)$$
算出该特征的信息增益:Gain(D, g) = H(D) − H(D|g)。
决策判定:对比所有特征,挑出信息增益最大的那一个特征,作为当前节点的核心分裂特征 Abest。
步骤 4:长出分支,切分数据集
针对挑选出的最佳特征 Abest,它有多少个可能的取值,就从当前节点向下拉出多少个对应的子分支(多叉树结构)。根据取值将数据集 D 划分到各个子节点中。
步骤 5:递归向下构建
对每一个子节点,把已经用掉的特征 Abest 从特征集中剔除,然后将子节点的数据集和缩减后的特征集重新喂回“步骤 1”,直到所有分支都触碰到叶子节点。
决策树算法是如何应对欠拟合和过拟合的
一、 决策树如何应对【过拟合】?
过拟合在决策树上的表现是:树长得太深、太茂盛,方差(Variance)极高,完美拟合训练集噪声,测试集一塌糊涂。
应对过拟合,单棵决策树的核心武器是“剪枝(Pruning)”,分为预剪枝和后剪枝:
1. 预剪枝(Pre-pruning)—— 提前叫停
在树的生长过程中,只要满足某些设定的硬性阈值,就直接强行停止分裂,让其直接退化为叶子节点。
- 限制最大深度(
max_depth):这是最直观的限制,强制树高不能超过指定的层数。 - 限制叶子节点所需最小样本数(
min_samples_leaf):如果某个分支切完后,子节点里的样本数少于 5 个,就不允许再切了。 - 限制分裂所需最小样本数(
min_samples_split):如果一个节点自己包含的样本数已经很少了,直接放弃继续往下分。 - 设置最小信息增益阈值:如果切完这刀,信息熵降低的幅度(信息增益)达不到规定标准,说明这刀不划算,不切了。
- 优点:计算效率极高,省时省算力。
- 缺点:非常盲目,容易带来欠拟合(因为你不知道当前的微小增益,会不会在下一次分裂时带来巨大的纯度飙升,即“视界局限”)。
2. 后剪枝(Post-pruning)—— 斩草除根
先让整棵树憋着一股劲完全长完(直到熵归 0),然后使用验证集,从下往上审视每一个非叶子节点。如果把这个节点的子树全部砍掉、直接退化为叶子节点后,验证集的准确率没有下降甚至上升了,那就果断挥刀把子树砍掉。
典型算法:代价复杂度剪枝(CCP, Cost-Complexity Pruning)。它在损失函数中加入了一个关于叶子节点个数的惩罚项:
Rα(T) = R(T) + α|Tf|
通过调节 α,在“训练误差 R(T)”与“树的复杂程度(叶子数 |Tf|)”之间找到完美的平衡。
优点:泛化能力极强,保留了真正有效的长远规则,防过拟合效果极佳。
缺点:需要把树完整建好再反向遍历,算力和时间开销非常大。
二、 决策树如何应对【欠拟合】?
欠拟合在决策树上的表现是:树长得太矮、太粗糙,偏差(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 个长得互不相同、但规模一样大的子数据集 {D1, D2, ..., DT}。
并行独立训练:
将这 T 个子数据集同时分发出去。并行地训练 T 个基模型(各个模型之间完全闭关锁国,不知道彼此的存在)。最终得到 T 个训练好的强基模型 {f1, f2, ..., fT}。
聚合投票/平均(Aggregating):
当来了一个新样本 x 需要预测时:
- 分类任务:让这 T 个基模型同时对 x 进行预测,统计得票数,少数服从多数(Voted),得票最多的类作为最终输出。
- 回归任务:让这 T 个基模型输出各自的连续值,直接取算术平均值(Averaged),作为最终输出。
二、 Boosting 算法的算法流程(串行架构)
Boosting 的流程核心是“接力、串行、动态纠错”。它不搞平行宇宙,它搞的是一代代版本的迭代演进。
同样面对包含 N 个样本的数据集 D,我们要迭代 T 轮,训练出 T 个基模型进行接力:
核心步骤:
初始化“新手包”:
- 如果是调整样本权重的流派(如 AdaBoost):给原始数据集里的每个样本都赋予一个相同的初始权重(均为 $\frac{1}{N}$),此时大家是平等的。
- 如果是拟合残差的流派(如 GBDT):先初始化一个最简单的常数预测值(比如全量标签的平均值),计算出初始的预测误差(残差)。
串行接力循环(迭代 T 轮):
进入一个严格的前后依赖循环,从 t = 1 到 T:
- 第 t 步训练:根据当前这轮的样本权重分布(或者当前模型留下的残差),训练第 t 个基模型 ft。这个基模型被强强要求:必须拼尽全力去拟合眼前的错题/残差。
- 计算本轮话语权:计算这个基模型 ft 在训练集上的表现(如错误率)。表现越好的模型,在最终团队里的发言权重 αt 就会被分配得越大。
- 动态更新,为下一轮铺路:
- 权重流派:把本轮 ft 做错的样本的权重调高,做对的样本权重调低,重新打包成一份“错题重灾区数据集”喂给下一轮。
- 残差流派:用真实值减去当前总模型的预测值,算出最新的残差,作为下一轮的目标。
加权联合表决:
最终预测新样本 x 时,不是简单的民主投票,而是采取带权重的强力组合。
最终的集成模型 F(x) 是这 T 个基模型的加权求和:
$$F(x) = \sum_{t=1}^{T} \alpha_t f_t(x)$$
那个话语权 αt 高的“学霸模型”说了算,话语权低的“偏科模型”只起微调辅助作用。
随机森林算法
随机森林算法核心流程
假设我们的原始数据集为 D,包含 N 个样本、共 M 个特征。我们准备构建一个包含 T 棵决策树的随机森林:
步骤 1:引入“双重随机性”并行建树(核心精髓)
启动一个并行循环,独立构建 T 棵 CART 决策树。在构建每棵树的过程中,都要注入以下两层随机性:
第一重随机(样本随机):
利用 Bootstrap 抽样(有放回的随机抽样),从原始的 N 个样本中强行抽取 N 次,形成一个用于训练当前树的子数据集 Dt。
- 注:因为是有放回的,大约会有 36.8% 的样本永远抽不到,这部分数据被称为袋外数据(OOB, Out-of-Bag),天然可以用来做不需要交叉验证的泛化评估。
第二重随机(特征随机):
当这棵树在向下分裂节点时,算法不从全部 M 个特征中挑选最优的,而是先随机盲选一部分特征(数量通常为 $m = \sqrt{M}$ 或 log2M),然后再从这 m 个随机候选特征中,利用基尼系数(Gini)或平方误差(MSE)选出那个最好的特征进行二叉切分。
步骤 2:树木无限生长(不剪枝)
让这 T 棵树在各自的随机宇宙里完全长完,直到每个叶子节点都达到极高的纯度。
- 底层哲学:因为引入了特征和样本的双重随机性,每棵树各过拟合各的(它们的过拟合噪声是高度不相关的),所以不需要单独对树进行繁琐的剪枝。
步骤 3:多方会审,聚合预测(Aggregating)
当森林构建完毕,来了一个全新的测试样本 x 时,所有树木同时开工:
- 分类任务(民主投票):让 T 棵树对 x 进行分类,统计各个类别的票数,少数服从多数,得票最高的类别即为最终预测结果。
- 回归任务(算术平均):让 T 棵树输出各自的连续值预测,直接计算这 T 个输出值的算术平均值,作为最终的预测结果。
Adaboost
1. 动态调整样本权重(关注错题)
在每一轮训练中,数据集里的每个样本都有一个权重。
- 如果某个样本被当前的弱分类器预测错误,它的权重就会在下一轮中被大幅调高,变成“重灾区错题”;
- 如果样本预测正确,它的权重就会被调低。
- 效果:下一轮的弱分类器被迫把绝大部分精力都放在那些“前人屡屡做错的难题”上。
2. 动态计算模型话语权(学霸权力大)
每个弱分类器训练完后,AdaBoost 会根据它在当前数据集上的分类错误率,为它计算一个发言权重(分类器权重 α)。
- 错误率越低(表现越好),这个模型的 α 就越大,在最终决议时的话语权就重;
- 错误率接近 50%(相当于瞎猜),它的 α 就会接近 0,几乎没有话语权。
3. 加权投票表决(精英联合)
最终预测时,不是简单的“少数服从多数”,而是“加权投票”。把所有弱分类器的预测结果乘以它们各自的发言权重 α 进行累加,最后看正负号或者总分决定最终类别。
无监督学习:距离度量与 K-means 聚类
KNN(K-Nearest Neighbors,K近邻)
步骤 1:设定超参数 K 值
在开始之前,我们需要人工指定一个整数 K(比如 K = 3 或 K = 5)。这个 K 代表我们最终要参考多少个“最近的邻居”。
- 注:如果是二分类任务,K 通常选奇数,防止投票时出现平局。
步骤 2:计算距离(全量大扫除)
算法会遍历训练集中的每一个样本,计算新样本 x 与训练集中各个样本之间的几何距离。
在连续特征空间中,最常用的是欧氏距离(Euclidean Distance):
$$d = \sqrt{\sum_{i=1}^{n} (x_i - y_i)^2}$$
在某些高维或特定业务场景下,也会使用曼哈顿距离或闵可夫斯基距离。
步骤 3:挑选出最近的 K 个“邻居”
将计算出的所有距离进行从小到大排序,挑选出距离最近(也就是相似度最高)的 K 个训练集样本。
步骤 4:投票决议,胜者为王(Aggregating)
统计这 K 个最邻居的标签类别。
- 分类任务:采用多数表决制(Majority Voting)。这 K 个邻居里哪种类别最多,新样本就归为哪一类(比如 5 个邻居里有 4 个是“猫”,1 个是“狗”,那新样本判定为“猫”)。
- 回归任务:如果预测的是连续值,则直接计算这 K 个邻居标签值的算术平均值作为最终输出。
K-means(K-均值)聚类
步骤 1:初始化“圈子中心”(随机选种)
在特征空间中,随机挑选 K 个点 作为初始的聚类中心(Centroids),我们把它们记为 {μ1, μ2, ..., μK}。
- 注:最原始的做法是直接从训练集里随机盲抽 K 个样本点作为中心。
步骤 2:对样本进行“划分子集”(E 步:分配身份)
遍历数据集中的每一个样本点 xi,计算它到这 K 个聚类中心的欧氏距离:
$$d = \sqrt{\sum (x_{i} - \mu_k)^2}$$
通过对比,把这个样本点分配给距离它最近的那一个聚类中心所在的簇。
- 通俗理解:每个样本点都在特征空间里找离自己最近的“组织”,并加入进去。这一步结束后台面上会诞生 K 个临时的圈子。
步骤 3:重新计算“圈子中心”(M 步:中心漂移)
对于刚刚诞生的这 K 个圈子,分别计算每个圈子内部所有成员特征的算术平均值(均值):
$$\mu_k = \frac{1}{\vert{}C_k\vert{}} \sum_{x \in C_k} x$$
将算出来的这个“几何重心”,作为全新的聚类中心。此时,这 K 个中心点会发生位置的“漂移”。
步骤 4:循环迭代,直到收敛
将更新后的新中心点重新喂回 “步骤 2”,再次让所有人重新找最近的组织分配身份,接着进 “步骤 3” 重新计算中心。
如此反复循环,直到触发以下终止条件之一:
- 中心点不再动了:新计算出来的均值中心和上一轮的中心完全重合(或变化小于极小阈值)。
- 所有人的身份固化了:连续两轮迭代中,没有任何一个样本点的簇分配发生改变。
- 达到了最大设定的迭代步数(防止死循环)。
SVM 深度探究与贝叶斯优化
降维
解释 PCA 算法的原理和步骤
假设我们的原始数据集为 X,包含 n 个样本,每个样本有 m 个特征。即 X 是一个 n × m 的矩阵。我们希望将其降维到 k 维(k < m)。
步骤 1:特征去中心化(中心化处理)
为了消除量纲对均值的影响,必须将每个特征的均值归零。计算每个特征(每一列)的平均值 μj,然后让每个样本的该特征都减去这个均值:
Xnew = X − μ
经过这一步后,数据集的中心点完美平移到了坐标轴的原点 (0, 0)。
步骤 2:计算协方差矩阵(Covariance Matrix)
协方差矩阵用来衡量特征与特征之间的相关性。计算中心化后的矩阵 Xnew 的协方差矩阵 Σ:
$$\Sigma = \frac{1}{n-1} X_{\text{new}}^T X_{\text{new}}$$
得到的 Σ 是一个 m × m 的对称矩阵。矩阵对角线上的元素是各个特征自己的方差,非对角线上的元素是特征之间的协方差。
步骤 3:特征值分解,求出特征值与特征向量
对协方差矩阵 Σ 进行矩阵特征值分解(Eigendecomposition):
Σv = λv
- 得到 m 个特征值 λ1, λ2, ..., λm(代表了新坐标轴方向上的方差大小)。
- 以及对应的 m 个特征向量 v1, v2, ..., vm(代表了新坐标轴的空间走向,且彼此正交)。
步骤 4:挑选前 k 个最大特征值对应的特征向量
- 将特征值 λ 从大到小进行排序。
- 挑选出最大的前 k 个特征值,并取出它们对应的特征向量 [v1, v2, ..., vk]。
- 把这 k 个列向量纵向拼接,组合成一个投影矩阵(变换矩阵) W,它的维度是 m × k。
步骤 5:矩阵相乘,完成降维投影
将去中心化后的原始数据矩阵 Xnew 与投影矩阵 W 进行矩阵乘法,得到降维后的全新数据集 Y:
Y = Xnew ⋅ W
由于 Xnew 的维度是 n × m,W 的维度是 m × k,相乘后得到的 Y 维度正是 n × k。降维大功告成!