https://wenku.baidu.com/view/ee9d9800cdbff121dd36a32d7375a417866fc131.html 使用kmeans算法做流量異常檢測 明確指出數據預處理需要規范化
例如網絡流量異常檢測方法,對網絡流量樣本數據進行歸一化和均值化處理,得到網絡流量樣本數據向量vk,1≤k≤M,M代表網絡流量樣本數據的類別數,對識別的網絡流量測試數據進行歸一化和均值化處理,得到網絡流量測試數據向量。
http://blog.csdn.net/sinat_31726559/article/details/52016652 含網絡流量異常檢測完整代碼 其找異常點代碼:
//度量新數據點到最近簇質心的距離 val distances = normalizedData.map(datum => distToCenter(datum, model)) //設置閥值為已知數據中離中心點最遠的第100個點到中心的距離 val threshold = distances.top(100).last //檢測,若超過該閥值就為異常點 (datum: Vector) => distToCenter(normalizeFunction(datum), model) > threshold
另外一個文章,kmeans聚類后會這樣找出異常點,我靠,貌似和上面的本質一樣:
//距離中心最遠的第100個點的距離 JavaDoubleRDD distances = labelsAndData.map(f -> f._2).mapToDouble(datum -> distToCentroid(datum, modelF)); Double threshold = distances.top(100).get(99); JavaRDD<Tuple2<String, Vector>> result = labelsAndData.filter(t -> distToCentroid(t._2, modelF) > threshold); System.out.println("result:---------"); result.foreach(f -> System.out.println(f._2));
代碼摘自 http://blog.csdn.net/zdy0_2004/article/details/52304771 其中還包括對k的最優選取等。
另外一個文章里是另外一種思路:http://blog.csdn.net/qq1010885678/article/details/51354486
使用歷史數據模型對全體數據進行聚類,使用這個聚類模型可以將數據中離質心最遠的點找出來。將這個點到質心的距離設置為閾值 當有新的數據進來時,判斷這個數據到其質心的距離是否超過這個閾值 超過就發出警報。給人感覺是歷史數據都是正常數據???
通過把數據聚成類,將那些不屬於任務一類的數據作為異常值。比如,使用基於密度的聚類DBSCAN,如果對象在稠密區域緊密相連,它們將被分組到一類。因此,那些不會被分到任何一類的對象就是異常值。
http://www.360doc.com/content/16/0827/21/20558639_586383718.shtml 也可以使用k-means算法來檢測異常。使用k-means算法,數據被分成k組,通過把它們分配到最近的聚類中心。然后,我們能夠計算每個對象到聚類中心的距離(或相似性),並且選擇最大的距離作為異常值。
http://blog.csdn.net/and_w/article/details/56481864 使用高斯聚類來做的 如下文
Anomaly Detection
我們的第一個任務是使用高斯模型來檢測數據集中一個未標記(unlabeled)的樣本是否應被視為異常。 我們從一個簡單的 2 維數據集開始,因此我們可以很容易地可視化這算法的工作原理。 讓我們 導入數據並畫出散點圖。
import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sb from scipy.io import loadmat %matplotlib inline data = loadmat('data/ex8data1.mat') X = data['X'] X.shape
(307L, 2L)
- 1
- 2
fig, ax = plt.subplots(figsize=(12,8)) ax.scatter(X[:,0], X[:,1])
- 1
- 2
看起來該聚類的中心十分緊密,只有幾個值遠離聚類中心。 在這個簡單的例子中,這些可以被認為是異常。 為了弄清楚這些,我們的任務是,估計數據中每個特征的高斯分布。 你可能還記得,為了定義概率分布,我們需要兩個東西——均值和方差。 為了實現這一點,我們將創建一個簡單的函數來計算數據集中每個特征的均值和方差。
def estimate_gaussian(X): mu = X.mean(axis=0) sigma = X.var(axis=0) return mu, sigma mu, sigma = estimate_gaussian(X) mu, sigma
(array([ 14.11222578, 14.99771051]), array([ 1.83263141, 1.70974533]))
現在有了我們模型的參數,我們需要確定概率閾值,其指示一個樣本是否應該被認為是異常。 為此,我們需要使用一組已被標記的驗證數據(其中真正的異常已經被標記出來了),並在不同閾值條件下測試模型識別異常的能力。
Xval = data['Xval'] yval = data['yval'] Xval.shape, yval.shape
((307L, 2L), (307L, 1L))
我們還需要一種方法能夠在給定參數下計算數據點屬於一個正態分布的概率。幸運的是, SciPy 已經內置了。
from scipy import stats dist = stats.norm(mu[0], sigma[0]) dist.pdf(X[:,0])[0:50]
array([ 0.183842 , 0.20221694, 0.21746136, 0.19778763, 0.20858956, 0.21652359, 0.16991291, 0.15123542, 0.1163989 , 0.1594734 , 0.21716057, 0.21760472, 0.20141857, 0.20157497, 0.21711385, 0.21758775, 0.21695576, 0.2138258 , 0.21057069, 0.1173018 , 0.20765108, 0.21717452, 0.19510663, 0.21702152, 0.17429399, 0.15413455, 0.21000109, 0.20223586, 0.21031898, 0.21313426, 0.16158946, 0.2170794 , 0.17825767, 0.17414633, 0.1264951 , 0.19723662, 0.14538809, 0.21766361, 0.21191386, 0.21729442, 0.21238912, 0.18799417, 0.21259798, 0.21752767, 0.20616968, 0.21520366, 0.1280081 , 0.21768113, 0.21539967, 0.16913173])
在不清楚的情況下,我們只計算了數據集的第一維的前 50 個樣本中的每一個屬於該分布的概率。 本質上,它計算的是每個實例與均值的距離,以及從均值角度比較這一“典型”距離。
讓我們在給定高斯模型參數情況下(上面計算過的)計算並保存數據集中每個值的概率密度.
p = np.zeros((X.shape[0], X.shape[1])) p[:,0] = stats.norm(mu[0], sigma[0]).pdf(X[:,0]) p[:,1] = stats.norm(mu[1], sigma[1]).pdf(X[:,1]) p.shape
(307L, 2L)
我們需要對驗證集進行相同的操作(使用相同的模型參數)。我們將使用這些概率再結合真標簽來確定指定為異常點的概率閾值。
pval = np.zeros((Xval.shape[0], Xval.shape[1])) pval[:,0] = stats.norm(mu[0], sigma[0]).pdf(Xval[:,0]) pval[:,1] = stats.norm(mu[1], sigma[1]).pdf(Xval[:,1])
- 1
- 2
- 3
接下來,我們需要一個只要給定概率密度值和真標簽就能找出最佳閾值的函數。 為此,我們需要計算不同的 ϵ 值的 F1 范數。 F1 范數 是真正( true positive)、假正(false positive)、假負(false negative)的函數。
def select_threshold(pval, yval): best_epsilon = 0 best_f1 = 0 f1 = 0 step = (pval.max() - pval.min()) / 1000 for epsilon in np.arange(pval.min(), pval.max(), step): preds = pval < epsilon tp = np.sum(np.logical_and(preds == 1, yval == 1)).astype(float) fp = np.sum(np.logical_and(preds == 1, yval == 0)).astype(float) fn = np.sum(np.logical_and(preds == 0, yval == 1)).astype(float) precision = tp / (tp + fp) recall = tp / (tp + fn) f1 = (2 * precision * recall) / (precision + recall) if f1 > best_f1: best_f1 = f1 best_epsilon = epsilon return best_epsilon, best_f1 epsilon, f1 = select_threshold(pval, yval) epsilon, f1
(0.0095667060059568421, 0.7142857142857143)
最后,我們將閾值應用到數據集並觀察結果。
# indexes of the values considered to be outliers outliers = np.where(p < epsilon) fig, ax = plt.subplots(figsize=(12,8)) ax.scatter(X[:,0], X[:,1]) ax.scatter(X[outliers[0],0], X[outliers[0],1], s=50, color='r', marker='o')
- 1
- 2
- 3
- 4
- 5
- 6
不錯! 紅色的點是被標記為異常值的點。 從視覺上來看這很合理。 右上那一點有一些分離(但沒有被標記)可能也是一個異常值,這已經很接近正確結果了。 應用其到高維數據集是練習文本的另一個例子,但由於它是二維情形的瑣碎擴展,我們將進入最后一節。