iOSでのCreateML/CoreMLを用いたオンデバイス機械学習

こんにちは、iOSエンジニア の 池田 です。

この記事は Enigmo Advent Calendar 202220日目の記事です。

はじめに

2018年のWWDCで発表されたCreateMLですが、発表当初Xcodeを用いたモデル作成などMacでの利用に限定されていました。 ですが最近ではiOS、iPadOS、tvOSでも利用できるようになっており、オンデバイスでの機械学習モデル作成ができます。 (利用可能OSは iOS15.0以降、iPadOS15.0以降、tvOS16.0以降です。)

この記事ではiOSを用いたオンデバイスでの機械学習モデル作成と、作成したモデルの利用をしてみようと思います。

MLStyleTransfer を利用してモデル作成を行い、画像の画風変換をしてみます。

コード内に見やすさのため Forced Unwrapping してる箇所がありますが、実装時はguard文等を使って適宜書き換える想定をしています。

機械学習モデルの作成

モデルの作成は以下のようなコードで作成できます。コード量も多くなく、簡単に機械学習のモデル作成ができます。

必要ライブラリの読み込み

import CreateML
import CoreML
import Combine

学習用のデータ、パラメータの準備

let styleUrl: URL // スタイル画像のURL
let contentUrl: URL // 学習用コンテンツ画像のディレクトリURL

let data = MLStyleTransfer.DataSource.images(styleImage: styleUrl, contentDirectory: contentUrl)
let sessionParameters = MLTrainingSessionParameters(sessionDirectory: sessionUrl)

学習実行

let job = try MLStyleTransfer.train(trainingData: data, sessionParameters: sessionParameters)

学習結果の待ち受けとモデルの保存

let writeToUrl: URL // モデルの書き込み先URL
var mlModel: MLModel // 作成した機械学習モデル

job.result.sink { result in
        switch result {
        case .failure(let error):
            // エラー時の処理
        case .finished:
            // 完了後の処理
    } receiveValue: { model in
        do {
            try model.write(to: writeToUrl)
            let compiledUrl = try MLModel.compileModel(at: writeToUrl)
            mlModel = try MLModel(contentsOf: compiledUrl)
        } catch {
            // エラー時の処理
        }
    }
    .store(in: &cancellables)

モデル作成コード実装時の注意事項

シミュレータのビルドでは動かないため、実機ビルドでビルドする必要があります。

シミュレータでビルドしようとすると、CreateMLのフレームワーク自体が見つからず以下エラーが出ます。

No such module 'CreateML'

機械学習モデルの利用

上記で作成したモデルは以下のように利用できます。

画風変換対象のUIImageを用意し、出力をUIImageとして利用できるように実装してみます。

必要ライブラリの読み込み

import CoreML
import Vision
import VideoToolbox

入力値の準備

let inputImage: UIImage // 画風変換の適応対象画像

let cgImage = inputImage.cgImage
let imageConstraint = mlModel.modelDescription.inputDescriptionsByName["image"]?.imageConstraint
let featureValue = try MLFeatureValue(cgImage: cgImage!, constraint: imageConstraint!)
let featureProvider = try MLDictionaryFeatureProvider(dictionary: ["image": featureValue])

画風変換後の出力データ取り出し

let mlModel: MLModel // 作成した機械学習モデル

let stylizedImage = try mlModel.prediction(from: featureProvider)
let imgBuffer = stylizedImage.featureValue(for: "stylizedImage")?.imageBufferValue

UIImageに変換

var cgImageForConvert: CGImage?
VTCreateCGImageFromCVPixelBuffer(imgBuffer!, options: nil, imageOut: &cgImageForConvert)
let stylizedUIImage = UIImage(cgImage: cgImageForConvert!, scale: 1.0, orientation: inputImage.imageOrientation)

結果の確認

変換結果
変換対象の画像にスタイル画像の画風を適応すると、こういった結果になるようです。

今回はデフォルトの設定をそのまま利用しましたが、モデル作成時にIterations、Strength、Densityなどのパラメータを調整することもできるので、そちらを変更するとまた違った出力を出すことができます。

おわりに

モデルの作成・利用が少ないコード量で簡単に実現できました。 この記事では画風変換を扱ったこともあり利用ケースは多くないかもしれませんが、Classfier や Regressor も利用できるものがあるため様々な展開が考えられそうです。

スマートフォンのデバイス上で動くので、データをクローズドな状態で管理でき、WebAPIに投げる必要もないので安全に扱うことができるのが大きなメリットだと思います。

反面の懸念事項としては、デバイスの処理能力に依存するので、快適な利用を考えるとある程度ユースケースに制限がかかってくるかもしれません。 (今回はチューニングなどは特に加えてないので、iPhone 11 Pro 端末でモデル作成時に30分ほど時間を要しています。)

とはいえ簡単に実装でき、機械学習のモデル作成も利用もオンデバイスで完結して動く、とても強力なFrameworkだと思います。直近のWWDCでは Create ML Components が発表されていたり、iOSでも機械学習関連はさらに進化を続けているのでこれからも楽しみです。

明日の記事の担当はデータエンジニアの谷元さんです。お楽しみに。


株式会社エニグモ すべての求人一覧

hrmos.co