📘

transformersに入門してみた!

2022/09/11に公開

はじめに

最近transformersというとても便利なライブラリがあることを知りました!今回はtransformersの初心者向けのガイドを参考に記事を書きたいと思います!(具体的には、テキストの感情分析を扱います。)
https://huggingface.co/docs/transformers/quicktour

Pipeline

pipeline()を使えば、代表的なタスクについて簡単に学習済みのモデルを使用できます。

テキスト:感情分析、テキスト生成、NER(固有表現抽出)、質問応答、空欄補充、要約、翻訳、特徴抽出
画像:画像分類、セグメンテーション、物体検出
音声:音声分類、自動音声認識

Pipelineの使い方

感情分析を例にpipeline()を使っていきます。pytorchをインストールしていない場合は、以下のコマンドでインストールします。

pip install torch

pipelineをインポートし、実行したいタスクを指定します。

from transformers import pipeline

classifier = pipeline('sentiment-analysis')

pipelineは感情分析向けのデフォルトの学習済みモデルとトークナイザーをダウンロードすることができます。pipeline()をターゲットとなるテキストに対して使用します。

classifier("We are very happy to show you the 🤗 Transformers library.")

・出力
[{'label': 'POSITIVE', 'score': 0.9997795224189758}]

2つ以上の文章をpipeline()に渡すと、辞書のリストを返します。

results = classifier(["We are very happy to show you the 🤗 Transformers library.", "We hope you don't hate it."])
for result in results:
    print(f"label: {result['label']}, with score: {round(result['score'], 4)}")

・出力
label: POSITIVE, with score: 0.9998
label: NEGATIVE, with score: 0.5309

ちなみに、resultsは以下のようなリストになっています。
[{'label': 'POSITIVE', 'score': 0.9997795224189758},
{'label': 'NEGATIVE', 'score': 0.5308602452278137}]

pipeline()はデータセット全体を反復処理することも可能です。
まず、取り組みたいタスクと使いたいモデルを指定して、pipeline()を作成します。なお、automatic-speech-recognitionは、人間が話した声を解析し、文字(テキスト)に変換するタスクです。

import torch
from transformers import pipeline

speech_recognizer = pipeline("automatic-speech-recognition", model="facebook/wav2vec2-base-960h")

次に、反復処理したいデータセットをダウンロードします。例えば、MInDS-14データセットをダウンロードします。

from datasets import load_dataset, Audio

dataset = load_dataset("PolyAI/minds14", name="en-US", split="train")

ちなみにdatasetを出力すると、以下のようになります。
Dataset({
features: ['path', 'audio', 'transcription', 'english_transcription', 'intent_class', 'lang_id'],
num_rows: 563
})

ここで、データセットのサンプリングレートとfacebook/wav2vec2-base-960hが学習したサンプリングレートを一致させる必要があります。ちなみに、サンプリングレートとは、アナログ信号をデジタルで表現する場合に、アナログの電圧をチェックする1秒あたりのサンプル数のことらしいです。

dataset = dataset.cast_column("audio", Audio(sampling_rate=speech_recognizer.feature_extractor.sampling_rate))

audio列を指定すると、音声ファイルが自動的に読み込まれて、リサンプリングされます。最初の4つのサンプルの波形を抽出して、pipelineにリストとして渡します。出力を見ると、音声がテキストに変換されていることが分かります。

result = speech_recognizer(dataset[:4]["audio"])
print([d["text"] for d in result])

・出力
['I WOULD LIKE TO SET UP A JOINT ACCOUNT WITH MY PARTNER HOW DO I PROCEED WITH DOING THAT', "FODING HOW I'D SET UP A JOIN TO HET WITH MY WIFE AND WHERE THE AP MIGHT BE", "I I'D LIKE TOY SET UP A JOINT ACCOUNT WITH MY PARTNER I'M NOT SEEING THE OPTION TO DO IT ON THE AP SO I CALLED IN TO GET SOME HELP CAN I JUST DO IT OVER THE PHONE WITH YOU AND GIVE YOU THE INFORMATION OR SHOULD I DO IT IN THE AP AND I'M MISSING SOMETHING UQUETTE HAD PREFERRED TO JUST DO IT OVER THE PHONE OF POSSIBLE THINGS", 'HOW DO I THURN A JOIN A COUNT']

パイプラインで別のモデルやトークナイザを使用する

pipeline()はModel Hubから任意のモデルを使うことができます。例えば、フランス語のテキストを分類するモデルが欲しい場合、Model Hub上のタグを使用して、適切なモデルをフィルタリングします。(下の写真参照) 今回は一番上に出てきたnlptown/bert-base-multilingual-uncased-sentimentというモデルを用います。このモデルは、英語、オランダ語、ドイツ語、フランス語、スペイン語、イタリア語の6つの言語で書かれた製品レビューの感情分析用にファインチューニングされた、BERTをベースとする多言語用の大文字と小文字を区別しないモデルであり、レビューの感情を1~5の数字で推測するようです。

model_name = "nlptown/bert-base-multilingual-uncased-sentiment"

AutoModelForSequenceClassificationとAutoTokenizerを使用して、学習済みモデルとそれに関連するトークナイザーをロードします

from transformers import AutoTokenizer, AutoModelForSequenceClassification

model = AutoModelForSequenceClassification.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)

そして、pipeline()でモデルやトークナイザーを指定し、対象のテキストに分類器を適用します。

classifier = pipeline("sentiment-analysis", model=model, tokenizer=tokenizer)
classifier("Nous sommes très heureux de vous présenter la bibliothèque 🤗 Transformers.")

・出力
[{'label': '5 stars', 'score': 0.7272651791572571}]

AutoClass

内部では、AutoModelForSequenceClassification と AutoTokenizer クラスが連携して pipeline() を動かしています。AutoClass は、学習済みモデルの構造を名前またはパスから自動的に取得するショートカットです。タスクに適した AutoClass を選択し、AutoTokenizer で関連付けられたトークナイザーを選択します。では例に戻って、pipeline()の結果を複製するためにどのようにAutoClassを使用するかを見ていきます。

AutoTokenizer

トークナイザーは、テキストをモデルに理解しやすい形式に前処理する役割を担っています。まず、トークナイザーはテキストをトークンと呼ばれる部品に分割します。どのように単語を分割するか、どのレベルで分割するかなど、トークン化の仕方には複数あります。しかし最も重要なことは、選んだモデルが事前に学習した際に用いたトークン化ルールと同じトークン化をするために、使用するモデルと同じモデル名でトークナイザーをインスタンス化する必要があるということです。(少し分かりにくいですが、例えばnlptown/bert-base-multilingual-uncased-sentimentというモデルを使いたい場合は、トークナイザーについてもbert-base-multilingual-uncased-sentimentというモデルを指定する必要があるということです。)

from transformers import AutoTokenizer

model_name = "nlptown/bert-base-multilingual-uncased-sentiment"
tokenizer = AutoTokenizer.from_pretrained(model_name)

・出力
{'input_ids': [101, 11312, 10320, 12495, 19308, 10114, 11391, 10855, 10103, 100, 58263, 13299, 119, 102], 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}

次に、トークナイザーがトークンを数値に変換し、モデルへの入力となるテンソルを作成します。

encoding = tokenizer("We are very happy to show you the 🤗 Transformers library.")
print(encoding)

・出力
{'input_ids': [101, 11312, 10320, 12495, 19308, 10114, 11391, 10855, 10103, 100, 58263, 13299, 119, 102], 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}

トークナイザーは以下のものを含む辞書を返します。
・input_ids:トークンを表す数字。
・attention_mask:どのトークンに注目すべきかを示す。
pipeline()と同じようにトークナイザーはリストを入力することができます。加えて、テキストを長くしたり短くしたりして一様な長さにすることができます。

pt_batch = tokenizer(
    ["We are very happy to show you the 🤗 Transformers library.", "We hope you don't hate it."],
    padding=True,
    truncation=True,
    max_length=512,
    return_tensors="pt",
)

AutoModel

AutoTokenizerをロードするのと同じようにAutoModelをロードすることができます。AutoModelの場合は、タスクに適した もの を選択する必要があります。今回は、テキストの分類を行っているため、AutoModelForSequenceClassificationをロードします。

from transformers import AutoModelForSequenceClassification

model_name = "nlptown/bert-base-multilingual-uncased-sentiment"
pt_model = AutoModelForSequenceClassification.from_pretrained(model_name)

先ほど前処理したpt_batchをモデルに入力します。辞書をアンパックするには**を使います。

pt_outputs = pt_model(**pt_batch)

モデルの出力のlogits属性を見ると、確率を確認することができます。このモデルは、テキストの感情を1~5の数字で推測するので、例えば1つ目の文章"We are very happy to show you the 🤗 Transformers library."については、1の確率が0.0021、5の確率が0.7725ということになります。

from torch import nn

pt_predictions = nn.functional.softmax(pt_outputs.logits, dim=-1)
print(pt_predictions)

・出力
tensor([[0.0021, 0.0018, 0.0115, 0.2121, 0.7725],
[0.2084, 0.1826, 0.1969, 0.1755, 0.2365]], grad_fn=<SoftmaxBackward0>)

モデルを保存する

モデルのファインチューニングができたら、save_pretrained()を使ってモデルを保存できます。

pt_save_directory = "/content/drive/MyDrive/tutorial/transformers/pt_save_pretrained"
tokenizer.save_pretrained(pt_save_directory)
pt_model.save_pretrained(pt_save_directory)

もう一度保存したモデルを使いたい場合は、from_pretrained()を使います。

pt_model = AutoModelForSequenceClassification.from_pretrained("/content/drive/MyDrive/tutorial/transformers/pt_save_pretrained")

おわりに

transformersの記事はいかがだったでしょうか?テキストの感情分析を簡単に実装できるのはすごいですね!今後もtransformersの勉強をしていきたいと思います!

GitHubで編集を提案

Discussion