iOSにTensorFlowを追加して予測する
iOSにTensorFlowを追加して予測する
この記事を書いている時点ではまだ目的を達成していないです。(今日は2024/4/4です)
まずは目的をはっきりさせましょう:
- TensorFlowをインポートしてアプリを起動できること
- モデルファイルを読み込んでモデルのレイヤーを確認できること
- テスト用のデータを入力して予測ができること
- 予測結果が変ではないこと(なぜかNativeをやってみたのもこれが理由、Flutter側では変な結果が出たので)
- 本当のインプットデータを用意してモデルの効果を確かめること
TensorFlowをインポートしてアプリを起動できること
まずはTensorFlowをインポートしてアプリを起動できることを確認しましょう。
まずは公式サイトを見てみてください:
日本語があって分かりやすい!!!
なので説明に沿って以下のものを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の知識と思います、調べます。
調べてこのサイトが出ました:
なので入れる場所は 「ターゲット」 -> 「Build Phases」 -> 「Copy Bundle Resources」です。
それはいいですが、うちのプロジェクトはTuistを使っているのでファイルを入れる時は要注意です、Tuistの場合はTarget
のresources
にパスを入れることです。
場所がわかれば早速入れてみましょう!!!
しかし、この時に問題が起きました、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
よくわからないですが、これはこれでいいです、次に進みましょう!!!
しばらく。。。
レイヤーが確認できないのは少しキツい、もう少し見てみるか、インタープリンターとかのやつは取れているし。
ほんま探せば見つかるモンですね、インタープリンター何ちゃらのやつのメンバーを見てみたらinput
とoutput
があるじゃないですか!!!
なので:
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