web-dev-qa-db-fra.com

Comment prédire les valeurs entières à l'aide de ML.NET?

Je regarde un fichier cs ici: https://www.Microsoft.com/net/learn/apps/machine-learning-and-ai/ml-dotnet/get-started/windows et tout fonctionne bien.

Maintenant, j'aimerais améliorer l'exemple: j'aimerais prédire un ensemble de données numérique et non un ensemble de données numérique, par exemple, la sortie d'un affichage à sept segments.

Voici mon jeu de données super facile, la dernière colonne est le nombre int que je veux prédire:

1,0,1,1,1,1,1,0
0,0,0,0,0,1,1,1
1,1,1,0,1,1,0,2
1,1,1,0,0,1,1,3
0,1,0,1,0,1,1,4
1,1,1,1,0,0,1,5
1,1,1,1,1,0,1,6
1,0,0,0,0,1,1,7
1,1,1,1,1,1,1,8
1,1,1,1,0,1,1,9

Et voici mon code de test:

public class Digit
{
    [Column("0")] public float Up;

    [Column("1")] public float Middle;

    [Column("2")] public float Bottom;

    [Column("3")] public float UpLeft;
    [Column("4")] public float BottomLeft;
    [Column("5")] public float TopRight;
    [Column("6")] public float BottomRight;

    [Column("7")] [ColumnName("DigitValue")]
    public float DigitValue;
}

public class DigitPrediction
{
    [ColumnName("PredictedDigits")] public float PredictedDigits;
}

public PredictDigit()
{
    var pipeline = new LearningPipeline();
    var dataPath = Path.Combine("Segmenti", "segments.txt");
    pipeline.Add(new TextLoader<Digit>(dataPath, false, ","));
    pipeline.Add(new ColumnConcatenator("Label", "DigitValue"));
    pipeline.Add(new ColumnConcatenator("Features", "Up", "Middle", "Bottom", "UpLeft", "BottomLeft", "TopRight", "BottomRight"));
    pipeline.Add(new StochasticDualCoordinateAscentClassifier());
    var model = pipeline.Train<Digit, DigitPrediction>();
    var prediction = model.Predict(new Digit
    {
        Up = 1,
        Middle = 1,
        Bottom = 1,
        UpLeft = 1,
        BottomLeft = 1,
        TopRight = 1,
        BottomRight = 1,
    });

    Console.WriteLine($"Predicted digit is: {prediction.PredictedDigits}");
    Console.ReadLine();
}

Comme vous pouvez le constater, il est très similaire à l'exemple fourni, à l'exception de la dernière colonne ("Label") qui traite le problème car je dois prédire un nombre et non une chaîne. J'essaye avec:

pipeline.Add(new ColumnConcatenator("Label", "DigitValue"));

mais ça ne marche pas, exception:

Training label column 'Label' type is not valid for multi-class: Vec<R4, 1>. Type must be R4 or R8.

Je suis sûr que quelque chose me manque, mais en réalité je ne trouve rien sur Internet qui puisse m'aider à résoudre ce problème.

METTRE &AGRAVE; JOUR

J'ai trouvé que l'ensemble de données doivent avoir une colonne Label comme celle-ci:

[Column("7")] [ColumnName("Label")] public float Label;

et la colonne DigitPrediction une colonne Score comme:

public class DigitPrediction
{
    [ColumnName("Score")] public float[] Score;
}

Maintenant, le système "fonctionne" et j'ai, en tant que prediction.Score, une valeur Single[] dans laquelle l'index associé à la valeur la plus élevée correspond à la valeur prédite . Est-ce la bonne approche?

UPDATE 2 - Exemple de code complet

Après la réponse et d’autres suggestions, j’ai obtenu le bon résultat. Si vous en avez besoin, vous pouvez trouver le code complet ici .

5
Rowandish

On dirait que vous auriez besoin d'ajouter ce champ à votre classe DigitPrediction:

public class DigitPrediction
{
    [ColumnName("PredicatedLabel")]
    public uuint ExpectedDigit; // <-- This is the predicted value

    [ColumnName("Score")]
    public float[] Score; // <-- This is the probability that the predicted value is the right classification
}

Et je pense que vous auriez besoin de changer la ligne où il écrit le résultat pour:

    Console.WriteLine($"Predicted digit is: {prediction.ExpectedDigit}");

Une dernière chose, il semble y avoir un bogue dans l’API où le chiffre attendu sera décalé d’un chiffre, mais si vous le décalez en ajoutant +1 à la valeur prédite, il s’agira de la valeur correcte. Je m'attends à ce qu'ils résolvent ce problème à l'avenir, il y a un problème: ( https://github.com/dotnet/machinelearning/issues/235 )

3
Kyle B

Vous pouvez également essayer d’échanger ColumnConcatenator avec ColumnCopier, dans le pipeline, pour la colonne Label. 

pipeline.Add(new ColumnCopier ("Label", "DigitValue"));

Cela indiquera au pipeline la colonne qui est l'étiquette, mais la sortie de ColumnCopier ne sera pas un vecteur, contrairement à la sortie de ColumnConcatenator. 

Et pourrait également ajouter une colonne Score. 

1
amy8374

Maintenant, il est essentiel de suivre le modèle:

  • Fonctionnalités de colonne (toutes les fonctionnalités - elles doivent avoir le même type)

  • Étiquette de colonne (vos "réponses")

Si le jeu de données d'origine a une autre colonne de réponse, utilisez:

pipeline.Add(new ColumnCopier(("DigitValue", "Label")));

Le premier est la source, le second est la destination. Comme je vois, double '(' est requis.

0
Arhisan