一:異常檢測回顧
異常檢測也是一個無監督學習算法
(一)異常檢測做什么?
從一組數據中找到那些“異常”的數據,基於高斯分布(正態分布)。
生活中的很多事情都是符合高斯分布的,對於數據也是如此。
我們通過參數估計,估計出數據符合的高斯分布參數,當其中的數據分布在高斯分布中概率很小的地方,就認為這是異常數據。
(二)具體怎么做?
選擇那些你認為處於異常狀態(有反常樣本)的特征xj作為輸入:(下面是該xj特征的樣本)

根據上面每個特征的樣本數據估計高斯分布的參數(對每一個特征)

對於一個新的數據,預測其發生概率

當概率小於一定閾值后認定為異常。
(三)這個算法有什么缺點?
可以看到,之前的模型中對每個特征都是獨立地處理,最后的組合只是簡單的相乘。這樣就是存在一些問題,特征之間的關聯沒有捕捉到。
升級的方式就是多元高斯分布,將不再單獨考慮特征,而是將特征一起考慮,自動捕捉之間的關聯。
參數的估計變為,其中的sigma為協方差矩陣:

預測變為:

這個模型有個前提就是m>n,而且協方差矩陣是非奇異矩陣。另外這個計算也是復雜的。
(四)怎么評估算法的效果?
使用標簽化的數據,計算F1score:

查准率和查全率公式:



二:作業介紹
在本練習中,將實現一個異常檢測算法來檢測服務器計算機中的異常行為。這些特性度量每個服務器的吞吐量(mb/s)和響應延遲(ms)。在您的服務器運行時,您收集了m = 307個關於它們行為的示例,因此有一個未標記的dataset {x(1),…,x(m)}。您懷疑這些示例中的絕大多數都是服務器正常運行的“正常”(非異常)示例,但是也可能有一些服務器在這個數據集中異常運行的示例。
將使用高斯模型來檢測數據集中的異常示例。您將首先從一個2D數據集開始,該數據集將允許您可視化算法在做什么。在該數據集上,將擬合高斯分布,然后找到概率非常低的值,因此可以考慮異常。之后,您將把異常檢測算法應用於具有多個維度的較大數據集
三:數據導入及可視化
import numpy as np import matplotlib.pyplot as plt import scipy.io as sio data = sio.loadmat("ex8data1.mat") X = data['X'] Xval = data['Xval'] #獲取驗證集 yval = data['yval'].flatten() print(X.shape) print(Xval.shape,yval.shape) plt.figure() plt.scatter(X[:,0],X[:,1],c='b',marker='x',s=15,linewidths=1) plt.show()
![]()

四:估計高斯分布的參數(對每一個特征)均值和方差

def estimate_gussian(X): mu = np.mean(X,0) sigma2 = np.sum(np.power(X-mu,2),0)/X.shape[0] return mu,sigma2
data = sio.loadmat("ex8data1.mat") X = data['X'] Xval = data['Xval'] #獲取驗證集 yval = data['yval'].flatten() mu,sigma2 = estimate_gussian(X) print(mu) print(sigma2)

五:實現高斯分布模型

def gaussian_distribution(X,mu,sigma2): p = (1/np.sqrt(2*np.pi*sigma2))*np.exp(-np.power((X-mu),2)/(2*sigma2)) return np.prod(p,axis=1) #橫向累乘
px = gaussian_distribution(X,mu,sigma2) print(px.shape) print(px[:10])

六:繪制輪廓線,進行可視化
def visualize_countours(mu,sigma2): #繪制高斯分布等高線 #由上圖可以知道,我們選取5-25,范圍比較合適 x = np.linspace(5,25,100) y = np.linspace(5,25,100) xx,yy =np.meshgrid(x,y) X = np.c_[xx.flatten(),yy.flatten()] #數據對應網格中每一個點 z = gaussian_distribution(X,mu,sigma2).reshape(xx.shape) #獲取每一個點坐標的高斯值 cont_levels = [10 ** h for h in range(-20, 0, 3)] #當z為當前列表的值才繪出等高線(最高1) 不設置的話,會比較奇怪 plt.contour(xx,yy,z,cont_levels)
data = sio.loadmat("ex8data1.mat") X = data['X'] Xval = data['Xval'] #獲取驗證集 yval = data['yval'].flatten() mu,sigma2 = estimate_gussian(X) px = gaussian_distribution(X,mu,sigma2) plt.figure() visualize_countours(mu,sigma2) plt.scatter(X[:,0],X[:,1],c='b',marker='x',s=15,linewidths=1) plt.show()

七:選擇閾值
取最好的F1分數及對應的閾值進行返回
計算F1score:

查准率和查全率公式:

def select_threshold(yval,pval): #yval是驗證集標簽 0或者1,pval是我們進行高斯處理后得到的概率在[0,1]之間 best_eps = 0 best_f1 = 0 for epsilon in np.linspace(np.min(pval),np.max(pval),num=1001): predictions = np.where(pval < epsilon, 1, 0) # 小於epsilon則預測為異常(為真) 滿足條件返回1,不滿足返回0 tp = np.sum(yval[np.where(predictions==1)]) #正確肯定 上面預測的為1,並且yval中也是1,我們才進行添加 fp = np.sum(np.where(yval[np.where(predictions==1)]==0,1,0)) #錯誤肯定 預測為真,實際為假 fn = np.sum(np.where(yval[np.where(predictions==0)]==1,1,0)) #錯誤否定 #計算查准率和查全率 if tp+fp == 0 or tp + fn ==0: continue prec = tp / (tp + fp) # 查准率 rec = tp / (tp + fn) # 查全率 #計算F1-score f1 = 2*prec*rec/(prec+rec) if f1 > best_f1: best_f1 = f1 best_eps = epsilon return best_eps,best_f1
mu,sigma2 = estimate_gussian(X) #利用訓練集獲取均值方差 px = gaussian_distribution(Xval,mu,sigma2) #利用驗證集數據,獲取高斯概率 eps,f1 = select_threshold(yval,px) #利用驗證集標簽進行判斷,獲取閾值 print(eps,f1)

八:根據閾值來判斷異常
def detection(X,eps,mu,sigma2): px = gaussian_distribution(X,mu,sigma2) #獲取訓練集的高斯分布值 #進行判斷異常點 anomaly_points = X[np.where(px<eps)] return anomaly_points
def circle_anomaly_points(X): #將異常點圈出 plt.scatter(X[:,0],X[:,1],s=80,facecolors='none', edgecolors='r')
data = sio.loadmat("ex8data1.mat") X = data['X'] Xval = data['Xval'] #獲取驗證集 yval = data['yval'].flatten() mu,sigma2 = estimate_gussian(X) px = gaussian_distribution(Xval,mu,sigma2) eps,f1 = select_threshold(yval,px) anomaly_points = detection(X,eps,mu,sigma2) plt.figure() visualize_countours(mu,sigma2) circle_anomaly_points(anomaly_points) plt.scatter(X[:,0],X[:,1],c='b',marker='x',s=15,linewidths=1) plt.show()

九:高維數據異常檢測
import numpy as np import matplotlib.pyplot as plt import scipy.io as sio def estimate_gussian(X): mu = np.mean(X,0) sigma2 = np.sum(np.power(X-mu,2),0)/X.shape[0] return mu,sigma2 def gaussian_distribution(X,mu,sigma2): #獲取高斯模型p(x)值 p = (1/np.sqrt(2*np.pi*sigma2))*np.exp(-np.power((X-mu),2)/(2*sigma2)) return np.prod(p,axis=1) #橫向累乘 def select_threshold(yval,pval): #yval是驗證集標簽 0或者1,pval是我們進行高斯處理后得到的概率在[0,1]之間 best_eps = 0 best_f1 = 0 for epsilon in np.linspace(np.min(pval),np.max(pval),num=1001): predictions = np.where(pval < epsilon, 1, 0) # 小於epsilon則預測為異常(為真) 滿足條件返回1,不滿足返回0 tp = np.sum(yval[np.where(predictions==1)]) #正確肯定 上面預測的為1,並且yval中也是1,我們才進行添加 fp = np.sum(np.where(yval[np.where(predictions==1)]==0,1,0)) #錯誤肯定 預測為真,實際為假 fn = np.sum(np.where(yval[np.where(predictions==0)]==1,1,0)) #錯誤否定 #計算查准率和查全率 if tp+fp == 0 or tp + fn ==0: continue prec = tp / (tp + fp) # 查准率 rec = tp / (tp + fn) # 查全率 #計算F1-score f1 = 2*prec*rec/(prec+rec) if f1 > best_f1: best_f1 = f1 best_eps = epsilon return best_eps,best_f1 def detection(X,eps,mu,sigma2): px = gaussian_distribution(X,mu,sigma2) #獲取訓練集的高斯分布值 #進行判斷異常點 anomaly_points = X[np.where(px<eps)] return anomaly_points def visualize_countours(mu,sigma2): #繪制高斯分布等高線 #由上圖可以知道,我們選取5-25,范圍比較合適 x = np.linspace(5,25,100) y = np.linspace(5,25,100) xx,yy =np.meshgrid(x,y) X = np.c_[xx.flatten(),yy.flatten()] #數據對應網格中每一個點 z = gaussian_distribution(X,mu,sigma2).reshape(xx.shape) #獲取每一個點坐標的高斯值 cont_levels = [10 ** h for h in range(-20, 0, 3)] #當z為當前列表的值才繪出等高線(最高1) 不設置的話,會比較奇怪 plt.contour(xx,yy,z,cont_levels) def circle_anomaly_points(X): #將異常點圈出 plt.scatter(X[:,0],X[:,1],s=80,facecolors='none', edgecolors='r') data = sio.loadmat("ex8data2.mat") X = data['X'] print(X.shape) Xval = data['Xval'] #獲取驗證集 yval = data['yval'].flatten() mu,sigma2 = estimate_gussian(X) px = gaussian_distribution(Xval,mu,sigma2) print(px) #(1000, 11) eps,f1 = select_threshold(yval,px) print(eps,f1) anomaly_points = detection(X,eps,mu,sigma2) print(anomaly_points)




