トランスフォーマーによる名前付き固有表現認識

はじめにパーマリンク

前回のブログ記事で、スペイン語の変換言語モデルであるSpanBERTaをゼロから大きなコーパスで事前学習した方法について説明した。このモデルは、文脈に基づいて、連続する単語の中で正しくマスクされた単語を予測できることを示しました。このブログポストでは、変換モデルのパワーを本当に活用するために、名前付きエンティティ認識タスクのためにSpanBERTaを微調整します。

その定義によると ウィキペディア名前付きエンティティ認識(NER)(エンティティ識別、エンティティチャンキング、エンティティ抽出とも呼ばれる)は、情報抽出のサブタスクであり、構造化されていないテキストで言及されている名前付きエンティティを探し出し、人名、組織、場所、医療コード、時間表現、数量、金額、パーセンテージなど、あらかじめ定義されたカテゴリに分類することを目指す。

スクリプト run_ner.py ハギング・フェイスと CoNLL-2002データセット SpanBERTaを微調整する。

セットアップパーマリンク

ダウンロード 変圧器 をインストールし、必要なパッケージをインストールする。

%%捕獲
!ギット クローン https://ギズブ.コム/ハグハグフェイス/変圧器
%cd 変圧器
!ピップ インストール .
!ピップ インストール -r .//要件.テキスト
%cd ..

データパーマリンク

1.データセットのダウンロードパーマリンク

以下のコマンドはデータセットをダウンロードし,解凍する.ファイルには、以下の3つの部分の訓練データとテストデータが含まれている。 CoNLL-2002 タスクを共有する:

  • esp.testa:開発段階のスペイン語テストデータ
  • esp.testb: スペインのテストデータ
  • esp.train:スペインの列車データ
%%捕獲
!ウィジェット -O 'conll2002.zip' 'https://drive.google.com/uc?export=download&id=1Wrl1b39ZXgKqCeAFNM9EoXtA1kzwNhCe'
!解凍 'conll2002.zip'

各データセットのサイズ:

!ダブリューシー -l コンル2002/エスプ.電車
!ダブリューシー -l コンル2002/エスプ.しゅひ
!ダブリューシー -l コンル2002/エスプ.テスト
273038 コンエル2002/ESP.トレイン
54838 conll2002/esp.testa
53050 conll2002/esp.testb

すべてのデータファイルには、単語、関連する品詞タグ、およびIOB2形式の名前付きエンティティタグの3つの列がある。文の区切りは空行でエンコードされる。

!ヘッド -n20 コンル2002/エスプ.電車
メルボルン NP B-LOC
( Fpa O
オーストラリアNP B-LOC
)Fpt O
Fc
25 Z O
may NC O
( Fpa O
EFE NC B-ORG
)Fpt O
.Fp O
- Fg O
El DA O
アボガド NC B-PER
一般AQ I-PER
SP I-PER
国家 NC I-PER
Fc O

ここでは、訓練データセット、開発データセット、テストデータセットについて、単語列と名前付きエンティティ・タグ列のみを保持する。

! コンル2002/エスプ.電車 | カット -d " " -f 1,3 > train_temp.テキスト
! コンル2002/エスプ.しゅひ | カット -d " " -f 1,3 > dev_temp.テキスト
! コンル2002/エスプ.テスト | カット -d " " -f 1,3 > test_temp.テキスト

2.前処理パーマリンク

さらなる前処理ステップとモデルのトレーニングに必要な変数を定義しよう:

MAX_LENGTH = 120 #@param {type:「整数"}。
モデル = "クリスハントラン/スパンベルタ" #@param ["chriskhanhtran/spanberta", "bert-base-multilingual-cased"].

以下のスクリプトは MAX_LENGTH (トークンに換算して)を小さなものに変換する。そうしないと、トークン化されたときに長い文が切り捨てられ、学習データが失われたり、テストセット内のいくつかのトークンが予測されなかったりする。

%%捕獲
!ウィジェット "https://raw.githubusercontent.com/stefan-it/fine-tuned-berts-seq/master/scripts/preprocess.py"
!パイソン3 前処理.パイ train_temp.テキスト $モデル $MAX_LENGTH > 電車.テキスト
!パイソン3 前処理.パイ dev_temp.テキスト $モデル $MAX_LENGTH > デヴ.テキスト
!パイソン3 前処理.パイ test_temp.テキスト $モデル $MAX_LENGTH > テスト.テキスト
2020-04-22 23:02:05.747294:I tensorflow/stream_executor/platform/default/dso_loader.cc:44]。ダイナミックライブラリ libcudart.so.10.1 のオープンに成功しました。
ダウンロード中:100% 1.03k/1.03k [00:00<00:00, 704kB/s].
ダウンロード中100% 954k/954k [00:00<00:00, 1.89MB/s] をダウンロード中。
ダウンロード中100% 512k/512k [00:00<00:00, 1.19MB/s] の場合
ダウンロード中100% 16.0/16.0 [00:00<00:00, 12.6kB/s] ダウンロード中。
2020-04-22 23:02:23.409488: I tensorflow/stream_executor/platform/default/dso_loader.cc:44]ダイナミックライブラリ libcudart.so.10.1 のオープンに成功しました。
2020-04-22 23:02:31.168967:I tensorflow/stream_executor/platform/default/dso_loader.cc:44] 動的ライブラリのオープンに成功しました。ダイナミックライブラリ libcudart.so.10.1 のオープンに成功しました。

3.ラベルパーマリンク

CoNLL-2002/2003データセットでは、NERタグは9クラスある:

  • O, 名前付きエンティティの外側
  • B-MIS、他の雑多なエンティティの直後に雑多なエンティティの開始
  • I-MIS、雑多なエンティティ
  • B-PER、他の人の名前のすぐ後にある人の名前の冒頭部分
  • I-PER、個人名
  • B-ORG、他の組織のすぐ後にある組織の始まり
  • I-ORG、組織
  • B-LOC、他の場所の直後の場所の始まり
  • I-LOC、ロケーション

もし、あなたのデータセットがCoNLL-2002/2003データセットと異なるラベルを持つか、それ以上のラベルを持つ場合は、以下の行を実行して、あなたのデータからユニークなラベルを取得し、それを以下に保存してください。 ラベル.txt.このファイルは、モデルの微調整を始めるときに使う。

! 電車.テキスト デヴ.テキスト テスト.テキスト | カット -d " " -f 2 | グレップ -v "^$"| ソート | ユニック > ラベル.テキスト

微調整モデルパーマリンク

以下は 変圧器のレポを使用して、NER用のモデルを微調整する。2020年4月21日以降、Hugging Faceはサンプルスクリプトを更新し、新しい トレーナー クラスを使用する。将来的な衝突を避けるために、これらのアップデートが行われる前のバージョンを使おう。

%%捕獲
!ウィジェット "https://raw.githubusercontent.com/chriskhanhtran/spanish-bert/master/ner/run_ner.py"
!ウィジェット "https://raw.githubusercontent.com/chriskhanhtran/spanish-bert/master/ner/utils_ner.py"

今度は移籍学習の番だ。私の 前のブログ記事私はRoBERTa言語モデルを非常に大規模なスペイン語コーパスに事前学習させ、文脈に基づいてマスクされた単語を予測するようにした。そうすることで、モデルは言語固有の特性を学習しました。学習済みのモデルをHugging Faceのサーバーにアップロードした。これからモデルをロードし、NERタスクのために微調整を開始する。

以下はトレーニングのハイパーパラメータである。

MAX_LENGTH = 128 #@param {type:「整数"}。
モデル = "クリスハントラン/スパンベルタ" #@param ["chriskhanhtran/spanberta", "bert-base-multilingual-cased"].
OUTPUT_DIR = 「スパンベルタナー #@param ["spanberta-ner", "bert-base-ml-ner"]。
バッチサイズ = 32 #@param {type:「整数"}。
NUM_EPOCHS = 3 #@param {type:「整数"}。
SAVE_STEPS = 100 #@param {type:「整数"}。
ロギング・ステップ = 100 #@param {type:「整数"}。
シード = 42 #@param {type:「整数"}。

トレーニングを始めよう

!パイソン3 ランナー.パイ \
 --data_dir ./ \
 --モデルタイプ バート \
 --ラベル ./ラベル.テキスト \
 --モデル名またはパス $モデル \
 --出力先 $OUTPUT_DIR \
 --max_seq_length $MAX_LENGTH \
 --num_train_epochs $NUM_EPOCHS \
 --per_gpu_train_batch_size $バッチサイズ \
 --セーブステップ $SAVE_STEPS \
 --ロギングステップ $ロギング・ステップ \
 --シード $シード \
 --do_train \
 --do_eval \
 --do_predict \
 --上書き出力先

開発セットでのパフォーマンス

04/21/2020 02:24:31 - INFO - __main__ - ***** 評価結果 *****
04/21/2020 02:24:31 - INFO - __main__ - f1 = 0.831027443864822
04/21/2020 02:24:31 - INFO - __main__ - loss = 0.1004064822183894
04/21/2020 02:24:31 - INFO - __main__ - 精度 = 0.8207885304659498
04/21/2020 02:24:31 - INFO - __main__ - 回収 = 0.8415250344510795

テストセットでのパフォーマンス:

04/21/2020 02:24:48 - INFO - __main__ - ***** 評価結果 *****
04/21/2020 02:24:48 - INFO - __main__ - f1 = 0.8559533721898419
04/21/2020 02:24:48 - INFO - __main__ - loss = 0.06848683688204177
04/21/2020 02:24:48 - INFO - __main__ - 精度 = 0.845858475041141
04/21/2020 02:24:48 - INFO - __main__ - 回収 = 0.8662921348314607

微調整のテンソルボードは以下の通り。 スパンベルタ そして バートベース多言語ケース を5エポッシュに渡って計算した。モデルは3エポッシュ後にトレーニングデータにオーバーフィットしていることがわかる。

分類レポート

このモデルの実際の性能を理解するために、予測値をロードして分類レポートを調べてみよう。

デフ ファイルからサンプルを読み込む(ファイルパス):
 """CoNLL-2002/2003データファイルから単語とラベルを読み込む。
 引数
 file_path (str): NER データファイルへのパス。
 戻り値
 examples (dict): 2つのキーを持つ辞書:words` (リストのリスト)
 各配列の単語を保持する `words` (リストのリスト) と、対応するラベルを保持する `labels` (リストのリスト)。
 対応するラベルを保持する `labels` (リスト)。
 """
  オープン(ファイルパス, エンコーディング="utf-8") として f:
  = {"言葉": [], "ラベル": []}
 言葉 = []
 ラベル = []
 にとって ライン  f:
 もし ライン.スタートウィズ(「DOCSTART) または ライン == "" または ライン == "\n":
 もし 言葉:
 ["言葉"].アペンド(言葉)
 ["ラベル"].アペンド(ラベル)
 言葉 = []
 ラベル = []
 その他:
 スプリッツ = ライン.スプリット(" ")
 言葉.アペンド(スプリッツ[0])
 もし レン(スプリッツ) > 1:
 ラベル.アペンド(スプリッツ[-1].置き換える("\n", ""))
 その他:
 # mode = "test "の例では、ラベルがありませんでした。
 ラベル.アペンド("O")
 戻る 

生テキストファイルからデータとラベルを読み込む:

y_true = ファイルからサンプルを読み込む("test.txt")["ラベル"]
y_pred = ファイルからサンプルを読み込む("spanberta-ner/test_predictions.txt")["ラベル"]

分類レポートを印刷する:

より seqeval.メトリクス インポート 分類報告 として 分類_報告_結果の確認
プリント(分類_報告_結果の確認(y_true, y_pred))
 精度 回想 f1スコア サポート
 loc 0.87 0.84 0.85 1084
 org 0.82 0.87 0.85 1401
 misc 0.63 0.66 0.65 340
 per 0.94 0.96 0.95 735
マイクロアベレージ 0.84 0.86 0.85 3560
マクロ平均 0.84 0.86 0.85 3560

このレポートにあるメトリクスは、NERや品詞タグ付けのようなNLPタスクのために特別に設計されたもので、エンティティのすべての単語が正しく予測されなければ、1つの正しい予測としてカウントされない。したがって、この分類レポートのメトリクスは scikit-learnの分類レポート.

インポート ナンピー として np
より sklearn.メトリクス インポート 分類報告
プリント(分類報告(np.連結(y_true), np.連結(y_pred)))
 精度 回想 f1 スコア サポート
 b-loc 0.88 0.85 0.86 1084
 b-misc 0.73 0.73 0.73 339
 b-org 0.87 0.91 0.89 1400
 B-per 0.95 0.96 0.95 735
 アイロック 0.82 0.81 0.81 325
 i-misc 0.85 0.76 0.80 557
 i-org 0.89 0.87 0.88 1104
 i-per 0.98 0.98 0.98 634
 O 1.00 1.00 1.00 45355
 精度 0.98 51533
 マクロ平均 0.89 0.87 0.88 51533
加重平均 0.98 0.98 0.98 51533

以上の報告から、我々のモデルは、人物、場所、組織の予測において良好なパフォーマンスを持っている。私たちは MISC エンティティのパフォーマンスを向上させる。

パイプラインパーマリンク

モデルを微調整したら、次のチュートリアルに従って、コミュニティと共有することができる。 ページ.これで、Hugging Faceのサーバーから微調整されたモデルをロードし、それを使ってスペイン語文書の名前付きエンティティを予測できるようになった。

より 変圧器 インポート パイプライン, AutoModelForTokenClassification(オートモデル・フォア・トークン・クラシフィケーション, オートトケナイザー
モデル = AutoModelForTokenClassification(オートモデル・フォア・トークン・クラシフィケーション.フロム_プレトレイン("skimai/spanberta-base-cased-ner-conll02")
トークナイザ = オートトケナイザー.フロム_プレトレイン("skimai/spanberta-base-cased-ner-conll02")
モデル = パイプライン(ナー, モデル=モデル, トークナイザ=トークナイザ)

以下の例は ラ・オピニオン を意味する。スティーブン・ムニューシン財務長官は、コロナウイルスのパンデミック後の米国の経済回復は数ヶ月の問題であると述べた。"

シーケンス = "アメリカ経済の回復" からの脱却 \
 "コロナウイルスのパンデミックは数ヶ月の問題である。 \
 "テソロ長官、スティーブン・ムニューチン"
モデル(シーケンス)
[{'エンティティ':'B-ORG', 'score': 0.9155661463737488, 'word': 'ĠEstados'}、
 {'entity':'I-ORG', 'score': 0.800682544708252, 'word': 'ĠUnidos'}、
 {'entity':'I-MISC', 'score': 0.5006815791130066, 'word': 'Ġcorona'}、
 {'entity':'I-MISC', 'score': 0.510674774646759, 'word': 'virus'}、
 {'entity':'B-PER', 'score': 0.5558510422706604, 'word': 'ĠSecretario'}、
 {'entity':'I-PER', 'score': 0.7758238315582275, 'word': 'Ġdel'}、
 {'entity':'I-PER', 'score': 0.7096233367919922, 'word': 'ĠTesoro'}、
 {'entity':B-PER', 'score': 0.9940345883369446, 'word': 'ĠSteven'}、
 {'entity':'I-PER', 'score': 0.9962581992149353, 'word': 'ĠM'}、
 {'entity':'I-PER', 'score': 0.9918380379676819, 'word': 'n'}、
 {'entity':'entity': 'I-PER', 'score': 0.9848328828811646, 'word': 'uch'}、
 {'entity':'I-PER', 'score': 0.8513168096542358, 'word': 'in'}].

素晴らしい!微調整されたモデルは、例のすべてのエンティティをうまく認識し、"コロナ・ウイルス "さえも認識する。

結論パーマリンク

名前付きエンティティ認識は、テキストから重要な情報を素早く抽出するのに役立つ。そのため、ビジネスへの応用は、契約書や文書を読む際の人間の生産性向上に直接的な影響を与える。しかし、NERは単語レベルでの正確な分類を必要とするため、Bag-of-Wordのような単純なアプローチではこのタスクに対処できない。

事前に訓練された BERT モデルを活用して、スペイン語の NER タスクで優れたパフォーマンスを素早く得る方法を説明した。事前に訓練された SpanBERTa モデルは、文書分類などの他のタスク用に微調整することもできます。シーケンス分類とセンチメント分析のために BERT を微調整する詳細なチュートリアルを書きました。

次回は、変圧器モデルのより効率的な事前学習アプローチであり、最先端の性能を素早く達成できるELECTRAについて解説します。ご期待ください!

ja日本語