Isolation Forest 异常检测怎么做?用 Python 找出表格中的可疑记录

用 Isolation Forest 为数值表格生成异常复核清单,保留原始行号并解释标签、分数和异常比例的限制。

Isolation Forest 可以在没有逐条异常标签的数值表格中,给每条记录一个相对异常分数,再生成待人工复核清单。它适合先筛查,最终判断仍要回到数据来源。

先理解标签与分数

按 scikit-learn 官方说明,predict 返回 1 表示模型视为正常、-1 表示异常;decision_function 越低越可疑,负值位于模型异常阈值一侧。不同模型或不同训练集的分数不能直接作跨系统排名。

Isolation Forest 异常检测怎么做?用 Python 找出表格中的可疑记录

contamination=0.05 用来设定训练样本的阈值,表达约 5% 的预期异常比例,不是已证实有 5% 错误,更不是异常概率。没有业务依据时先比较 auto 和若干候选阈值,再由人工确认可接受的误报。

准备独立 Python 环境

本文使用 Python 3.13。下面命令适用于 Windows PowerShell,在新建练习目录运行;其他系统用对应的 Python 路径。先用 python –version 确认版本,再创建环境。

python -m venv .venv
.\.venv\Scripts\python.exe -m pip install "scikit-learn==1.9.1" "numpy==2.5.3" "pandas==3.0.6"

以下代码和数据只用于教学。本站于 2026-10-01 在 Windows、Python 3.13.14、scikit-learn 1.9.1、NumPy 2.5.3、pandas 3.0.6 环境运行了本文脚本;这只验证示例能执行和断言通过,不代表真实业务效果。

运行一个保留行号的完整示例

示例生成 100 条集中分布的虚构记录,再加 3 条极端样本。amount 和 duration 只是教学字段名,单位需在真实数据中定义;不对应任何客户订单。模型只读取 amount 和 duration 两列,不把 row_id 当作特征。

把下方代码保存为 anomaly.py,再运行 .\.venv\Scripts\python.exe anomaly.py。

import numpy as np
import pandas as pd
from sklearn.ensemble import IsolationForest

rng = np.random.default_rng(42)
normal = rng.normal(loc=[100, 5], scale=[8, 0.6], size=(100, 2))
X = np.vstack([normal, [[240, 15], [20, 0.5], [110, 18]]])
df = pd.DataFrame(X, columns=["amount", "duration"])
df.insert(0, "row_id", [f"R{i:03d}" for i in range(len(df))])
features = ["amount", "duration"]
assert df[features].notna().all().all()
model = IsolationForest(n_estimators=200, contamination=0.05,
                        random_state=42, n_jobs=1)
model.fit(df[features])
result = df.copy()
result["flag"] = model.predict(df[features])
result["score"] = model.decision_function(df[features])
review = result[result["flag"] == -1].sort_values("score")
review.to_csv("anomaly_review.csv", index=False, encoding="utf-8-sig")
assert len(result) == 103
assert set(result["flag"].unique()) <= {-1, 1}
assert (review["score"] < 0).all()
assert set(["R100", "R101", "R102"]) <= set(review["row_id"])
print("input_rows", len(result), "review_rows", len(review))
print(review[["row_id", "flag", "score"]].to_string(index=False))

核对清单,而不是立即删除

核对输入共有 103 行,原始表没有删行,复核清单保留 row_id、flag 和 score。清单中 R100、R101、R102 是人为插入的三个极端样本。代码专门检查它们是否被标出;真实数据通常没有这种提前知道答案的条件。

input_rows 103 review_rows 6
row_id  flag     score
  R100    -1 -0.322675
  R101    -1 -0.306831
  R102    -1 -0.255267
  R069    -1 -0.107890
  R071    -1 -0.014906
  R002    -1 -0.000128

这是上述合成数据的本地运行输出。打开 anomaly_review.csv,按 row_id 回查原记录,把每条标记为“已确认错误”“合法但少见”或“信息不足”,并记处理理由。先抽查正常组也很重要,否则只能看到误报,看不到漏报。

替换自己的表格时要改什么

把生成数据部分替换为 pd.read_csv(“input.csv”);保留一个稳定的唯一行ID,再选两列或多列有意义的数值特征。字符串类别先设计合适的编码,缺失值先按业务规则处理,不能直接把手机号、客户ID当连续数值喂给模型。检查 np.isfinite 的结果,避免无穷值进入拟合。

如果用于上线后检测新记录,应在有代表性的历史参考集上 fit,再对新批次 predict;不要每次把所有新异常混进拟合后还期待同一阈值含义不变。重复记录、季节变化或整体业务转型都会改变分数解释。

失败与适用边界

异常标签不代表欺诈、故障或脏数据;它只是模型按当前特征和阈值发现的可疑记录。样本量太小、特征无意义、参考集已被大量异常污染时,清单会失去实用价值。

若安装失败,先确认运行与安装使用同一个 .venv Python;若缺失值检查失败,先保留原表并修复输入规则;若极端样本断言失败,核对版本、随机种子和代码是否被改过,再查看分数,不要删除断言来掩盖结果。

一个常见问题:标出的异常太多怎么办?

先检查是否把不同人群或不同单位混在一起,再看 contamination 是否强行设了过高比例。仅调低比例会减少待复核条数,却不证明漏报降低。应拿人工已确认的样本比较误报与漏报后再决定。

Ai菜鸟网。发布者:AI小管家,转载请注明出处:https://www.alyyhw.com/30147.html

赞 (0)
AI小管家的头像AI小管家
用 DeepSeek 转换文件格式:将 CSV 转为 JSON 并保留编号前导零
上一篇 1天前
DeepSeek 如何生成 Excel 表格?用 Python 写入明细和汇总两个工作表
下一篇 1天前

相关推荐

联系我们

联系我们

1

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信
关注微信
分享本页
返回顶部