Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Windows ML supporta il carico ad alte prestazioni e l'esecuzione delle catene di modelli ottimizzando attentamente il percorso GPU. Le catene di modelli sono definite da due o più modelli eseguiti in sequenza, in cui gli output di un modello diventano gli input del modello successivo verso il basso nella catena.
Per spiegare come concatenare in modo efficiente i modelli con Windows ML, utilizziamo un modello ONNX di trasferimento di stile FNS-Candy come esempio semplice. È possibile trovare questo tipo di modello nella cartella di esempio trasferimento stile FNS-Candy in GitHub.
Si supponga di voler eseguire una catena composta da due istanze dello stesso modello di FNS-Candy, qui denominato mosaic.onnx. Il codice dell'applicazione passa un'immagine al primo modello della catena, consente di calcolare gli output e quindi di passare l'immagine trasformata a un'altra istanza di FNS-Candy, producendo un'immagine finale.
I passaggi seguenti illustrano come eseguire questa operazione usando Windows ML.
Annotazioni
In uno scenario di parole reali è molto probabile che si usino due modelli diversi, ma questo dovrebbe essere sufficiente per illustrare i concetti.
- Prima di tutto, caricare il modello mosaic.onnx in modo da poterlo usare.
std::wstring filePath = L"path\\to\\mosaic.onnx";
LearningModel model = LearningModel::LoadFromFilePath(filePath);
string filePath = "path\\to\\mosaic.onnx";
LearningModel model = LearningModel.LoadFromFilePath(filePath);
- Creare quindi due sessioni identiche nella GPU predefinita del dispositivo usando lo stesso modello del parametro di input.
LearningModelSession session1(model, LearningModelDevice(LearningModelDeviceKind::DirectX));
LearningModelSession session2(model, LearningModelDevice(LearningModelDeviceKind::DirectX));
LearningModelSession session1 =
new LearningModelSession(model, new LearningModelDevice(LearningModelDeviceKind.DirectX));
LearningModelSession session2 =
new LearningModelSession(model, new LearningModelDevice(LearningModelDeviceKind.DirectX));
Annotazioni
Per sfruttare i vantaggi del concatenamento delle prestazioni, è necessario creare sessioni GPU identiche per tutti i modelli. In caso contrario, lo spostamento dei dati aggiuntivo dalla GPU e nella CPU potrebbe ridurre le prestazioni.
- Le righe di codice seguenti creeranno associazioni per ogni sessione:
LearningModelBinding binding1(session1);
LearningModelBinding binding2(session2);
LearningModelBinding binding1 = new LearningModelBinding(session1);
LearningModelBinding binding2 = new LearningModelBinding(session2);
- Successivamente, dobbiamo collegare un input al nostro primo modello. Passeremo un'immagine che si trova sullo stesso percorso del nostro modello. In questo esempio l'immagine è denominata "fish_720.png".
//get the input descriptor
ILearningModelFeatureDescriptor input = model.InputFeatures().GetAt(0);
//load a SoftwareBitmap
hstring imagePath = L"path\\to\\fish_720.png";
// Get the image and bind it to the model's input
try
{
StorageFile file = StorageFile::GetFileFromPathAsync(imagePath).get();
IRandomAccessStream stream = file.OpenAsync(FileAccessMode::Read).get();
BitmapDecoder decoder = BitmapDecoder::CreateAsync(stream).get();
SoftwareBitmap softwareBitmap = decoder.GetSoftwareBitmapAsync().get();
VideoFrame videoFrame = VideoFrame::CreateWithSoftwareBitmap(softwareBitmap);
ImageFeatureValue image = ImageFeatureValue::CreateFromVideoFrame(videoFrame);
binding1.Bind(input.Name(), image);
}
catch (...)
{
printf("Failed to load/bind image\n");
}
//get the input descriptor
ILearningModelFeatureDescriptor input = model.InputFeatures[0];
//load a SoftwareBitmap
string imagePath = "path\\to\\fish_720.png";
// Get the image and bind it to the model's input
try
{
StorageFile file = await StorageFile.GetFileFromPathAsync(imagePath);
IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read);
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
SoftwareBitmap softwareBitmap = await decoder.GetSoftwareBitmapAsync();
VideoFrame videoFrame = VideoFrame.CreateWithSoftwareBitmap(softwareBitmap);
ImageFeatureValue image = ImageFeatureValue.CreateFromVideoFrame(videoFrame);
binding1.Bind(input.Name, image);
}
catch
{
Console.WriteLine("Failed to load/bind image");
}
- Affinché il modello successivo nella catena usi gli output della valutazione del primo modello, è necessario creare un tensore di output vuoto e associare l'output in modo da avere un marcatore a catena con:
//get the output descriptor
ILearningModelFeatureDescriptor output = model.OutputFeatures().GetAt(0);
//create an empty output tensor
std::vector<int64_t> shape = {1, 3, 720, 720};
TensorFloat outputValue = TensorFloat::Create(shape);
//bind the (empty) output
binding1.Bind(output.Name(), outputValue);
//get the output descriptor
ILearningModelFeatureDescriptor output = model.OutputFeatures[0];
//create an empty output tensor
List<long> shape = new List<long> { 1, 3, 720, 720 };
TensorFloat outputValue = TensorFloat.Create(shape);
//bind the (empty) output
binding1.Bind(output.Name, outputValue);
Annotazioni
È necessario usare il tipo di dati TensorFloat quando si associa l'output. Ciò impedirà che si verifichi la de-tensorizzazione una volta completata la valutazione del primo modello, evitando quindi ulteriori code GPU per le operazioni di caricamento e associazione per il secondo modello.
- A questo punto, si esegue la valutazione del primo modello e si associano gli output all'input del modello successivo:
//run session1 evaluation
session1.EvaluateAsync(binding1, L"");
//bind the output to the next model input
binding2.Bind(input.Name(), outputValue);
//run session2 evaluation
auto session2AsyncOp = session2.EvaluateAsync(binding2, L"");
//run session1 evaluation
await session1.EvaluateAsync(binding1, "");
//bind the output to the next model input
binding2.Bind(input.Name, outputValue);
//run session2 evaluation
LearningModelEvaluationResult results = await session2.EvaluateAsync(binding2, "");
- Infine, recuperare l'output finale generato dopo l'esecuzione di entrambi i modelli usando la riga di codice seguente.
auto finalOutput = session2AsyncOp.get().Outputs().First().Current().Value();
var finalOutput = results.Outputs.First().Value;
Questo è tutto! Entrambi i modelli ora possono essere eseguiti in sequenza sfruttando al massimo le risorse GPU disponibili.
Annotazioni
Usare le risorse seguenti per assistenza con Windows ML:
- Per porre o rispondere a domande tecniche su Windows ML, usare il tag windows-machine-learning in Stack Overflow.
- Per segnalare un bug, segnalare un problema in GitHub.