Bagikan melalui


Menjalankan beberapa model ML dalam rantai

Windows ML mendukung beban performa tinggi dan eksekusi rantai model dengan mengoptimalkan jalur GPU dengan hati-hati. Rantai model didefinisikan oleh dua model atau lebih yang dijalankan secara berurutan, di mana output dari satu model menjadi input ke model berikutnya ke bawah rantai.

Untuk menjelaskan cara menautkan model secara efisien dengan Windows ML, mari kita gunakan model ONNX Transfer Gaya FNS-Candy sebagai contoh mainan. Anda dapat menemukan jenis model ini di folder sampel FNS-Candy Style Transfer di GitHub kami.

Katakanlah kita ingin mengeksekusi rantai yang terdiri dari dua instans dari model FNS-Candy yang sama, di sini disebut mosaic.onnx. Kode aplikasi akan meneruskan gambar ke model pertama dalam rantai, membiarkannya menghitung output, dan kemudian meneruskan gambar yang diubah ke instans lain FNS-Candy, menghasilkan gambar akhir.

Langkah-langkah berikut menggambarkan cara mencapainya menggunakan Windows ML.

Catatan

Dalam skenario kata nyata Anda kemungkinan besar akan menggunakan dua model yang berbeda, tetapi ini harus cukup untuk menggambarkan konsep.

  1. Pertama, mari kita muat model mosaic.onnx sehingga kita dapat menggunakannya.
std::wstring filePath = L"path\\to\\mosaic.onnx"; 
LearningModel model = LearningModel::LoadFromFilePath(filePath);
string filePath = "path\\to\\mosaic.onnx";
LearningModel model = LearningModel.LoadFromFilePath(filePath);
  1. Kemudian, mari kita buat dua sesi yang identik pada GPU default perangkat menggunakan model yang sama dengan parameter 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));

Catatan

Untuk menuai manfaat performa penautan, Anda perlu membuat sesi GPU yang identik untuk semua model Anda. Tidak melakukannya akan mengakibatkan pergerakan data tambahan keluar dari GPU dan ke CPU, yang akan mengurangi performa.

  1. Baris kode berikut akan membuat pengikatan untuk setiap sesi:
LearningModelBinding binding1(session1);
LearningModelBinding binding2(session2);
LearningModelBinding binding1 = new LearningModelBinding(session1);
LearningModelBinding binding2 = new LearningModelBinding(session2);
  1. Selanjutnya, kita akan mengikat input untuk model pertama kita. Kami akan meneruskan gambar yang terletak di jalur yang sama dengan model kami. Dalam contoh ini gambar disebut "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");
}
  1. Agar model berikutnya dalam rantai menggunakan output evaluasi model pertama, kita perlu membuat tensor output kosong dan mengikat output sehingga kita memiliki penanda untuk ditautkan dengan:
//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);

Catatan

Anda harus menggunakan jenis data TensorFloat saat mengikat output. Ini akan mencegah de-tensorisasi terjadi setelah evaluasi untuk model pertama selesai, oleh karena itu juga menghindari antrean GPU tambahan untuk operasi beban dan pengikatan untuk model kedua.

  1. Sekarang, kita menjalankan evaluasi model pertama, dan mengikat outputnya ke input model berikutnya:
//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, "");
  1. Terakhir, mari kita ambil output akhir yang dihasilkan setelah menjalankan kedua model dengan menggunakan baris kode berikut.
auto finalOutput = session2AsyncOp.get().Outputs().First().Current().Value();
var finalOutput = results.Outputs.First().Value;

Itu saja! Kedua model Anda sekarang dapat dijalankan secara berurutan dengan memanfaatkan sumber daya GPU yang tersedia secara maksimal.

Catatan

Gunakan sumber daya berikut untuk bantuan dengan Windows ML:

  • Untuk mengajukan atau menjawab pertanyaan teknis tentang Windows ML, silakan gunakan tag windows-machine-learning di Stack Overflow.
  • Untuk melaporkan bug, silakan ajukan masalah di GitHub kami.