
みなさんこんにちは!
3週目のAKARI Tech Blog担当になりました、
DX Solution 事業本部 Dev チームリーダーの三澤(拓真)が担当します!普段は画像・点群系のAIエンジニアをしています!
今回の記事では「iOSで機械学習を扱うためのフレームワークであるCoreML」についてご紹介しようと思います!
TL;DR
- CoreMLはiOSで機械学習を扱うためのフレームワーク
- CoreML Modelの作成方法は主に以下の2つ
- CreateMLを使ってMac上で訓練する方法
- coremltoolsを使って訓練済みモデルを変換する方法
- とりあえず試したいって方はApple公式のモデルやAPIを使うのがおすすめ
1. Core MLとは?
iOSで機械学習を扱うためのフレームワークとして、Core MLがあります。
iOS11で登場し、他のフレームワークと比べて扱いやすい点が特に評価されて人気が出ているようです。
後述する方法を用いてCoreML Modelを用意することで、Core ML経由でCPU, Neural Engineにアクセスできます。
https://developer.apple.com/documentation/coreml
2. 何がいいの?
じゃあ、Core MLを扱えて何がいいの?という話ですが、なんといってもオンデバイスで機械学習(特に画像系)を気軽に扱えることだと思っています。
一般的に想像されるエッジデバイス(raspi, Jetson等)では軽量化されたモデルを動かしたり、onnx化したり…と色々あります。
しかし、iOSやiPad OSで動かすには、一見ハードルが高そうに見えますよね。
Core MLを使えば、難しいことを考えずに動かせます!
また、iPhone, iPad自体は処理能力に加えてカメラやセンサー類も優秀ですので、画像系との相性がとてもいいと思います!
3. Core ML Modelの作成方法
CoreML Modelを作成する方法は2025年2月27日時点で以下の2つが主流だと思います!
- CreateMLを使ってMac上で訓練する方法
- coremltoolsを使って訓練済みモデルを変換する方法
- coremltools 4.0からはonnx経由で変換することが非推奨になったので注意.
- Pytorchモデルから直接coremlモデルに変換できます
- coremltools 4.0からはonnx経由で変換することが非推奨になったので注意.
3.1 CreateMLを使用する方法
iOSに限らず、私が知っている中で一番簡単にモデルを訓練できる方法だと思っているCreateMLですが、大まかな手順は以下です!
① Xcodeを入手 (入手されていない方は手順2までに色々と手間がかかるかもしれませんが、今回は入っている前提で進めます)
② 左上のXcode > Open Developer Tool > CreateMLを選択

③ New Documentで訓練させたいタスクに対してのテンプレートを選択可能(今回はImage Classification)

④ ProjectNameを決めて作成

⑤ あとはtrain ,val, testでそれぞれデータを渡してあげるだけ!

これだけの手順で訓練から推論までできるCreateML、素晴らしいですよね。
個人的には、モデルのアーキテクチャや詳細なパラメータが抽象化されているおかげで経験が少ない人でも触れるようになっていることが魅力的に感じます。
ただ、普段からAI開発をしていて精度を求める人は次に紹介する方法でモデル変換をした方がいいと思います。
3.2 coremltoolsを使用する方法
すでに訓練済みのモデルをCoreML Modelとして扱いたい場合は、coremltoolsを使って変換することができます。
pythonを使ってpytorchのモデルを変換させてみる手順を紹介します!
今回、torchvisionで用意されている事前学習済みモデルを使おうと思っていますが、モデル自体がdictを返すため、そのままだとエラーが起きます。そのため、既存のモデルのWrapperを作成して受け取れる形式のmodelを作成します。
import coremltools as ct import torch import torchvision import json class WrappedSegmentationModel(torch.nn.Module): def __init__(self, model: torch.nn.Module): super(WrappedSegmentationModel, self).__init__() self.model = model def forward(self, x: torch.Tensor) -> torch.Tensor: return self.model(x)["out"] model = torchvision.models.segmentation.deeplabv3_resnet50(pretrained=True) model = WrappedSegmentationModel(model) # これがないとエラーが起きる model.eval()
3.2.3 pytorchのモデルをtraceする
CoreML Modelに変換するために、モデルをTorchScriptの形式に変換する必要があります。
とは言ってもそんなに難しくなく、入力を定義して渡すだけでできます。
example_input = torch.rand(1, 3, 224, 224) traced_model = torch.jit.trace(model, example_input, strict=False)
3.2.4 CoreML Modelに変換
あとはtraced_modelをCoreML Modelに変換するだけです!
labels_json = {"labels": ["background", "aeroplane", "bicycle", "bird", "board", "bottle", "bus", "car", "cat", "chair", "cow", "diningTable", "dog", "horse", "motorbike", "person", "pottedPlant", "sheep", "sofa", "train", "tvOrMonitor"]}
mlmodel = ct.convert(
traced_model,
inputs=[ct.ImageType(name="input", shape=example_input.shape, color_layout="RGB", scale=1/255.0, bias=[-2.1179, -2.0357, -1.8044])],
outputs=[ct.TensorType(name="output")]
)
mlmodel.user_defined_metadata["com.apple.coreml.model.preview.type"] = "imageSegmenter"
mlmodel.user_defined_metadata["com.apple.coreml.model.preview.params"] = json.dumps(labels_json)
なんだ、これだけ?と思う方もいるかもしれませんが、調べてみると先駆者が少なくて絶望した方も多いかもしれません。 ちゃんとcoremltoolsのドキュメント(https://apple.github.io/coremltools/docs-guides/source/xcode-model-preview-types.html)を読み込む必要がありますが、特にハマりがちなポイントをいくつか紹介します!
ハマりポイント1 - 正規化の有無
さりげなくinputsでImageType を指定していますが、ネットで調べるとTensorTypeで書かれていることもあります。
iOSで扱う場合、どちらを指定しても動かせますが、画像系のモデルを動かすならImageType を指定することを推奨します。
それは、正規化をフローの中に組み込めるかどうか、です。
今回だとImageNetを訓練させた重みを使っているので、mean = [0.485, 0.456, 0.406], std = [0.229, 0.224, 0.225] という値で正規化されています。bias = - mean / std になるので、今回だとscale=1/255.0, bias=[-2.1179, -2.0357, -1.8044] を指定します。これを指定しないと、悲惨なことになります。

なんだこりゃ。

ハマりポイント2 - .mlmodel vs .mlpackage
調べていると、多くの人がモデルの書き出しを.mlmodelで実施しています。
しかし、いくつか前のバージョンからmlpackageが出てきており、現在は.mlpackageが推奨されています。
調べてみると.mlpackageではプレビューが出ないなどの問題が見つかりますが、現在のバージョンではほとんど解決されているので安心してmlpackageを使いましょう!(最新のcoremltoolsではmlmodelを使うとエラーが出ました)
ハマりポイント3 - プレビューできない
CoreML Modelは、変換方法によってXCodeでプレビュー(推論)ができます。
ImageType同様、iOSで扱う場合にはプレビューを出さなくてもいいんですが、ちゃんと変換できたかの確認のために毎回アプリに組み込んで…としているととても時間がかかるので、プレビューを使うことをお勧めします。
しかし、プレビューを出すのにも実はいくつかの苦労が…
今回だと最後にさりげなく書いていたこの2行です。
mlmodel.user_defined_metadata["com.apple.coreml.model.preview.type"] = "imageSegmenter" mlmodel.user_defined_metadata["com.apple.coreml.model.preview.params"] = json.dumps(labels_json)
これでpreviewのtypeとlabelを付与しています。これがないと、プレビューができません…

3.2.5 コード全体
import coremltools as ct import torch import torchvision import json class WrappedSegmentationModel(torch.nn.Module): def __init__(self, model: torch.nn.Module): super(WrappedSegmentationModel, self).__init__() self.model = model def forward(self, x: torch.Tensor) -> torch.Tensor: return self.model(x)["out"] model = torchvision.models.segmentation.deeplabv3_resnet50(pretrained=True) model = WrappedSegmentationModel(model) model.eval() example_input = torch.rand(1, 3, 224, 224) traced_model = torch.jit.trace(model, example_input, strict=False) labels_json = {"labels": ["background", "aeroplane", "bicycle", "bird", "board", "bottle", "bus", "car", "cat", "chair", "cow", "diningTable", "dog", "horse", "motorbike", "person", "pottedPlant", "sheep", "sofa", "train", "tvOrMonitor"]} mlmodel = ct.convert( traced_model, inputs=[ct.ImageType(name="input", shape=example_input.shape, color_layout="RGB", scale=1/255.0, bias=[-2.1179, -2.0357, -1.8044])], outputs=[ct.TensorType(name="output")] ) mlmodel.user_defined_metadata["com.apple.coreml.model.preview.type"] = "imageSegmenter" mlmodel.user_defined_metadata["com.apple.coreml.model.preview.params"] = json.dumps(labels_json) mlmodel.save("DeepLabV3ResNet50.mlpackage")
4. その他のモデル活用
ここまで作り方を説明してきましたが、すでにCoreML Modelに変換されているものを使うという手もあります。
例えば、Appleのhuggingfaceに飛ぶと単眼深度推定、セマンティックセグメンテーション、画像分類、画像生成…など、いろいろなcoremlモデルが公開されています。
おそらく、一番手っ取り早いのはこれらのモデルを使うことだと思います。公式が出してることもあって、ちゃんと高速で精度も良さげです。

他にも、huggingfaceなどで変換されたモデルがあったり、githubで変換するコードを置いていたりするので、それを活用する、という選択肢もあります。
まとめ
CoreMLは簡単なのに扱いやすいので、機械学習の選択肢にiOSを入れてみるのはどうでしょうか??
We’re Hiring!
燈では、iOSエンジニア/AIエンジニア/ソフトウェアエンジニアを、正社員もインターンのどちらも募集しております!
興味がある方は、ぜひカジュアル面談でお話しましょう!🔥
今回の記事を書いた燈メンバー🙌
