深秋的果园里,老李对着一筐青苹果发愁:要捡出混在里面的烂苹果,可这些苹果没标签、没照片,他也说不清“烂的究竟长什么样”。他想到一个笨办法——蒙上眼睛,随手抽出一把刀,对着筐子横一刀、竖一刀,把空间切成越来越小的格子。奇怪的事发生了:好苹果你挨着我、我挨着你,要切十几刀才能把它们单个分开;那一两颗烂苹果,因为颜色怪、气味冲,孤零零待在角落,往往两三刀就“落单”了。老李恍然大悟:判断苹果好坏,根本不用先定义“什么是烂”,只要看“把它单独切出来需要几刀”就行。这正是孤立森林 iForest 的全部秘密。它不跟你讲“正常的模样”,只问一句话:这颗苹果,是躲在大部队里,还是早就独自站在角落?接下来,我们跟着老李的刀,看看这片森林的每一道年轮。

岗位关联

掌握 iForest,等于给无标签世界装上一双“一眼识别局外人”的眼睛——这是风控、安全、运维等 AI 工程岗位的高频基本功。

目录
  1. 可视化演示
  2. 算法原理:快刀为何能挑出烂苹果
  3. 构建流程:如何种出一片孤立森林
  4. 得分计算:给每颗苹果打异常分
  5. 核心参数:四把刻度尺
  6. 性能特性:快在哪里,又怕什么
  7. 应用场景:风控、安全、监控里的挑果人
  8. 变体优化:更锋利的新刀
  9. 对比总结:何时该用这把刀
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

展示系统处理流水线、实时性能指标曲线及多方案对比分析,包含数据流转、吞吐延迟监控与方案评估。

本节配有交互动效(进入视口后自动加载,约 3KB)。

系统可视化 处理流程:输入→处理→模型→输出 性能监控:实时指标 P=L×T

算法原理:快刀为何能挑出烂苹果

老李把切苹果的发现教给了儿子小李。小李问:“为什么烂苹果总是先落单?”老李说:“因为正常苹果彼此太像,挤成一团;那几颗异类,既少又不同,天生就站在角落。随机切几刀,先被单独切出来的,总是它们。”

换成数据语言:iForest 假设异常样本有两个共同点——“少”(占比极小)和“不同”(分布偏离主流)。算法不比较距离、不算密度,而是用随机切分把空间割成小格,每颗样本落进一个格;从根到样本所在格的“切割次数”,就是路径长度 h(x),字面意思就是“几刀落单”。

单棵随机树叫孤立树(iTree),一大片叫孤立森林。每棵树只在随机采样的子集上生长,节点递归挑选特征与切割点。异常点容易落单,h(x) 通常很小;正常点要切很多刀,h(x) 偏大。为了抵消随机性,用多棵树取平均,得到平均路径长度。

小李听完恍然大悟:“所以森林里树多,不是要人多,是要大家投票,别让一棵树的坏运气带偏。”老李点头——正是这个道理。iForest 把“孤立的快慢”变成数字,接下来的任务,是把这套切法变成一棵棵真实的树。

E[h(x)]=1t∑i=1thi(x)\displaystyle \mathbb{E}[h(x)] = \frac{1}{t} \sum_{i=1}^{t} h_i(x)
公式说的是把样本 x 丢进 t 棵随机树,记录每棵树的路径长度,再算平均数;数字越小,x 越像“几刀就被切出来的烂苹果”。
  1. 期望记号$\mathbb{E}[h(x)]$ 表示样本 x 的“平均路径长度”,这是判断异常的核心指标。
    E[h(x)]\mathbb{E}[h(x)]
  2. 求和符号把 x 在每一棵孤立树里得到的路径长度全部累加起来。
    ∑i=1thi(x)\sum_{i=1}^{t} h_i(x)
  3. 取平均除以树的棵数 t,抹平单棵树的随机抖动,森林的结论才稳定。
    1t\frac{1}{t}

构建流程:如何种出一片孤立森林

老李开始动手造“切苹果的机器”。机器的工作流程就三步:先随机抱一小筐苹果出来(采样),再闭眼选一个角度(选特征),然后沿这个角度随机切一刀(选切割值);切完之后,对切出的两半各自重复同样的动作。

对应到 iTree 的递归生长:从根节点开始,随机挑选特征 q,在该特征当前取值范围内随机取一个切割点 p,把样本按 x_q < p 分成左右两支;左右两支各自递归,直到一个节点只剩一个样本,或达到深度上限。整个构建过程不需要任何标签,也不需要算两两距离。

深度上限的经验值是 L = ⌈log₂ψ⌉,其中 ψ 是采样大小。这样每棵树都“短小精悍”,异常点能快速沉到底部。多棵这样的树凑成森林,切分点的随机性由下面的公式给出。

老李边装机器边感叹:“这些树从不多想,见什么切什么。正因为傻,才不看人脸色。”在数据里,这份“傻”恰恰是优势——不用先定义正常,异常自己会暴露出来。

p∼U(min⁡x∈Dxq, max⁡x∈Dxq)\displaystyle p \sim U\left(\min_{x \in D} x_q,\ \max_{x \in D} x_q\right)
一棵树每次只选一个特征,在这个特征的最小值和最大值之间随便挑一刀,完全不看“苹果长什么样”。
  1. 切割点 pp 是第 q 个特征上的一次随机切割值,样本按它分成左右两支。
    pp
  2. 均匀分布 U在给定区间内每个位置被选中的概率都相同,保证切割完全随机。
    U(⋅)U(\cdot)
  3. 取值范围切割点只在当前节点样本的最小值与最大值之间挑选,确保左右两格都不空。
    min⁡x∈Dxq, max⁡x∈Dxq\min_{x\in D} x_q,\ \max_{x\in D} x_q

得分计算:给每颗苹果打异常分

机器装好了,老李要给每颗苹果打分:分越高越像烂果。评分逻辑很简单——先看这颗苹果平均被几刀切出来,再和一个“普通人”做比较,看它落单得有多“反常”。

这个“普通人”就是完全随机二叉树的平均搜索路径 c(n),它只与总样本数 n 有关。有了基准,就能把“平均几刀”换算成一个 0 到 1 之间的异常得分。什么分数算可疑?原始论文给出经验线:得分超过 0.6 高度可疑,低于 0.5 基本正常,0.5 附近说明落单速度与随机无异。

老李给机器挂上一只“嫌疑筐”:超过 0.6 直接进筐。试验那天,十颗烂果靠着高速落单被一颗颗点亮——这就是异常得分的魔力。

s(x,n)=2−E[h(x)]c(n),c(n)=2H(n−1)−2(n−1)n\displaystyle s(x, n) = 2^{-\frac{\mathbb{E}[h(x)]}{c(n)}}, \qquad c(n) = 2H(n-1) - \frac{2(n-1)}{n}
如果平均不到几刀就落单,指数部分为负且绝对值大,得分迅速逼近 1,异常嫌疑极高;若路径与普通人差不多,得分就徘徊在 0.5 附近。
  1. 异常得分 ss(x,n) 取值在 (0,1],越接近 1 越异常,越接近 0 越正常。
    s(x,n)=2−E[h(x)]c(n)s(x,n) = 2^{-\frac{\mathbb{E}[h(x)]}{c(n)}}
  2. 归一化基准 c(n)等价于在 n 个叶子上随机二叉搜索的平均查找路径,是一个只与数据量有关的常数。
    c(n)=2H(n−1)−2(n−1)nc(n) = 2H(n-1) - \frac{2(n-1)}{n}
  3. 调和数 HH(n-1)=1+1/2+……+1/(n-1),用来近似二叉搜索树的平均路径,大样本时 c(n)≈ln(n-1)+γ。
    H(n−1)=∑k=1n−11kH(n-1) = \sum_{k=1}^{n-1} \frac{1}{k}

核心参数:四把刻度尺

机器虽好用,老李却得先回答四个问题:种多少棵树?每筐抱多少苹果?每棵树看几个特征?筐里大概有几个烂的?这四个答案,就是 iForest 的核心参数。

树数量 t(n_estimators):默认 100 棵,太少抖动大,太多浪费算力;采样大小 ψ(sample_size):默认 256,既够用又让每棵树小巧;特征数(max_features):默认用全部特征或 log₂ 个,控制每棵树的视角;污染率(contamination):你对“烂苹果比例”的业务预判,用来反推判定阈值。

特别提醒:contamination 不是“期望的误报率”随便填,它直接影响 predict 阶段阈值;设成 0 会让阈值定得极高,等于把烂果全部放过。它和阈值的关系由下面的公式描述。

老李把四把刻度尺刻在机身上:“树数管稳定,采样管效率,特征管角度,污染管收口。”调好参数,机器才算真正属于这片果园。

r^=1N∑i=1NI(s(xi,n)>θ)\displaystyle \hat{r} = \frac{1}{N}\sum_{i=1}^{N} \mathbb{I}\big(s(x_i, n) > \theta\big)
污染率 r 是“把前多少比例的苹果判为异常”的业务预期;给定 r 后,模型按得分从高到低数出相应数量,从而确定阈值 θ。
  1. 指示函数当括号里的条件成立时取 1,否则取 0,用来统计“被判为异常”的样本个数。
    I(⋅)\mathbb{I}(\cdot)
  2. 异常占比对所有样本求和再除以 N,得到当前阈值下的异常比例。
    1N∑i=1N\frac{1}{N}\sum_{i=1}^{N}
  3. 阈值反推调小 θ 则抓得多、误报多;调大 θ 则抓得少、漏报多。contamination 帮你把 θ 定在“业务能接受的比例”处。
    s(xi,n)>θs(x_i,n) > \theta

性能特性:快在哪里,又怕什么

老李的机器比隔壁王婶的人工捡果快出天际。王婶挑一颗要看颜色、闻气味、掂重量,老李的机器闭眼切就行。快,是孤立森林的第一张王牌。

它从不计算样本两两距离,也没有任何密度估计;每棵树只是在随机子样本上做递归二分。训练开销只与“树数 × 采样 × 树高”有关,对全量样本规模近似线性,非常适合海量数据的批量扫描与在线打分。

但机器也有两条红线:一是高维数据下,好苹果坏苹果的落单速度被拉得差不多,分数全挤在 0.5 附近;二是异常如果成串抱团出现(连片烂果),随机切分反而不容易第一刀见血。老李在机身上贴了张条:快而省,怕高维,躲成群。

O(t⋅ψ⋅log⁡ψ)\displaystyle O\big(t \cdot \psi \cdot \log \psi\big)
括号里是三个乘数:树的数量 t、每棵树用到的样本数 ψ、树的深度上限 logψ。三者都不随全量数据 n 暴涨,所以训练又快又省。
  1. 树的数量 t森林中孤立树的总数,直接放大训练与打分的总工作量。
    tt
  2. 采样大小 ψ每棵树只接触 ψ 个样本,这是“潜行”的根源——树永远不用看完全部数据。
    ψ\psi
  3. 树高对数项每棵树深度限制为 logψ,切分计算随深度线性叠加,取对数后增长非常缓慢。
    log⁡ψ\log \psi

应用场景:风控、安全、监控里的挑果人

机器名声传开,镇上三家单位都来请老李“挑果”:银行要挑盗刷交易,运营商要挑攻击流量,工厂要挑坏掉的传感器。老李把机器搬上三轮车,挨家试刀。

这些场景有个共同点:异常极少、花样翻新、标签难找。银行交易里欺诈占 0.01%;网络流量里攻击模式天天变;传感器故障没有足够历史样本。iForest 不挑食,先按得分排序,把 Top 0.1% 捞出来送人工复核,效率和召回都立竿见影;还有人把它当“清洁工”,清洗训练集里脏样本。

酒席上老李总结:“哪里的烂苹果又少又邪门,哪里就适合我。”金融、安全、运维正是这样的三块地——异常检测的第一站,永远是先找“局外人”。

y^(x)={1,s(x,n)>θ0,s(x,n)≤θ\displaystyle \hat{y}(x) = \begin{cases} 1, & s(x,n) > \theta \\ 0, & s(x,n) \le \theta \end{cases}
这就是“切一刀判定”:得分超过阈值 θ 就直接判异常,否则放行。θ 一般取 0.6 附近,也可以由污染率倒推。
  1. 判定输出$\hat{y}(x)$ 是模型对样本 x 的最终决定,1 代表异常、0 代表正常。
    y^(x)\hat{y}(x)
  2. 分段函数得分高于阈值输出 1,否则输出 0,等价于老李把苹果投进“嫌疑筐”还是“合格筐”。
    {1,s(x,n)>θ0,s(x,n)≤θ\begin{cases} 1, & s(x,n) > \theta \\ 0, & s(x,n) \le \theta \end{cases}
  3. 阈值 θ业务含义是“宁愿多抓也不放过”还是“宁缺毋滥”,需要结合误报成本来调整。
    θ\theta

变体优化:更锋利的新刀

日子一久,老李发现只会“横切竖切”的机器,遇到斜着排的苹果堆就费刀。村里的工程师小张给出妙计:让刀学会斜着切。

这就是 Extended iForest 的思想——不再把切割面限制成垂直于坐标轴,而是给每个特征配一个随机权重 w,用加权和构造任意方向的切割超平面。斜切能更好地贴合任意方向的分布形态,在高维稀疏数据上显著提升分数区分度。

小张还带了另外两把新刀:流式孤立森林(Streaming iForest)逐批喂数据、用滑动窗口淘汰旧样本,做到在线检测;多粒度孤立森林(Multi-Granularity iForest)自动扫描特征子集,把“选角度”也变成学习对象。他顺手用网格搜索把污染率和树数一起调优。小张看着果园说:“刀越锋利,能切的果园就越大。”

∑j=1dwjxj≤p,wj∼N(0,1)\displaystyle \sum_{j=1}^{d} w_j x_j \le p, \qquad w_j \sim \mathcal{N}(0, 1)
左边是一把“歪着拿的刀”:每个特征乘一个随机权重再加起来,相当于把空间旋转、拉伸后再切;w 就是各方向上的倾斜幅度。
  1. 加权和切割面用所有特征的线性组合定义切割边界,切割不再平行于坐标轴。
    ∑j=1dwjxj\sum_{j=1}^{d} w_j x_j
  2. 随机权重每个特征的权重独立从标准正态分布里抽一个数,保证方向随机均匀。
    wj∼N(0,1)w_j \sim \mathcal{N}(0,1)
  3. 阈值 pp 与基础 iForest 类似,在该节点样本的“加权和”区间内均匀采样。
    ≤p\le p

对比总结:何时该用这把刀

集市上卖检测工具的很多:统计派用“三西格玛”只认单列,距离派用 LOF 非要算远近,聚类派得先数清有几堆。老李掂了掂自己的刀,给出选型标准。

异常又少又怪、维度不高、要求快——iForest 首选;异常成串、局部密度不均明显——LOF 更稳;单变量问题——3σ 就够。高维场景呢?先 PCA 或特征筛选降维,再换 Extended 变体上门。为什么高维会退化,数学直觉就藏在下面这个极限里:维度一高,平均路径和基准路径几乎相等,得分全部挤到 0.5 附近,阈值形同虚设。

老李把结论刻在木牌上:“快而准,怕高维,躲成群。”何时选孤立森林?回到故事的开头——在无标签的世界里,先问一句:谁,最早落单?

E[h(x)]c(n)→1⟹s(x,n)→0.5\displaystyle \frac{\mathbb{E}[h(x)]}{c(n)} \to 1 \quad \Longrightarrow \quad s(x,n) \to 0.5
维度越高,所有点的“落单速度”都向随机基准靠拢,异常得分被压到 0.5 附近——就像烂苹果混进一堆同样稀稀拉拉的苹果里,切几刀都看不出差别。
  1. 比值趋近 1平均路径与基准路径几乎相等,意味着好坏苹果的落单速度不再有差别。
    E[h(x)]c(n)→1\frac{\mathbb{E}[h(x)]}{c(n)} \to 1
  2. 推出号箭头表示必然推论,比值趋近 1 直接导致得分退化。
    ⟹\Longrightarrow
  3. 得分退化到 0.52⁻¹ = 0.5,所有样本分数挤在 0.5 附近,阈值失去了分辨力。
    s(x,n)→0.5s(x,n) \to 0.5

AI 应用场景

银行卡里的「烂苹果」:金融反欺诈

阶段:无监督建模与数据预处理

解决的问题:欺诈交易占比极小、标签滞后且不断翻新,传统规则引擎只能拦截已知套路。iForest 不需要标签,直接对交易特征打分,把“最早落单的苹果”先捞出来,再送人工复核。

具体案例:某支付平台对每笔交易提取金额、频次、设备指纹、时段等 30 维特征,建 100 棵树、采样 256,对千万级交易打分,Top 0.1% 送人工复核,欺诈资金拦截率提升约 3 倍。

网络里的「离群流量」:入侵检测

阶段:特征工程与异常识别

解决的问题:攻击流量特征多变、正样本奇缺,无法稳定标注。iForest 把连接时长、包大小、端口分布建模成“苹果特征”,快速标记偏离主流的会话。

具体案例:安全团队对防火墙日志做 15 维特征,用 iForest 检测横向移动与暴力破解:攻击会话的平均路径只有正常的 1/3,得分高于 0.8,误报率控制在 5% 以内。

机器提前「喊疼」:工业运维监控

阶段:数据清洗与故障预警

解决的问题:传感器数据噪声大、故障样本稀罕、人工阈值疲于应付。先用 iForest 清洗脏数据,把设备在异常工况下的无意义读数剔除,再做故障预警。

具体案例:某工厂上千台设备的温度、振动、电流传感器接入 iForest,识别出 0.2% 的离群读数;把这些读数对应的时刻集中排查,提前发现 3 台轴承的早期故障。

Python 演示

python91 行
import numpy as np  def _path_c(n):    if n <= 1:        return 0.0    return 2 * (np.log(n - 1) + 0.5772156649) - 2 * (n - 1) / n  class Node:    def __init__(self, size, depth):        self.size = size        self.depth = depth        self.split_feat = -1        self.split_val = 0.0        self.left = None        self.right = None  def build_tree(X, depth, max_depth):    n = X.shape[0]    node = Node(n, depth)    if n <= 1 or depth >= max_depth:        return node    feat = np.random.randint(X.shape[1])    lo, hi = X[:, feat].min(), X[:, feat].max()    if lo == hi:        return node    val = np.random.uniform(lo, hi)    left_idx = X[:, feat] < val    if left_idx.all() or not left_idx.any():        return node    node.split_feat = feat    node.split_val = val    node.left = build_tree(X[left_idx], depth + 1, max_depth)    node.right = build_tree(X[~left_idx], depth + 1, max_depth)    return node  def path_length(node, x, depth):    if node.split_feat < 0 or node.left is None:        return depth    if x[node.split_feat] < node.split_val:        return path_length(node.left, x, depth + 1)    return path_length(node.right, x, depth + 1)  class IsolationForest:    def __init__(self, n_trees=100, sample_size=256):        self.n_trees = n_trees        self.sample_size = sample_size        self.max_depth = int(np.ceil(np.log2(sample_size)))        self.trees = []     def fit(self, X):        n = X.shape[0]        m = min(self.sample_size, n)        for _ in range(self.n_trees):            idx = np.random.choice(n, m, replace=False)            self.trees.append(build_tree(X[idx], 0, self.max_depth))        return self     def average_depth(self, x):        total = 0.0        for tree in self.trees:            total += path_length(tree, x, 0)        return total / self.n_trees     def anomaly_score(self, X):        c = _path_c(self.sample_size)        scores = []        for x in X:            avg = self.average_depth(x)            scores.append(2 ** (-avg / c))        return np.array(scores)  if __name__ == "__main__":    rng = np.random.RandomState(42)    normal = rng.randn(300, 2) * 0.5    anomaly = rng.uniform(-4, 4, size=(10, 2))    X = np.vstack([normal, anomaly])     model = IsolationForest(n_trees=100, sample_size=128)    model.fit(X)    scores = model.anomaly_score(X)    top = np.argsort(scores)[::-1][:10]    print("得分最高的10条:")    for i in top:        flag = "注入异常" if i >= 300 else "正常样本"        print("idx=%3d  score=%.3f  %s" % (i, scores[i], flag))
目的:从零手写孤立森林,在合成数据(300 个正常点 + 10 个注入异常点)上训练打分,验证“落单越快、得分越高”的核心逻辑。
  1. val = np.random.uniform(lo, hi)在当前特征范围里随机挑一个切割点,等于老李闭眼切下的那一刀。
  2. left_idx = X[:, feat] < val把样本按“小于/大于切割点”分成左右两堆,对应苹果被分进两个格子。
  3. node.left = build_tree(X[left_idx], depth + 1, max_depth)对左堆继续递归切分,直到堆里只剩一个样本或到达深度上限。
  4. self.max_depth = int(np.ceil(np.log2(sample_size)))树高上限取 log₂ψ 的经验值,让每棵树短小精悍。
  5. idx = np.random.choice(n, m, replace=False)每棵树只随机抱一小筐样本,换一棵树换一筐,森林才有多样性。
  6. scores.append(2 ** (-avg / c))直接套用正文的异常得分公式:平均路径越短,得分越接近 1。
  7. model = IsolationForest(n_trees=100, sample_size=128)实例化模型:100 棵树、每棵 128 个样本,纯手工实现。

常见误区

误区想用 iForest 检测异常,得先准备好标好“正常/异常”的标签,不然它怎么知道我要找什么?

正解iForest 是无监督算法。它只利用“异常既少又不同”这个结构性假设,用随机切分测量“落单的快慢”,全程不需要任何标签。真有少量标签时,标签更适合用来事后校准阈值或评估效果,而不是喂给训练。老李挑烂苹果之前,也从没给苹果贴过标签。

为何常见:人们习惯“先教后测”的机器学习思维,看到“检测”两个字就以为必须有正例样本。

误区contamination=0 表示我不想有任何异常,这样模型就不会误报,最安全。

正解contamination 不是“期望误报率”,它是你对数据中异常占比的估计,直接决定 predict 阶段的阈值。设 0 会让阈值定得极高(甚至全判正常),把真实异常全部埋掉。要按业务对“烂苹果比例”的估计设置,并用验证集微调。

为何常见:低估了阈值的作用,以为它只影响“抓多抓少”,没意识到设 0 会直接掩盖问题。

误区随机森林树越多越准,iForest 反正也便宜,我直接建 5000 棵树总没错。

正解实验表明约 100 棵后异常得分已收敛,更多树主要换来计算量。真正影响效果的是采样大小与特征选择;树数拉满只会重复放大相同的随机切分模式,边际收益极低。

为何常见:把 bagging 类算法的经验直接平移到孤立森林,忽略了“单树很短、森林很齐”的特性。

误区s(x,n)=0.8 就是说这个样本有 80% 的概率是异常,可以当概率用。

正解s 是“相对异常程度”的单调刻画,不是统计概率。它衡量“落单速度相对于随机基准快多少”:0.5 表示无明显异常,接近 1 表示高度可疑。真正判定要靠排序 + 阈值/污染率,而不是把 s 当概率代入其他模型。

为何常见:分数范围在 0~1,天然让人联想到概率,而文档往往只给公式不给概率化解释。

误区iForest 在低维好用,那我把 1000 维特征全塞进去,它一定能抓到更细的异常。

正解维度升高后,随机切分被大量无关/噪声特征稀释,所有点的平均路径都向基准 c(n) 靠拢,分数挤在 0.5 附近失去区分度。应对方案:先做特征筛选/降维,换 Extended iForest,或用 Multi-Granularity iForest 自动选择特征子集。

为何常见:对“维度灾难”缺乏直觉,以为特征越多信息越多,忘了随机切分在冗余维度上会“迷路”。

面试题

Q1. 孤立森林 iForest 最核心的定位是?

单选题 · easy

  • A.用于有监督分类
  • B.无监督异常检测算法← 正确答案
  • C.用于半监督回归
  • D.深度生成网络模型

答案:B。iForest 是无监督异常检测算法,训练时不看标签,只靠“异常少而不同、易被随机切分快速孤立”的结构性假设。老李挑烂苹果前从不给苹果贴标签,切几刀就有了答案。A 说它是分类器,C 说半监督,D 说生成模型,都不符合定位。

Q2. iForest 判定异常的核心直觉是?

单选题 · easy

  • A.异常点远离大多数样本
  • B.异常点只需极少切分便孤立← 正确答案
  • C.异常点具有最大的特征值
  • D.异常点在低密度区域聚集

答案:B。iForest 不比较远近,也不算密度,而是用随机切分衡量“被单独切出来需要几刀”。异常点又少又不同,几刀就落单;A 是距离直觉,C/D 是其他算法的思路。真正的核心是“落单速度”,所以选 B。

Q3. 异常得分 s(x,n) 越接近 1 表示?

单选题 · easy

  • A.样本点越接近数据中心
  • B.样本点越可能是正常点
  • C.样本点越可能是异常点← 正确答案
  • D.样本数量变得越来越少

答案:C。得分定义在 (0,1],平均路径越短,s 越接近 1,代表越异常。老李的得分牌上,越靠近 1 越要进“嫌疑筐”,所以选 C。A/B 描述的是正常点,D 与得分定义无关。

Q4. 孤立树的最大深度通常设置为?

单选题 · mid

  • A.等于采样大小的数值
  • B.向上取整的 log₂采样← 正确答案
  • C.数据总行数的一半
  • D.不受任何深度限制

答案:B。为了避免树无限长,iTree 设深度上限 L = ⌈log₂ψ⌉,这来自完全二叉树的期望高度,保证树的“短小精悍”。A 是采样大小本身,C/D 都不是正确的上限公式。

Q5. iForest 推荐采样大小 sample_size 是?

单选题 · mid

  • A.固定取全部数据量
  • B.通常 256 左右即可← 正确答案
  • C.必须大于特征数量
  • D.必须等于树的数量

答案:B。iForest 通过子采样兼顾效率与多样性,经验上 ψ=256 已能捕获正常与异常的形态。A 取全量会拖慢训练,C/D 的说法都没有依据。老李每筐只抱一小把苹果,不代表。

Q6. iForest 训练阶段的时间复杂度约为?

单选题 · mid

  • A.近线性 复杂度近似 O(tψlogψ)← 正确答案
  • B.平方级 计算量随样本暴涨
  • C.立方级 数据量大非常慢
  • D.指数级 几乎无法训练

答案:A。iForest 每棵树只在 ψ 个样本上生长、深度为 logψ,总训练复杂度约 O(t·ψ·logψ),对全量 n 近似线性。B/C/D 都夸大了复杂度。速度优势正来自“不碰距离、只看子样本”。

Q7. 下列哪种数据场景 iForest 效果最差?

单选题 · hard

  • A.异常占比约千分之一
  • B.正常数据呈现球状分布
  • C.含数百维且噪声特征多← 正确答案
  • D.数据总量达到十万级别

答案:C。高维且含大量噪声特征时,随机切分被无关维度稀释,所有点路径向基准靠拢,分数挤在 0.5 附近,检测力大幅下降。极低异常占比、球状分布、大数据量都不是 iForest 的致命伤。

Q8. iForest 的三个核心超参数是?

多选题 · mid

  • A.树数量 n_estimators← 正确答案
  • B.采样大小 sample_size← 正确答案
  • C.污染率 contamination← 正确答案
  • D.学习率 learning_rate

答案:ABC。iForest 三大超参是树数量 t、采样大小 ψ、污染率 contamination(推阈值),分别对应正文里的“树数管稳定、采样管效率、污染管收口”。学习率是神经网络等梯度类模型的参数,与孤立森林无关,排除 D。

Q9. iForest 相比距离类方法的优势是?

多选题 · hard

  • A.无需计算两两样本距离← 正确答案
  • B.整体复杂度接近线性← 正确答案
  • C.需要预先给定异常标签
  • D.在高维空间天然最优

答案:AB。iForest 全程不计算两两距离,复杂度近线性,这两点相对 LOF 等距离类方法是明显优势。C 错在 iForest 是无监督、不需要标签;D 错在高维恰是 iForest 的软肋,并非“天然最优”。

Q10. 关于 iForest 得分公式,正确说法是?

多选题 · extreme

  • A.平均路径越短得分越近 1← 正确答案
  • B.c(n) 是归一化基准长度← 正确答案
  • C.路径趋近 c(n) 则得分 0.5← 正确答案
  • D.得分等于异常概率假设

答案:ABC。由 s = 2^(−E/c) 可得:E 越短分数越接近 1;c(n) 是归一化基准,只与样本量有关;当 E ≈ c 时 s ≈ 2⁻¹ = 0.5,故 A/B/C 正确。D 错在把相对得分当成统计概率——s 只能用于排序与阈值比较。