【iOS11 / CoreML】自作した回帰予測モデル(.mlmodel)の結果を得る実装方法 (Regression, VNCoreMLRequest)
iOS11がリリースされて3日経過したが、本家が提供するモデルはMobileNet、SqueezeNet、Places205-GoogLeNet、ResNet50、Inception v3と分類モデルが多く、サンプルコードも分類しか見つけられない。
なので、今回は回帰予測モデル(具体的には、1次元配列 : 3次元ベクトル回帰)について説明。(世間で回帰関連の記事もないので)
説明すること:回帰の場合の実装方法(比較として分類の場合も記載)
説明しないこと:CoreMLの基本的な使い方、実行方法(巷に溢れているので割愛)
参考資料
本家で提供される学習済みモデル一覧
Machine Learning - Apple Developer
CoreMLの分類サンプルコード
Classifying Images with Vision and Core ML | Apple Developer Documentation
回帰モデルの説明
自作したモデルは、1次元配列(3次元ベクトル)を求めるようなモデル。
(まぁ多次元配列でもスカラー値でも、話は同じだったので割愛)
Kerasで学習させた回帰モデルをCoreMLToolsを用いて変換する。
変換イメージ
- Keras model (.h5) → [CoreMLTools] → CoreML model (.mlmodel)
生成されたモデル (例えば、MyRegression.mlmodel) はXcodeでプロジェクトにドラック&ドロップすることで見える。
モデルの確認方法
- プロジェクト上にドラック&ドロップした自作モデルをクリック -> [Model Evaluation Parameters] -> [outputs]
モデル情報は次の通り。
Name | Type | Description |
output1 | MultiArray<Double, 3> | (未記入) |
MultiArrayとして、3要素のDouble型1次元配列を回帰するモデルとなっていると確認できる。
[分類/回帰]モデルをロード
なんてことはない、分類も回帰も同じ手順
//学習済みmodelをロード (分類) let model = try! VNCoreMLModel(for: MyClassification().model) # 提供される学習済みであればMobileNet()とか //学習済みmodelをロード (回帰) let model = try! VNCoreMLModel(for: MyRegression().model)
[分類/回帰]モデルと結果を受け取るコールバックを設定
ここも特に差はない、分類も回帰も同じ手順
//分類 let coremlRequest = VNCoreMLRequest(model: model, completionHandler: { (request, error) in self?.processClassification(for: request, error: error) }) //回帰 let coremlRequest = VNCoreMLRequest(model: model, completionHandler: { (request, error) in self?.processRegression(for: request, error: error) })
[分類/回帰]コールバック関数 / 結果の読み取り【最重要】
ポイントは下記で、分類と回帰でクラスを使い分ける
分類の場合 | 回帰の場合 |
VNClassificationObservation | VNCoreMLFeatureValueObservation |
//分類(VNClassificationObservation) func processClassification(for request: VNRequest, error: Error?) { guard let observations = request.results as? [VNClassificationObservation] else { fatalError() } guard let best = observations.first else { fatalError() } //best.identifier : best時のクラス情報 //best.confidence : best時の信頼度 } //回帰(VNCoreMLFeatureValueObservation) func processClassification(for request: VNRequest, error: Error?) { guard let observations = request.results as? [VNCoreMLFeatureValueObservation] else { fatalError() } guard let values = observations[0].featureValue.multiArrayValue! //valuesはここでArrayになっているので //あとはランダムアクセスすればスカラー値が取得できる //values[0], values[1], values[2] }
ちなみに、回帰でbservations[0]の0は、学習時のバッチサイズの問題だと思っている。(確か)
感想
- 単純な回帰だけでなく生成モデルとかやる場合は使いそう。
- 17/09/23時点では、 Webで調べても全く記事が無く、世間はあまり回帰に興味が無いのか?
- もっといい方法があれば教えてください。