From 3e70083b35de741823d549a71b66a363d2b16f9d Mon Sep 17 00:00:00 2001 From: Eugene Gusarov <eugene.gusarov@devfactory.com> Date: Tue, 12 Mar 2019 11:46:27 +0300 Subject: [PATCH 1/2] added an extension method for saving statically typed model (#1286) --- .../ModelOperationsCatalog.cs | 23 +++++++++++++++++++ .../Api/CookbookSamples/CookbookSamples.cs | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/Microsoft.ML.StaticPipe/ModelOperationsCatalog.cs diff --git a/src/Microsoft.ML.StaticPipe/ModelOperationsCatalog.cs b/src/Microsoft.ML.StaticPipe/ModelOperationsCatalog.cs new file mode 100644 index 0000000000..4481b80abe --- /dev/null +++ b/src/Microsoft.ML.StaticPipe/ModelOperationsCatalog.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.IO; + +namespace Microsoft.ML.StaticPipe +{ + public static class ModelOperationsCatalog + { + /// <summary> + /// Save statically typed model to the stream. + /// </summary> + /// <param name="catalog">The model explainability operations catalog.</param> + /// <param name="model">The trained model to be saved.</param> + /// <param name="stream">A writeable, seekable stream to save to.</param> + public static void Save<TInShape, TOutShape, TTransformer>(this ML.ModelOperationsCatalog catalog, Transformer<TInShape, TOutShape, TTransformer> model, Stream stream) + where TTransformer : class, ITransformer + { + catalog.Save(model.AsDynamic, stream); + } + } +} diff --git a/test/Microsoft.ML.Tests/Scenarios/Api/CookbookSamples/CookbookSamples.cs b/test/Microsoft.ML.Tests/Scenarios/Api/CookbookSamples/CookbookSamples.cs index b60afc07f2..4bbf27b1b5 100644 --- a/test/Microsoft.ML.Tests/Scenarios/Api/CookbookSamples/CookbookSamples.cs +++ b/test/Microsoft.ML.Tests/Scenarios/Api/CookbookSamples/CookbookSamples.cs @@ -149,7 +149,7 @@ private void TrainRegression(string trainDataPath, string testDataPath, string m using (var stream = File.Create(modelPath)) { // Saving and loading happens to 'dynamic' models, so the static typing is lost in the process. - mlContext.Model.Save(model.AsDynamic, stream); + mlContext.Model.Save(model, stream); } // Potentially, the lines below can be in a different process altogether. From b929023c814a9b1ed94a842c25d38a02fe6bd574 Mon Sep 17 00:00:00 2001 From: Eugene Gusarov <gusarov.email@gmail.com> Date: Sat, 30 Mar 2019 12:52:15 +0300 Subject: [PATCH 2/2] added an extension method for saving statically typed model - adjust api changes & documentation example --- .../experimental/MlNetCookBookStaticApi.md | 2 +- .../ModelOperationsCatalog.cs | 23 ---------- .../ModelOperationsCatalogExtensions.cs | 42 +++++++++++++++++++ .../Api/CookbookSamples/CookbookSamples.cs | 2 +- 4 files changed, 44 insertions(+), 25 deletions(-) delete mode 100644 src/Microsoft.ML.StaticPipe/ModelOperationsCatalog.cs create mode 100644 src/Microsoft.ML.StaticPipe/ModelOperationsCatalogExtensions.cs diff --git a/docs/code/experimental/MlNetCookBookStaticApi.md b/docs/code/experimental/MlNetCookBookStaticApi.md index 086e3b8e3b..99ce4a8d3c 100644 --- a/docs/code/experimental/MlNetCookBookStaticApi.md +++ b/docs/code/experimental/MlNetCookBookStaticApi.md @@ -397,7 +397,7 @@ Here's what you do to save the model to a file, and reload it (potentially in a ```csharp // Saving and loading happens to 'dynamic' models, so the static typing is lost in the process. -mlContext.Model.Save(model.AsDynamic, trainData.AsDynamic.Schema, modelPath); +mlContext.Model.Save(model, trainData, modelPath); // Potentially, the lines below can be in a different process altogether. diff --git a/src/Microsoft.ML.StaticPipe/ModelOperationsCatalog.cs b/src/Microsoft.ML.StaticPipe/ModelOperationsCatalog.cs deleted file mode 100644 index 4481b80abe..0000000000 --- a/src/Microsoft.ML.StaticPipe/ModelOperationsCatalog.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.IO; - -namespace Microsoft.ML.StaticPipe -{ - public static class ModelOperationsCatalog - { - /// <summary> - /// Save statically typed model to the stream. - /// </summary> - /// <param name="catalog">The model explainability operations catalog.</param> - /// <param name="model">The trained model to be saved.</param> - /// <param name="stream">A writeable, seekable stream to save to.</param> - public static void Save<TInShape, TOutShape, TTransformer>(this ML.ModelOperationsCatalog catalog, Transformer<TInShape, TOutShape, TTransformer> model, Stream stream) - where TTransformer : class, ITransformer - { - catalog.Save(model.AsDynamic, stream); - } - } -} diff --git a/src/Microsoft.ML.StaticPipe/ModelOperationsCatalogExtensions.cs b/src/Microsoft.ML.StaticPipe/ModelOperationsCatalogExtensions.cs new file mode 100644 index 0000000000..c42b983edc --- /dev/null +++ b/src/Microsoft.ML.StaticPipe/ModelOperationsCatalogExtensions.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.IO; +using Microsoft.ML.Data; + +namespace Microsoft.ML.StaticPipe +{ + public static class ModelOperationsCatalogExtensions + { + /// <summary> + /// Save statically typed model to the stream. + /// </summary> + /// <param name="catalog">The model explainability operations catalog.</param> + /// <param name="model">The trained model to be saved. Note that this can be <see langword="null"/>, as a shorthand + /// for an empty transformer chain. Upon loading with <see cref="ML.ModelOperationsCatalog.Load(Stream, out DataViewSchema)"/> the returned value will + /// be an empty <see cref="TransformerChain{TLastTransformer}"/>.</param> + /// <param name="dataView">The data view with the schema of the input to the transformer. This can be <see langword="null"/>.</param> + /// <param name="stream">A writeable, seekable stream to save to.</param> + public static void Save<TInShape, TOutShape, TTransformer>(this ML.ModelOperationsCatalog catalog, Transformer<TInShape, TOutShape, TTransformer> model, DataView<TInShape> dataView, Stream stream) + where TTransformer : class, ITransformer + { + catalog.Save(model?.AsDynamic, dataView?.AsDynamic.Schema, stream); + } + + /// <summary> + /// Save statically typed model to the stream. + /// </summary> + /// <param name="catalog">The model explainability operations catalog.</param> + /// <param name="model">The trained model to be saved. Note that this can be <see langword="null"/>, as a shorthand + /// for an empty transformer chain. Upon loading with <see cref="ML.ModelOperationsCatalog.Load(Stream, out DataViewSchema)"/> the returned value will + /// be an empty <see cref="TransformerChain{TLastTransformer}"/>.</param> + /// <param name="dataView">The data view with the schema of the input to the transformer. This can be <see langword="null"/>.</param> + /// <param name="filePath">Path where model should be saved.</param> + public static void Save<TInShape, TOutShape, TTransformer>(this ML.ModelOperationsCatalog catalog, Transformer<TInShape, TOutShape, TTransformer> model, DataView<TInShape> dataView, string filePath) + where TTransformer : class, ITransformer + { + catalog.Save(model?.AsDynamic, dataView?.AsDynamic.Schema, filePath); + } + } +} diff --git a/test/Microsoft.ML.Tests/Scenarios/Api/CookbookSamples/CookbookSamples.cs b/test/Microsoft.ML.Tests/Scenarios/Api/CookbookSamples/CookbookSamples.cs index cce1de27b5..dc66dd570d 100644 --- a/test/Microsoft.ML.Tests/Scenarios/Api/CookbookSamples/CookbookSamples.cs +++ b/test/Microsoft.ML.Tests/Scenarios/Api/CookbookSamples/CookbookSamples.cs @@ -147,7 +147,7 @@ private void TrainRegression(string trainDataPath, string testDataPath, string m var metrics = mlContext.Regression.Evaluate(model.Transform(testData), label: r => r.Target, score: r => r.Prediction); // Saving and loading happens to 'dynamic' models, so the static typing is lost in the process. - mlContext.Model.Save(model.AsDynamic, trainData.AsDynamic.Schema, modelPath); + mlContext.Model.Save(model, trainData, modelPath); // Potentially, the lines below can be in a different process altogether.