检测异常值
异常值是与数据集中的其他数据点有很大区别的数据点。您可以将异常值检测用于欺诈检测和系统运行状况监控等应用程序,或者您可以检测异常值并将其从数据中移除。如果在训练机器学习模型时在数据中留下异常值,则生成的模型存在偏差和偏斜预测的风险。Vertica 支持两种检测异常值的方法:DETECT_OUTLIERS 函数和 IFOREST 算法。
注意
下面的示例使用来自机器学习示例数据的棒球数据集。如果尚未下载,请下载机器学习示例数据。隔离森林
隔离森林 (iForest) 是一种无监督算法,它在异常值很少且不同的假设下运行。这种假设使异常值容易受到称为隔离的分离机制的影响。隔离不是将数据实例与每个数据特征的构造正态分布进行比较,而是关注异常值本身。
为了直接隔离异常值,iForest 构建了名为隔离树 (iTree) 的二叉树结构来对特征空间进行建模。这些 iTree 以随机和递归方式拆分特征空间,使得树的每个节点代表一个特征子空间。例如,第一次拆分将整个特征空间分成两个子空间,由根节点的两个子节点表示。当数据实例是特征子空间的唯一成员时,它被认为是孤立的。由于假设异常值很少且不同,因此异常值可能比正常数据实例更早被隔离。
为了提高算法的强健性,iForest 构建了一个 iTree 集合,每个 iTree 以不同的方式分隔特征空间。该算法计算跨所有 iTree 隔离数据实例所需的平均路径长度。此平均路径长度有助于确定数据集中每个数据实例的 anomaly_score
。anomaly_score
高于给定阈值的数据实例被视为异常值。
您不需要大型数据集来训练 iForest,即使是小样本也足以训练准确的模型。数据可以具有 CHAR、VARCHAR、BOOL、INT 或 FLOAT 类型的列。
训练好 iForest 模型后,您可以使用 APPLY_IFOREST 函数检测向数据集中添加的任何新数据中的异常值。
以下示例演示了如何训练 iForest 模型和检测棒球数据集上的异常值。
要构建和训练 iForest 模型,请调用 IFOREST:
=> SELECT IFOREST('baseball_outliers','baseball','hr, hits, salary' USING PARAMETERS max_depth=30, nbins=100);
IFOREST
----------
Finished
(1 row)
您可以使用 GET_MODEL_SUMMARY 查看训练模型的摘要:
=> SELECT GET_MODEL_SUMMARY(USING PARAMETERS model_name='baseball_outliers');
GET_MODEL_SUMMARY
---------------------------------------------------------------------------------------------------------------------------------------------
===========
call_string
===========
SELECT iforest('public.baseball_outliers', 'baseball', 'hr, hits, salary' USING PARAMETERS exclude_columns='', ntree=100, sampling_size=0.632,
col_sample_by_tree=1, max_depth=30, nbins=100);
=======
details
=======
predictor| type
---------+----------------
hr | int
hits | int
salary |float or numeric
===============
Additional Info
===============
Name |Value
------------------+-----
tree_count | 100
rejected_row_count| 0
accepted_row_count|1000
(1 row)
您可以使用 APPLY_IFOREST 将经过训练的 iForest 模型应用于棒球数据集。要仅查看标识为异常值的数据实例,可以运行以下查询:
=> SELECT * FROM (SELECT first_name, last_name, APPLY_IFOREST(hr, hits, salary USING PARAMETERS model_name='baseball_outliers', threshold=0.6)
AS predictions FROM baseball) AS outliers WHERE predictions.is_anomaly IS true;
first_name | last_name | predictions
------------+-----------+--------------------------------------------------------
Jacqueline | Richards | {"anomaly_score":0.8572338674053986,"is_anomaly":true}
Debra | Hall | {"anomaly_score":0.6007846156043213,"is_anomaly":true}
Gerald | Fuller | {"anomaly_score":0.6813650107767862,"is_anomaly":true}
(3 rows)
您可以设置 contamination
参数,而不是为 APPLY_IFOREST 指定 threshold
值。此参数设置一个阈值,以便标记为异常值的训练数据点的比率大约等于 contamination
的值:
=> SELECT * FROM (SELECT first_name, last_name, APPLY_IFOREST(team, hr, hits, avg, salary USING PARAMETERS model_name='baseball_anomalies',
contamination = 0.1) AS predictions FROM baseball) AS outliers WHERE predictions.is_anomaly IS true;
first_name | last_name | predictions
------------+-----------+--------------------------------------------------------
Marie | Fields | {"anomaly_score":0.5307715717521868,"is_anomaly":true}
Jacqueline | Richards | {"anomaly_score":0.777757463074347,"is_anomaly":true}
Debra | Hall | {"anomaly_score":0.5714649698133808,"is_anomaly":true}
Gerald | Fuller | {"anomaly_score":0.5980549926114661,"is_anomaly":true}
(4 rows)
DETECT_OUTLIERS
DETECT_OUTLIERS 函数假定每个数据维度的正态分布,然后标识与任何维度的正态分布有很大差异的数据实例。该函数使用稳健的 Z-score 检测方法对每个输入列进行标准化。如果数据实例包含大于指定阈值的标准化值,则将其标识为异常值。该函数输出一个包含所有异常值的表。
该函数接受仅具有数字输入列的数据,独立处理每一列,并假定每一列上的高斯分布。如果要检测添加到数据集的新数据中的异常值,则必须重新运行 DETECT_OUTLIERS。
以下示例演示了如何根据 hr、hits 和 salary 列检测棒球数据集中的异常值。DETECT_OUTLIERS 函数创建一个包含异常值的表,其中包含输入列和键列:
=> SELECT DETECT_OUTLIERS('baseball_hr_hits_salary_outliers', 'baseball', 'hr, hits, salary', 'robust_zscore'
USING PARAMETERS outlier_threshold=3.0);
DETECT_OUTLIERS
--------------------------
Detected 5 outliers
(1 row)
要查看异常值,请查询包含异常值的输出表:
=> SELECT * FROM baseball_hr_hits_salary_outliers;
id | first_name | last_name | dob | team | hr | hits | avg | salary
----+------------+-----------+------------+-----------+---------+---------+-------+----------------------
73 | Marie | Fields | 1985-11-23 | Mauv | 8888 | 34 | 0.283 | 9.99999999341471e+16
89 | Jacqueline | Richards | 1975-10-06 | Pink | 273333 | 4490260 | 0.324 | 4.4444444444828e+17
87 | Jose | Stephens | 1991-07-20 | Green | 80 | 64253 | 0.69 | 16032567.12
222 | Gerald | Fuller | 1991-02-13 | Goldenrod | 3200000 | 216 | 0.299 | 37008899.76
147 | Debra | Hall | 1980-12-31 | Maroon | 1100037 | 230 | 0.431 | 9000101403
(5 rows)
您可以创建一个省略表中异常值的视图:
=> CREATE VIEW clean_baseball AS
SELECT * FROM baseball WHERE id NOT IN (SELECT id FROM baseball_hr_hits_salary_outliers);
CREATE VIEW