Android によるテキスト分類

このチュートリアルでは、TensorFlow Lite を使用して自然言語テキストを分類する Android アプリケーションを構築する方法を示します。このアプリケーションは物理 Android デバイス用に設計されていますが、デバイス エミュレータ上でも実行できます。

このサンプル アプリケーションでは、 TensorFlow Lite を使用してテキストをポジティブまたはネガティブに分類し、自然言語 (NL) のタスク ライブラリを使用してテキスト分類機械学習モデルの実行を可能にします。

既存のプロジェクトを更新する場合は、サンプル アプリケーションを参照またはテンプレートとして使用できます。既存のアプリケーションにテキスト分類を追加する方法については、 「アプリケーションの更新と変更」を参照してください。

テキスト分類の概要

テキスト分類は、事前に定義された一連のカテゴリを自由形式のテキストに割り当てる機械学習タスクです。テキスト分類モデルは自然言語テキストのコーパスでトレーニングされ、単語やフレーズが手動で分類されます。

トレーニングされたモデルはテキストを入力として受け取り、分類するためにトレーニングされた既知のクラスのセットに従ってテキストを分類しようとします。たとえば、この例のモデルはテキストの断片を受け入れ、テキストのセンチメントがポジティブかネガティブかを判断します。テキスト分類モデルは、テキストの各スニペットに対して、テキストが肯定的または否定的のいずれかに正しく分類されている信頼度を示すスコアを出力します。

このチュートリアルのモデルがどのように生成されるかについての詳細は、 TensorFlow Lite Model Maker チュートリアルによるテキスト分類を参照してください。

モデルとデータセット

このチュートリアルでは、 SST-2 (Stanford Sentiment Treebank) データセットを使用してトレーニングされたモデルを使用します。 SST-2 には、トレーニング用の 67,349 件の映画レビューとテスト用の 872 件の映画レビューが含まれており、各レビューは肯定的または否定的に分類されています。このアプリで使用されるモデルは、TensorFlow Lite Model Makerツールを使用してトレーニングされました。

サンプル アプリケーションでは、次の事前トレーニングされたモデルを使用します。

  • Average Word Vector ( NLClassifier ) - タスク ライブラリのNLClassifier入力テキストをさまざまなカテゴリに分類し、ほとんどのテキスト分類モデルを処理できます。

  • MobileBERT ( BertNLClassifier ) - タスク ライブラリのBertNLClassifier NLClassifier に似ていますが、グラフ外のワードピースとセンテンスピースのトークン化が必要な場合に合わせて調整されています。

サンプルアプリをセットアップして実行する

テキスト分類アプリケーションをセットアップするには、 GitHubからサンプル アプリをダウンロードし、 Android Studioを使用して実行します。

システム要求

  • Android Studioバージョン 2021.1.1 (Bumblebee) 以降。
  • Android SDK バージョン 31 以降
  • 開発者モードが有効になっている SDK 21 (Android 7.0 - Nougat) の最小 OS バージョンを搭載した Android デバイス、または Android エミュレータ。

サンプルコードを入手する

サンプル コードのローカル コピーを作成します。このコードを使用して Android Studio でプロジェクトを作成し、サンプル アプリケーションを実行します。

サンプルコードを複製してセットアップするには、次のようにします。

  1. git リポジトリ
    git clone https://github.com/tensorflow/examples.git
    
    のクローンを作成します
  2. 必要に応じて、スパース チェックアウトを使用するように Git インスタンスを構成すると、テキスト分類サンプル アプリのファイルのみが用意されます:
    cd examples
    git sparse-checkout init --cone
    git sparse-checkout set lite/examples/text_classification/android
    

プロジェクトをインポートして実行する

ダウンロードしたサンプル コードからプロジェクトを作成し、プロジェクトをビルドして実行します。

サンプル コード プロジェクトをインポートしてビルドするには:

  1. Android Studioを起動します。
  2. Android Studio から、 [ファイル] > [新規作成] > [プロジェクトのインポート]を選択します。
  3. build.gradle ファイルを含むサンプル コード ディレクトリ ( .../examples/lite/examples/text_classification/android/build.gradle ) に移動し、そのディレクトリを選択します。
  4. Android Studio が Gradle Sync を要求する場合は、[OK] を選択します。
  5. Android デバイスがコンピュータに接続されており、開発者モードが有効になっていることを確認してください。緑色のRun矢印をクリックします。

正しいディレクトリを選択すると、Android Studio は新しいプロジェクトを作成してビルドします。コンピューターの速度や、他のプロジェクトで Android Studio を使用しているかどうかによっては、このプロセスに数分かかる場合があります。ビルドが完了すると、Android Studio の[ビルド出力ステータス] パネルにBUILD SUCCESSFULメッセージが表示されます。

プロジェクトを実行するには:

  1. Android Studio から、 [実行] > [実行…]を選択してプロジェクトを実行します。
  2. アプリをテストするには、接続されている Android デバイス (またはエミュレーター) を選択します。

アプリケーションの使用

Android のテキスト分類サンプル アプリ

Android Studio でプロジェクトを実行すると、接続されたデバイスまたはデバイス エミュレーター上でアプリケーションが自動的に開きます。

テキスト分類子を使用するには:

  1. テキストボックスにテキストの一部を入力します。
  2. [デリゲート]ドロップダウンから、 CPUまたはNNAPIを選択します。
  3. AverageWordVecまたはMobileBERTを選択してモデルを指定します。
  4. [分類]を選択します。

アプリケーションは、正のスコアと負のスコアを出力します。これら 2 つのスコアの合計は 1 になり、入力テキストの感情が肯定的であるか否定的である可能性を測定します。数値が大きいほど、信頼度が高いことを示します。

これで、テキスト分類アプリケーションが機能するようになりました。次のセクションを使用して、サンプル アプリケーションがどのように動作するか、および実稼働アプリケーションにテキスト分類機能を実装する方法をよりよく理解します。

サンプルアプリの仕組み

アプリケーションは、自然言語 (NL) パッケージのタスク ライブラリを使用して、テキスト分類モデルを実装します。 Average Word Vector と MobileBERT の 2 つのモデルは、TensorFlow Lite Model Makerを使用してトレーニングされました。アプリケーションはデフォルトで CPU 上で実行されますが、オプションで NNAPI デリゲートを使用したハードウェア アクセラレーションを使用できます。

次のファイルとディレクトリには、このテキスト分類アプリケーションの重要なコードが含まれています。

  • TextClassificationHelper.kt - テキスト分類子を初期化し、モデルとデリゲートの選択を処理します。
  • MainActivity.kt - TextClassificationHelperおよびResultsAdapterの呼び出しを含む、アプリケーションを実装します。
  • ResultsAdapter.kt - 結果を処理し、フォーマットします。

アプリケーションを変更する

次のセクションでは、サンプル アプリに示されているモデルを実行するように独自の Android アプリを変更するための主要な手順について説明します。これらの手順では、サンプル アプリを参照ポイントとして使用します。独自のアプリに必要な具体的な変更は、サンプル アプリとは異なる場合があります。

Android プロジェクトを開くか作成します

以下の残りの手順に従うには、Android Studio で Android 開発プロジェクトが必要です。以下の手順に従って、既存のプロジェクトを開くか、新しいプロジェクトを作成します。

既存の Android 開発プロジェクトを開くには:

  • Android Studio で、 [ファイル] > [開く]を選択し、既存のプロジェクトを選択します。

基本的な Android 開発プロジェクトを作成するには:

Android Studio の使用方法の詳細については、 Android Studio のドキュメントを参照してください。

プロジェクトの依存関係を追加する

独自のアプリケーションでは、TensorFlow Lite 機械学習モデルを実行し、文字列などのデータを、使用しているモデルで処理できるテンソル データ形式に変換するユーティリティ関数にアクセスするには、特定のプロジェクトの依存関係を追加する必要があります。

次の手順では、必要なプロジェクトとモジュールの依存関係を独自の Android アプリ プロジェクトに追加する方法について説明します。

モジュールの依存関係を追加するには:

  1. TensorFlow Lite を使用するモジュールで、モジュールのbuild.gradleファイルを更新して、次の依存関係を含めます。

    サンプル アプリケーションでは、依存関係はapp/build.gradleにあります。

    dependencies {
      ...
      implementation 'org.tensorflow:tensorflow-lite-task-text:0.4.0'
    }
    

    プロジェクトにはテキスト タスク ライブラリ ( tensorflow-lite-task-text ) が含まれている必要があります。

    このアプリをグラフィックス プロセッシング ユニット (GPU) で実行するように変更する場合は、GPU ライブラリ ( tensorflow-lite-gpu-delegate-plugin ) が GPU でアプリを実行するためのインフラストラクチャを提供し、デリゲート ( tensorflow-lite-gpu ) に互換性リストを示します。このアプリを GPU で実行することは、このチュートリアルの範囲外です。

  2. Android Studio で、 [ファイル] > [プロジェクトを Gradle ファイルと同期]を選択して、プロジェクトの依存関係を同期します。

ML モデルを初期化する

Android アプリでは、モデルで予測を実行する前に、パラメーターを使用して TensorFlow Lite 機械学習モデルを初期化する必要があります。

TensorFlow Lite モデルは*.tfliteファイルとして保存されます。モデル ファイルには予測ロジックが含まれており、通常は予測クラス名など、予測結果の解釈方法に関するメタデータが含まれています。通常、モデル ファイルは、コード例にあるように、開発プロジェクトのsrc/main/assetsディレクトリに保存されます。

  • <project>/src/main/assets/mobilebert.tflite
  • <project>/src/main/assets/wordvec.tflite

利便性とコードの読みやすさを考慮して、この例ではモデルの設定を定義するコンパニオン オブジェクトを宣言しています。

アプリでモデルを初期化するには:

  1. コンパニオン オブジェクトを作成してモデルの設定を定義します。サンプル アプリケーションでは、このオブジェクトはTextClassificationHelper.ktにあります。

    companion object {
      const val DELEGATE_CPU = 0
      const val DELEGATE_NNAPI = 1
      const val WORD_VEC = "wordvec.tflite"
      const val MOBILEBERT = "mobilebert.tflite"
    }
    
  2. 分類子オブジェクトを構築してモデルの設定を作成し、 BertNLClassifierまたはNLClassifierのいずれかを使用して TensorFlow Lite オブジェクトを構築します。

    サンプル アプリケーションでは、これはTextClassificationHelper.kt内のinitClassifier関数にあります。

    fun initClassifier() {
      ...
      if( currentModel == MOBILEBERT ) {
        ...
        bertClassifier = BertNLClassifier.createFromFileAndOptions(
          context,
          MOBILEBERT,
          options)
      } else if (currentModel == WORD_VEC) {
          ...
          nlClassifier = NLClassifier.createFromFileAndOptions(
            context,
            WORD_VEC,
            options)
      }
    }
    

ハードウェア アクセラレーションを有効にする (オプション)

アプリで TensorFlow Lite モデルを初期化するときは、モデルの予測計算を高速化するためにハードウェア アクセラレーション機能の使用を検討する必要があります。 TensorFlow Liteデリゲートは、グラフィックス プロセッシング ユニット (GPU) やテンソル プロセッシング ユニット (TPU) など、モバイル デバイス上の特殊な処理ハードウェアを使用して機械学習モデルの実行を高速化するソフトウェア モジュールです。

アプリでハードウェア アクセラレーションを有効にするには:

  1. 変数を作成して、アプリケーションが使用するデリゲートを定義します。サンプル アプリケーションでは、この変数はTextClassificationHelper.ktの前半にあります。

    var currentDelegate: Int = 0
    
  2. デリゲートセレクターを作成します。サンプル アプリケーションでは、デリゲート セレクターはTextClassificationHelper.kt内のinitClassifier関数にあります。

    val baseOptionsBuilder = BaseOptions.builder()
    when (currentDelegate) {
       DELEGATE_CPU -> {
           // Default
       }
       DELEGATE_NNAPI -> {
           baseOptionsBuilder.useNnapi()
       }
    }
    

TensorFlow Lite モデルの実行にはデリゲートを使用することが推奨されますが、必須ではありません。 TensorFlow Lite でのデリゲートの使用の詳細については、 「TensorFlow Lite デリゲート」を参照してください。

モデルのデータを準備する

Android アプリでは、コードは、生のテキストなどの既存のデータをモデルで処理できるTensorデータ形式に変換することにより、解釈用のデータをモデルに提供します。モデルに渡す Tensor 内のデータは、モデルのトレーニングに使用されるデータの形式と一致する特定の次元または形状を持っている必要があります。

このテキスト分類アプリは文字列を入力として受け入れ、モデルは英語コーパスのみでトレーニングされます。特殊文字と英語以外の単語は推論中に無視されます。

テキスト データをモデルに提供するには:

  1. 「ML モデルの初期化」および「ハードウェア アクセラレーションの有効化」セクションで説明されているように、 initClassifier関数にデリゲートとモデルのコードが含まれていることを確認します。

  2. initブロックを使用してinitClassifier関数を呼び出します。サンプル アプリケーションでは、 init TextClassificationHelper.ktにあります。

    init {
      initClassifier()
    }
    

予測を実行する

Android アプリで、 BertNLClassifierオブジェクトまたはNLClassifierオブジェクトのいずれかを初期化したら、モデルに入力テキストを入力して「ポジティブ」または「ネガティブ」に分類できるようになります。

予測を実行するには:

  1. 選択した分類子 ( currentModel ) を使用し、入力テキストの分類にかかる時間 ( inferenceTime ) を測定するclassify関数を作成します。サンプル アプリケーションでは、 classify関数はTextClassificationHelper.ktにあります。

    fun classify(text: String) {
      executor = ScheduledThreadPoolExecutor(1)
    
      executor.execute {
        val results: List<Category>
        // inferenceTime is the amount of time, in milliseconds, that it takes to
        // classify the input text.
        var inferenceTime = SystemClock.uptimeMillis()
    
        // Use the appropriate classifier based on the selected model
        if(currentModel == MOBILEBERT) {
          results = bertClassifier.classify(text)
        } else {
          results = nlClassifier.classify(text)
        }
    
        inferenceTime = SystemClock.uptimeMillis() - inferenceTime
    
        listener.onResult(results, inferenceTime)
      }
    }
    
  2. 結果をclassifyからリスナーオブジェクトに渡します。

    fun classify(text: String) {
      ...
      listener.onResult(results, inferenceTime)
    }
    

モデル出力を処理します

テキスト行を入力すると、モデルは「ポジティブ」カテゴリと「ネガティブ」カテゴリに対して 0 ~ 1 の範囲で、浮動小数点数で表される予測スコアを生成します。

モデルから予測結果を取得するには:

  1. 出力を処理するリスナー オブジェクトのonResult関数を作成します。サンプル アプリケーションでは、リスナー オブジェクトはMainActivity.ktにあります。

    private val listener = object : TextClassificationHelper.TextResultsListener {
      override fun onResult(results: List<Category>, inferenceTime: Long) {
        runOnUiThread {
          activityMainBinding.bottomSheetLayout.inferenceTimeVal.text =
            String.format("%d ms", inferenceTime)
    
          adapter.resultsList = results.sortedByDescending {
            it.score
          }
    
          adapter.notifyDataSetChanged()
        }
      }
      ...
    }
    
  2. エラーを処理するためにonError関数をリスナー オブジェクトに追加します。

      private val listener = object : TextClassificationHelper.TextResultsListener {
        ...
        override fun onError(error: String) {
          Toast.makeText(this@MainActivity, error, Toast.LENGTH_SHORT).show()
        }
      }
    

モデルが一連の予測結果を返したら、アプリケーションは結果をユーザーに提示するか、追加のロジックを実行することで、それらの予測に基づいて動作できます。サンプル アプリケーションでは、ユーザー インターフェイスに予測スコアがリストされます。

次のステップ