分享

机器学习之异常点检测

 NeighborMrSun 2023-02-27 发布于湖南

参考链接:

#1. scikit-learn官网 https:///stable/modules/classes.html

#2. scikit-learn中文手册https://sklearn./docs/master/30.html

#3. 分类回归方法介绍https://www.cnblogs.com/qiuyuyu/p/11399697.html

--- IsolationForest和LOF效果比较好

许多应用程序需要能够对新观测值(observation 译注:观测到的样本的值 )进行判断,判断其是否与现有观测值服从同一分布(即新观测值为内围点(inlier)),相反则被认为不服从同一分布(即新观测值为离群点(outlier))。通常,这种能力被用于清理真实数据集, 但它有两种重要区分:

离群点检测: 训练数据包含离群点,即远离其它内围点。离群点检测估计器会尝试拟合出训练数据中内围点聚集的区域, 会忽略有偏离的观测值。
新奇点检测: 训练数据未被离群点污染,我们对新观测值是否为离群点感兴趣。在这个语境下,离群点被认为是新奇点。

离群点检测 和 新奇点检测 都被用于异常检测, 所谓异常检测就是检测反常的观测值或不平常的观测值。离群点检测 也被称之为 无监督异常检测; 而 新奇点检测 被称之为 半监督异常检测。在离群点检测的语境下, 离群点/异常点 不能够形成一个稠密的聚类簇,因为可用的估计器都假定了 离群点/异常点 位于低密度区域。相反的,在新奇点检测的语境下,新奇点/异常点 是可以形成 稠密聚类簇的,只要它们在训练数据的一个低密度区域,这被认为是正常的。

1. EllipticEnvelope¶

假定了数据是服从高斯分布的且要学习一个椭圆(ellipse)

import numpy as npfrom sklearn.covariance import EllipticEnvelopetrue_cov = np.array([[.8, .3],                     [.3, .4]])X = np.random.RandomState(0).multivariate_normal(mean=[0, 0],                                                 cov=true_cov,                                                 size=500)cov = EllipticEnvelope(random_state=0).fit(X)# predict returns 1 for an inlier and -1 for an outliercov.predict([[0, 0],             [3, 3]])
cov.covariance_

cov.location_

2. OneClassSVM

对离群点本来就很敏感,因此在离群点检测中表现的不是很好(译注: 这里的敏感 应该指的是会把离群点划到决策边界内)

from sklearn.svm import OneClassSVMX = [[0], [0.44], [0.45], [0.46], [1]]clf = OneClassSVM(gamma='auto').fit(X)clf.predict(X)
clf.score_samples(X)

3.IsolationForest

        在高维数据集中实现离群点检测的一种有效方法是使用随机森林。ensemble.IsolationForest 通过随机选择一个特征,然后随机选择所选特征的最大值和最小值之间的分割值来'隔离'观测。

        由于递归划分可以由树形结构表示,因此隔离样本所需的分割次数等同于从根节点到终止节点的路径长度。

        在这样的随机树的森林中取平均的路径长度是数据正态性和我们的决策功能的量度。

        随机划分能为异常观测产生明显的较短路径。因此,当随机树的森林共同地为特定样本产生较短的路径长度时,这些样本就很有可能是异常的。

from sklearn.ensemble import IsolationForestX = [[-1.1], [0.3], [0.5], [100]]clf = IsolationForest(random_state=0).fit(X)# clf.predict([[0.1], [0], [90]])clf.predict(X)
from sklearn.ensemble import IsolationForestimport numpy as npimport scipy.stats as stx0=[-1.1, 0.3, 0.5, 100]X = np.array(x0).reshape(-1, 1)clf = IsolationForest(random_state=0).fit(X)classresult=clf.predict(X)KM_num_cal=st.mode(classresult)[0][0] #求众数newresult=[]for oneres,onedata in zip(classresult,x0): if oneres==KM_num_cal: newresult.append(onedata)print(newresult)

4. LocalOutlierFactor

        对轻度高维数据集(即维数勉强算是高维)实现异常值检测的另一种有效方法是使用局部离群因子(LOF)算法。

        neighbors.LocalOutlierFactor (LOF)算法计算出反映观测异常程度的得分(称为局部离群因子)。它测量给定数据点相对于其邻近点的局部密度偏差。算法思想是检测出具有比其邻近点明显更低密度的样本。

        实际上,局部密度从 k 个最近邻得到。观测数据的 LOF 得分等于其 k 个最近邻的平均局部密度与其本身密度的比值:正常情况预期与其近邻有着类似的局部密度,而异常数据则预计比近邻的局部密度要小得多。

        考虑的k个近邻数(别名参数 n_neighbors )通常选择 1) 大于一个聚类簇必须包含对象的最小数量,以便其它对象可以成为该聚类簇的局部离散点,并且 2) 小于可能成为聚类簇对象的最大数量, 减少这K个近邻成为离群点的可能性。在实践中,这样的信息通常不可用,并且使 n_neighbors = 20 似乎通常都能使得算法有很好的表现。当离群点的比例较高时(即大于 10% 时,如下面的示例),n_neighbors 应该较大(在下面的示例中,n_neighbors = 35)。

        LOF 算法的优点是考虑到数据集的局部和全局属性:即使在具有不同潜在密度的离群点数据集中,它也能够表现得很好。问题不在于样本是如何被分离的,而是样本与周围近邻的分离程度有多大。

        当使用 LOF 进行离群点检测的时候,不能使用 predict, decisionfunction 和 score_samples 方法, 只能使用 fit_predict 方法。训练样本的异常性得分可以通过 negative_outlier_factor 属性来获得。注意当使用LOF算法进行新奇点检测的时候(novelty 设为 True), predict, decision_function 和 score_samples 函数可被用于新的未见过数据。请查看使用LOF进行新奇点检测.

import numpy as npfrom sklearn.neighbors import LocalOutlierFactorX = [[-1.1], [0.2], [101.1], [0.3]]clf = LocalOutlierFactor(n_neighbors=2)clf.fit_predict(X)
clf.negative_outlier_factor_

*异常点检查效果比对

# Author: Alexandre Gramfort <alexandre.gramfort@inria.fr># Albert Thomas <albert.thomas@telecom-paristech.fr># License: BSD 3 clause
import time
import numpy as npimport matplotlibimport matplotlib.pyplot as plt
from sklearn import svmfrom sklearn.datasets import make_moons, make_blobsfrom sklearn.covariance import EllipticEnvelopefrom sklearn.ensemble import IsolationForestfrom sklearn.neighbors import LocalOutlierFactor
print(__doc__)
matplotlib.rcParams['contour.negative_linestyle'] = 'solid'
# Example settingsn_samples = 300outliers_fraction = 0.15n_outliers = int(outliers_fraction * n_samples)n_inliers = n_samples - n_outliers
# define outlier/anomaly detection methods to be comparedanomaly_algorithms = [ ('Robust covariance', EllipticEnvelope(contamination=outliers_fraction)), ('One-Class SVM', svm.OneClassSVM(nu=outliers_fraction, kernel='rbf', gamma=0.1)), ('Isolation Forest', IsolationForest(contamination=outliers_fraction, random_state=42)), ('Local Outlier Factor', LocalOutlierFactor( n_neighbors=35, contamination=outliers_fraction))]
# Define datasetsblobs_params = dict(random_state=0, n_samples=n_inliers, n_features=2)datasets = [ make_blobs(centers=[[0, 0], [0, 0]], cluster_std=0.5, **blobs_params)[0], make_blobs(centers=[[2, 2], [-2, -2]], cluster_std=[0.5, 0.5], **blobs_params)[0], make_blobs(centers=[[2, 2], [-2, -2]], cluster_std=[1.5, .3], **blobs_params)[0], 4. * (make_moons(n_samples=n_samples, noise=.05, random_state=0)[0] - np.array([0.5, 0.25])), 14. * (np.random.RandomState(42).rand(n_samples, 2) - 0.5)]
# Compare given classifiers under given settingsxx, yy = np.meshgrid(np.linspace(-7, 7, 150), np.linspace(-7, 7, 150))
plt.figure(figsize=(len(anomaly_algorithms) * 2 + 3, 12.5))plt.subplots_adjust(left=.02, right=.98, bottom=.001, top=.96, wspace=.05, hspace=.01)
plot_num = 1rng = np.random.RandomState(42)
for i_dataset, X in enumerate(datasets): # Add outliers X = np.concatenate([X, rng.uniform(low=-6, high=6, size=(n_outliers, 2))], axis=0)
for name, algorithm in anomaly_algorithms: t0 = time.time() algorithm.fit(X) t1 = time.time() plt.subplot(len(datasets), len(anomaly_algorithms), plot_num) if i_dataset == 0: plt.title(name, size=18)
# fit the data and tag outliers if name == 'Local Outlier Factor': y_pred = algorithm.fit_predict(X) else: y_pred = algorithm.fit(X).predict(X)
# plot the levels lines and the points if name != 'Local Outlier Factor': # LOF does not implement predict Z = algorithm.predict(np.c_[xx.ravel(), yy.ravel()]) Z = Z.reshape(xx.shape) plt.contour(xx, yy, Z, levels=[0], linewidths=2, colors='black')
colors = np.array(['#377eb8', '#ff7f00']) plt.scatter(X[:, 0], X[:, 1], s=10, color=colors[(y_pred + 1) // 2])
plt.xlim(-7, 7) plt.ylim(-7, 7) plt.xticks(()) plt.yticks(()) plt.text(.99, .01, ('%.2fs' % (t1 - t0)).lstrip('0'), transform=plt.gca().transAxes, size=15, horizontalalignment='right') plot_num += 1
# plt.show()

图片

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多