Я получаю противоречивые результаты с классификацией Accord.Net K-Means

У меня есть тестовая программа, которая не дает последовательных результатов для Accord.Net K-Means.

Я прилагаю воспроизводимую тестовую программу, которую можно запустить в Visual Studio 2013.

Программа представляет собой консольное приложение, и для воспроизведения результатов необходимо ссылаться:

  Accord.MachineLearning
  Accord.Statistics,

из библиотеки Accord.Net 2.15.

Когда я запускаю программу несколько раз, я каждый раз получаю разные результаты. Программа использует классический набор данных Fisher Iris. Набор данных имеет 150 строк, и я разделил данные на 120 строк данных обучения и 30 строк данных тестирования.

Когда я запускаю программу, я могу правильно классифицировать 26 из 30. Повторный запуск может дать 2 из 30 правильных ответов.

Например:

 Number correct: 2 out of 30
         FScore: NaN
      Precision: 0
 True Positives: 0
False Positives: 9
 True Negatives: 9
False Negatives: 12
       Accuracy: 0.3
 Standard Error: 0.107268513868515
       Variance: 0.0115065340675597

Мне интересно, правильно ли я использую Accord.Net. Любая помощь будет оценена.

Моя программа:

using System;
using System.IO;
using System.Net;

using Accord.MachineLearning;
using Accord.Statistics.Analysis;

namespace K_Keans {

  #region K_Means
  public static class K_Means {
    private static KMeans kmeans;

    #region DowloadIrisData
    private static void DowloadIrisData(out double[][] predictors, out int[] targets) {
      using (var fileDownloader = new WebClient()) {
        // http://www.math.uah.edu/stat/data/Fisher.html
        // The dataset gives Ronald Fisher's measurements of type, petal width (PW), petal length (PL),
        // sepal width (SW), and sepal length (SL) for a sample of 150 irises, measured in millimeters. 
        // Type 0 is Setosa; type 1 is Verginica; and type 2 is Versicolor.
        const string webLocation = @"http://www.math.uah.edu/stat/data/Fisher.csv";
        const string fileName = @"c:\Temp\iris.csv";
        fileDownloader.DownloadFile(webLocation, fileName);
        var s = File.ReadAllText(fileName);
        var sarray = s.Split('\n');
        var nrows = sarray.Length - 2;
        var ncols = sarray[0].Split(',').Length;
        predictors = new double[nrows][];
        targets = new int[nrows];
        for (var j=1; j<=nrows; j++) {
          predictors[j-1] = new double[ncols-1];
          var line = sarray[j].Split(',');
          for (var k = 1; k < ncols; k++) {
            targets[j-1] = Convert.ToInt32(line[0]);
            predictors[j-1][k-1] = Convert.ToDouble(line[k]);
          }
        }
      }
    }
    #endregion

    #region IrisData
    public static void IrisData(out double[][] trainingData, out int[] expectedTrainingTargets,
                                out double[][] testingData, out int[] expectedTestingTargets) {
      double[][] predictors;
      int[] targets;
      DowloadIrisData(out predictors, out targets);

      var nRows = predictors.Length;
      var nCols = predictors[0].Length;
      var nRowsTesting = Convert.ToInt32(0.2*nRows);
      var nRowsTraining = nRows - nRowsTesting;

      trainingData = new double[nRowsTraining][];
      expectedTrainingTargets = new int[nRowsTraining];
      for (var k = 0; k < nRowsTraining; k++) {
        trainingData[k] = new double[nCols];
        Array.Copy(predictors[k], trainingData[k], nCols);
        expectedTrainingTargets[k] = targets[k];
      }
      testingData = new double[nRowsTesting][];
      expectedTestingTargets = new int[nRowsTesting];
      for (var k = 0; k < nRowsTesting; k++) {
        testingData[k] = new double[nCols];
        Array.Copy(predictors[nRows-nRowsTesting+k], testingData[k], nCols);
        expectedTestingTargets[k] = targets[nRows-nRowsTesting+k];
      }
    }
    #endregion

    #region Train
    public static void Train(double[][] trainingData, out int[] predicted) {

      kmeans = new KMeans(3) {
        Tolerance = 1e-5,
        ComputeInformation = true
      };

      predicted = kmeans.Compute(trainingData);
    }
    #endregion

    #region Test
    public static void Test(double[][] testingData, out int[] predicted) {
      var nRowsTesting = testingData.Length;
      predicted = new int[nRowsTesting];
      for (var k = 0; k < nRowsTesting; k++) {
        predicted[k] = kmeans.Clusters.Nearest(testingData[k]);
      }
    }
    #endregion
  }
  #endregion

  class Program {
    static void Main(string[] args) {
      double[][] trainingData, testingData;
      int[] expectedTrainingTargets, expectedTestingTargets;

      K_Means.IrisData(out trainingData, out expectedTrainingTargets, out testingData, out expectedTestingTargets);

      int[] predictedTrainingTargets;
      K_Means.Train(trainingData, out predictedTrainingTargets);

      int[] predictedTestingTargets;
      K_Means.Test(testingData, out predictedTestingTargets);

      var confusionMatrix = new ConfusionMatrix(predictedTestingTargets, expectedTestingTargets);

      var nCorrect = 0;
      var nRows = expectedTestingTargets.Length;
      for (var k=0; k<nRows; k++) {
        if (predictedTestingTargets[k] == expectedTestingTargets[k]) { nCorrect++; }
      }

      Console.WriteLine(" Number correct: {0} out of {1}", nCorrect, nRows);
      Console.WriteLine("         FScore: {0}", confusionMatrix.FScore);
      Console.WriteLine("      Precision: {0}", confusionMatrix.Precision);
      Console.WriteLine(" True Positives: {0}", confusionMatrix.TruePositives);
      Console.WriteLine("False Positives: {0}", confusionMatrix.FalsePositives);
      Console.WriteLine(" True Negatives: {0}", confusionMatrix.TrueNegatives);
      Console.WriteLine("False Negatives: {0}", confusionMatrix.FalseNegatives);
      Console.WriteLine("       Accuracy: {0}", confusionMatrix.Accuracy);
      Console.WriteLine(" Standard Error: {0}", confusionMatrix.StandardError);
      Console.WriteLine("       Variance: {0}", confusionMatrix.Variance);
      Console.WriteLine(" ");
      Console.WriteLine("Hit enter to exit.");
      Console.ReadKey();
    }
  }
}

person CBrauer    schedule 06.05.2015    source источник


Ответы (1)


Метод K-средних не является алгоритмом классификации.

Но это рандомизированный алгоритм, поэтому неудивительно, что вы каждый раз получаете разные результаты.

Теперь, поскольку он рандомизирован, метки, используемые k-средними, тоже случайны.

Таким образом, 2 из 30 правильных ответов могут быть такими же, как 28 правильных из 30 (просто метки перетасованы).

Запустите его еще раз, и он может дать те же самые кластеры, но со всеми перепутанными «метками». (На самом деле, он не знает о видах ириса. Он помечает объекты 0,1,2, а не «радужная оболочка»).

person Has QUIT--Anony-Mousse    schedule 07.05.2015