機器學習基礎之新奇和異常值檢測

異常值檢測一般要求新發現的數據是否與現有觀測數據具有相同的分佈或者不同的分佈,相同的分佈可以稱之爲內點(inlier),具有不同分佈的點可以稱之爲離羣值。離羣點和新奇點檢測是不同的,有一個重要的區分必須掌握:

離羣點檢測:訓練數據包含離羣點,這些離羣點被定義爲遠離其它內點的觀察值。因此,離羣點檢測估計器會嘗試擬合出訓練數據中內圍點聚集的區域, 而忽略異常值觀察。

新奇點檢測:訓練數據沒有受到離羣點污染,我們感興趣的是檢測一個新的觀測值是否爲離羣點。在這種情況下,離羣點被認爲是新奇點。

離羣點檢測和新奇點檢測都用於異常檢測, 其中一項感興趣的是檢測異常或異常觀察。離羣點檢測又被稱之爲無監督異常檢測,新奇點檢測又被稱之爲半監督異常檢測。 在離羣點檢測的背景下, 離羣點/異常點不能夠形成密集的簇,因爲可用的估計器假設離羣點/異常點位於低密度區域。相反的,在新奇點檢測的背景下, 新奇點/異常點只要位於訓練數據的低密度區域,是可以形成稠密聚類簇的,在此背景下被認爲是正常的。

scikit-learn有一套機器學習工具estimator.fit(X_train),可用於新奇點或離羣值檢測。然後可以使用estimator.predict(X_test)方法將新觀察值分類爲離羣點或內點 :內圍點會被標記爲1,而離羣點標記爲-1。

離羣點檢測方法總結

下面的例子展示了二維數據集上不同異常檢測算法的特點。數據集包含一種或兩種模式(高密度區域),以說明算法處理多模式數據的能力。

對於每個數據集,產生15%的樣本作爲隨機均勻噪聲。這個比例是給予OneClassSVM的nu參數和其他離羣點檢測算法的污染參數的值。由於局部離羣因子(LOF)用於離羣值檢測時沒有對新數據應用的預測方法,因此除了局部離羣值因子(LOF)外,inliers和離羣值之間的決策邊界以黑色顯示。

sklearn.svm。一個已知的eclasssvm對異常值很敏感,因此在異常值檢測方面表現不太好。該估計器最適合在訓練集沒有異常值的情況下進行新穎性檢測。也就是說,在高維的離羣點檢測,或者在不對嵌入數據的分佈做任何假設的情況下,一個類支持向量機可能在這些情況下給出有用的結果,這取決於它的超參數的值。

sklearn.covariance。橢圓包絡假設數據是高斯分佈,並學習一個橢圓。因此,當數據不是單峯時,它就會退化。但是請注意,這個估計器對異常值是穩健的。

sklearn.ensemble。IsolationForest sklearn.neighbors。LocalOutlierFactor對於多模態數據集似乎表現得相當好。sklearn的優勢。第三個數據集的局部離羣因子超過其他估計顯示,其中兩種模式有不同的密度。這種優勢是由LOF的局域性來解釋的,即它只比較一個樣本的異常分數與其相鄰樣本的異常分數。

最後,對於最後一個數據集,很難說一個樣本比另一個樣本更反常,因爲它們是均勻分佈在超立方體中。除了sklearn。svm。有一點過度擬合的支持向量機,所有的估計器都對這種情況給出了合適的解決方案。在這種情況下,明智的做法是更密切地觀察樣本的異常分數,因爲一個好的估計器應該給所有樣本分配相似的分數。

雖然這些例子給出了一些關於算法的直覺,但這種直覺可能不適用於非常高維的數據。

最後,請注意,模型的參數在這裏是精心挑選的,但在實踐中需要進行調整。在沒有標記數據的情況下,這個問題是完全無監督的,因此模型的選擇是一個挑戰。

# Author: Alexandre Gramfort <[email protected]>
#         Albert Thomas <[email protected]>
# License: BSD 3 clause
​
import time
​
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
​
from sklearn import svm
from sklearn.datasets import make_moons, make_blobs
from sklearn.covariance import EllipticEnvelope
from sklearn.ensemble import IsolationForest
from sklearn.neighbors import LocalOutlierFactor
​
print(__doc__)
​
matplotlib.rcParams['contour.negative_linestyle'] = 'solid'
​
# Example settings
n_samples = 300
outliers_fraction = 0.15
n_outliers = int(outliers_fraction * n_samples)
n_inliers = n_samples - n_outliers
​
# define outlier/anomaly detection methods to be compared
anomaly_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 datasets
blobs_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 settings
xx, 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 = 1
rng = 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()

一個新奇點檢測例子

下圖是一個使用支持向量機進行新奇點檢測的例子。

支持向量機是一種無監督的算法,它學習一個用於新鮮度檢測的決策函數:將新數據分類爲與訓練集相似或不同的數據。

print(__doc__)
​
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.font_manager
from sklearn import svm
​
xx, yy = np.meshgrid(np.linspace(-5, 5, 500), np.linspace(-5, 5, 500))
# Generate train data
X = 0.3 * np.random.randn(100, 2)
X_train = np.r_[X + 2, X - 2]
# Generate some regular novel observations
X = 0.3 * np.random.randn(20, 2)
X_test = np.r_[X + 2, X - 2]
# Generate some abnormal novel observations
X_outliers = np.random.uniform(low=-4, high=4, size=(20, 2))
​
# fit the model
clf = svm.OneClassSVM(nu=0.1, kernel="rbf", gamma=0.1)
clf.fit(X_train)
y_pred_train = clf.predict(X_train)
y_pred_test = clf.predict(X_test)
y_pred_outliers = clf.predict(X_outliers)
n_error_train = y_pred_train[y_pred_train == -1].size
n_error_test = y_pred_test[y_pred_test == -1].size
n_error_outliers = y_pred_outliers[y_pred_outliers == 1].size
​
# plot the line, the points, and the nearest vectors to the plane
Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
​
plt.title("Novelty Detection")
plt.contourf(xx, yy, Z, levels=np.linspace(Z.min(), 0, 7), cmap=plt.cm.PuBu)
a = plt.contour(xx, yy, Z, levels=[0], linewidths=2, colors='darkred')
plt.contourf(xx, yy, Z, levels=[0, Z.max()], colors='palevioletred')
​
s = 40
b1 = plt.scatter(X_train[:, 0], X_train[:, 1], c='white', s=s, edgecolors='k')
b2 = plt.scatter(X_test[:, 0], X_test[:, 1], c='blueviolet', s=s,
                 edgecolors='k')
c = plt.scatter(X_outliers[:, 0], X_outliers[:, 1], c='gold', s=s,
                edgecolors='k')
plt.axis('tight')
plt.xlim((-5, 5))
plt.ylim((-5, 5))
plt.legend([a.collections[0], b1, b2, c],
           ["learned frontier", "training observations",
            "new regular observations", "new abnormal observations"],
           loc="upper left",
           prop=matplotlib.font_manager.FontProperties(size=11))
plt.xlabel(
    "error train: %d/200 ; errors novel regular: %d/40 ; "
    "errors novel abnormal: %d/40"
    % (n_error_train, n_error_test, n_error_outliers))
plt.show()

(1)獲取更多優質內容及精彩資訊,可前往:https://www.cda.cn/?seo

(2)瞭解更多數據領域的優質課程:

機器學習經典算法之k-means聚類

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章