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

然后,示例应用创建 100,000 个 MarsHabitatPricerInput 对象,用作顺序 Core ML 预测的输入。 每个生成的样本都有一个随机值,用于太阳能电池板数、温室数量和英亩数:

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);
        }
    });
    // ...
}

点击应用的三个按钮中的任何一个执行两个预测序列:一个使用 for 循环,另一个使用 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 方法所需的输入参数),创建一个 MLPredictionOptions 对象,该对象阻止预测计算限制为 CPU,并使用 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 预测更快地完成。