我有一个测试程序不能为 Accord.Net K-Means 提供一致的结果。
我附上了一个可在 Visual Studio 2013 中运行的可重现测试程序。
该程序是一个控制台应用程序,要重现您需要参考的结果:
Accord.MachineLearning
Accord.Statistics,
来自 Accord.Net 2.15 库。
当我多次运行该程序时,每次都会得到不同的结果。该程序使用经典的 Fisher Iris 数据集。数据集有 150 行,我将数据拆分为 120 行训练数据和 30 行测试数据。
当我运行该程序时,我可能会在 30 个中得到正确分类的 26 个。再次运行它可能会产生 30 次中的 2 次正确。
例如:
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();
}
}
}