Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Este breve tutorial le guía por el uso de Windows ML para ejecutar el modelo de clasificación de imágenes ResNet-50 en Windows, detallando los pasos de adquisición y preprocesamiento de modelos. La implementación implica seleccionar dinámicamente proveedores de ejecución para optimizar el rendimiento de la inferencia.
El modelo ResNet-50 es un modelo pyTorch diseñado para la clasificación de imágenes.
En este tutorial, obtendrá el modelo ResNet-50 de Hugging Face y lo convertirá a formato ONNX de QDQ usando el AI Toolkit.
A continuación, cargará el modelo, preparará los tensores de entrada y ejecutará la inferencia mediante las API de Windows ML, incluidos los pasos posteriores al procesamiento para aplicar softmax y recuperará las predicciones principales.
Adquisición del modelo y preprocesamiento
Puede adquirir ResNet-50 desde Hugging Face (la plataforma donde la comunidad de ML colabora en modelos, conjuntos de datos y aplicaciones). Convertirá ResNet-50 al formato ONNX de QDQ mediante ai Toolkit (consulte Conversión de modelos al formato ONNX para obtener más información).
El objetivo de este código de ejemplo es aprovechar windows ML runtime para realizar el trabajo pesado.
El entorno de ejecución de Windows ML hará lo siguiente:
- Cargue el modelo.
- Seleccione dinámicamente el proveedor de ejecución proporcionado por IHV (EP) preferido para el modelo y descargue su EP desde Microsoft Store a petición.
- Ejecute inferencia en el modelo mediante el EP.
Para obtener referencia de API, consulte OrtSessionOptions y Microsoft::Windows::AI::MachineLearning::Infrastructure class.
// Create a new instance of EnvironmentCreationOptions
EnvironmentCreationOptions envOptions = new()
{
logId = "ResnetDemo",
logLevel = OrtLoggingLevel.ORT_LOGGING_LEVEL_ERROR
};
// Pass the options by reference to CreateInstanceWithOptions
OrtEnv ortEnv = OrtEnv.CreateInstanceWithOptions(ref envOptions);
// Use WinML to download and register Execution Providers
Microsoft.Windows.AI.MachineLearning.Infrastructure infrastructure = new();
Console.WriteLine("Ensure EPs are downloaded ...");
await infrastructure.DownloadPackagesAsync();
await infrastructure.RegisterExecutionProviderLibrariesAsync();
//Create Onnx session
Console.WriteLine("Creating session ...");
var sessionOptions = new SessionOptions();
// Set EP Selection Policy
sessionOptions.SetEpSelectionPolicy(ExecutionProviderDevicePolicy.MIN_OVERALL_POWER);
Compilación EP
Si el modelo aún no está compilado para el EP (lo cual puede variar en función del dispositivo), primero se debe compilar para ese EP. Se trata de un proceso único. El código de ejemplo siguiente lo controla compilando el modelo en la primera ejecución y, a continuación, almacenándolo localmente. Las ejecuciones posteriores del código recogen la versión compilada y la ejecutan; lo que da lugar a inferencias rápidas optimizadas.
Para obtener referencia a la API, vea Struct Ort::ModelCompilationOptions, Ort::Status struct y Ort::CompileModel.
// Prepare paths
string executableFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly()!.Location)!;
string labelsPath = Path.Combine(executableFolder, "ResNet50Labels.txt");
string imagePath = Path.Combine(executableFolder, "dog.jpg");
// TODO: Please use AITK Model Conversion tool to download and convert Resnet, and paste the converted path here
string modelPath = @"";
string compiledModelPath = @"";
// Compile the model if not already compiled
bool isCompiled = File.Exists(compiledModelPath);
if (!isCompiled)
{
Console.WriteLine("No compiled model found. Compiling model ...");
using (var compileOptions = new OrtModelCompilationOptions(sessionOptions))
{
compileOptions.SetInputModelPath(modelPath);
compileOptions.SetOutputModelPath(compiledModelPath);
compileOptions.CompileModel();
isCompiled = File.Exists(compiledModelPath);
if (isCompiled)
{
Console.WriteLine("Model compiled successfully!");
}
else
{
Console.WriteLine("Failed to compile the model. Will use original model.");
}
}
}
else
{
Console.WriteLine("Found precompiled model.");
}
var modelPathToUse = isCompiled ? compiledModelPath : modelPath;
Ejecución de la inferencia
La imagen de entrada se convierte en formato de datos tensor y, a continuación, la inferencia se ejecuta en ella. Aunque esto es típico de todo el código que usa el entorno de ejecución de ONNX, la diferencia en este caso es que es ONNX Runtime directamente a través de Windows ML. El único requisito es agregar #include <win_onnxruntime_cxx_api.h>
al código.
Consulte también Conversión de un modelo con AI Toolkit para VS Code
Para obtener referencia de API, vea estructura Ort::Session, estructura Ort::MemoryInfo, estructura Ort::Value, estructura Ort::AllocatorWithDefaultOptions, estructura Ort::RunOptions.
using var session = new InferenceSession(modelPathToUse, sessionOptions);
Console.WriteLine("Preparing input ...");
// Load and preprocess image
var input = await PreprocessImageAsync(await LoadImageFileAsync(imagePath));
// Prepare input tensor
var inputName = session.InputMetadata.First().Key;
var inputTensor = new DenseTensor<float>(
input.ToArray(), // Use the DenseTensor<float> directly
new[] { 1, 3, 224, 224 }, // Shape of the tensor
false // isReversedStride should be explicitly set to false
);
// Bind inputs and run inference
var inputs = new List<NamedOnnxValue>
{
NamedOnnxValue.CreateFromTensor(inputName, inputTensor)
};
Console.WriteLine("Running inference ...");
var results = session.Run(inputs);
for (int i = 0; i < 40; i++)
{
results = session.Run(inputs);
}
// Extract output tensor
var outputName = session.OutputMetadata.First().Key;
var resultTensor = results.First(r => r.Name == outputName).AsEnumerable<float>().ToArray();
// Load labels and print results
var labels = LoadLabels(labelsPath);
PrintResults(labels, resultTensor);
Posprocesamiento
La función softmax se aplica a la salida sin procesar devuelta, y los datos de etiqueta se usan para asociar e imprimir los nombres con las cinco probabilidades más altas.
private static void PrintResults(IList<string> labels, IReadOnlyList<float> results)
{
// Apply softmax to the results
float maxLogit = results.Max();
var expScores = results.Select(r => MathF.Exp(r - maxLogit)).ToList(); // stability with maxLogit
float sumExp = expScores.Sum();
var softmaxResults = expScores.Select(e => e / sumExp).ToList();
// Get top 5 results
IEnumerable<(int Index, float Confidence)> topResults = softmaxResults
.Select((value, index) => (Index: index, Confidence: value))
.OrderByDescending(x => x.Confidence)
.Take(5);
// Display results
Console.WriteLine("Top Predictions:");
Console.WriteLine("-------------------------------------------");
Console.WriteLine("{0,-32} {1,10}", "Label", "Confidence");
Console.WriteLine("-------------------------------------------");
foreach (var result in topResults)
{
Console.WriteLine("{0,-32} {1,10:P2}", labels[result.Index], result.Confidence);
}
Console.WriteLine("-------------------------------------------");
}
Salida
Este es un ejemplo del tipo de salida que se va a esperar.
285, Egyptian cat with confidence of 0.904274
281, tabby with confidence of 0.0620204
282, tiger cat with confidence of 0.0223081
287, lynx with confidence of 0.00119624
761, remote control with confidence of 0.000487919
Ejemplos de código completos
Los ejemplos de código completos están disponibles en el repositorio de GitHub aquí.