Amazon Web Services ブログ

Amazon SageMaker Ground Truth と Amazon Comprehend を使用しての NER モデルの開発

固有表現抽出 (NER) とは、テキストデータを選別して固有表現と呼ばれる名詞句を特定し、「人」「組織」「ブランド」などのラベルによってそれぞれを分類する処理のことです。たとえば「私は最近 Amazon プライムに登録した」というテキストにおいては、「Amazon プライム」が固有表現であり「ブランド」として分類可能です。自社内において、精密な表現抽出機能を構築することは手の込んだ作業になり得ます。これには、手動で注釈付けをしたトレーニングドキュメントをいくつも用意することや、モデルトレーニング用に適切なアルゴリズムとパラメータを選択することが求められます。

今回の記事では、カスタム NER モデルを構築するための、Amazon SageMaker Ground TruthAmazon Comprehend を使用するエンドツーエンドのパイプラインを取り上げていきます。

Amazon SageMaker Ground Truth を使用すると、機械学習システムのトレーニングに必要なデータセットを、効率的かつ正確にラベル付けすることが可能になります。Ground Truth には、ラベル付けをする人間にそのタスクをステップバイステップで示してくれる、ラベル付けワークフローが組み込まれています。さらに、機械学習 (ML) システムのトレーニングに必要とされる注釈付きの NER データセットを効率よく、正確に構築するためのツールも提供されています。

Amazon Comprehend は、機械学習を使用してテキストに関するインサイトやその内部の関係性を抽出できる、自然言語処理 (NLP) サービスです。Amazon Comprehend では、UTF–8 形式であれば任意のテキストファイルを処理できます。ドキュメント内にある、表現、主要なフレーズ、言い回し、感情、および他の一般的な要素を認識することで、インサイトを生成します。カスタムの表現抽出サービスを使用するには、モデルトレーニングのためのデータセットを作成する必要があります。そのためには、注釈がつけられた一連のドキュメントを使用するか、表現とそのタイプ (例: PERSON) を記載したリストに加え対象となる表現を含むドキュメントを用意します。このサービスは、モデルのトレーニングに使用する、アルゴリズムとパラメータにおける最良かつ最も精度の高い組合せを得るための、自動的なテストを実施します。

次の図は、このソリューションのアーキテクチャを示しています。

ここでのエンドツーエンドのプロセスは次のとおりです。

  1. Amazon Simple Storage Service (Amazon S3) に一連のテキストファイルをアップロードします。
  2. Ground Truth 内に、非公開のワークチームと、NER 用のラベル付けジョブを作成します。
  3. 非公開ワークチームがすべてのテキストドキュメントに対しラベル付けを行います。
  4. 上記が完了すると、Ground Truth は Amazon S3 内のマニフェストとして、拡張マニフェストを作成します。
  5. この拡張された出力マニフェストファイルは解析され、Amazon Comprehend が利用可能な CSV 形式で、注釈およびドキュメントのファイルが作成されます。今回は特に、拡張された出力マニフェストファイルを自動的に変換するパイプラインを取り扱っていきます。このパイプラインは、AWS CloudFormation を使用するとワンクリックでのデプロイが可能です。さらに、Amazon Comprehend の GitHub レポジトリ にある convertGroundtruthToComprehendERFormat.sh スクリプトにより上記の出力マニフェストファイルを解析し、CSV 形式で注釈およびドキュメントのファイルを作成するための方法もご紹介していきます。どちらか 1 つの手法だけでも変換処理を完了できますが、ここでは両方のオプションをお試しになることを強く推奨いたします。
  6. Amazon Comprehend コンソールから、AWS Lambda で生成したデータセットを使用しながら、カスタム NER トレーニングジョブを起動します。

本記事に沿って作業する際に、手動の注釈付けにかかる作業時間を最小にするには、付属している小さなサンプルコーパスを利用すると便利です。必ずしも高性能なモデルを提供するものではありませんが、このプロセスの全体を素早く体験することが可能です。その後で、さらに大型なコーパスを使用したり、Lambda 関数を他の AWS のサービスと置き換えることで、実験を進めることができます。

設定

まず、ご自身のコンピュータ上に、AWS コマンドラインインターフェイス (AWS CLI) をインストールする必要があります。手順については「AWS CLI のインストール」をご参照ください。

S3 バケットと変換パイプラインを作成するために、CloudFormation スタックを作成します。このパイプラインにより変換は自動的に実行されますが、変換スクリプトを直接使用し、本稿の後半で説明している設定手順に従うこともできます。

変換パイプラインの設定

この記事では、次にあげるような初期設定の大半を自動的に実行する、CloudFormation テンプレートを提供しています。

  • 新しい S3 バケットの作成
  • Python 3.8 ランタイムを使用する Lambda 関数と、依存関係を追加するための Lambda レイヤーの作成
  • output.manifest の出力時に、Lambda 関数を自動トリガーさせるための、S3 バケットにおける設定

今回のパイプラインのソースコードは、GitHub レポジトリでホスティングされています。異なるブラウザウィンドウもしくはタブから、テンプレートによるデプロイを行うためには、us-east-1 にある AWS アカウントにサインインします。

次でスタックを起動します。

次の手順を完了します。

  1. [Amazon S3 URL] に、テンプレートの URL を入力します。
  2. [Next (次へ)] をクリックします。
  3. [Stack name (スタックの名前)] に、スタックの名前を入力します。
  4. [S3 Bucket Name (S3 バケット名)] には、新しいバケットの名前を入力します。
  5. その他のパラメータは、デフォルト値のままにしておきます。
  6. [Next (次へ)] をクリックします。
  7. [Configure stack options (スタックオプションの設定)] ページで、[Next (次へ)] をクリックします。
  8. スタックの詳細を確認します。
  9. チェックボックスを 3 つともオンにし、AWS CloudFormation による追加的なリソースと機能の作成を承認します。
  10. [Create stack (スタックの作成)] をクリックします。

これで、CloudFormation がスタックの作成を開始しました。作成が完了したら、次のスクリーンショットのような表示が出力されます。

変換スクリプトの設定

ご使用のコンピュータから次の手順を完了し、変換スクリプトの設定を行います。

  1. コンピュータで Git のダウンロードとインストールを行います。
  2. ローカルマシン上でのレポジトリ保存場所を決定します。後にコマンドプロンプトを使用しながら閲覧する際の利便性を考え、専用のフォルダーを作成することをお勧めします。
  3. ブラウザ上で、Amazon Comprehend の GitHub レポジトリを開きます。
  4. [Contributors (寄稿者)] の下で [Clone or download (クローンまたはダウンロード)] をクリックします。
  5. [Clone with HTTPS (HTTPS でクローン)] の下で、クリップボードアイコンをクリックし、レポジトリの URL をコピーします。

ご自身の組織の SSH 認証機関が発行した証明書を含む、SSH キーを使用してのレポジトリの複製を行うには、[Use SSH (SSH を使用)] の次にクリップボードアイコンをクリックし、レポジトリ URL をクリップボードにコピーします。

  1. ターミナルを開き、複製したレポジトリを保存したい場所に移動します。これは、$ cd <directory> と入力することで実行できます。
  2. 次のコードを入力します。
    $ git clone <repo-url>

レポジトリの複製が完了したら、README ファイルに記載されている手順に従い、スクリプトを使って Ground Truth NER のラベル付けジョブと Amazon Comprehend のカスタム表現抽出機能の統合を実行します。

ラベル付けが行われていないサンプル集のアップロード

次のコマンドを実行し、サンプルのデータファイルを S3 バケットにコピーします。

$ aws s3 cp s3://aws-ml-blog/artifacts/blog-groundtruth-comprehend-ner/sample-data/groundtruth/doc-00.txt s3://<your-bucket>/raw/

$ aws s3 cp s3://aws-ml-blog/artifacts/blog-groundtruth-comprehend-ner/sample-data/groundtruth/doc-01.txt s3://<your-bucket>/raw/

$ aws s3 cp s3://aws-ml-blog/artifacts/blog-groundtruth-comprehend-ner/sample-data/groundtruth/doc-02.txt s3://<your-bucket>/raw/

サンプルデータにより、注釈付けに要する時間を短縮できます。またこれには、モデルのパフォーマンスを最良にする目的での調整を、あえて行う必要もありません。

NER ラベル付けジョブの実行

このステップは、次のような 3 段階の手動手順により実施します。

  1. 非公開ワークチームを作成します。
  2. ラベル付けジョブを作成します。
  3. データに注釈を付けます。

ここでの非公開ワークチームは、他の異なるジョブにおいても再利用が可能です。

ジョブが完了すると、output.manifest ファイルが出力され、Lambda 関数により自動的にピックアップされます。この関数は、この拡張マニフェストファイルを、.csv と .txt 形式の 2 つのファイルに変換します。出力マニフェストファイルが s3://<your-bucket>/gt/<gt-jobname>/manifests/output/output.manifest だとすると、Amazon Comprehend に渡される 2 つのファイルは、s3://<your-bucket>/gt/<gt-jobname>/manifests/output/comprehend/ の下に配置されます。

非公開ワークチームの作成

今回のユースケースでは、唯一のワーカーとしてご自身の E メールアドレスを使用し、非公開ワークチームを編成します。Ground Truth では、Amazon Mechanical Turk、もしくはベンダーのワークフォースを使用することも可能です。

  1. Amazon SageMaker コンソールで、[Ground Truth] の下で [Labeling workforces (ラベル付け従業員)] をクリックします。
  2. [Private (プライベート)] タブを表示し、[Create private team (非公開チームの作成)] を選択します。
  3. [Team name (チーム名)] に、チームの名称を入力します。
  4. [Add workers (作業者の追加)] で、[Invite new workers by email (E メールで新しい作業者を招待する)] を選択します。
  5. [Email addresses (E メールアドレス)] に ご自身の E メールアドレスを入力します。
  6. [Organization name (組織名)] に、所属する組織の名称を入力します。
  7. [Contact email (連絡先の E メール)] に、ご自身の E メールアドレスを入力します。
  8. [Create private team (非公開チームの作成)] をクリックします。
  9. 作成した非公開チームを開き、ラベル付け用ポータルの URL を取得します。

    このチームに最初に加わる場合 (もしくは、Amazon Simple Notification Service (Amazon SNS) 通知を設定した場合) には、この URL と、ユーザー名、そして一時的パスワードが記載された登録 E メールが送信されます。
  10. ラベル付け作業用の URL にサインインします。
  11. 一時的パスワードを新規のパスワードに変更します。

ラベル付けジョブの作成

次に行うのは、NER 用のラベル付けジョブの作成です。今回の記事では、主要な手順を概説します。詳細については、「Amazon SageMaker Ground Truth に固有表現抽出用のデータラベル付けワークフローが追加」をご参照ください。

注釈付けの作業時間を削減するために、Ground Truth ジョブへの入力用として先に S3 バケットにコピー済みの、サンプルコーパスを使用します。

  1. Amazon SageMaker コンソール で、[Ground Truth] の下にある [Labeling jobs (ラベル付けジョブ)] をクリックします。
  2. [Create labeling job (ラベル付けジョブを作成)] をクリックします。
  3. [Job name (ジョブ名)] に、ジョブの名称を入力します。
  4. [I want to specify a label attribute name different from the labeling job name (ラベル付けジョブ名とは異なるラベル属性名を指定したいです。)] をオンにします。
  5. [Label attribute name (ラベル属性名を入力)] には、ner と入力します。
  6. [Create manifest file (マニフェストファイルの作成)] をクリックします。

このステップにより、Ground Truth がテキストコーパスを自動的にマニフェストファイルに変換します。

ポップアップウィンドウが表示されます。

  1. [Input dataset location (入力データセットの場所)] に、Amazon S3 のロケーションを入力します。
  2. [ Data type (データ型)] では、[Text (テキスト)] を選択します。
  3. [Create (作成)] をクリックします。

マニフェストが作成中であることを示すメッセージが表示されます。

  1. マニフェストの作成が完了したら、[Create (作成)] をクリックします。

入力マニフェストは、ご自身で準備することもできます。NER のラベル付けジョブには、{"source-ref": "s3://bucket/prefix/file-01.txt"} という参照スタイルではなく、{"source": "embedded text"} 形式の入力マニフェストが必要なことに注意してください。ここで生成された入力マニフェストでは、\n による改行を自動検出し、各行に 1 つの JSON 行を配置するドキュメントを生成します。ただし、これをご自身で生成した場合は、ドキュメントごとに 1 つの JSON 行を記述することも選択できます (この場合でも、後に続く処理のために \n を記述する必要があります) 。

  1. [IAM role (IAM ロール)] で、CloudFormation テンプレートにより作成されたロールを選択します。
  2. [Task selection (タスク選択)] で [Named entity recognition (固有表現抽出)] を選択します。
  3. [Next (次へ)] をクリックします。
  4. [Select workers and configure tool (作業者の選択およびツールの設定)] ページで、[Worker types (作業者タイプ)] に [Private (非公開)] を選択します。
  5. [Private teams (非公開チーム)] では、先に作成済みの非公開のワークチームを選択します。
  6. [Number of workers per dataset object (データセットオブジェクトあたりの作業者数)] で、作業者数が (1 となっており) 非公開ワークチームのサイズと一致していることを確認します。
  7. テキストボックスにラベル付けに関する指示を入力します。
  8. [Labels (ラベル)] の下で、指定したいラベルを追加します。次のスクリーンショットに、今回の推奨コーパスで必要なラベルを示します。
  9. [Create (作成)] をクリックします。

これでジョブの作成は完了しました。[Labeling jobs (ラベル付けジョブ)] ページで、個別のラベル付けタスクのステータスが追跡できます。

ジョブに関する詳細を、次のスクリーンショットに示します。

データへのラベル付け

推奨のコーパスを使用している場合は、このセクションでの処理は数分で完了するはずです。

ジョブの作成が終わると、非公開ワークチームはラベル付けポータルにそのジョブが一覧表示されていることを確認できるようになります。この状態で、割り当てられたタスクでの注釈付けを開始できます。

次のスクリーンショットに、作業者 UI を示します。

全タスクの完了後、ラベル付けジョブのステータスが [ Completed (完了)] と表示されます。

完了後チェック

この CloudFormation テンプレートでは、指定された S3 バケットに manifests/output/output.manifest とプレフィックスされた新規のオブジェクトが保存される度に、Amazon S3 のプットイベントを Lambda 関数に対しエミットするよう、その S3 バケットを定義しています。また、AWS では最近、Amazon CloudWatch Events にラベル付けジョブのサポートを追加しており、変換処理をトリガーするための別のメカニズムとして、これを使用することもできます。詳細な情報については、「Amazon SageMaker Ground Truth がマルチラベル画像およびテキスト分類と Amazon CloudWatch Events のサポートを開始」をご参照ください。

拡張マニフェストは、Lambda 関数によりロードされ、その出力マニフェストと同じプレフィックスの下に配置される、comprehend/output.csvcomprehend/output.txt に変換されます。例としては、s3://<your_bucket>/gt/<gt-jobname>/manifests/output/output.manifest からは、次のようなファイルが生成されます。

s3://<your_bucket>/gt-output/<gt-jobname>/manifests/output/comprehend/output.csv
s3://<your_bucket>/gt-output/<gt-jobname>/manifests/output/comprehend/output.txt

CloudWatch Logs の中で、Lambda 実行に関する項目をより詳しく追跡することもできます。これには、Lambda 関数により output.manifest に追加されたタグを、Amazon S3 コンソールか AWS CLI を使用し検索します。

Amazon S3 コンソールでこの追跡を行うには、次の手順を実行します。

  1. Amazon S3 コンソール内で、[output (出力)] まで移動します。
  2. [output.manifest] をオンにします。
  3. [Properties (プロパティ)] タブで、[Tags (タグ)] をクリックします。
  4. Lambda 関数により追加されたタグを表示します。

AWS CLI を使用する場合には、次のコードを入力します (ストリームタグの __LATEST_xxx [$LATEST]xxx という CloudWatch ログストリームを意味しています。Amazon S3 では [$] が無効なため、Lambda 関数による置き換えが行われています) 。

$ aws s3api get-object-tagging --bucket gtner-blog --key gt/test-gtner-blog-004/manifests/output/output.manifest
{
    "TagSet": [
        {
            "Key": "lambda_log_stream",
            "Value": "2020/02/25/__LATEST_24497900b44f43b982adfe2fb1a4fbe6"
        },
        {
            "Key": "lambda_req_id",
            "Value": "08af8228-794e-42d1-aa2b-37c00499bbca"
        },
        {
            "Key": "lambda_log_group",
            "Value": "/aws/lambda/samtest-ConllFunction-RRQ698841RYB"
        }
    ]
}

これで、実際のロググループ、ログストリーム、および RequestId が、CloudWatch コンソールを使用して追跡可能になります。次のスクリーンショットに例を示します。

Amazon Comprehend でのカスタム NER モデルのトレーニング

Amazon Comprehend への入力コーパスでは、次のような最低要件をエンティティごとにクリアしている必要があります。

  • サンプル数は 1000 個
  • コーパスのサイズは 5120 バイト
  • 注釈数は 200 個

今回、Ground Truth に適用したサンプルコーパスでは、この最低要件に適合していません。それに対応するため、ここでは Amazon Comprehend 用に事前生成済みの追加入力をご用意しています。このサンプルデータにより、カスタムモデルのトレーニングを迅速に開始でき、また、モデルにパフォーマンスを発揮させるための調整を、あえて行う必要もありません。

ご使用のコンピュータにおいて次のコードを入力し、事前生成済みデータをバケットにアップロードしてください。

$ aws s3 cp s3://aws-ml-blog/artifacts/blog-groundtruth-comprehend-ner/sample-data/comprehend/output-x112.txt s3://<your_bucket>/gt/<gt-jobname>/manifests/output/comprehend/documents/

$ aws s3 cp s3://aws-ml-blog/artifacts/blog-groundtruth-comprehend-ner/sample-data/comprehend/output-x112.csv s3://<your_bucket>/gt/<gt-jobname>/manifests/output/comprehend/annotations/

この結果、s3://<your_bucket>/gt/<gt-jobname>/manifests/output/comprehend/documents/ フォルダーには、output.txt および output-x112.txt の、2 つのファイルが作成されるはずです。

また、 s3://<your_bucket>/gt/<gt-jobname>/manifests/output/comprehend/annotations/ フォルダーには、output.csvoutput-x112.csv が格納されます。

これで、カスタムの NER トレーニングが開始できるようになりました。

  1. Amazon Comprehend コンソールにおいて、[Customization (カスタマイズ)] の下の [Custom entity recognition (表現抽出のカスタマイズ)] をクリックします。
  2. [Train recognizer (レコグナイザーをトレーニング)] をクリックします。
  3. [Recognizer name (レコグナイザー名)] に名称を入力します。
  4. [Custom entity type (カスタムエンティティのタイプ)] に、ご使用のラベルを入力します。

ここでのカスタムエンティティのタイプは、Ground Truth ジョブで使用したものと一致する必要があります。

  1. [Training type (トレーニングタイプ)] では、[Using annotations and training docs (注釈とトレーニングドキュメントを使用する)] を選択します。
  2. 注釈およびトレーニングドキュメントのための、Amazon S3 ロケーションを入力します。
  3. Amazon Comprehend の使用が初めての場合は、[IAM role (IAM ロール)] で [Create an IAM role (IAM ロールの作成)] をオンにします。
  4. [Permissions to access (アクセス許可)] から、[Input and output (if specified) S3 bucket (入力および出力の (指定がある場合の) S3 バケット)] を選択します。
  5. [Name suffix (名前のサフィックス)] に、サフィックスを入力します。
  6. [Train (トレーニング)] をクリックします。

これで、ご使用のレコグナイザーが一覧表示されるようになります。

トレーニング完了時の表示を次のスクリーンショットに示します。完了までは最大 1 時間かかります。

クリーンアップ

今回のエクササイズを完了した後は、次の手順に従いリソースの削除を行います。

  1. S3 バケットを空に (もしくは削除) します。
  2. CloudFormation スタックを停止します。

まとめ

今回は、Ground Truth を使用して NER トレーニング用のデータセットを構築する方法、ならびに、そこで生成される拡張マニフェストを、Amazon Comprehend がダイジェストしやすい形式に自動変換する方法を解説しました。

いつものように、AWS では皆さんのフィードバックをお待ちしています。コメントや質問があればお寄せください。


著者について

Verdi March は、AWS プロフェッショナルサービスのシニアデータサイエンティストで、お客様が機械学習ソリューションを AWS で開発・実装するための支援をしています。余暇での彼は、コーヒーメイクの腕を磨いたり、家族とともに過ごすことを楽しんでいます。

 

 

 

 

Jyoti Bansal は、AWS Comprehend チームのソフトウェア開発エンジニアです。彼女は、Comprehend サービス向けの NLP をベースにした機能の、実装および改良を担当しています。余暇では、スケッチや読書を楽しんでいます。

 

 

 

 

Nitin Gaur は、AWS Comprehend のソフトウェア開発エンジニアです。AWS での NLP ベースの機能を、実装および改良しています。余暇には音楽の演奏や録音を楽しんでいます。