Delen via


Stapsgewijze instructies voor Windows ML

In deze korte zelfstudie wordt stapsgewijs uitgelegd hoe u Windows ML gebruikt om het ResNet-50-afbeeldingsclassificatiemodel in Windows uit te voeren, met gedetailleerde stappen voor het verkrijgen van modellen en het vooraf verwerken van modellen. De implementatie omvat het dynamisch selecteren van uitvoeringsproviders voor geoptimaliseerde deductieprestaties.

Het ResNet-50-model is een PyTorch-model dat is bedoeld voor afbeeldingsclassificatie.

In deze zelfstudie verkrijgt u het ResNet-50-model van Hugging Face en converteert u het naar de QDQ ONNX-indeling met behulp van de AI Toolkit.

Vervolgens laadt u het model, bereidt u invoertenors voor en voert u deductie uit met behulp van de Windows ML-API's, inclusief naverwerkingsstappen om softmax toe te passen en de belangrijkste voorspellingen op te halen.

Het model verkrijgen en vooraf verwerken

U kunt ResNet-50 verkrijgen bij Hugging Face (het platform waar de ML-community samenwerkt aan modellen, gegevenssets en apps). U converteert ResNet-50 naar QDQ ONNX-indeling met behulp van de AI Toolkit (zie modellen converteren naar ONNX-indeling voor meer informatie).

Het doel van deze voorbeeldcode is om de Windows ML-runtime te gebruiken om het zware werk te doen.

De Windows ML-runtime doet het volgende:

  • Laad het model.
  • Selecteer dynamisch de door IHV geleverde uitvoeringsprovider (EP) van voorkeur voor het model en download de EP uit de Microsoft Store, op aanvraag.
  • Voer deductie uit op het model met behulp van het EP.

Zie OrtSessionOptions en de klasse ExecutionProviderCatalog voor API-naslaginformatie .

// 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 Windows ML to download and register Execution Providers
var catalog = Microsoft.Windows.AI.MachineLearning.ExecutionProviderCatalog.GetDefault();
Console.WriteLine("Ensuring and registering execution providers...");
await catalog.EnsureAndRegisterCertifiedAsync();

//Create Onnx session
Console.WriteLine("Creating session ...");
var sessionOptions = new SessionOptions();
// Set EP Selection Policy
sessionOptions.SetEpSelectionPolicy(ExecutionProviderDevicePolicy.MIN_OVERALL_POWER);

EP-compilatie

Als uw model nog niet is gecompileerd voor de EP (die afhankelijk van het apparaat kan variƫren), moet het model eerst op dat EP worden gecompileerd. Dit is een eenmalig proces. Met de onderstaande voorbeeldcode wordt het verwerkt door het model te compileren bij de eerste uitvoering en vervolgens lokaal op te slaan. Volgende uitvoeringen van de code halen de gecompileerde versie op en voeren die uit; resulteert in geoptimaliseerde snelle deducties.

Voor API-naslaginformatie, zie Ort::ModelCompilationOptions struct, Ort::Status struct en 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;

De deductie uitvoeren

De invoerafbeelding wordt geconverteerd naar het tensor-dataformaat en vervolgens wordt inferentie uitgevoerd. Hoewel dit gebruikelijk is voor alle code die de ONNX Runtime gebruikt, is het verschil in dit geval dat de ONNX Runtime direct verloopt via Windows ML. De enige vereiste is het toevoegen #include <winml/onnxruntime_cxx_api.h> aan de code.

Zie Ook Een model converteren met AI Toolkit voor VS Code

Zie Ort::Session struct, Ort::MemoryInfo struct, Ort::Value struct, Ort::AllocatorWithDefaultOptions struct, Ort::RunOptions struct.

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);

Naverwerking

De softmax-functie wordt toegepast op geretourneerde onbewerkte uitvoer en labelgegevens worden gebruikt om de namen met de vijf hoogste waarschijnlijkheden toe te wijzen en af te drukken.

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("-------------------------------------------");
}

Uitvoer

Hier volgt een voorbeeld van het soort uitvoer dat moet worden verwacht.

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

Volledige codevoorbeelden

De volledige codevoorbeelden zijn beschikbaar in de WindowsAppSDK-Samples GitHub-opslagplaats. Zie WindowsML.