【问题标题】:[scikit learn]: Anomaly Detection - Alternative for OneClassSVM[scikit learn]:异常检测 - OneClassSVM 的替代方案
【发布时间】:2013-09-28 23:51:20
【问题描述】:

我已经从 sklearn-framework 实现了 LinearSVC 和 SVC 用于文本分类。 我正在使用 TfidfVectorizer 来获取由两个不同类(良性数据和恶意数据)组成的输入数据的稀疏表示。这部分工作得很好,但现在我想通过使用 OneClassSVM 分类器并训练一个只有一个类的模型(异常值检测......)来实现某种异常检测。不幸的是,它不适用于稀疏数据。一些开发人员正在开发补丁 (https://github.com/scikit-learn/scikit-learn/pull/1586),但存在一些错误,因此尚无使用 OneClassSVM 实现的解决方案。

sklearn-framework 中是否还有其他方法可以做类似的事情?我正在查看示例,但似乎没有任何内容适合。

谢谢!

【问题讨论】:

    标签: python machine-learning svm scikit-learn


    【解决方案1】:

    有点晚了,但万一其他人正在寻找这方面的信息……这里有一个用于 sklearn 的第三方异常检测模块:http://www.cit.mak.ac.ug/staff/jquinn/software/lsanomaly.html,基于最小二乘法。它应该是 OneClassSVM 的插件替代品。

    【讨论】:

      【解决方案2】:

      不幸的是,scikit-learn 目前implements 只有一类 SVM 和鲁棒的协方差估计器用于异常值检测

      您可以通过检查二维数据的差异来尝试比较这些方法 (as provided in the doc):

      import numpy as np
      import pylab as pl
      import matplotlib.font_manager
      from scipy import stats
      
      from sklearn import svm
      from sklearn.covariance import EllipticEnvelope
      
      # Example settings
      n_samples = 200
      outliers_fraction = 0.25
      clusters_separation = [0, 1, 2]
      
      # define two outlier detection tools to be compared
      classifiers = {
          "One-Class SVM": svm.OneClassSVM(nu=0.95 * outliers_fraction + 0.05,
                                           kernel="rbf", gamma=0.1),
          "robust covariance estimator": EllipticEnvelope(contamination=.1)}
      
      # Compare given classifiers under given settings
      xx, yy = np.meshgrid(np.linspace(-7, 7, 500), np.linspace(-7, 7, 500))
      n_inliers = int((1. - outliers_fraction) * n_samples)
      n_outliers = int(outliers_fraction * n_samples)
      ground_truth = np.ones(n_samples, dtype=int)
      ground_truth[-n_outliers:] = 0
      
      # Fit the problem with varying cluster separation
      for i, offset in enumerate(clusters_separation):
          np.random.seed(42)
          # Data generation
          X1 = 0.3 * np.random.randn(0.5 * n_inliers, 2) - offset
          X2 = 0.3 * np.random.randn(0.5 * n_inliers, 2) + offset
          X = np.r_[X1, X2]
          # Add outliers
          X = np.r_[X, np.random.uniform(low=-6, high=6, size=(n_outliers, 2))]
      
          # Fit the model with the One-Class SVM
          pl.figure(figsize=(10, 5))
          for i, (clf_name, clf) in enumerate(classifiers.iteritems()):
              # fit the data and tag outliers
              clf.fit(X)
              y_pred = clf.decision_function(X).ravel()
              threshold = stats.scoreatpercentile(y_pred,
                                                  100 * outliers_fraction)
              y_pred = y_pred > threshold
              n_errors = (y_pred != ground_truth).sum()
              # plot the levels lines and the points
              Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
              Z = Z.reshape(xx.shape)
              subplot = pl.subplot(1, 2, i + 1)
              subplot.set_title("Outlier detection")
              subplot.contourf(xx, yy, Z, levels=np.linspace(Z.min(), threshold, 7),
                               cmap=pl.cm.Blues_r)
              a = subplot.contour(xx, yy, Z, levels=[threshold],
                                  linewidths=2, colors='red')
              subplot.contourf(xx, yy, Z, levels=[threshold, Z.max()],
                               colors='orange')
              b = subplot.scatter(X[:-n_outliers, 0], X[:-n_outliers, 1], c='white')
              c = subplot.scatter(X[-n_outliers:, 0], X[-n_outliers:, 1], c='black')
              subplot.axis('tight')
              subplot.legend(
                  [a.collections[0], b, c],
                  ['learned decision function', 'true inliers', 'true outliers'],
                  prop=matplotlib.font_manager.FontProperties(size=11))
              subplot.set_xlabel("%d. %s (errors: %d)" % (i + 1, clf_name, n_errors))
              subplot.set_xlim((-7, 7))
              subplot.set_ylim((-7, 7))
          pl.subplots_adjust(0.04, 0.1, 0.96, 0.94, 0.1, 0.26)
      
      pl.show()
      

      【讨论】:

        猜你喜欢
        • 2018-03-25
        • 2020-10-20
        • 2015-04-08
        • 2016-02-17
        • 2017-03-09
        • 2016-04-15
        • 2019-07-21
        • 2023-03-06
        • 2016-09-24
        相关资源
        最近更新 更多