Проблемы с задачей классификации Accord.NET SVM - PullRequest
0 голосов
/ 21 мая 2018

Уважаемые пользователи C #, пользователи Accord.NET и любители / профессионалы в области машинного обучения,

У меня проблемы с внедрением Kernel SVM из среды Accord.Net Framework.

В частности,моя задача состоит в том, чтобы классифицировать (множественные метки) записи набора данных, состоящего из 11-мерного вектора (действительное значение) плюс 12-я целочисленная категориальная запись для каждого из них, в диапазоне от 0 до 10 (несмотря только на 3, ..., 8на самом деле присутствуют).Я имею в виду этот набор данных.

Я разделил исходный набор данных (1599 элементов) на 10%, оставив их отдельно в качестве тестового набора, который будет использоваться в качестве проверки после выполнения тренировки с оставшимися 90%, действительно в качестве тренировочного набора.

Я следовал этому примеру (внизу, второй).

// Let's say we have the following data to be classified
// into three possible classes. Those are the samples:
// 
double[][] inputs =
{
    //               input         output
    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
    new double[] { 1, 0, 0, 0 }, //  1
    new double[] { 1, 0, 0, 0 }, //  1
    new double[] { 1, 0, 0, 1 }, //  1
    new double[] { 0, 0, 0, 1 }, //  1
    new double[] { 0, 0, 0, 1 }, //  1
    new double[] { 1, 1, 1, 1 }, //  2
    new double[] { 1, 0, 1, 1 }, //  2
    new double[] { 1, 1, 0, 1 }, //  2
    new double[] { 0, 1, 1, 1 }, //  2
    new double[] { 1, 1, 1, 1 }, //  2
};

int[] outputs = // those are the class labels
{
    0, 0, 0, 0, 0,
    1, 1, 1, 1, 1,
    2, 2, 2, 2, 2,
};

// Create the multi-class learning algorithm for the machine
var teacher = new MulticlassSupportVectorLearning<Gaussian>()
{
    // Configure the learning algorithm to use SMO to train the
    //  underlying SVMs in each of the binary class subproblems.
    Learner = (param) => new SequentialMinimalOptimization<Gaussian>()
    {
        // Estimate a suitable guess for the Gaussian kernel's parameters.
        // This estimate can serve as a starting point for a grid search.
        UseKernelEstimation = true
    }
};

// The following line is only needed to ensure reproducible results. Please remove it to enable full parallelization
teacher.ParallelOptions.MaxDegreeOfParallelism = 1; // (Remove, comment, or change this line to enable full parallelism)

// Learn a machine
var machine = teacher.Learn(inputs, outputs);

// Obtain class predictions for each sample
int[] predicted = machine.Decide(inputs);

// Get class scores for each sample
double[] scores = machine.Score(inputs);

// Compute classification error
double error = new ZeroOneLoss(outputs).Loss(predicted);

Я попробовал его самостоятельно, и он работает, правильно классифицируя входные данные как принадлежащие 0, 1, 2,

Но то же самое не относится к моим данным.В частности, мой input является экземпляром класса DataObject, где я соединяю числовую матрицу и целочисленный массив (категории; импорт успешно выполнен, я дважды проверил).Проблема в том, что, хотя в приведенном примере predict содержит целое число, соответствующее меткам 0, 1, 2, в моем случае прогнозируемые метки равны только 0 и 1, тогда как в исходном наборе данных у меня 0, ..., 5 (адаптировано из 3, ..., 8, которые были в необработанных данных).

ПРИМЕЧАНИЕ: как сделано в примере, было применено к моему вводу, , но в строке

int [] predict = machine.Decide(TestSet.ItemsFeatures);

Я использовал векторы тестового набора, а в строке

double error = new ZeroOneLoss(TestSet.CatsIDs).Loss(predict);

соответствующие метки, составляющие CatsIDs Int32массив, используемый для обозначения каждого вектора.Я использовал линейное ядро ​​вместо гауссовского, таким образом уменьшив ошибку примерно до 0,49.

Что конкретно я хотел выяснить: может ли это быть проблемой данных?Должен ли я подробнее изучить свойства используемых здесь классов?Другой вопрос, на который я не могу ответить: SVM - это двоичный классификатор, но в предыдущем примере он успешно используется для мультиклассовой классификации, в то время как я получаю классификацию по двум категориям (с незначительной ошибкой).Есть ли концептуальная ошибка в моем рабочем процессе?И о коде: я использую обучающий набор по методу Learn, затем вместо него используется Decide() набор тестов, что я считаю разумным, но я не уверен на 100% в использовании набора тестов впоследняя строка, для ошибки.Я думаю, что как то, как сообщается, исправлено, так что сравнивая метки набора тестов и отображение прогноза.

Я хотел бы заранее поблагодарить кого-либо, любая помощь очень важна.

PS.Я совершенно новичок как в C #, так и в машинном обучении, простите мои возможные ошибки или поверхностное понимание.Кроме того, как подвергается воздействию исключительно необходимо для академического упражнения.Нет Accord.NET, ни Связанные данные используются ненадлежащим образом.

Я прилагаю отрывок моего кода (DataObject и DataAquisition работают довольно хорошо) ПРИМЕЧАНИЕ: SetsData[0] = Test Set;SetsData[1] = Учебный комплект.

static void Main(string[] args)
        {
            string pathFolderSourceData = @"C:\Users\Matteo\Desktop\MLProj2018\IO\Source";
            string pathFolderDropData = @"C:\Users\Matteo\Desktop\MLProj2018\IO\Drop";

            // data import and new labels
            DataSetImport DSIn = new DataSetImport(pathFolderSourceData);
            DataObject DataMatrix = DSIn.FeaturesImport();

            // DataSet partitioning: - TestSet (10% out of the DS); - TrainingSet (remaining 90%)
            DataSetPartition DSPrt = new DataSetPartition(DataMatrix);
            DataObject[] SetsData = DSPrt.TestSetExtraction(DataMatrix);

            // write sets train and test on file to check the correctness of the 
            // previous classes
            StreamWriter write = new StreamWriter(pathFolderDropData + @"\SplittedDataSet.dat");
            for (int k = 0; k < 2; k++)
            {
                for (int i = 0; i < SetsData[k].GetDimensionRows(); i++)
                {
                    for (int j = 0; j < SetsData[k].ItemsFeats[i].Length; j++)
                    {
                        write.Write("{0}\t", SetsData[k].ItemsFeats[i][j]);
                    } write.Write("{0}\n", SetsData[k].CatIDs[i]);
                }
                write.Write("\n\n\n");
            }
            write.Close();

            // data aquired, now I train the algorithm

            var teacher = new MulticlassSupportVectorLearning<Linear>()
            {
                Learner = (p) => new SequentialMinimalOptimization<Linear>()
                {
                    // UseKernelEstimation = true,
                    UseComplexityHeuristic = true
                }
            };

            // this is for learning parameters w and b, thus eventually 
            // draw the margin
            var machine = teacher.Learn(SetsData[1].ItemsFeats, SetsData[1].CatIDs);

            // parameters have been learned, here I put TestSet SetsData[0] 
            // as entries to be predicted, so the classification of the 
            // test set vectors can be performed
            int[] predicted = machine.Decide(SetsData[0].ItemsFeats);

            double error = new ZeroOneLoss(SetsData[0].CatIDs).Loss(predicted);

            for (int i = 0; i < predicted.Length; i++)
            {
                Console.WriteLine(predicted[i]);
            }

            Console.WriteLine(error);

            // end program
            Console.WriteLine("E N D _ P R O G R A M");
            Console.WriteLine("Press any key to quit");
            Console.ReadKey();
        }
...