TensorFlow Lite と Firebase を使用してアプリにおすすめコンテンツを追加する - iOS Codelab

1. 概要

「TensorFlow Lite と Firebase によるレコメンデーション」Codelab にようこそ。この Codelab では、TensorFlow Lite と Firebase を使用してレコメンデーション モデルをアプリにデプロイする方法を学びます。この Codelab は、こちらの TensorFlow Lite のに基づいています。

おすすめを使用すると、アプリは機械学習を使用して、各ユーザーに最も関連性の高いコンテンツをインテリジェントに提供できます。多数の他のユーザーの全体的な行動でトレーニングされたモデルを使用して、過去のユーザーの行動を考慮して、そのユーザーが今後利用したいと思うアプリのコンテンツを提案します。

このチュートリアルでは、Firebase 向け Google アナリティクスを使用してアプリのユーザーからデータを取得し、そのデータからレコメンデーション用の ML モデルを構築して、iOS アプリでそのモデルを使用して推論を実行し、レコメンデーションを取得する方法を示します。具体的には、ユーザーが過去に高く評価した映画のリストに基づき、視聴する可能性が高い映画を提案します。

学習内容

  • Firebase 向け Google アナリティクスを Android アプリに統合してユーザーの行動データを収集する
  • そのデータを Google BigQuery にエクスポートする
  • データを前処理して TF Lite レコメンデーション モデルをトレーニングする
  • TF Lite モデルを Firebase ML にデプロイし、アプリからアクセスする
  • モデルを使用してデバイス上で推論を実行し、ユーザーにおすすめを提案する

必要なもの

  • Xcode 11(以降)
  • CocoaPods 1.9.1 以降

このチュートリアルをどのように使用されますか?

通読のみ 通読して演習を行う

iOS アプリの作成に関するご経験について、どのように思われますか。

<ph type="x-smartling-placeholder"></ph> 初心者 中級 上達 をご覧ください。

2. Firebase コンソール プロジェクトを作成する

Firebase をプロジェクトに追加する

  1. Firebase コンソールに移動します。
  2. [Create New Project] を選択し、プロジェクトに「Firebase ML iOS Codelab」という名前を付けます。

3. サンプル プロジェクトを取得する

コードのダウンロード

まず、サンプル プロジェクトのクローンを作成し、プロジェクト ディレクトリで pod update を実行します。

git clone https://github.com/FirebaseExtended/codelab-contentrecommendation-ios.git
cd codelab-contentrecommendation-ios/start
pod install --repo-update

git がインストールされていない場合は、GitHub ページから、またはこちらのリンクをクリックして、サンプル プロジェクトをダウンロードすることもできます。プロジェクトをダウンロードしたら、Xcode で実行し、推奨事項をいろいろ試してみて、その仕組みを確認します。

Firebase を設定する

こちらのドキュメントの手順に沿って、新しい Firebase プロジェクトを作成します。プロジェクトを取得したら、Firebase コンソールからプロジェクトの GoogleService-Info.plist ファイルをダウンロードして、Xcode プロジェクトのルートにドラッグします。

4a923d5c7ae0d8f3.png

Podfile に Firebase を追加し、pod install を実行します。

pod 'FirebaseAnalytics'
pod 'FirebaseMLModelDownloader', '9.3.0-beta'
pod 'TensorFlowLiteSwift'

AppDelegatedidFinishLaunchingWithOptions メソッドで、ファイルの先頭に Firebase をインポートします。

import FirebaseCore

Firebase を構成する呼び出しを追加します。

FirebaseApp.configure()

プロジェクトを再度実行して、アプリが正しく設定され、起動時にクラッシュしないことを確認します。

  1. [このプロジェクトの Google アナリティクスを有効にする] がオンになっていることを確認します有効になります。
  2. Firebase コンソールで残りの設定手順を実施した後、[プロジェクトを作成](既存の Google プロジェクトを使用する場合は [Firebase を追加])をクリックします。

4. アプリに Firebase アナリティクスを追加する

このステップでは、Firebase Analytics をアプリに追加して、ユーザー行動データ(この場合は、ユーザーが気に入っている映画)を記録します。このデータは、今後のステップで集計され、レコメンデーション モデルのトレーニングに使用されます。

アプリで Firebase アナリティクスを設定する

LikedMoviesViewModel には、ユーザーが好きな映画を保存する関数が含まれています。ユーザーが新しい映画に「高評価」を付けるたびに、アナリティクス ログイベントを送信して、その高評価を記録したいとします。

以下のコードを追加して、ユーザーが映画の「高評価」をクリックしたときにアナリティクス イベントを登録します。

AllMoviesCollectionViewController.swift

import FirebaseAnalytics
//


override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
//

if movie.liked == nil {
      movie.liked = true
      Analytics.logEvent(AnalyticsEventSelectItem, parameters: [AnalyticsParameterItemID: movie.id])
    } else {
      movie.liked?.toggle()
    }
       
}

5. アナリティクスとの統合をテストする

このステップでは、アプリでアナリティクス イベントを生成し、それが Firebase コンソールに送信されていることを確認します。

アナリティクスのデバッグ ロギングを有効にする

一般的に、アプリによってロギングされるイベントは、約 1 時間の周期でバッチ処理され、まとめてアップロードされます。このアプローチにより、エンドユーザーのネットワーク データ使用量を削減できます。ただし、アナリティクスの実装を検証する(また、DebugView レポートでアナリティクスを確認する)目的では、開発デバイスでデバッグモードを有効にすることで、最小限の遅延でイベントをアップロードできます。

開発用デバイスでアナリティクスのデバッグモードを有効にするには、Xcode で次のコマンドライン引数を指定します。

-FIRDebugEnabled

これで、Firebase Analytics がアプリに正常に統合されました。ユーザーがアプリを使用して映画に高評価を付けると、高評価が集計されて記録されます。この Codelab の残りの部分では、この集計データを使用してレコメンデーション モデルをトレーニングします。次の手順では、Logcat で表示したアナリティクス イベントと同じものを Firebase コンソールにストリーミングすることもできます。次のページに進んでいただいても構いません。

省略可: Firebase コンソールでアナリティクス イベントを確認する

  1. Firebase コンソールに移動します。
  2. [アナリティクス] で [DebugView] を選択します。
  3. Xcode で [Run] を選択してアプリを起動し、高く評価したリストに映画を追加します。
  4. Firebase コンソールの DebugView で、アプリで映画を追加するときにこれらのイベントが記録されていることを確認します。

6. アナリティクスのデータを BigQuery にエクスポートする

BigQuery は、大量のデータを調べて処理できる Google Cloud プロダクトです。このステップでは、Firebase コンソール プロジェクトを BigQuery に接続して、アプリで生成されたアナリティクス データが BigQuery に自動的にエクスポートされるようにします。

BigQuery エクスポートを有効にする

  1. Firebase コンソールに移動します。
  2. [プロジェクトの概要] の横にある設定の歯車アイコンを選択し、[プロジェクトの設定] を選択します。
  3. [Integrations] タブを選択します。
  4. [BigQuery] ブロック内の [リンク](または [管理])を選択します。
  5. [Firebase と BigQuery のリンクについて] の手順で [次へ] を選択します。
  6. [統合を設定] セクションで、スイッチをクリックして Google アナリティクス データの送信を有効にし、[BigQuery にリンク] を選択します。

これで、Firebase コンソール プロジェクトから Firebase Analytics イベントデータを BigQuery に自動的に送信できるようになりました。この処理はそれ以上の操作なしで自動的に行われますが、BigQuery に分析データセットを作成する最初のエクスポートは 24 時間行われない場合があります。データセットが作成されると、Firebase は新しいアナリティクス イベントを BigQuery のイントラデイ テーブルに継続的にエクスポートし、過去の日付のイベントをイベント テーブルにグループ化します。

レコメンデーション モデルをトレーニングするには、大量のデータが必要です。大量のデータを生成するアプリはまだないため、次のステップでは、このチュートリアルの残りの部分で使用するサンプル データセットを BigQuery にインポートします。

7. BigQuery を使用してモデルのトレーニング データを取得する

Firebase コンソールを BigQuery に接続してエクスポートを設定したので、しばらくするとアプリ アナリティクスのイベントデータが BigQuery コンソールに自動的に表示されます。このチュートリアルで使用する初期データを取得するために、このステップでは既存のサンプル データセットを BigQuery コンソールにインポートして、レコメンデーション モデルのトレーニングに使用します。

サンプル データセットを BigQuery にインポートする

  1. Google Cloud コンソールで BigQuery ダッシュボードに移動します。
  2. メニューでプロジェクト名を選択します。
  3. BigQuery の左側のナビゲーションの下部にあるプロジェクト名を選択して、詳細を表示します。
  4. [データセットを作成] を選択してデータセット作成パネルを開きます。
  5. [データセット ID] に「firebase_recommendations_dataset」と入力し、[データセットを作成] を選択します。
  6. 新しいデータセットが左側のメニューのプロジェクト名の下に表示されます。これをクリックします。
  7. [テーブルを作成] を選択してテーブル作成パネルを開きます。
  8. [テーブルの作成元] で [Google Cloud Storage] を選択します。
  9. [GCS バケットからファイルを選択] フィールドに「gs://firebase-recommendations/recommendations-test/formatted_data_filtered.txt」と入力します。
  10. [JSONL] を選択[ファイル形式] プルダウンを選択します。
  11. [テーブル名] に「recommendations_table」と入力します。
  12. [スキーマ >自動検出 >スキーマと入力パラメータ
  13. [テーブルを作成] を選択します。

サンプル データセットを探索する

この時点で、必要に応じてスキーマを調べて、このデータセットをプレビューできます。

  1. 左側のメニューで [firebase-recommendations-dataset] を選択して、含まれているテーブルを開きます。
  2. recommendations-table テーブルを選択して、テーブル スキーマを表示します。
  3. [プレビュー] を選択すると、このテーブルに含まれている実際のアナリティクス イベントデータを確認できます。

サービス アカウントの認証情報を作成する

次に、Google Cloud コンソール プロジェクトでサービス アカウントの認証情報を作成します。この認証情報は、次のステップで Colab 環境で BigQuery データにアクセスして読み込むために使用します。

  1. Google Cloud プロジェクトの課金が有効になっていることを確認します。
  2. BigQuery API と BigQuery Storage API を有効にします。<こちらをクリック>
  3. [サービス アカウント キーの作成] ページに移動します。
  4. [サービス アカウント] リストから [新しいサービス アカウント] を選択します。
  5. [サービス アカウント名] フィールドに名前を入力します。
  6. [役割] リストで、[プロジェクト] > [オーナー] を選択します。
  7. [作成] をクリックします。キーを含む JSON ファイルがパソコンにダウンロードされます。

次のステップでは、Google Colab を使用してこのデータを前処理し、おすすめモデルをトレーニングします。

8. データを前処理してレコメンデーション モデルをトレーニングします。

このステップでは、Colab ノートブックを使用して次の操作を行います。

  1. BigQuery データを Colab ノートブックにインポートする
  2. データを前処理してモデルのトレーニング用に準備する
  3. 分析データでレコメンデーション モデルをトレーニングする
  4. モデルを TF Lite モデルとしてエクスポートする
  5. モデルを Firebase コンソールにデプロイして、アプリで使用できるようにする

Colab トレーニング ノートブックをリリースする前に、まず Firebase Model Management API を有効にして、Colab がトレーニング済みモデルを Firebase コンソールにデプロイできるようにします。

Firebase Model Management API を有効にする

ML モデルを保存するバケットを作成する

Firebase コンソールで [Storage] に移動し、[始める] をクリックします。fbbea78f0eb3dc9f.png

ダイアログに沿ってバケットを設定します。

19517c0d6d2aa14d.png

Firebase ML API を有効にする

Google Cloud コンソールの Firebase ML API ページに移動し、[有効にする] をクリックします。

Colab ノートブックを使用してモデルをトレーニングしてデプロイする

次のリンクを使用して Colab ノートブックを開き、以下の手順に沿って操作します。Colab ノートブックでの手順を完了すると、Firebase コンソールにデプロイされた TF Lite モデルファイルがアプリに同期されます。

Colab で開く

9. アプリにモデルをダウンロードする

このステップでは、先ほどトレーニングしたモデルを Firebase Machine Learning からダウンロードするようにアプリを変更します。

Firebase ML の依存関係を追加する

アプリで Firebase ML モデルを使用するには、次の依存関係が必要です。すでに追加されているはずです(確認)。

Podfile

import FirebaseCore
import FirebaseMLModelDownloader

Firebase Model Manager API を使用してモデルをダウンロードする

以下のコードを ModelLoader.swift にコピーして、モデルのダウンロードが発生する条件を設定し、ダウンロード タスクを作成してリモートモデルをアプリに同期します。

ModelLoader.swift

static func downloadModel(named name: String,
                            completion: @escaping (CustomModel?, DownloadError?) -> Void) {
    guard FirebaseApp.app() != nil else {
      completion(nil, .firebaseNotInitialized)
      return
    }
    guard success == nil && failure == nil else {
      completion(nil, .downloadInProgress)
      return
    }
    let conditions = ModelDownloadConditions(allowsCellularAccess: false)
    ModelDownloader.modelDownloader().getModel(name: name, downloadType: .localModelUpdateInBackground, conditions: conditions) { result in
            switch (result) {
            case .success(let customModel):
                    // Download complete.
                    // The CustomModel object contains the local path of the model file,
                    // which you can use to instantiate a TensorFlow Lite classifier.
                    return completion(customModel, nil)
            case .failure(let error):
                // Download was unsuccessful. Notify error message.
              completion(nil, .downloadFailed(underlyingError: error))
            }
    }
  }

10. Tensorflow Lite レコメンデーション モデルをアプリに統合する

Tensorflow Lite ランタイムを使用すると、アプリでモデルを使用してレコメンデーションを生成できます。前の手順では、ダウンロードしたモデルファイルを使用して TFlite インタープリタを初期化しました。このステップでは、まず推論ステップでモデルに付随する辞書とラベルを読み込みます。次に、モデルへの入力を生成するための前処理と、推論から結果を抽出する後処理を追加します。

辞書とラベルを読み込む

レコメンデーション モデルによってレコメンデーションの候補を生成するために使用されるラベルは、アセット フォルダの sorted_movie_vocab.json ファイルにリストされています。次のコードをコピーして、これらの候補を読み込みます。

RecommendationsViewController.swift

  func getMovies() -> [MovieItem] {
    let barController = self.tabBarController as! TabBarController
    return barController.movies
  }

前処理の実装

前処理のステップでは、モデルが想定する内容に合わせて入力データの形式を変更します。ここでは、ユーザーの「高評価」がまだ多く生成されていない場合は、入力の長さをプレースホルダ値でパディングします。以下のコードをコピーします。

RecommendationsViewController.swift

  // Given a list of selected items, preprocess to get tflite input.
  func preProcess() -> Data {
    let likedMovies = getLikedMovies().map { (MovieItem) -> Int32 in
      return MovieItem.id
    }
    var inputData = Data(copyingBufferOf: Array(likedMovies.prefix(10)))

    // Pad input data to have a minimum of 10 context items (4 bytes each)
    while inputData.count < 10*4 {
      inputData.append(0)
    }
    return inputData
  }

インタープリタを実行して推奨事項を生成する

ここでは、前のステップでダウンロードしたモデルを使用して、前処理済みの入力に対して推論を実行します。モデルの入力と出力のタイプを設定し、推論を実行して映画のレコメンデーションを生成します。アプリに次のコードをコピーします。

RecommendationsViewController.swift

import TensorFlowLite

RecommendationsViewController.swift

 private var interpreter: Interpreter?

 func loadModel() {
    // Download the model from Firebase
    print("Fetching recommendations model...")
    ModelDownloader.fetchModel(named: "recommendations") { (filePath, error) in
      guard let path = filePath else {
        if let error = error {
          print(error)
        }
        return
      }
      print("Recommendations model download complete")
      self.loadInterpreter(path: path)
    }
  }

 func loadInterpreter(path: String) {
    do {
      interpreter = try Interpreter(modelPath: path)

      // Allocate memory for the model's input `Tensor`s.
      try interpreter?.allocateTensors()

      let inputData = preProcess()

      // Copy the input data to the input `Tensor`.
      try self.interpreter?.copy(inputData, toInputAt: 0)

      // Run inference by invoking the `Interpreter`.
      try self.interpreter?.invoke()

      // Get the output `Tensor`
      let confidenceOutputTensor = try self.interpreter?.output(at: 0)
      let idOutputTensor = try self.interpreter?.output(at: 1)

      // Copy output to `Data` to process the inference results.
      let confidenceOutputSize = confidenceOutputTensor?.shape.dimensions.reduce(1, {x, y in x * y})

      let idOutputSize = idOutputTensor?.shape.dimensions.reduce(1, {x, y in x * y})

      let confidenceResults =
        UnsafeMutableBufferPointer<Float32>.allocate(capacity: confidenceOutputSize!)
      let idResults =
        UnsafeMutableBufferPointer<Int32>.allocate(capacity: idOutputSize!)
      _ = confidenceOutputTensor?.data.copyBytes(to: confidenceResults)
      _ = idOutputTensor?.data.copyBytes(to: idResults)

      postProcess(idResults, confidenceResults)

      print("Successfully ran inference")
      DispatchQueue.main.async {
        self.tableView.reloadData()
      }
    } catch {
      print("Error occurred creating model interpreter: \(error)")
    }
  }

後処理の実装

最後に、モデルからの出力を後処理して、信頼度が最も高い結果を選択し、含まれる値(ユーザーがすでに高く評価している映画)を削除します。次のコードをアプリにコピーします。

RecommendationsViewController.swift

  // Postprocess to get results from tflite inference.
  func postProcess(_ idResults: UnsafeMutableBufferPointer<Int32>, _ confidenceResults: UnsafeMutableBufferPointer<Float32>) {
    for i in 0..<10 {
      let id = idResults[i]
      let movieIdx = getMovies().firstIndex { $0.id == id }
      let title = getMovies()[movieIdx!].title
      recommendations.append(Recommendation(title: title, confidence: confidenceResults[i]))
    }
  }

アプリをテストする

アプリを再実行します。映画をいくつか選択すると、新しいモデルが自動的にダウンロードされ、おすすめの生成が開始されます。

11. 完了

TensorFlow Lite と Firebase を使用して、アプリにレコメンデーション機能を組み込みました。この Codelab で紹介する手法とパイプラインは一般化して、他のタイプのレコメンデーションにも使用できます。

学習した内容

  • Firebase ML
  • Firebase アナリティクス
  • 分析イベントを BigQuery にエクスポートする
  • アナリティクス イベントを事前処理する
  • レコメンデーションの TensorFlow モデルをトレーニングする
  • モデルをエクスポートして Firebase コンソールにデプロイする
  • アプリで映画のレコメンデーションを提供する

次のステップ

  • アプリに Firebase ML のおすすめを実装する。

詳細

質問がある場合

問題を報告する