当前位置:   article > 正文

机器学习基础(十)—异常检测_异常检测交叉验证

异常检测交叉验证

异常数据检查

  • 假设我们已经收集到了一些数据集,并希望利用这些数据形成一个模型P,当我们输入测试样本x_test,这个模型能够帮我们判断这个样本是否为异常数据(数据分布如下图所示)。
    在这里插入图片描述

1 参数估计

  • 概念:给定不带标签的数据集,来近似的估计出正态分布的期望值与方差。

  • 期望:每个特征的期望可以通过求每个特征的均值来获得。

  • 方差:通过样本与期望之差的平方除以样本总数来估计方差。
    (注:这同时也称为μ与σ的极大似然估计)
    在这里插入图片描述

2 异常检测程序

  1. 选择能够表现出异常样本的特征
  2. 利用参数估计,计算出期望和方差
  3. 然后给定一个新样本,来计算样本的密度
  4. 看密度是否小于阀值来判断该样本是否为异常值
    在这里插入图片描述
  • 假设我们有一些样本,每个样本具有两个特征值x_1,x_2。从下方的三维图中可以比较直观的看出,粉色圈之外的P都是密度比较低的,也就是说这些点出现的概率是比较小的。那么当出现这些点时,就要注意这是否为异常值了。
    在这里插入图片描述

3 异常检测分组

  1. 假设我们有10000个正常的样本,20个异常样本。将这些样本分为训练集(6000个好样本),交叉验证集(2000个好样本,10个异常样本)和测试集(2000个好样本,10个异常样本)。 在这里插入图片描述
  2. 然后使用训练集计算出一个模型。接着用交叉验证集和测试集来测试y=0/1的数量。
  3. 最后利用准确性和召回来计算F值。(注:通过使用不同的阀值来获取最大的F值)

在这里插入图片描述

4 何时用异常检测和监督学习?

  • 异常检测:当我们的正样本数量很少时,我们很难让我们的算法从正样本当中学习到一定的规律,并且异常出现的情况可能也有很大的不同。

  • 监督学习:我们有足够多的正样本,因此我们的算法能够从这些样本中学习到一定的规律,从而进行预测。

在这里插入图片描述

5 误差分析思想

  • 首先检验异常样本,观察异常样本当中是否存在某些规律,然后重新创建一个新的特征值。

在这里插入图片描述

比如说我的四个特征值当中,经常出现CPU很高,但是网络流量比较低,那么这个时候就可以创建一个新的特征值用(CPU2)或(CPU)/网络流量。

在这里插入图片描述

6 多变量异常检测

  • 多元高斯分布密度公式
    在这里插入图片描述

  • Σ的第一行第一列是x1的方差,第二行第二列是x2的方差。当方差变小是,坡度就会变陡,当方差变大时,坡度就会变大,如下图所示。
    在这里插入图片描述

  • 测试相关性

如果改变协方差,就会得到不同的高斯分布,下图可看到,x与y时一起增加的。
在这里插入图片描述

如果将协方差变为负数,还会出现同样趋势的话,那么这个时候我们就可以看出,x1与x2是呈现除负相关的。
在这里插入图片描述

7 代码实战:

  1. 读取数据
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import os
from scipy.io import loadmat
os.chdir('E:/Data/Ng/Coursera-ML-AndrewNg-Notes-master/code/ex8-anomaly detection and recommendation/data/')
data = loadmat('ex8data1.mat')
data
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

数据如下:
在这里插入图片描述

  1. 查看分布
X = data['X']
fig,ax = plt.subplots(figsize=(12,8))
ax.scatter(X[:,0],X[:,1],s=50)
plt.show()
  • 1
  • 2
  • 3
  • 4

分布情况如下:
在这里插入图片描述

  1. 参数估计每个特征值的期望和方差,并利用参数拟合模型,计算训练集每个数据的概率密度函数
from scipy import stats
def compute(X):
    """计算期望值与方差
    Params:
        X:训练集数据
    return:
        X1_mean,X1_sigma,X2_mean,X2_sigma"""
    m = X.shape[0]
    X1 = X[:,0]
    X2 = X[:,1]
    X1_mean = X1.mean()
    X2_mean = X2.mean()
    X1_sigma = np.power(X1-X1_mean,2).mean()
    X2_sigma = np.power(X2-X2_mean,2).mean()
    return X1_mean,X1_sigma,X2_mean,X2_sigma


if __name__ == '__main__':
	X1_mean,X1_sigma,X2_mean,X2_sigma=compute(X)
	p = np.zeros((X.shape[0],X.shape[1]))
	p[:,0] = stats.norm(X1_mean,X1_sigma).pdf(X[:,0])
	p[:,1] = stats.norm(X2_mean,X2_sigma).pdf(X[:,1])
	p.shape
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

结果如下:
在这里插入图片描述

  1. 利用训练好的模型计算交叉训练集每个样本的概率密度
def val_pd(Xval,X1_mean,X1_sigma,X2_mean,X2_sigma):
    """利用训练好的模型来计算交叉验证集的概率密度
    Param:
        Xval:交叉验证集数据"""
    p_val = np.zeros((Xval.shape[0],Xval.shape[1]))
    p_val[:,0] = stats.norm(X1_mean,X1_sigma).pdf(Xval[:,0])
    p_val[:,1] = stats.norm(X2_mean,X2_sigma).pdf(Xval[:,1])
    return p_val

if __name__ == '__main__':
    Xval = data['Xval']
    yval = data['yval']
    p_val = val_pd(Xval,X1_mean,X1_sigma,X2_mean,X2_sigma)
    p_val.shape
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

结果如下:
在这里插入图片描述

  1. 寻找合适的阀值
    在这里插入图片描述
def select_threshold(p_val,yval):
    """选择最优阀值
    Params:
        p_val:运用训练好的模型计算出来的交叉集的概率密度
        yval:交叉集数据对应的真实标签
    return:
        best_threshod:最终阀值
        best_f1:最好的f值"""
    best_threshod = 0 
    best_f1 = 0
    f1 = 0
    step = (p_val.max()-p_val.min())/1000
    for epsilon in np.arange(p_val.min(),p_val.max(),step):
        preds = p_val < epsilon
        # np.logical_and(x1==1,x2==2) 检查两个narray在对应位置上的数据是否一致,默认返回bool型
        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)
        
        prec = tp/(tp+fp)
        rec = tp/(tp+fn)
        f1 = (2*prec*rec)/(prec+rec)
        if f1>best_f1:
            best_f1 = f1
            best_threshod = epsilon
    return best_threshod,best_f1

if __name__ == "__main__":
    best_threshod,best_f1 = select_threshold(p_val,yval)
    best_threshod,best_f1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

在这里插入图片描述

  1. 绘制出训练集当中的异常点
outliners = np.where(p<best_threshod)
outliners
fig,ax = plt.subplots(figsize=(12,8))
ax.scatter(X[:,0],X[:,1])
ax.scatter(X[outliners[0],0],X[outliners[0],1],color='red')
plt.show()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

结果如下:
在这里插入图片描述

参考资料:

  1. Ng机器学习
  2. 黄博笔记
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/320261?site
推荐阅读
相关标签
  

闽ICP备14008679号