{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "h2q27gKz1H20" }, "source": [ "##### Copyright 2020 The TensorFlow Authors." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "cellView": "form", "id": "TUfAcER1oUS6" }, "outputs": [], "source": [ "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n", "# you may not use this file except in compliance with the License.\n", "# You may obtain a copy of the License at\n", "#\n", "# https://www.apache.org/licenses/LICENSE-2.0\n", "#\n", "# Unless required by applicable law or agreed to in writing, software\n", "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", "# See the License for the specific language governing permissions and\n", "# limitations under the License." ] }, { "cell_type": "markdown", "metadata": { "id": "Gb7qyhNL1yWt" }, "source": [ "# TensorFlow Lite Model Maker による BERT 質疑応答" ] }, { "cell_type": "markdown", "metadata": { "id": "Fw5Y7snSuG51" }, "source": [ "\n", " \n", " \n", " \n", " \n", "
TensorFlow.org で表示 Google Colab で実行 GitHub でソースを表示 ノートブックをダウンロード
" ] }, { "cell_type": "markdown", "metadata": { "id": "sr3q-gvm3cI8" }, "source": [ "TensorFlow Lite Model Maker ライブラリは、TensorFlow モデルを適合し、オンデバイス ML アプリケーションにこのモデルをデプロイする際に特定の入力データに変換するプロセスを単純化します。\n", "\n", "このノートブックでは、Model Maker ライブラリを使用したエンドツーエンドの例を示し、質疑応答タスクで一般的に使用される質疑応答モデルの適合と変換を説明します。" ] }, { "cell_type": "markdown", "metadata": { "id": "UxEHFTk755qw" }, "source": [ "# BERT 質疑応答タスクの基礎" ] }, { "cell_type": "markdown", "metadata": { "id": "cFbKTCF25-SG" }, "source": [ "このライブラリでサポートされているタスクは、抽出型の質疑応答タスクです。特定の文章と質問に対する回答が文章に含まれていることになります。以下の画像は、質疑応答の例を示します。\n", "\n", "

\n", "\n", "

\n", " 回答は文章に含まれている(画像提供: SQuAD ブログ\n", "

\n", "\n", "質疑応答タスクのモデルでは、入力は、すでに前処理されている文章と質問のペアで、出力は、文章の各トークンの開始ロジットと終了ロジットです。入力のサイズは設定可能で、文章と質問の長さに応じて調整することができます。" ] }, { "cell_type": "markdown", "metadata": { "id": "gb7P4WQta8Ub" }, "source": [ "## エンドツーエンドの概要\n" ] }, { "cell_type": "markdown", "metadata": { "id": "w7cIHjIfbDlG" }, "source": [ "次のコードスニペットでは、数行のコード内でモデルを取得する方法を示します。全体的なプロセスには、(1)モデルの選択、(2)データの読み込み、(3)モデルの再トレーニング、(4)評価、(5)TensorFlow Lite 形式へのエクスポート、という 5 つのステップが含まれます。" ] }, { "cell_type": "markdown", "metadata": { "id": "xQPdlxZBYuZG" }, "source": [ "```python\n", "# Chooses a model specification that represents the model.\n", "spec = model_spec.get('mobilebert_qa')\n", "\n", "# Gets the training data and validation data.\n", "train_data = DataLoader.from_squad(train_data_path, spec, is_training=True)\n", "validation_data = DataLoader.from_squad(validation_data_path, spec, is_training=False)\n", "\n", "# Fine-tunes the model.\n", "model = question_answer.create(train_data, model_spec=spec)\n", "\n", "# Gets the evaluation result.\n", "metric = model.evaluate(validation_data)\n", "\n", "# Exports the model to the TensorFlow Lite format with metadata in the export directory.\n", "model.export(export_dir)\n", "```" ] }, { "cell_type": "markdown", "metadata": { "id": "exScAdvBbNEi" }, "source": [ "上記のコードについて、次のセクションでより詳しく説明します。" ] }, { "cell_type": "markdown", "metadata": { "id": "bcLF2PKkSbV3" }, "source": [ "## 前提条件\n", "\n", "この例を実行するには、[GitHub リポジトリ](https://github.com/tensorflow/examples/tree/master/tensorflow_examples/lite/model_maker) から、Model Maker パッケージを含む必要なパッケージをインストールする必要があります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "qhl8lqVamEty" }, "outputs": [], "source": [ "!sudo apt -y install libportaudio2\n", "!pip install -q tflite-model-maker-nightly" ] }, { "cell_type": "markdown", "metadata": { "id": "l6lRhVK9Q_0U" }, "source": [ "必要なパッケージをインポートします。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "XtxiUeZEiXpt" }, "outputs": [], "source": [ "import numpy as np\n", "import os\n", "\n", "import tensorflow as tf\n", "assert tf.__version__.startswith('2')\n", "\n", "from tflite_model_maker import model_spec\n", "from tflite_model_maker import question_answer\n", "from tflite_model_maker.config import ExportFormat\n", "from tflite_model_maker.question_answer import DataLoader" ] }, { "cell_type": "markdown", "metadata": { "id": "l65ctmtW7_FF" }, "source": [ "「エンドツーエンドの概要」では、簡単なエンドツーエンドの例を実演しています。次のセクションでは、順を追ってより詳しく例を説明します。" ] }, { "cell_type": "markdown", "metadata": { "id": "kJ_B8fMDOhMR" }, "source": [ "## 質疑応答のモデルを表現する model_spec を選択する\n", "\n", "各 `model_spec` オブジェクトは、質疑応答用の特定のモデルを表現します。Model Maker は現在、MobileBERT と BERT ベースモデルをサポートしています。\n", "\n", "サポートされているモデル | model_spec の名前 | モデルの説明\n", "--- | --- | ---\n", "[MobileBERT](https://arxiv.org/pdf/2004.02984.pdf) | 'mobilebert_qa' | BERT ベースより 4.3 倍小さく、5.5 倍高速ですが、オンデバイスシナリオに適した、優位性のある結果を達成します。\n", "[MobileBERT-SQuAD](https://arxiv.org/pdf/2004.02984.pdf) | 'mobilebert_qa_squad' | MobileBERT モデルと同じモデルアーキテクチャを持ち、最初のモデルは [SQuAD1.1](https://rajpurkar.github.io/SQuAD-explorer/) で再トレーニング済みです。\n", "[BERT-Base](https://arxiv.org/pdf/1810.04805.pdf) | 'bert_qa' | NLP タスクで広く使用される標準的な BERT モデルです。\n", "\n", "このチュートリアルでは、例として [MobileBERT-SQuAD](https://arxiv.org/pdf/2004.02984.pdf) を使用します。モデルは [SQuAD1.1](https://rajpurkar.github.io/SQuAD-explorer/) で再トレーニング済みであるため、質疑応答タスクではより高速に収束する可能性があります。\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "vEAWuZQ1PFiX" }, "outputs": [], "source": [ "spec = model_spec.get('mobilebert_qa_squad')" ] }, { "cell_type": "markdown", "metadata": { "id": "ygEncJxtl-nQ" }, "source": [ "## オンデバイス ML アプリ固有の入力データを読み込み、データを前処理する\n", "\n", "[TriviaQA](https://nlp.cs.washington.edu/triviaqa/) は、読解問題のデータセットで、質問、回答、エビデンスの 3 つを 1 組とした 65 万個を超えるデータが含まれます。このチュートリアルでは、このデータセットのサブセットを使用して、Model Maker ライブラリの使用方法を学習します。\n", "\n", "データを読み込むには、`--sample_size=8000` とした[コンバータ用 Python スクリプト](https://github.com/mandarjoshi90/triviaqa#miscellaneous)と一連の `web` データを実行して、TriviaQA データセットを [SQuAD1.1](https://rajpurkar.github.io/SQuAD-explorer/) 形式に変換します。次のようにして、変換コードを少し変更してください。\n", "\n", "- 文脈ドキュメントで回答が見つからなかったサンプルを省略します。\n", "- 大文字や小文字を無視し、文脈の元の解答を取得します。\n", "\n", "変換済みデータセットのアーカイブバージョンをダウンロードします。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "7tOfUr2KlgpU" }, "outputs": [], "source": [ "train_data_path = tf.keras.utils.get_file(\n", " fname='triviaqa-web-train-8000.json',\n", " origin='https://storage.googleapis.com/download.tensorflow.org/models/tflite/dataset/triviaqa-web-train-8000.json')\n", "validation_data_path = tf.keras.utils.get_file(\n", " fname='triviaqa-verified-web-dev.json',\n", " origin='https://storage.googleapis.com/download.tensorflow.org/models/tflite/dataset/triviaqa-verified-web-dev.json')" ] }, { "cell_type": "markdown", "metadata": { "id": "UfZk8GNr_1nc" }, "source": [ "また、独自のデータセットを使用しても、MobileBERT モデルをトレーニングできます。Colab でこのノートブックを実行している場合は、左のサイドバーを使ってデータをアップロードしてください。\n", "\n", " \"Upload\n", "\n", "データをクラウドにアップロードしない場合は、[ガイド](https://github.com/tensorflow/examples/tree/master/tensorflow_examples/lite/model_maker)に従ってオフラインでライブラリを実行することもできます。" ] }, { "cell_type": "markdown", "metadata": { "id": "E051HBUM5owi" }, "source": [ "`DataLoader.from_squad` メソッドを使用して、[SQuAD 形式](https://rajpurkar.github.io/SQuAD-explorer/)データを読み込み、特定の `model_spec` に従って前処理します。SQuAD2.0 または SQuAD1.1 のいずれかの形式を使用できます。パラメータ `version_2_with_negative` を `True` に設定すると、形式は SQuAD2.0 となり、そうでない場合は SQuAD1.1 となります。デフォルトでは、`version_2_with_negative` は `False` に設定されています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "I_fOlZsklmlL" }, "outputs": [], "source": [ "train_data = DataLoader.from_squad(train_data_path, spec, is_training=True)\n", "validation_data = DataLoader.from_squad(validation_data_path, spec, is_training=False)" ] }, { "cell_type": "markdown", "metadata": { "id": "AWuoensX4vDA" }, "source": [ "## TensorFlow モデルをカスタマイズする\n", "\n", "読み込んだデータに基づいて、カスタムの質疑応答モデルを作成します。`create` 関数は次のステップで構成されています。\n", "\n", "1. `model_spec` に基づいて質疑応答のモデルを作成します。\n", "2. 質疑応答モデルをトレーニングします。デフォルトのエポックとデフォルトのバッチサイズは、`default_training_epochs` と `default_batch_size` の 2 つの変数に従って `model_spec` オブジェクトに設定されています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "TvYSUuJY3QxR" }, "outputs": [], "source": [ "model = question_answer.create(train_data, model_spec=spec)" ] }, { "cell_type": "markdown", "metadata": { "id": "0JKI-pNc8idH" }, "source": [ "モデル構造を詳しく確認します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "gd7Hs8TF8n3H" }, "outputs": [], "source": [ "model.summary()" ] }, { "cell_type": "markdown", "metadata": { "id": "LP5FPk_tOxoZ" }, "source": [ "## カスタマイズ済みのモデルを評価する\n", "\n", "検証データでモデルを評価し、`f1` スコアや `exact match` などを含むメトリクスの dict を取得します。SQuAD1.1 と SQuAD2.0 のメトリクスは異なることに注意してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "A8c2ZQ0J3Riy" }, "outputs": [], "source": [ "model.evaluate(validation_data)" ] }, { "cell_type": "markdown", "metadata": { "id": "aeHoGAceO2xV" }, "source": [ "## TensorFlow Lite モデルをエクスポートする\n", "\n", "トレーニングされたモデルを[メタデータ](https://www.tensorflow.org/lite/models/convert/metadata)で TensorFlow Lite モデル形式に変換し、後でオンデバイス ML アプリケーションで使用できるようにします。語彙ファイルはメタデータに埋め込まれています。デフォルトの TFLite ファイル名は `model.tflite` です。\n", "\n", "多くのオンデバイス ML アプリケーションでは、モデルサイズが重要な要因です。そのため、モデルの量子化を適用して小さくし、実行速度を高められるようにすることをお勧めします。デフォルトのポストトレーニング量子化手法は、BERT および MobileBERT モデルのダイナミックレンジ量子化です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "Im6wA9lK3TQB" }, "outputs": [], "source": [ "model.export(export_dir='.')" ] }, { "cell_type": "markdown", "metadata": { "id": "w12kvDdHJIGH" }, "source": [ "Colab の左サイドバーからダウンロードすることで、[bert_qa](https://github.com/tensorflow/examples/tree/master/lite/examples/bert_qa/android) 参照アプリで [BertQuestionAnswerer API](https://www.tensorflow.org/lite/inference_with_metadata/task_library/bert_question_answerer)([TensorFlow Lite Task ライブラリ](https://www.tensorflow.org/lite/inference_with_metadata/task_library/overview))を使って TensorFlow Lite モデルファイルを使用できます。" ] }, { "cell_type": "markdown", "metadata": { "id": "VFnJPvq3VGh3" }, "source": [ "次のいずれかのエクスポートフォーマットを使用できます。\n", "\n", "- `ExportFormat.TFLITE`\n", "- `ExportFormat.VOCAB`\n", "- `ExportFormat.SAVED_MODEL`\n", "\n", "デフォルトでは、メタデータとともに TensorFlow Lite モデルをエクスポートするだけです。さまざまなファイルを選択的にエクスポートすることも可能です。たとえば、vocab ファイルのみをエクスポートする場合は、次のように行います。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "ro2hz4kXVImY" }, "outputs": [], "source": [ "model.export(export_dir='.', export_format=ExportFormat.VOCAB)" ] }, { "cell_type": "markdown", "metadata": { "id": "HZKYthlVrTos" }, "source": [ "また、`evaluate_tflite` メソッドを使って tflite モデルを評価することも可能です。このステップには長い時間がかかります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "ochbq95ZrVFX" }, "outputs": [], "source": [ "model.evaluate_tflite('model.tflite', validation_data)" ] }, { "cell_type": "markdown", "metadata": { "id": "EoWiA_zX8rxE" }, "source": [ "## 高度な使用\n", "\n", "`create` 関数は、`model_spec` パラメータがモデルの仕様を定義するため、このライブラリでは重要な部分です。現在、`BertQASpec` クラスがサポートされています。モデルには MobileBERT モデルと BERT ベースモデルの 2 つがあります。`create` 関数は次のステップで構成されています。\n", "\n", "1. `model_spec` に基づいて質疑応答のモデルを作成します。\n", "2. 質疑応答モデルをトレーニングします。\n", "\n", "このセクションでは、モデルの調整やトレーニングハイパーパラメータの調整など、いくつかの高度なトピックを説明します。" ] }, { "cell_type": "markdown", "metadata": { "id": "mwtiksguDfhl" }, "source": [ "### モデルの調整\n", "\n", "`BertQASpec` クラスの `seq_len` や `query_len` パラメータなどのモデルインフラストラクチャを調整できます。\n", "\n", "モデルの調整可能なパラメータは次のとおりです。\n", "\n", "- `seq_len`: モデルにフィードする文章の長さ。\n", "- `query_len`: モデルにフィードする質問の長さ。\n", "- `doc_stride`: ドキュメントの塊を取るためのスライドウィンドウアプローチを実行する際のストライド。\n", "- `initializer_range`: すべての重み行列を初期化する truncated_normal_initializer の stdev。\n", "- `trainable`: トレーニング済みレイヤーがトレーニング可能かどうかを示すブール型。\n", "\n", "トレーニングパイプラインの調整可能なパラメータは次のとおりです。\n", "\n", "- `model_dir`: モデルチェックポイントファイルの場所。設定されていない場合、一時ディレクトリが使用されます。\n", "- `dropout_rate`: ドロップアウトのレート。\n", "- `learning_rate`: Adam の初期学習率。\n", "- `predict_batch_size`: 予測のバッチサイズ。\n", "- `tpu`: 接続先の TPU アドレス。TPU を使用している場合にのみ使用されます。\n" ] }, { "cell_type": "markdown", "metadata": { "id": "cAOd5_bzH9AQ" }, "source": [ "たとえば、より長いシーケンス長でモデルをトレーニングできます。モデルを変更する場合、最初に新しい `model_spec` を構築する必要があります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "e9WBN0UTQoMN" }, "outputs": [], "source": [ "new_spec = model_spec.get('mobilebert_qa')\n", "new_spec.seq_len = 512" ] }, { "cell_type": "markdown", "metadata": { "id": "6LSTdghTP0Cv" }, "source": [ "残りのステップは同じです。モデルの仕様によって異なる前処理ステップがあるため、`dataloader` と `create` の両方の部分を再実行する必要があります。\n" ] }, { "cell_type": "markdown", "metadata": { "id": "LvQuy7RSDir3" }, "source": [ "### トレーニングハイパーパラメータの調整\n", "\n", "`epochs` や `batch_size` など、モデルのパフォーマンスに影響のあるトレーニングハイパーパラメータを調整することもできます。次にその例を示します。\n", "\n", "- `epochs`: エポック数が多いほどパフォーマンスが改善されますが、過適合が発生する可能性があります。\n", "- `batch_size`: 1 つのトレーニングステップに使用するサンプル数。\n", "\n", "たとえば、エポック数とバッチサイズを増やしてトレーニングすることができます。\n", "\n", "```python\n", "model = question_answer.create(train_data, model_spec=spec, epochs=5, batch_size=64)\n", "```" ] }, { "cell_type": "markdown", "metadata": { "id": "Eq6B9lKMfhS6" }, "source": [ "### モデルアーキテクチャを変更する\n", "\n", "`model_spec` を変更して、データをトレーニングするベースモデルを変更できます。たとえば、BERT ベースモデルに変更するには、次を実行します。\n", "\n", "```python\n", "spec = model_spec.get('bert_qa')\n", "```" ] }, { "cell_type": "markdown", "metadata": { "id": "L2d7yycrgu6L" }, "source": [ "残りのステップは同じです。" ] }, { "cell_type": "markdown", "metadata": { "id": "wFQrDMXzOVoB" }, "source": [ "### TensorFlow Lite モデルでポストトレーニング量子化をカスタマイズする\n", "\n", "[ポストトレーニング量子化](https://www.tensorflow.org/lite/performance/post_training_quantization)は、モデルサイズと推論レイテンシを縮小できる変換テクニックです。このテクニックでは、モデル精度にほとんど影響することなく、CPU とハードウェアアクセラレータの推論速度も改善することができます。したがって、モデルを改善するために広く使われています。\n", "\n", "Model Maker ライブラリは、モデルをエクスポートする際に、デフォルトのポストトレーニング量子化手法を適用します。ポストトレーニング量子化をカスタマイズするのであれば、Model Maker は、[QuantizationConfig](https://www.tensorflow.org/lite/api_docs/python/tflite_model_maker/config/QuantizationConfig) を使った複数のポストトレーニング量子化オプションもサポートしています。例として、float16 量子化を見てみましょう。まず、量子化構成を定義します。\n", "\n", "```python\n", "config = QuantizationConfig.for_float16()\n", "```\n", "\n", "次に、その構成で TensorFlow Lite モデルをエクスポートします。\n", "\n", "```python\n", "model.export(export_dir='.', tflite_filename='model_fp16.tflite', quantization_config=config)\n", "```" ] }, { "cell_type": "markdown", "metadata": { "id": "wPVopCeB6LV6" }, "source": [ "# その他の資料\n", "\n", "技術的な詳細については、[BERT 質疑応答](https://www.tensorflow.org/lite/examples/bert_qa/overview)の例をご覧ください。詳細については、以下をご覧ください。\n", "\n", "- TensorFlow Lite Model Maker の[ガイド](https://www.tensorflow.org/lite/models/modify/model_maker)と [API リファレンス](https://www.tensorflow.org/lite/api_docs/python/tflite_model_maker)\n", "- タスクライブラリ: デプロイ用の [BertQuestionAnswerer](https://www.tensorflow.org/lite/inference_with_metadata/task_library/bert_question_answerer)\n", "- エンドツーエンドリファレンスアプリ: [Android](https://github.com/tensorflow/examples/tree/master/lite/examples/bert_qa/android) およおび [iOS](https://github.com/tensorflow/examples/tree/master/lite/examples/bert_qa/ios)" ] } ], "metadata": { "accelerator": "GPU", "colab": { "collapsed_sections": [], "name": "question_answer.ipynb", "toc_visible": true }, "kernelspec": { "display_name": "Python 3", "name": "python3" } }, "nbformat": 4, "nbformat_minor": 0 }