HuggingFaceでConvBertの質問応答を試す

BERTはSelf Attentionベースなので全体の情報は取得できるのですが、局所的な情報が抜け落ちそうなイメージがあります。

ConvBertを使えば、局所的な情報を取得できるぞ

ConvBertとは

上図の(a)がSelf Attentionで全体の情報を各トークンで考慮しています。(b)のDynamic convolutionは一つの入力のみを考慮しています。(c)のSpan-based dynamic convolutionは窓幅を設定して、その窓幅分の局所的な情報を取得しています。図の例では窓幅3になっています。

実際のそれぞれのレイヤー構成は上図のようになっています。

Self AttentionとDynamic convolution、Span-based dynamic convolutionを組み合わせます。これらを組み合わせることで全体情報、局所情報、トークンのダイレクトの情報を混ぜ合わせることができます。

GLUEデータ・セットでのパフォーマンスは下記になります。ConvBertが最も精度が高くなっています。

https://gluebenchmark.com/

畳み込みのカーネルサイズとパフォーマンスも調査されています。カーネルサイズが10の際に最も性能が高いことがわかりました。

動作環境

Google Colabで動作確認をしました。Google Colabの設定方法は下記記事をご覧ください。

Question Answering

まず必要なライブラリをインストールします。

! pip install transformers[ja]

ConvBertモデルを作成します。

質問応答の学習済みモデルを公開してくれているので、こちらを使用します。

https://huggingface.co/Salesforce/qaconv-bert-large-uncased-whole-word-masking-squad2

from transformers import ConvBertTokenizer, ConvBertForQuestionAnswering
import torch

tokenizer = AutoTokenizer.from_pretrained("Salesforce/qaconv-bert-large-uncased-whole-word-masking-squad2")
model = AutoModelForQuestionAnswering.from_pretrained("Salesforce/qaconv-bert-large-uncased-whole-word-masking-squad2")

質問文と答えが含まれるテキストを準備します。

questions = [
     "How many pretrained models are available in 🤗 Transformers?",
     "What does 🤗 Transformers provide?",
     "🤗 Transformers provides interoperability between which frameworks?",
]

text = r"""
 🤗 Transformers (formerly known as pytorch-transformers and pytorch-pretrained-bert) provides general-purpose
 architectures (BERT, GPT-2, RoBERTa, XLM, DistilBert, XLNet…) for Natural Language Understanding (NLU) and Natural
 Language Generation (NLG) with over 32+ pretrained models in 100+ languages and deep interoperability between
 TensorFlow 2.0 and PyTorch.
"""

下記のコードで各質問に対する答えを取得します。

下記の流れで動作しています。

  • 質問文と答えが含まれる文のペアを前処理
  • モデルで予測
  • 答えが含まれる文のどの位置に質問の答えがあるかの開始位置と終了位置を取得
  • 答えを出力
for question in questions:
    inputs = tokenizer(question, text, add_special_tokens=True, return_tensors="pt")
    input_ids = inputs["input_ids"].tolist()[0]

    outputs = model(**inputs)
    answer_start_scores = outputs.start_logits
    answer_end_scores = outputs.end_logits

    answer_start = torch.argmax(
        answer_start_scores
    )  # Get the most likely beginning of answer with the argmax of the score
    answer_end = torch.argmax(answer_end_scores) + 1  # Get the most likely end of answer with the argmax of the score

    print(answer_start, answer_end)
    answer = tokenizer.convert_tokens_to_string(tokenizer.convert_ids_to_tokens(input_ids[answer_start:answer_end]))

    print(f"Question: {question}")
    print(f"Answer: {answer}")

下記のような結果になります。質問に対応する答えが得られています。

tensor(82) tensor(85)
Question: How many pretrained models are available in 🤗 Transformers?
Answer: over 32 +
tensor(33) tensor(38)
Question: What does 🤗 Transformers provide?
Answer: general - purpose architectures
tensor(98) tensor(108)
Question: 🤗 Transformers provides interoperability between which frameworks?
Answer: tensorflow 2. 0 and pytorch

以外に簡単に試せました。

局所的な情報も考慮できるので、BERTで十分な精度が出ない場合は試す価値はあるぞ

Close Bitnami banner
Bitnami