【问题标题】:In Accord.Net how to use One-Class SVM for anomaly detection?在 Accord.Net 中如何使用 One-Class SVM 进行异常检测?
【发布时间】:2018-02-16 02:26:02
【问题描述】:

我正在尝试通过在 Accord.Net 中使用 OneclassSupportVectorLearning 来实现异常检测。我在训练过程中遇到了 NullReference 错误。下面是我在测试中的示例代码。 感谢是否有人可以帮助我解决这个问题。

 double[][] inputs =
 {
    new double[] { 0, 1, 1, 0 }, //  0 
    new double[] { 0, 1, 0, 0 }, //  0
    new double[] { 0, 0, 1, 0 }, //  0
    new double[] { 0, 1, 1, 0 }, //  0
    new double[] { 0, 1, 0, 0 }, //  0
 };
 var oteacher = new OneclassSupportVectorLearning<ChiSquare,double[]>();
 var k = oteacher.Learn(inputs); //NullReference error occur here. 

编辑------------------------------ ----------------------

根据 Jstreet 的评论,尝试下面的代码,但它适用于 2-dim,但在更高维度上会失败。

static void Main(string[] args)
{
Random r = new Random(DateTime.Now.Millisecond);

int size = 1000;
int min = 45;
int max = 55;

double[][] inputs = new double[size][];

for (int i = 0; i < size; i++)
{
    double[] d = new double[] { r.Next(min,max), r.Next(min,max), r.Next(min,max), r.Next(min,max) };
    inputs[i] = d;
}

var oteacher = new OneclassSupportVectorLearning<ChiSquare>();
var k = oteacher.Learn(inputs);

double[][] test =
 {
    // normal
    new double[] { 50, 53 , 50, 50}, 
    new double[] { 49, 52 , 50, 50},
    new double[] { 48, 51 , 50, 50},
    new double[] { 47, 52 , 50, 50},
    new double[] { 46, 53 , 50, 50},
    // anomalies
    new double[] { 50, 70, 70, 70 }, 
    new double[] { 51, 69, 70, 70 },
    new double[] { 52, 68, 70, 70 },
    new double[] { 53, 67, 70, 70 },
    new double[] { 54, 66, 70, 70 },
 };

foreach (double[] d in test)
{
    if (k.Decide(d) == true)
        Console.WriteLine(" OK = {0}, {1}, {2}, {3}", d[0], d[1], d[2], d[3]);
    else Console.WriteLine(" Anomaly = {0}, {1}, {2}, {3}", d[0], d[1], d[2], d[3]);
}

Console.ReadLine();

}

【问题讨论】:

  • 更新到版本 3.4.2-alpha.
  • 感谢 jstress!我尝试了最新的预版本,它现在可以运行了。当它完成学习时,我通过传回训练集来运行“k.Decide(inputs)”方法。但它只是返回整个训练集的所有“假”(假设都是“真”)。我在这里检查了代码,根据在线文档它应该是有效的。不胜感激,如果你能分享我更多的提示。

标签: c# .net machine-learning svm accord.net


【解决方案1】:

我建议您尝试使用二维数据集,以便将结果可视化并感受一下:

    static void Main(string[] args)
    {
        Random r = new Random(DateTime.Now.Millisecond);

        int size = 100;
        int min = 45;
        int max = 55;

        double[][] inputs = new double[size][];

        for (int i = 0; i < size; i++)
        {
            double[] d = new double[] { r.Next(min,max), r.Next(min,max) };
            inputs[i] = d;
        }

        var oteacher = new OneclassSupportVectorLearning<ChiSquare>();
        var k = oteacher.Learn(inputs);

        double[][] test =
         {
            // normal
            new double[] { 50, 53 }, 
            new double[] { 49, 52 },
            new double[] { 48, 51 },
            new double[] { 47, 52 },
            new double[] { 46, 53 },
            // anomalies
            new double[] { 50, 70 }, 
            new double[] { 51, 69 },
            new double[] { 52, 68 },
            new double[] { 53, 67 },
            new double[] { 54, 66 },
         };

        foreach (double[] d in test)
        {
            if (k.Decide(d) == true)
                Console.WriteLine(" OK = {0}, {1}", d[0], d[1]);
            else Console.WriteLine(" Anomaly = {0}, {1}", d[0], d[1]);
        }

        Console.ReadLine();
    }

此示例代码生成以下输出:

 OK = 50, 53 
 OK = 49, 52 
 OK = 48, 51 
 OK = 47, 52 
 OK = 46, 53 
 Anomaly = 50, 70 
 Anomaly = 51, 69 
 Anomaly = 52, 68 
 Anomaly = 53, 67 
 Anomaly = 54, 66

这是相同结果的图形视图:


编辑:就像我说的,这需要一些实验。这是我对 4 维输入数据集的结果。请注意,我减少了每个维度的可变性并保持相同的输入大小,100。

    static void Main(string[] args)
    {
        Random r = new Random(DateTime.Now.Millisecond);

        int size = 100;
        int min = 45;
        int max = 50;
        int min2 = 60;
        int max2 = 65;

        double[][] inputs = new double[size][];

        for (int i = 0; i < size; i++)
        {
            double[] d = new double[] { r.Next(min, max), r.Next(min, max), r.Next(min, max), r.Next(min, max) };
            inputs[i] = d;
        }

        var oteacher = new OneclassSupportVectorLearning<ChiSquare>();
        var k = oteacher.Learn(inputs);

        double[][] test =
         {
            // normal
            new double[] {  r.Next(min, max),  r.Next(min, max), r.Next(min, max),  r.Next(min, max) },
            new double[] {  r.Next(min, max),  r.Next(min, max), r.Next(min, max),  r.Next(min, max) },
            new double[] {  r.Next(min, max),  r.Next(min, max), r.Next(min, max),  r.Next(min, max) },
            new double[] {  r.Next(min, max),  r.Next(min, max), r.Next(min, max),  r.Next(min, max) },
            new double[] {  r.Next(min, max),  r.Next(min, max), r.Next(min, max),  r.Next(min, max) },
            // anomalies
            new double[] {  r.Next(min2, max2),  r.Next(min2, max2), r.Next(min2, max2),  r.Next(min2, max2) },
            new double[] {  r.Next(min2, max2),  r.Next(min2, max2), r.Next(min2, max2),  r.Next(min2, max2) },
            new double[] {  r.Next(min2, max2),  r.Next(min2, max2), r.Next(min2, max2),  r.Next(min2, max2) },
            new double[] {  r.Next(min2, max2),  r.Next(min2, max2), r.Next(min2, max2),  r.Next(min2, max2) },
            new double[] {  r.Next(min2, max2),  r.Next(min2, max2), r.Next(min2, max2),  r.Next(min2, max2) },
         };

        foreach (double[] d in test)
        {
            if (k.Decide(d) == true)
                Console.WriteLine("OK = {0}, {1}, {2}, {3}", d[0], d[1], d[2], d[3]);
            else Console.WriteLine("Anomaly = {0}, {1}, {2}, {3}", d[0], d[1], d[2], d[3]);
        }

        Console.ReadLine();
    }

结果:

OK = 49, 46, 47, 49
OK = 49, 45, 45, 47
OK = 45, 45, 46, 47
OK = 47, 49, 47, 48
OK = 45, 45, 47, 48
Anomaly = 62, 60, 61, 63
Anomaly = 61, 63, 63, 64
Anomaly = 64, 60, 60, 64
Anomaly = 61, 64, 63, 63
Anomaly = 62, 60, 62, 62

【讨论】:

  • 再次感谢 Jstreet。但是当我尝试增加数据维度时,似乎无法正确预测真/假。
  • 尝试增加输入中的点数(size)。
  • 已经尝试了 5000 个输入样本,但它仍然给出了所有错误,按照我发布的示例代码。可能是 OneclassSupportVectorLearning 还不成熟?
  • 请看我的编辑
  • 似乎预测性能对每个维度内的方差非常敏感。如果我输入 min=30,max = 40, min2=60, max2=70,结果仍然是错误的,尽管这对人类来说是显而易见的:) 我会放一些真实的生产数据来尝试。
猜你喜欢
  • 2017-10-10
  • 2019-12-13
  • 2018-08-20
  • 2015-02-28
  • 2015-07-14
  • 1970-01-01
  • 2016-03-13
  • 2018-09-06
  • 1970-01-01
相关资源
最近更新 更多