Salvar e carregar modelos treinados

Saiba como salvar e carregar modelos treinados em seu aplicativo.

Em todo o processo de criação de modelo, um modelo reside na memória e é acessível em todo o ciclo de vida do aplicativo. No entanto, depois que o aplicativo terminar a execução, se o modelo não for salvo em algum lugar local ou remotamente, ele não ficará mais acessível. Normalmente, os modelos são usados em algum momento após o treinamento em outros aplicativos para inferência de tipos ou novo treinamento. Assim, é importante armazenar o modelo. Salve e carregue modelos usando as etapas descritas nas seções subsequentes deste documento ao usar pipelines de treinamento de modelo e preparação de dados como os detalhados abaixo. Embora este exemplo use um modelo de regressão linear, o mesmo processo se aplica a outros algoritmos do ML.NET.

HousingData[] housingData = new HousingData[]
{
    new HousingData
    {
        Size = 600f,
        HistoricalPrices = new float[] { 100000f, 125000f, 122000f },
        CurrentPrice = 170000f
    },
    new HousingData
    {
        Size = 1000f,
        HistoricalPrices = new float[] { 200000f, 250000f, 230000f },
        CurrentPrice = 225000f
    },
    new HousingData
    {
        Size = 1000f,
        HistoricalPrices = new float[] { 126000f, 130000f, 200000f },
        CurrentPrice = 195000f
    }
};

// Create MLContext
MLContext mlContext = new MLContext();

// Load Data
IDataView data = mlContext.Data.LoadFromEnumerable<HousingData>(housingData);

// Define data preparation estimator
EstimatorChain<RegressionPredictionTransformer<LinearRegressionModelParameters>> pipelineEstimator =
    mlContext.Transforms.Concatenate("Features", new string[] { "Size", "HistoricalPrices" })
        .Append(mlContext.Transforms.NormalizeMinMax("Features"))
        .Append(mlContext.Regression.Trainers.Sdca());

// Train model
ITransformer trainedModel = pipelineEstimator.Fit(data);

// Save model
mlContext.Model.Save(trainedModel, data.Schema, "model.zip");

Porque a maioria dos pipelines de preparação de dados e modelos herda o mesmo conjunto de classes, as assinaturas do método salvar e carregar para esses componentes são iguais. Dependendo do seu caso de uso, você pode tanto combinar o pipeline de preparação de dados e o modelo em um único EstimatorChain que geraria um único ITransformer quanto separá-los, criando um ITransformer separado para cada um.

Salvar um modelo localmente

Ao salvar um modelo, você precisa de dois itens:

  1. O ITransformer do modelo.
  2. O DataViewSchema da entrada esperada de ITransformer.

Depois de treinar o modelo, use o método Save para salvar o modelo treinado em um arquivo chamado model.zip usando o DataViewSchema dos dados de entrada.

// Save Trained Model
mlContext.Model.Save(trainedModel, data.Schema, "model.zip");

Salvar um modelo ONNX localmente

Para salvar uma versão ONNX do seu modelo localmente, você precisará ter instalado o pacote NuGet Microsoft.ML.OnnxConverter.

Com o pacote OnnxConverter instalado, podemos usá-lo para salvar nosso modelo no formato ONNX. Isso requer um objeto Stream que podemos fornecer como um FileStream usando o método File.Create. O método File.Create usa uma cadeia de caracteres como um parâmetro que será o caminho do modelo ONNX.

using FileStream stream = File.Create("./onnx_model.onnx");

Com o fluxo criado, podemos chamar o método ConvertToOnnx e fornecer o modelo treinado, os dados usados para treinar o modelo e o fluxo. No entanto, nem todos os treinadores e transformadores são exportáveis para o ONNX. Para obter uma lista completa, visite os guias Transformações e Como escolher um algoritmo de ML.NET.

mlContext.Model.ConvertToOnnx(trainedModel, data, stream);

Carregar um modelo armazenado localmente

Os modelos armazenados localmente podem ser usados em outros processos ou aplicativos, como ASP.NET Core e Serverless Web Applications. Veja os artigos de instruções Usar ML.NET na API Web e Implantar aplicativo Web sem servidor do ML.NET para saber mais.

Em um aplicativo ou processo separado, use o método Load juntamente com o caminho do arquivo para obter o modelo treinado em seu aplicativo.

//Define DataViewSchema for data preparation pipeline and trained model
DataViewSchema modelSchema;

// Load trained model
ITransformer trainedModel = mlContext.Model.Load("model.zip", out modelSchema);

Carregar um modelo ONNX localmente

Para carregar um modelo ONNX para previsões, você precisará do pacote NuGet Microsoft.ML.OnnxTransformer.

Com o pacote OnnxTransformer instalado, você pode carregar um modelo ONNX existente usando o método ApplyOnnxModel. O parâmetro necessário é uma cadeia de caracteres que é o caminho do modelo ONNX local.

OnnxScoringEstimator estimator = mlContext.Transforms.ApplyOnnxModel("./onnx_model.onnx");

O método ApplyOnnxModel retorna um objeto OnnxScoringEstimator. Primeiro, precisamos carregar os novos dados.

HousingData[] newHousingData = new HousingData[]
{
    new()
    {
        Size = 1000f,
        HistoricalPrices = new[] { 300_000f, 350_000f, 450_000f },
        CurrentPrice = 550_00f
    }
};

Com os novos dados, podemos carregá-los em um IDataView usando o método LoadFromEnumerable.

IDataView newHousingDataView = mlContext.Data.LoadFromEnumerable(newHousingData);

Agora, podemos usar o novo IDataView para se ajustar aos novos dados.

estimator.Fit(newHousingDataView);

Depois de usar o método Fit em um avaliador de ApplyOnnxModel, ele poderá ser salvo como um novo modelo usando o método Save mencionado na seção Salvar um modelo localmente.

Carregar um modelo armazenado remotamente

Para carregar os pipelines de preparação de dados e modelos armazenados em um local remoto em seu aplicativo, use Stream em vez de um caminho de arquivo no método Load.

// Create MLContext
MLContext mlContext = new MLContext();

// Define DataViewSchema and ITransformers
DataViewSchema modelSchema;
ITransformer trainedModel;

// Load data prep pipeline and trained model
using (HttpClient client = new HttpClient())
{
    Stream modelFile = await client.GetStreamAsync("<YOUR-REMOTE-FILE-LOCATION>");

    trainedModel = mlContext.Model.Load(modelFile, out modelSchema);
}

Trabalhando com pipelines de modelo e preparação de dados separados

Observação

Trabalhar com pipelines de treinamento de modelo e preparação de dados separados é opcional. A separação de pipelines facilita a inspeção dos parâmetros do modelo aprendido. Para obter previsões, é mais fácil de salvar e carregar um único pipeline que inclua as operações de treinamento de modelo e preparação de dados.

Ao trabalhar com modelos e pipelines de preparação de dados separados, aplica-se o mesmo processo que o para pipelines únicos, exceto que agora os dois pipelines precisam ser salvos e carregados simultaneamente.

Dados pipelines de treinamento de modelo e preparação de dados separados:

// Define data preparation estimator
IEstimator<ITransformer> dataPrepEstimator =
    mlContext.Transforms.Concatenate("Features", new string[] { "Size", "HistoricalPrices" })
        .Append(mlContext.Transforms.NormalizeMinMax("Features"));

// Create data preparation transformer
ITransformer dataPrepTransformer = dataPrepEstimator.Fit(data);

// Define StochasticDualCoordinateAscent regression algorithm estimator
var sdcaEstimator = mlContext.Regression.Trainers.Sdca();

// Pre-process data using data prep operations
IDataView transformedData = dataPrepTransformer.Transform(data);

// Train regression model
RegressionPredictionTransformer<LinearRegressionModelParameters> trainedModel = sdcaEstimator.Fit(transformedData);

Salve o pipeline de preparação de dados e o modelo treinado

Para salvar o pipeline de preparação de dados e o modelo treinado, use os seguintes comandos:

// Save Data Prep transformer
mlContext.Model.Save(dataPrepTransformer, data.Schema, "data_preparation_pipeline.zip");

// Save Trained Model
mlContext.Model.Save(trainedModel, transformedData.Schema, "model.zip");

Carregar o pipeline de preparação de dados e o modelo treinado

Em um processo ou aplicativo separado, carregue o modelo treinado e o pipeline de preparação de dados simultaneamente da seguinte maneira:

// Create MLContext
MLContext mlContext = new MLContext();

// Define data preparation and trained model schemas
DataViewSchema dataPrepPipelineSchema, modelSchema;

// Load data preparation pipeline and trained model
ITransformer dataPrepPipeline = mlContext.Model.Load("data_preparation_pipeline.zip",out dataPrepPipelineSchema);
ITransformer trainedModel = mlContext.Model.Load("model.zip", out modelSchema);