Почему эти чистые данные дают странные результаты классификации SVM?

Моя проблема и вопрос ниже выделены жирным шрифтом.

Я успешно использовал векторные машины поддержки от Accord.NET, следуя примерам на их страницах документации, например . Однако при использовании KernelSupportVectorMachine = "html" = "html": accord-framework.net/docs/html/T_Accord_MachineLearning_VectorMachines_Learning_OneclassSupportVectorLearning.htm "rel =" nofollow "> OneclassSupportVectorLearning, класс процесса обучения приводит к большим ошибкам и неправильным значениям.

Следующий мнимый пример показывает, что я имею в виду. Он генерирует плотный кластер обучающих точек, а затем обучает SVM классифицировать точки как выпадающие или выпадающие для кластера. Обучающий кластер представляет собой квадрат размером 0,6 на 0,6 с центром в начале координат, а обучающие точки расположены с интервалом 0,1:

static void Main(string[] args)
{
    // Model and training parameters
    double kernelSigma = 0.1;
    double teacherNu = 0.5;
    double teacherTolerance = 0.01;


    // Generate input point cloud, a 0.6 x 0.6 square centered at 0,0.
    double[][] trainingInputs = new double[49][];
    int inputIdx = 0;
    for (double x = -0.3; x <= 0.31; x += 0.1) {
        for (double y = -0.3; y <= 0.31; y += 0.1) {
            trainingInputs[inputIdx] = new double[] { x, y };
            inputIdx++;
        }
    }


    // Generate inlier and outlier test points.
    double[][] outliers =
    {
        new double[] { 1E6, 1E6 },  // Very far outlier
        new double[] { 0, 1E6 },    // Very far outlier
        new double[] { 100, -100 }, // Far outlier
        new double[] { 0, -100 },   // Far outlier
        new double[] { -10, -10 },  // Still far outlier
        new double[] { 0, -10 },    // Still far outlier
    };
    double[][] inliers =
    {
        new double[] { 0, 0 },      // Middle of cluster
        new double[] { .15, .15 },  // Halfway to corner of cluster
        new double[] { -0.1, 0 },   // Comfortably inside cluster
        new double[] { 0.25, 0 }    // Near inside edge of cluster
    };


    // Construct the kernel, model, and trainer, then train.
    Console.WriteLine($"Training model with parameters:");
    Console.WriteLine($"  kernelSigma = {kernelSigma.ToString("#.##")}");
    Console.WriteLine($"  teacherNu={teacherNu.ToString("#.##")}");
    Console.WriteLine($"  teacherTolerance={teacherTolerance}");
    Console.WriteLine();

    var kernel = new Gaussian(kernelSigma);
    var svm = new KernelSupportVectorMachine(kernel, inputs: 1);
    var teacher = new OneclassSupportVectorLearning(svm, trainingInputs)
    {
        Nu = teacherNu,
        Tolerance = teacherTolerance
    };
    double error = teacher.Run();

    Console.WriteLine($"Training complete - error is {error.ToString("#.##")}");
    Console.WriteLine();


    // Test trained classifier.
    Console.WriteLine("Testing outliers:");
    foreach (double[] outlier in outliers) {
        WriteResultDetail(svm, outlier);
    }
    Console.WriteLine();
    Console.WriteLine("Testing inliers:");
    foreach (double[] inlier in inliers) {
        WriteResultDetail(svm, inlier);
    }
}

private static void WriteResultDetail(KernelSupportVectorMachine svm, double[] coordinate)
{
    string prettyCoord = $"{{ {string.Join(", ", coordinate)} }}".PadRight(20);
    Console.Write($"Classifying: {prettyCoord} Result: ");

    // Classify coordinate, print results.
    double result = svm.Compute(coordinate);
    if (Math.Sign(result) == 1) {
        Console.Write("Inlier");
    }
    else {
        Console.Write("Outlier");
    }
    Console.Write($" ({result.ToString("#.##")})\n");
}

Вот результат для разумного набора параметров:

Training model with parameters:
  kernelSigma = .1
  teacherNu=.5
  teacherTolerance=0.01

Training complete - error is 222.4

Testing outliers:
Classifying: { 1000000, 1000000 } Result: Inlier (2.28)
Classifying: { 0, 1000000 }       Result: Inlier (2.28)
Classifying: { 100, -100 }        Result: Inlier (2.28)
Classifying: { 0, -100 }          Result: Inlier (2.28)
Classifying: { -10, -10 }         Result: Inlier (2.28)
Classifying: { 0, -10 }           Result: Inlier (2.28)

Testing inliers:
Classifying: { 0, 0 }             Result: Inlier (4.58)
Classifying: { 0.15, 0.15 }       Result: Inlier (4.51)
Classifying: { -0.1, 0 }          Result: Inlier (4.55)
Classifying: { 0.25, 0 }          Result: Inlier (4.64)

Число в скобках - это оценка, присвоенная SVM для этой координаты. С SVM от Accord.NET (и в целом) отрицательная оценка - это один класс, а положительная - другая. Здесь все имеет положительную оценку. Выбросы классифицируются правильно, но выбросы (даже очень) также классифицируются как выбросы.

Обратите внимание, что в любой другой раз, когда я обучал модели с Accord.NET, ошибка обучения была довольно близка к нулю, но здесь она превышает 200.

Вот еще один вывод набора параметров:

Training model with parameters:
  kernelSigma = .3
  teacherNu=.8
  teacherTolerance=0.01

Training complete - error is 1945.67

Testing outliers:
Classifying: { 1000000, 1000000 } Result: Inlier (20.96)
Classifying: { 0, 1000000 }       Result: Inlier (20.96)
Classifying: { 100, -100 }        Result: Inlier (20.96)
Classifying: { 0, -100 }          Result: Inlier (20.96)
Classifying: { -10, -10 }         Result: Inlier (20.96)
Classifying: { 0, -10 }           Result: Inlier (20.96)

Testing inliers:
Classifying: { 0, 0 }             Result: Inlier (44.52)
Classifying: { 0.15, 0.15 }       Result: Inlier (41.62)
Classifying: { -0.1, 0 }          Result: Inlier (43.85)
Classifying: { 0.25, 0 }          Result: Inlier (40.53)

Опять же, очень высокая ошибка обучения, все положительные оценки.

Модели определенно получают кое-что от обучения - оценки различаются между инлиссирующими и выпадающими значениями. Но почему этот простой сценарий не дает результатов, которые различаются положительным и отрицательным знаком, как должны?


PS. Вот аналогичная программа, которая тестирует многие комбинации параметров обучения и модели, а также вот его результат. Опять же, все приводит к положительным результатам классификации, высоким значениям ошибок и неправильно классифицированным выбросам.


person kdbanman    schedule 28.07.2016    source источник
comment
Пожалуйста, откройте проблему в системе отслеживания проблем проекта   -  person Cesar    schedule 09.07.2017
comment
Эта проблема была исправлена ​​в версии v3.7.0.   -  person Cesar    schedule 22.08.2017


Ответы (1)