我們可以在 LearningModel 類別上套用數個靜態方法,以載入機器學習模型,例如從應用程式中的檔案、從磁碟上的檔案載入模型,或從數據流載入模型。
從數據流方法載入可讓您更妥善地控制模型。 在此情況下,您可以選擇在磁碟上加密模型,並在呼叫其中一個LoadFromStream方法之前,只在記憶體中解密模型。
在本教學課程中,您將瞭解如何整合加密的機器學習模型與 Windows ML 應用程式 (C#)。
Windows ML API 不提供機器學習加密服務,且不會對任何類型的損害或遺失負責。
取得 ONNX 模型
在本教學課程中,您將使用 ONNX 格式的 SqueezeNet 模型,從數據流執行加密、解密和載入。
從 GitHub 下載或複製 SqueezeNet 物件偵測範例應用程式 ,以取得 SqueezeNet.onnx 模型。
指定必要的宣告和變數
- 複製下列 using 語句宣告,以存取您需要的所有 API:
using System;
using System.Threading.Tasks;
using Windows.AI.MachineLearning;
using Windows.Security.Cryptography;
using Windows.Security.Cryptography.Core;
using Windows.Storage;
using Windows.Storage.Streams;
using Windows.UI.Xaml.Controls;
您將為索引鍵和初始化向量定義兩個特殊變數。
密鑰是CryptographicKey 類別的變數,代表對稱密鑰組(或非對稱密鑰組)。 您將需要這個類別中的 對象,因為您將使用 AsymmetricKeyAlgorithmProvider 方法來建立或匯入索引鍵。
初始化向量是IBuffer類別的變數,代表位元組數據流讀取和寫入介面所使用的位元組參考數位。
CryptographicKey和 IBuffer 類別變數都用來加密和解密數據流。
- 在 crypto 命名空間內的 using 語句之後,新增下列變數宣告和
MainPage類別:
namespace crypto
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
private CryptographicKey _key;
private IBuffer _initialization_vector;
public MainPage()
{
this.InitializeComponent();
Run();
}
}
}
加密模型
Windows API 提供一組豐富的特性和功能,可增強 Windows ML API 集合的功能。 在這裡,您將使用 Windows API 集合中提供的加密和解密服務來產生記憶體中的數據流,並使用 Windows ML API 從該數據流載入模型。
您可以根據您的便利性,使用任何加密服務來加密機器學習模型。 在本教學課程中,我們將使用加密方法 – SymmetricAlgorithmNames - .AesCbcPkcs7。
SymmetricAlgorithmNames 類別可協助您擷取對稱密鑰演演算法,以在您的模型上套用對稱密鑰加密。 這種類型的加密需要用於加密的相同金鑰也用於解密。
使用 類別 SymmetricKeyAlgorithmProvider ,您可以選取演算法並建立金鑰。 在本教學課程中,我們將使用 .AesCbcPkcs7. 演算法。
此 AES_CBC_PKCS7 演算法代表進階加密標準(AES)演算法,結合加密區塊鏈結模式和 PKCS#7 填充。
- 下列程式代碼示範如何產生金鑰並加密模型。
async Task<IBuffer> EncryptAsync(StorageFile model_file)
{
// get a buffer for the model file
var file_buffer = await Windows.Storage.FileIO.ReadBufferAsync(model_file);
// set up the encryption algorithm
var algorithm = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7);
uint key_length = 32;
var key_buffer = CryptographicBuffer.GenerateRandom(key_length);
_key = algorithm.CreateSymmetricKey(key_buffer);
_initialization_vector = CryptographicBuffer.GenerateRandom(algorithm.BlockLength);
// perform the encryption
var encrypted_buffer = CryptographicEngine.Encrypt(_key, file_buffer, _initialization_vector);
return encrypted_buffer;
}
[注意!] 有興趣深入瞭解密碼編譯密鑰嗎? 請檢閱 密碼編譯密鑰檔。
從資料流解密並載入模型
載入模型之前,您必須使用 CryptographicEngine.Decrypt 方法來解密模型。
CryptographicEngine.Decrypt 是解密先前使用對稱或非對稱演算法加密內容的方法。 呼叫 方法時,您必須提供先前產生的金鑰。
若要存取解密的模型,您將使用 InMemoryRandomAccessStream 類別,其會提供儲存在記憶體中而非磁碟之輸入和輸出數據流中的數據隨機存取。
在最後一個步驟中,您將使用 LearningModel.LoadFromStreamAsync 方法建立會話,以從數據流載入模型。 您可以將此方法呼叫為同步或異步工作。
下列程式代碼示範如何使用產生的密鑰解密模型、將它寫入數據流,然後從數據流載入模型。
async Task DecryptAndRunAsync(IBuffer encryptyed_buffer)
{
// decrypt the buffer
var decrypted_buffer = CryptographicEngine.Decrypt(_key, encryptyed_buffer, _initialization_vector);
// write it to a stream
var decrypted_stream = new InMemoryRandomAccessStream();
await decrypted_stream.WriteAsync(decrypted_buffer);
// load the model from the stream
var model = await LearningModel.LoadFromStreamAsync(RandomAccessStreamReference.CreateFromStream(decrypted_stream));
// create a session
var session = new LearningModelSession(model);
}
執行模型
複製下列 Run 方法以呼叫稍早定義的方法。
async Task Run()
{
// get the model file
var model_file = await StorageFile.GetFileFromApplicationUriAsync(new Uri($"ms-appx:///Assets/SqueezeNet.onnx"));
// encrypt the model file.
var encryptyed_buffer = await EncryptAsync(model_file);
// decrypt the model file and load it
await DecryptAndRunAsync(encryptyed_buffer);
}
總結
介紹完畢! 您已成功將模型載入 Windows ML 應用程式。
載入模型之後,您可以繼續建立會話、系結模型輸入和輸出,並評估模型以完成 Windows ML 應用程式。
其他資源
若要深入瞭解本教學課程中提及的主題,請流覽下列資源: