#c# #ml.net
#c# #ml.net
Вопрос:
Я использую ML.Net модель, использующая преобразование MapValueToKey в pipleline. После обучения модели я сохраняю ее.
Во время выполнения я загружаю сохраненную модель и делаю прогноз. Это работает нормально, но я получаю только значение (целое число). Как я могу извлечь ключи (строковые значения), которые соответствуют прогнозируемым значениям, используя модель, загруженную из сохраненного файла (я знаю, что сопоставление включено в сохраненную модель, потому что я вижу это, если печатаю матрицу путаницы).
Ниже приведен пример кода, показывающий основные элементы моей проблемы:
//Note: this.AllData is preloaded: IDataView AllData
//Create the PipeLine - Mapping Treatment Name to a Label as needed by the Multiclass Classification model
var pipeline = mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: "Label", nameof(TreatmentObservation.NextTreatmentName))
.Append(mlContext.Transforms.Categorical.OneHotEncoding(outputColumnName: "roadclass", inputColumnName: nameof(TreatmentObservation.RoadClass)))
.Append(mlContext.Transforms.Categorical.OneHotEncoding(outputColumnName: "surf_mat", inputColumnName: nameof(TreatmentObservation.SurfMaterial)))
.Append(mlContext.Transforms.Concatenate("Features", "roadclass", nameof(TreatmentObservation.Rut85th), nameof(TreatmentObservation.Naasra85th)));
//Create a LightGBM Trainer
IEstimator<ITransformer> trainer = mlContext.MulticlassClassification.Trainers.LightGbm();
var trainingPipeline = pipeline.Append(trainer);
var trainedModelWithPreproc = trainingPipeline.Fit(this.AllData); //Fit the pipleline on all the preloaded data
//Save the model
string modelSaveFilePath = "modelPipeline.zip";
mlContext.Model.Save(trainedModelWithPreproc, dataSplit.TrainSet.Schema, modelSaveFilePath);
//Now Load back the model and test it
// Define trained model schemas
DataViewSchema modelSchema;
ITransformer allInOneModel = mlContext.Model.Load(modelSaveFilePath, out modelSchema);
List<TreatmentObservation> testingData = null;
//Load testing data here...(code not included)
var observations = mlContext.Data.LoadFromEnumerable(testingData);
var engine = this.mlContext.Model.CreatePredictionEngine<TreatmentObservation, Prediction_MultiLabel>(allInOneModel); //Create the prediction engine
foreach (TreatmentObservation observation in testingData)
{
var predicted = engine.Predict(observation);
uint label_value = predicted.PredictedLabel;
string label_key;
//How to get back the Key from the predicted value?
}
И вот класс, используемый для прогнозирования в приведенном выше примере:
// Class used to capture predictions.
public class Prediction_MultiLabel
{
// Original label.
public uint Label { get; set; }
// Predicted label from the trainer.
public uint PredictedLabel { get; set; }
}
Итак, мой вопрос: как я могу изменить отображение при составлении прогнозов с использованием сохраненной и загруженной модели?
Я рассмотрел примеры, подобные этому: ML.NET пример но в этих примерах не используется хранимая модель. Они создают, а затем напрямую используют конвейер. Мне нужно знать, как отменить сопоставление из хранимой модели. Я не эксперт в ML.NET , поэтому, пожалуйста, извините, если в моем вопросе есть какое-то невежество!
Ответ №1:
К сожалению, через два дня я не получил никаких предложенных решений от ML.NET сообщество. Но мне удалось собрать решение, используя это ML.NET сообщение о помощи. Код, показанный в приведенной выше формулировке вопроса, необходимо изменить, используя следующий шаблон:
//First create an explicit map for mapping keys to values. The values will be the index of the items in the array.
var lookupData = new[] {
new LookupMap { Key = "Banana" },
new LookupMap { Key = "Apple" },
new LookupMap { Key = "Orange" },
new LookupMap { Key = "Melon" },
};
//Convert to IDataView
var lookupIdvMap = mlContext.Data.LoadFromEnumerable(lookupData);
//Now create the pipeline, with an explicit keyData Map using the above mapping
var pipeline = mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: "Label", nameof(Fruit.Name), keyData: lookupIdvMap)
.Append(mlContext.Transforms.Concatenate("Features", nameof(Fruit.Color), nameof(Fruit.Diameter), nameof(Fruit.Weight)));
Теперь обучите модель с использованием этого конвейера, затем сохраните ее (пример кода приведен в приведенном выше вопросе).
Затем загрузите сохраненную модель обратно для тестирования и создайте механизм прогнозирования. Опять же, пример кода приведен в приведенном выше вопросе. После того, как вы это сделаете, вы можете сделать прогноз и получить имя вместо значения следующим образом:
//Here is an example of how you make a prediction:
//In this case 'observation' is an instance of the type 'Fruit'
var predicted = engine.Predict(observation);
//Compare the observed and predicted name of the fruit
string obs_Name = observation.Name; //this is the observed value
string pred_Name = lookupData[predicted.PredictedLabel - 1].Key; //this is the predicted value.
Тип LookupMap — это простой класс, определенный следующим образом:
// Type for the IDataView that will be serving as the map
public class LookupMap
{
public string Key { get; set; }
}