检测异常值

异常值是与数据集中的其他数据点有很大区别的数据点。您可以将异常值检测用于欺诈检测和系统运行状况监控等应用程序,或者您可以检测异常值并将其从数据中移除。如果在训练机器学习模型时在数据中留下异常值,则生成的模型存在偏差和偏斜预测的风险。Vertica 支持两种检测异常值的方法:DETECT_OUTLIERS 函数和 IFOREST 算法。

隔离森林

隔离森林 (iForest) 是一种无监督算法,它在异常值很少且不同的假设下运行。这种假设使异常值容易受到称为隔离的分离机制的影响。隔离不是将数据实例与每个数据特征的构造正态分布进行比较,而是关注异常值本身。

为了直接隔离异常值,iForest 构建了名为隔离树 (iTree) 的二叉树结构来对特征空间进行建模。这些 iTree 以随机和递归方式拆分特征空间,使得树的每个节点代表一个特征子空间。例如,第一次拆分将整个特征空间分成两个子空间,由根节点的两个子节点表示。当数据实例是特征子空间的唯一成员时,它被认为是孤立的。由于假设异常值很少且不同,因此异常值可能比正常数据实例更早被隔离。

为了提高算法的强健性,iForest 构建了一个 iTree 集合,每个 iTree 以不同的方式分隔特征空间。该算法计算跨所有 iTree 隔离数据实例所需的平均路径长度。此平均路径长度有助于确定数据集中每个数据实例的 anomaly_scoreanomaly_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

另请参阅