Я получаю противоречивые результаты с классификацией 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();
}
}
}
1 ответ
K-means не является алгоритмом классификации.
Но это рандомизированный алгоритм, поэтому неудивительно, что вы каждый раз получаете разные результаты.
Теперь, поскольку он рандомизирован, метки, используемые k-means, тоже случайны.
Таким образом, 2 из 30 правильных могут совпадать с 28 из 30 правильных (только метки перемешаны).
Запустите его снова, и он может дать те же кластеры, но со всеми "метками". (На самом деле, он не знает о видах ириса. Он маркирует объекты 0,1,2; не "ирис сетоа")