File: ResNet50Extension.cs
Web Access
Project: src\src\Microsoft.ML.DnnImageFeaturizer.ResNet50\Microsoft.ML.DnnImageFeaturizer.ResNet50.csproj (Microsoft.ML.DnnImageFeaturizer.ResNet50)
// 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;
using System.IO;
using Microsoft.ML.Data;
using Microsoft.ML.Runtime;
using Microsoft.ML.Transforms;
using Microsoft.ML.Transforms.Onnx;
 
namespace Microsoft.ML
{
    /// <summary>
    /// This is an extension method to be used with the <see cref="DnnImageFeaturizerEstimator"/> in order to use a pretrained ResNet50 model.
    /// The NuGet containing this extension is also guaranteed to include the binary model file.
    /// </summary>
    public static class ResNet50Extension
    {
        /// <summary>
        /// Returns an estimator chain with the two corresponding models (a preprocessing one and a main one) required for the ResNet pipeline.
        /// Also includes the renaming ColumnsCopyingTransforms required to be able to use arbitrary input and output column names.
        /// This assumes both of the models are in the same location as the file containing this method, which they will be if used through the NuGet.
        /// This should be the default way to use ResNet50 if importing the model from a NuGet.
        /// </summary>
        public static EstimatorChain<ColumnCopyingTransformer> ResNet50(this DnnImageModelSelector dnnModelContext, IHostEnvironment env, string outputColumnName, string inputColumnName)
        {
            return ResNet50(dnnModelContext, env, outputColumnName, inputColumnName, Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "DnnImageModels"));
        }
 
        /// <summary>
        /// This allows a custom model location to be specified. This is useful is a custom model is specified,
        /// or if the model is desired to be placed or shipped separately in a different folder from the main application. Note that because Onnx models
        /// must be in a directory all by themselves for the OnnxTransformer to work, this method appends a ResNet50Onnx/ResNetPrepOnnx subdirectory
        /// to the passed in directory to prevent having to make that directory manually each time.
        /// </summary>
        public static EstimatorChain<ColumnCopyingTransformer> ResNet50(this DnnImageModelSelector dnnModelContext, IHostEnvironment env, string outputColumnName, string inputColumnName, string modelDir)
        {
            var modelChain = new EstimatorChain<ColumnCopyingTransformer>();
 
            var inputRename = new ColumnCopyingEstimator(env, new[] { ("OriginalInput", inputColumnName) });
            var midRename = new ColumnCopyingEstimator(env, new[] { ("Input750", "PreprocessedInput") });
            var endRename = new ColumnCopyingEstimator(env, new[] { (outputColumnName, "Pooling1096_Output_0") });
 
            // There are two estimators created below. The first one is for image preprocessing and the second one is the actual DNN model.
            var prepEstimator = new OnnxScoringEstimator(env, new[] { "PreprocessedInput" }, new[] { "OriginalInput" }, Path.Combine(modelDir, "ResNetPrepOnnx", "ResNetPreprocess.onnx"));
            var mainEstimator = new OnnxScoringEstimator(env, new[] { "Pooling1096_Output_0" }, new[] { "Input750" }, Path.Combine(modelDir, "ResNet50Onnx", "ResNet50.onnx"));
            modelChain = modelChain.Append(inputRename);
            var modelChain2 = modelChain.Append(prepEstimator);
            modelChain = modelChain2.Append(midRename);
            modelChain2 = modelChain.Append(mainEstimator);
            modelChain = modelChain2.Append(endRename);
            return modelChain;
        }
    }
}