4. 机器学习基础概念:分类与异常检测的区别、监督/无监督/半监督学习、过拟合与欠拟合

好,我们直接进入正题。这一章要聊的这几个概念,是后续所有模型工作的地基。你如果把它们理清了,后面看算法就不会犯迷糊。

本章核心:搞懂分类和异常检测到底有什么不同,三种学习范式该怎么选,以及模型为啥会"学过头"或"没学够"。

机器学习基础概念知识体系 机器学习基础概念 分类 vs 异常检测 三大学习范式 模型泛化问题 分类 异常检测 监督学习 无监督学习 半监督学习 过拟合 欠拟合 理解这些基础概念,是后续构建审计日志异常检测模型的基石。 每个分支都会在后面章节中反复用到,务必吃透。

4.1 分类与异常检测——本质上的差异

很多人一开始会混淆这两个概念。我刚开始做审计日志时也犯过这个错。简单来说:分类是找共性,异常检测是找差异。

分类模型的任务是"这个东西属于哪一类"。它需要大量带标签的数据,每个样本都告诉模型"这是A类""那是B类"。模型学的是不同类别之间的边界。

异常检测就完全不一样了。它的目标是"这个东西是不是跟大多数不一样"。正常样本多如牛毛,异常样本凤毛麟角。模型只需要见过正常行为,就能判断出异常。

对比维度 分类 异常检测
数据标签 需要完整标签 通常不需要标签,或仅有正常标签
数据分布 各类别相对平衡 极度不平衡(异常常低于1%)
学习目标 找到类别间的决策边界 描述正常数据的边界
评估指标 准确率、精确率、召回率 F1、PR曲线、AUC
典型算法 逻辑回归、随机森林、SVM Isolation Forest、LOF、One-Class SVM

我的经验:在审计日志场景中,异常样本占比往往不到 0.1%。如果硬用分类模型,你会被"类别不平衡"折磨得够呛。我个人建议——优先尝试异常检测方法,除非你确信能拿到足够多的标注异常样本。

你在实际项目里可以这样判断:如果业务方说"我们想识别出所有攻击行为",但你翻遍日志只找到几十条攻击记录,那就乖乖走异常检测路线。如果你有上万条标注好的攻击和正常数据,分类也可以试试。

看看代码上的区别,会更直观:

# 分类路线:需要标签 y
from sklearn.ensemble import RandomForestClassifier
clf = RandomForestClassifier()
clf.fit(X_train, y_train)  # y 包含 0(正常)和 1(异常)

# 异常检测路线:不需要标签
from sklearn.ensemble import IsolationForest
detector = IsolationForest(contamination=0.01)
detector.fit(X_train)  # 只用 X,不需要 y
predictions = detector.predict(X_test)  # 返回 -1 为异常

看到了吧?异常检测不需要标签也能干活。这在审计日志这种标签稀缺的领域,简直是救命稻草。

4.2 三大学习范式——怎么选才对路

你肯定经常听到这三个词:监督、无监督、半监督。它们到底该怎么选?

监督学习:所有训练样本都有标签。模型直接从"输入-输出"对中学习。效果通常最好,但标签成本最高。在审计场景中,如果你有标注团队,或者能用规则自动生成一批标签,可以试试。

无监督学习:完全没有标签。模型自己找数据中的结构。异常检测里的 Isolation Forest、聚类算法都属于这一类。我当年第一次做日志异常检测时,手里只有几十条标注数据,根本没法训练分类器。后来直接用无监督方法,效果反而超出预期。

半监督学习:少量标签 + 大量无标签数据。这其实最接近真实场景——你费劲心力标注了几百条日志,剩下几百万条都是没标的。半监督学习能利用无标签数据帮助模型理解数据分布,再用少量标签指导方向。

学习范式 标签需求 典型场景 优点 缺点
监督学习 全部有标签 已知攻击模式,标签充足 精度高,可解释性强 标签成本高,对未知攻击无能为力
无监督学习 无标签 标签极少,或未知攻击较多 能发现未知异常,部署快 误报率可能较高
半监督学习 少量标签 有部分标注,大量未标注日志 兼顾精度和覆盖率 实现复杂度稍高

你想想看,大多数审计日志项目的标签状态其实介于"完全没有"和"足够多"之间。这时候,我建议你从无监督方法起步,建立基线,再通过半监督方式逐步迭代。

4.3 过拟合与欠拟合——模型的两大死穴

模型训练中最让人头疼的问题,无非就两个:学过头了,或者没学够。

过拟合:模型把训练数据里的噪声和偶然规律也记住了,导致在训练集上表现完美,在测试集上崩得一塌糊涂。说白了就是"考试只背了原题,换个题目就懵了"。

我踩过一个坑——有一次我在审计日志上训练了一个深度模型,训练集的 F1 到了 0.99,我高兴得不行。结果上线当天,误报刷了上千条。后来一看,模型把某个时间段的特定日志格式当成了规律,其实那只是网络抖动造成的。嗯,从此我再也不敢只看训练集指标了。

欠拟合:模型太简单,连训练数据的基本模式都没学到。表现就是训练集和测试集上的误差都很高。这通常是因为模型容量不够,或者特征工程没做好。

对比维度 过拟合 欠拟合
训练集表现 非常好(误差极低) 差(误差高)
测试集表现 差(泛化能力弱) 差(没学到模式)
模型复杂度 过高 过低
常见原因 数据太少、模型太深、训练太久 特征不足、模型容量不够
解决方法 正则化、早停、增加数据、降低模型容量 增加特征、提升模型复杂度、减少正则化

注意:不要为了提高训练集准确率而不停增加模型复杂度。我曾见过一个团队为了把训练集 AUC 从 0.98 提到 0.99,把模型参数量翻了三倍,结果测试集 AUC 从 0.95 掉到了 0.88。过拟合的代价,往往是上线后才知道。

怎么诊断过拟合和欠拟合?我的习惯是画学习曲线:看训练误差和验证误差随着训练数据量增加的变化。如果两条曲线之间的差距很大,就是过拟合;如果两条曲线都居高不下,就是欠拟合。

还记得有一次,我手头只有 2000 条标注日志,硬着头皮训练了一个随机森林。训练集准确率 0.97,验证集只有 0.82。典型的过拟合。后来加了一些正则化参数,又把树的数量从 500 降到 100,验证集准确率反而升到了 0.88。有时候,少即是多。

欠拟合呢?我遇到过一个场景——只用 "登录时间" 和 "登录IP" 两个特征去检测账号被盗。模型怎么调都只有 0.6 的 F1。后来增加了"登录频率""操作序列异常度""设备指纹变化"等特征,F1 直接跳到 0.85。特征才是模型的天花板。

一个小建议:在审计日志异常检测项目里,初期不要追求复杂模型。先用一个简单的 Isolation Forest 或 One-Class SVM 跑通全流程,画出学习曲线,确认没有过拟合/欠拟合问题后,再逐步迭代模型复杂度。这样能少走很多弯路。

好了,这一章的内容就是这些。概念虽然基础,但它们是后续所有章节的"操作系统"——你后面遇到的具体算法、评估方法、调优策略,全都建立在这些概念之上。