Xamarin.iOS の Core ML 2
Core ML は、iOS、macOS、tvOS、watchOS で利用できる機械学習テクノロジです。 これにより、アプリは機械学習モデルに基づいて予測を行うことができます。
iOS 12 では、Core ML にはバッチ処理 API が含まれています。 この API は、Core ML をより効率的にし、連続した予測を行うためにモデルが使用されるシナリオでパフォーマンスの向上をもたらします。
サンプル データを作成する
ViewController
では、以下のように、サンプル アプリの ViewDidLoad
メソッドが LoadMLModel
を呼び出し、これによって含まれている Core ML モデルが読み込まれます。
void LoadMLModel()
{
var assetPath = NSBundle.MainBundle.GetUrlForResource("CoreMLModel/MarsHabitatPricer", "mlmodelc");
model = MLModel.Create(assetPath, out NSError mlErr);
}
次に、サンプル アプリは、連続する Core ML の予測の入力として使用する 100,000 個の MarsHabitatPricerInput
オブジェクトを作成します。 以下のように、生成された各サンプルでは、ソーラー パネルの数、温室の数、牧草地の数にランダムな値が設定されています。
async void CreateInputs(int num)
{
// ...
Random r = new Random();
await Task.Run(() =>
{
for (int i = 0; i < num; i++)
{
double solarPanels = r.NextDouble() * MaxSolarPanels;
double greenHouses = r.NextDouble() * MaxGreenHouses;
double acres = r.NextDouble() * MaxAcres;
inputs[i] = new MarsHabitatPricerInput(solarPanels, greenHouses, acres);
}
});
// ...
}
アプリの 3 つのボタンのいずれかをタップすると、次の 2 つの予測シーケンスが実行されます。1 つは for
ループを使用するもので、もう 1 つは iOS 12 で導入された新しいバッチ GetPredictions
メソッドを使用するものです。
async void RunTest(int num)
{
// ...
await FetchNonBatchResults(num);
// ...
await FetchBatchResults(num);
// ...
}
for ループ
テストの for
ループ バージョンは、指定された数の入力を単純に反復処理し、それぞれに対して GetPrediction
を呼び出し結果を破棄します。 以下のように、このメソッドは自身が予測に要する時間を計測します。
async Task FetchNonBatchResults(int num)
{
Stopwatch stopWatch = Stopwatch.StartNew();
await Task.Run(() =>
{
for (int i = 0; i < num; i++)
{
IMLFeatureProvider output = model.GetPrediction(inputs[i], out NSError error);
}
});
stopWatch.Stop();
nonBatchMilliseconds = stopWatch.ElapsedMilliseconds;
}
GetPredictions (新しいバッチ API)
テストのバッチ バージョンは、入力配列から MLArrayBatchProvider
オブジェクトを作成し (これは GetPredictions
メソッドに必要な入力パラメーターであるためです)、予測計算が CPU に制限されることを防ぐ MLPredictionOptions
オブジェクトを作成し、GetPredictions
API を使用して予測をフェッチします。ここでも結果は破棄されます。
async Task FetchBatchResults(int num)
{
var batch = new MLArrayBatchProvider(inputs.Take(num).ToArray());
var options = new MLPredictionOptions()
{
UsesCpuOnly = false
};
Stopwatch stopWatch = Stopwatch.StartNew();
await Task.Run(() =>
{
model.GetPredictions(batch, options, out NSError error);
});
stopWatch.Stop();
batchMilliseconds = stopWatch.ElapsedMilliseconds;
}
結果
シミュレーターとデバイスのどちらでも、GetPredictions
はループベースの Core ML 予測よりも早く終了します。