🔍

iOSにTensorFlowを追加して予測する

2024/04/04に公開

iOSにTensorFlowを追加して予測する

この記事を書いている時点ではまだ目的を達成していないです。(今日は2024/4/4です)

まずは目的をはっきりさせましょう:

  • TensorFlowをインポートしてアプリを起動できること
  • モデルファイルを読み込んでモデルのレイヤーを確認できること
  • テスト用のデータを入力して予測ができること
  • 予測結果が変ではないこと(なぜかNativeをやってみたのもこれが理由、Flutter側では変な結果が出たので)
  • 本当のインプットデータを用意してモデルの効果を確かめること

TensorFlowをインポートしてアプリを起動できること

まずはTensorFlowをインポートしてアプリを起動できることを確認しましょう。

まずは公式サイトを見てみてください:

https://www.tensorflow.org/lite/guide/ios?hl=ja

日本語があって分かりやすい!!!

なので説明に沿って以下のものをPodfileに追加します:

use_frameworks!
pod 'TensorFlowLiteSwift'

そして。。。

そう!! pod install です!!!

pod install

Flutterの時と同じでインストールがめっちゃ遅いです。。。(今回はエラーが出なかったですが、エラー出た人はあの記事を見れば何とか助かるかも)

確認用のコードを入れてアプリを起動

インポートを確認したいので、以下のコードを入れてアプリを起動してみましょう:

import TensorFlowLite


class TensorFlowTest {
  
  func test() {
    try! Interpreter(modelPath: "")
  }
}

実行しないので単純にコンパイルが通ればOKです。

アプリが起動できれば問題ないです。(よっしゃーーーーーーーーーー)

モデルファイルを読み込んでモデルのレイヤーを確認できること

今の瞬間はまだできていない状態だが!!!
多分ファイルをどこかに入れるのだろう。。。よし調べるわい!!!

公式サイト:https://www.tensorflow.org/lite/guide/inference?hl=ja#swift_でモデルを読み込んで実行する

もう一回言う:日本語があって分かりやすい!!!

しかし:

// Getting model path
guard
  let modelPath = Bundle.main.path(forResource: "model", ofType: "tflite")
else {
  // Error handling...
}

しか書いてなくてどこにファイルを置くか書いてないです、おそらくそれはiOSの知識と思います、調べます。

調べてこのサイトが出ました:

https://stackoverflow.com/a/43129166/20989579

なので入れる場所は 「ターゲット」 -> 「Build Phases」 -> 「Copy Bundle Resources」です。

それはいいですが、うちのプロジェクトはTuistを使っているのでファイルを入れる時は要注意です、Tuistの場合はTargetresourcesにパスを入れることです。

場所がわかれば早速入れてみましょう!!!

しかし、この時に問題が起きました、Tuistに入れたのにこのコードではnilが返ってきます。。。

let modelPath = Bundle.main.path(forResource: "SensorModel", ofType: "tflite")

あっちゃーー、どうしよう〜

冷静にして考えましょう。。。

iOSに詳しくないですが、何とかできるはずです、プロジェクトの他のメンバーのコードを見てこのようなコードがあります:

let modelPath = Bundle(for: self).path(forResource: "SensorModel", ofType: "tflite")

よし、これでいけるかも!!!

やってみたらできました!!!

イェーーーーーーーーーーーー

しかし詳しいレイヤーは確認できないみたいです:

let itp = try! Interpreter(modelPath: modelPath)
print("\(itp.inputTensorCount)")  // output: 1
print("\(itp.outputTensorCount)")  // output: 1

よくわからないですが、これはこれでいいです、次に進みましょう!!!

しばらく。。。

レイヤーが確認できないのは少しキツい、もう少し見てみるか、インタープリンターとかのやつは取れているし。

ほんま探せば見つかるモンですね、インタープリンター何ちゃらのやつのメンバーを見てみたらinputoutputがあるじゃないですか!!!

なので:

print("\(try! itp.input(at: 0))")
print("\(try! itp.output(at: 0))")

しかし、実行してみたらMust call allocateTensors().というエラーが出ました、調べてみましたがまともに解決策が出てこなかったです。それでエラーをみたら、あらら、そのまま書いてあるじゃないですか!!!

try! itp.allocateTensors()
print("\(try! itp.input(at: 0))")
print("\(try! itp.output(at: 0))")

これでエラーが消えました!!!

でででだ

Tensor(name: "serving_default_flatten_input:0", dataType: TensorFlowLite.Tensor.DataType.float32, shape: TensorFlowLite.Tensor.Shape(rank: 3, dimensions: [1, 100, 9]), data: 3600 bytes, quantizationParameters: nil)
Tensor(name: "StatefulPartitionedCall:0", dataType: TensorFlowLite.Tensor.DataType.float32, shape: TensorFlowLite.Tensor.Shape(rank: 2, dimensions: [1, 5]), data: 20 bytes, quantizationParameters: nil)

のようにテンサーちゃらのやつが出ました!!!

よし、俺のモデルのレイヤーだ!!!

テスト用のデータを入力して予測ができること

センサーのデータをセットとして入れるので、企業機密に関わる部分もあって詳しくは書けませんが、書けるところだけ書きます。

ここは難しいところです、「重力」、「加速度」、「ジャイロ」三つのセンサー、合わせて9つの軸のそれぞれ100個のデータを一つのセットとして入れないといけないです。

Discussion