zoukankan      html  css  js  c++  java
  • 异常检测 与 One Class SVM

    异常检测

    我们经常需要识别一些异常行为或者表现,比如 机器是否故障,产品是否合格,这类问题的特点就是 正常数据很多,异常数据很少,甚至根本没有

    解决这种问题的思路就是,把 训练样本中 一小部分数据认为是 异常数据,然后训练一个 非常紧凑的决策边界,把 大部分被认为是正常的样本 框起来,并以此边界作为衡量标准,边界外就是异常;

    如下图

    这种算法我们称为 单分类算法

    解决单分类问题的算法有很多,如

    1. 孤立森林:我的博客

    2. 自编码器:我的博客

    把 自编码器 用来做 异常检测 真的很奇妙,它的思路是,用正常样本训练 自编码器, 输入和输出一定相差不大,如果新的样本通过自编码器,输入和输出相差很大,就是异常样本;

    3. One Class SVM:这种方法类似于 SVM,在理解 SVM 的基础上,这个算法没有什么好讲的,所以不单独写一篇博客了;

    由于 SVM 在核函数计算时速度很慢,故不适合海量数据,而 孤立森林 可运行在分布式系统上,自编码器 可用 GPU 进行加速,适合海量数据;

    One Class SVM

    sklearn 提供了一些机器学习算法,用于 奇异点(Novelty) 或者 异常点(Outlier) 检测;

    novelty detection:训练样本中没有离群点,我们用训练好的模型去检测,边界外的就是异常;      【自编码器】

    outlier  dection:训练样本中存在离群点,训练模型时要匹配密集样本,忽略离群点;   【孤立森林】

    One Class SVM 既可以是 novelty,也可以是 Outlier,当然,严格的讲,它应该属于 novelty,但实际上训练样本都会存在噪音,我们需要绕过噪音,得到一个干净的模型,这就是 Outlier;

    One Class SVM 是一种无监督算法,它的思想是 寻找一个 超球面,使得 正常样本 在球体内,异常样本在球体外,然后 最小化这个球 的半径或者体积;

    其中 o 是球心,r 是半径,V(r) 是球的体积,c 是惩罚系数,ξ 是松弛变量;    【基本上等同于 SVM 我的博客

    SVDD 介绍

    解决  One Class SVM 的方法很多, SVDD 就是其中一种,SVDD 的思路仍然类似于上面的公式,但略作简化

    s.t.

    再来张图把

    sklearn API

    官网示例

    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()

    nu 代表异常样本的占比,nu 越大,R 越小,条件越 苛刻 

    优化

    基于蚁群算法的优化 ,可以参考下

    参考资料:

    https://www.cnblogs.com/wj-1314/p/10701708.html#top

    https://blog.csdn.net/a1154761720/article/details/50708398

  • 相关阅读:
    redis问题排查
    javassist介绍
    Idea创建父子工程
    sentry的配置
    Redis的基本操作以及info命令
    es~日期类型需要注意的
    jboss~静态文件路由和自定义日志
    java~RMI引起的log4j漏洞
    链路跟踪~对接阿里ARMS
    navicat~导出数据库密码
  • 原文地址:https://www.cnblogs.com/yanshw/p/12575816.html
Copyright © 2011-2022 走看看