机器学习作业---异常检测

一:异常检测回顾

异常检测也是一个无监督学习算法

(一)异常检测做什么?

从一组数据中找到那些“异常”的数据,基于高斯分布(正态分布)。

生活中的很多事情都是符合高斯分布的,对于数据也是如此。

我们通过参数估计,估计出数据符合的高斯分布参数,当其中的数据分布在高斯分布中概率很小的地方,就认为这是异常数据。

(二)具体怎么做?

选择那些你认为处于异常状态(有反常样本)的特征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)

posted @ 2020-05-24 17:58  山上有风景  阅读(775)  评论(3编辑  收藏  举报