数据-R语言-图表-决策-Linux-PythonR语言:TCGA数据分析R语言小技能

Anomaly Detection with Isolation

2018-11-11  本文已影响3人  Liam_ml

简介

异常检测是一种常见的数据科学问题,其目标是识别我们数据中的奇怪或可疑观察,事件或项目,这些可能表明我们的数据收集过程中存在某些问题(例如传感器损坏,收集表格中的拼写错误等或安全漏洞,服务器故障等意外事件。

可以以监督,半监督和无监督的方式执行异常检测。

对于监督方法,我们需要知道每个观察,事件或项目是否异常或真实,我们在训练期间使用此信息。但是为每次观察获取标签可能通常是不现实的,甚至需要消耗大量的人力物力对样本尽心打标签。

半监督方法使用的假设是我们只知道哪些观测是真实的,非异常的,并且我们没有关于异常观测的任何信息。因此,我们只使用真实数据进行训练。在预测期间,模型评估新观察与训练数据的相似程度以及它与模型的拟合程度。

无监督方法假定训练集包含真实和异常观察。由于标记数据或仅拥有干净的数据通常很难且耗时,因此我想更多地关注使用Isolation Forests进行异常检测的无监督方法之一。

加载数据

在我们进入异常检测之前,让我们初始化h2o集群并加载我们的数据。我们将使用信用卡数据集,其中包含有关信用卡交易的各种属性的信息。有492个欺诈性交易和284,807个真实交易,这使得目标类别高度不平衡。我们不会在异常检测建模过程中使用标签,但我们会在评估异常检测时使用它。

import h2o 
h2o.init()

df = h2o.import_file(“creditcard.csv”)

Isolation Forests

有一种无监督异常检测问题的方法,试图利用共同和独特观察的属性之间的差异。Isolation Forests背后的想法如下。

让我们训练我们的isoforest,看看预测的样子。数据的最后一列(索引30)包含类标签,因此我们将其从培训过程中排除。

seed = 12345
ntrees = 100
isoforest = h2o.estimators.H2OIsolationForestEstimator(
   ntrees=ntrees, seed=seed)
isoforest.train(x=df.col_names[0:31], training_frame=df)
predictions = isoforest.predict(df)

predictions

检查预测

我们可以看到预测 结果包含两列:预测显示标准化的异常分数,mean_length显示所有树的平均分裂数以隔离观察。

根据它们的定义,这两列应该具有反比例的属性,因为隔离观察所需的随机分裂越少,它就越不正常。我们可以轻松检查一下。

predictions.cor()  

使用分位数预测异常

当我们以无人监督的方式制定这个问题时,我们如何从平均分裂/异常分数到实际预测? 如果我们对数据集中异常值的相对数量有所了解,我们可以找到分数的相应分位数值,并将其用作我们预测的阈值。

quantile = 0.95 
quantile_frame = predictions.quantile([quantile])
quantile_frame

我们可以使用阈值来预测异常类。

threshold = quantile_frame[0, "predictQuantiles"]
predictions["predicted_class"] = predictions["predict"] > threshold
predictions["class"] = df["Class"]
predictions

评估

由于隔离林是一种无监督的方法,因此有必要查看不依赖于预测阈值的分类度量,并估计评分质量。两个这样的度量是接收器操作特性曲线下面积(AUC)和精确调用曲线下面积(AUCPR)。

AUC是评估二元分类模型如何区分真阳性和假阳性的度量。完美的AUC分数是1; 随机猜测的基线得分为0.5。

AUCPR是使用连续预测分数的不同阈值来评估二元分类的精确回忆权衡的度量。完美的AUCPR得分是1; 基线分数是阳性分类的相对数。

对于高度不平衡的数据,建议AUCPR优于AUC,因为AUCPR对真阳性,假阳性和假阴性更敏感,而不关心真阴性,其中大量阴性通常会掩盖其他指标的影响。

%matplotlib notebook
from sklearn.metrics import roc_curve, precision_recall_curve, auc
import matplotlib.pyplot as plt
import numpy as np


def get_auc(labels, scores):
    fpr, tpr, thresholds = roc_curve(labels, scores)
    auc_score = auc(fpr, tpr)
    return fpr, tpr, auc_score


def get_aucpr(labels, scores):
    precision, recall, th = precision_recall_curve(labels, scores)
    aucpr_score = np.trapz(recall, precision)
    return precision, recall, aucpr_score


def plot_metric(ax, x, y, x_label, y_label, plot_label, style="-"):
    ax.plot(x, y, style, label=plot_label)
    ax.legend()
    
    ax.set_ylabel(x_label)
    ax.set_xlabel(y_label)


def prediction_summary(labels, predicted_score, predicted_class, info, plot_baseline=True, axes=None):
    if axes is None:
        axes = [plt.subplot(1, 2, 1), plt.subplot(1, 2, 2)]

    fpr, tpr, auc_score = get_auc(labels, predicted_score)
    plot_metric(axes[0], fpr, tpr, "False positive rate",
                "True positive rate", "{} AUC = {:.4f}".format(info, auc_score))
    if plot_baseline:
        plot_metric(axes[0], [0, 1], [0, 1], "False positive rate",
                "True positive rate", "baseline AUC = 0.5", "r--")

    precision, recall, aucpr_score = get_aucpr(labels, predicted_score)
    plot_metric(axes[1], recall, precision, "Recall",
                "Precision", "{} AUCPR = {:.4f}".format(info, aucpr_score))
    if plot_baseline:
        thr = sum(labels)/len(labels)
        plot_metric(axes[1], [0, 1], [thr, thr], "Recall",
                "Precision", "baseline AUCPR = {:.4f}".format(thr), "r--")

    plt.show()
    return axes


def figure():
    fig_size = 4.5
    f = plt.figure()
    f.set_figheight(fig_size)
    f.set_figwidth(fig_size*2)


h2o_predictions = predictions.as_data_frame()

figure()
axes = prediction_summary(
    h2o_predictions["class"], h2o_predictions["predict"], h2o_predictions["predicted_class"], "h2o")

Isolation Forests in scikit-learn

我们可以使用scikit-learn执行相同的异常检测。此示例中使用的scikit-learn版本为0.20。某些行为在其他版本中可能有所不同。该score_samples方法返回与异常分数相反的方法; 因此它是倒置的。Scikit-learn还接受一个contamination参数,即数据集中异常值的比例。


from sklearn.ensemble import IsolationForest
import pandas as pd

df_pandas = df.as_data_frame()
df_train_pandas = df_pandas.iloc[:, :30]

x = IsolationForest(random_state=seed, contamination=(1-quantile),
                    n_estimators=ntrees, behaviour="new").fit(df_train_pandas)

iso_predictions = x.predict(df_train_pandas)
iso_score = x.score_samples(df_train_pandas)

sk_predictions = pd.DataFrame({
    "predicted_class": list(map(lambda x: 1*(x == -1), iso_predictions)),
    "class": h2o_predictions["class"],
    "predict": -iso_score
})

sk_predictions.head()

评估scikit-learn

figure()
axes = prediction_summary(
    sk_predictions [ “class” ],sk_predictions [ “predict” ],sk_predictions [ “ predict_class ” ],“sklearn”)
上一篇下一篇

猜你喜欢

热点阅读