このシリーズでは、自然言語処理において主流であるTransformerを中心に、環境構築から学習の方法までまとめます。
今回の記事ではHuggingface Transformersの入門として、概要と基本的なタスクのデモを紹介します。
パイプラインによる実装を通じて、タスクのイメージをつかんでいきましょう。
Google colabを使用して、簡単に最新の自然言語処理モデルを実装することができますので、ぜひ最後までご覧ください。
【前回】
今回の内容
・Transformerとは
・Huggingfaceとは
・Huggingface Transformersの導入
・pipelineによるタスクの紹介
(テキスト分類・感情分析・質問応答・マスク言語処理・テキスト生成・固有表現認識・要約・翻訳)
自然言語処理におけるタスクの概要
概要
自然言語処理「NLP (Natural Language Processing)」とは、人が使っている言語(自然言語)をコンピュータで処理・分析する技術全般のことを指します。
自然言語とは、普段私たちがコミュニケーションをとる際に使う言葉のことをいい、数式やプログラミング言語など人工的、形式的に定義された言語を「人工言語」といいます。
自然言語は日常的に人が使用する言葉であり、曖昧さを多く含んでおり、同じ言葉でも、話す人物や文脈によって違う意味を示すことも珍しくないため、コンピュータで機械的に分析するのには高度な技術が求められます。
最近ではこの自然言語処理でも深層学習の導入が盛んに行われており、実用化も進んでいます。
自然言語処理の分野では、目的ごとに以下のようなタスクに分類されており、必要に応じて使い分けを行います。
このシリーズでは、以下のようなタスクの実装を紹介していきます。
タスク名称 | 日本語名称 | 主な用途 |
text-classification | テキスト分類 | テキスト分類は、テキストにラベルまたはクラスを割り当てる一般的な NLP タスクです。 |
sentiment-analysis | 感情分析 | テキスト分類の応用で、ラベルを感情表現にすることで、文章中の感情を分析することができます。 |
language-modeling | 言語モデル | 言語モデリングは、文中の単語を予測します。言語モデリングには 2 つの形式があります。 ・因果言語モデリングは、一連のトークンの次のトークンを予測し、モデルは左側のトークンのみに注意を向けることができます。 ・マスク言語モデリングは、シーケンス内のマスクされたトークンを予測するため、フィル マスク タスクとも呼ばれます。マスク言語モデリングのモデルでは、左側のコンテキストだけでなく、シーケンス全体のコンテキストを十分に理解する必要があります。 |
token-classification | 固有表現抽出 | トークン分類は、テキスト内のいくつかのトークンにラベルが割り当てられる自然言語理解タスクです。いくつかの一般的なトークン分類サブタスクは、固有表現認識 (NER) と品詞 (PoS) タグ付けです。NER モデルは、日付、個人、場所など、テキスト内の特定のエンティティを識別するようにトレーニングできます。PoS タグ付けは、たとえば、テキスト内のどの単語が動詞、名詞、および句読点であるかを識別します。 |
multiple-choice | 多肢選択 | 質問応答に似ていますが、いくつかの回答候補がコンテキストとともに提供される点が異なります。 |
question-answering | 質問応答 | 質問応答タスクは、質問に対して回答を返します。質問応答には、次の 2 つの一般的な形式があります。 抽出: 与えられた文脈から答えを抽出します。 抽象的: 質問に正しく答えるコンテキストから回答を生成します。 |
text-generation | テキスト生成 | テキスト生成 (オープンエンド テキスト生成とも呼ば れます) の目標は、特定のコンテキストからの継続であるテキストの一貫した部分を作成することです。 |
summarization | 要約 | 要約は、すべての重要な情報をキャプチャするドキュメントまたは記事の短いバージョンを作成します。翻訳と並んで、シーケンスからシーケンスへのタスクとして定式化できるタスクのもう 1 つの例です。要約は次のとおりです。 抽出: ドキュメントから最も関連性の高い情報を抽出します。 抽象的: 最も関連性の高い情報を捉えた新しいテキストを生成します。 |
translation | 翻訳 | 翻訳では、一連のテキストをある言語から別の言語に変換します。これは、sequence-to-sequence 問題として定式化できるいくつかのタスクの 1 つであり、視覚および音声タスクに拡張される強力なフレームワークです。 |
bertology | BERTology | のような大規模なTransformerの調査に関する研究分野が拡大しています 。これを「BERTology」とも呼びます。 |
Transformerとは
概要
「Transformer」は2017年にGoogleが「Attention is all you need」で発表した深層学習モデルです。
現在では、自然言語処理に利用する深層学習モデルの主流になっています。
これまでの自然言語処理分野で多く使われていた「RNN」(Recurrent Neural Network)や「CNN」(Convolutional Neural Network)を利用せず、Attentionのみを用いたEncoder-Decoder型のモデルとなっています。
「Transformer」が登場して以降、多くの自然言語処理モデルが再構築され、過去を上回る成果を上げています。
最近では自然言語処理だけでなく、ViTやDETRなどといった画像認識にも応用されています。
特徴
Transformerは従来のモデルをベースにしつつ、様々な工夫によって、計算を高速化した上で文脈情報を保持するため、より正確な変換を実現しました。
主な改善点として、以下の3点が挙げられます。
①RNNやCNNを使わずAttention層のみで構成
並列計算が可能となり、高速化が可能となりました。
②PositionalEncording層の採用
入力する単語データに「文全体における単語の位置情報」を埋め込むことで、本来RNNなどを利用しないことで失われてしまう文脈情報を保持することに成功しました。
③Query-Key-ValueモデルをAttention層に採用
初期のAttentionにおける単純な「Source-Target型」から改良され、より単語同士の照応関係(アライメント)を正確に反映することができるようになったことで、精度向上が図られています。
Huggingface Transformersとは
概要
「Hugging Face」とは米国のHugging Face社が提供している、自然言語処理に特化したディープラーニングのフレームワークです。
「Huggingface Transformers」は、先ほど紹介したTransformerを実装するためのフレームワークであり、「自然言語理解」と「自然言語生成」の最先端の汎用アーキテクチャ(BERT、GPT-2など)と、何千もの事前学習済みモデルを提供しています。
ソースコードは全てGitHub上で公開されており、誰でも無料で使うことができます。
事前学習済みモデル
Hugging Faceではタスクに応じた様々な事前学習済みモデルが提供されています。
こちらからご確認ください。
Google colabによる導入
ここからはGoogle colabを使用して実装していきます。
今回紹介するコードは以下のボタンからコピーして使用していただくことも可能です。
まずはGoogleドライブをマウントして、作業フォルダを作成します。
from google.colab import drive
drive.mount('/content/drive')
!mkdir -p '/content/drive/My Drive/huggingface_transformers_demo/'
%cd '/content/drive/My Drive/huggingface_transformers_demo/'
次にtransformersをクローンします。
transformersはpipでインストールすることができます。
!git clone https://github.com/huggingface/transformers
%cd transformers
!pip install transformers
パイプラインとトークナイザー
Huggingface Transformersにおける自然言語処理では「パイプライン」と「トークナイザー」による実装方法があります。
パイプライン | ・「タスク種別」と「入力テキスト」を指定するだけで、1行のみで推論を行うシンプル。 ・簡単に実行できるが、カスタマイズ性には乏しく、日本語での推論はあまり使えない。 (今回紹介する方法) |
トークナイザー | ・「トークナイザー」で入力テキストを深層学習モデルに対応した形式に変換し、その入力データを使って「モデル」を直接操作して、推論を実行する方法 ・カスタマイズ性が高く、多くのタスクで日本語での推論にも対応。 |
実際には「トークナイザー」による実装の方が実用的ですが、今回のデモでは、簡単に概要を紹介する目的から「パイプライン」を使用します。
ここからはタスクごとに概要とデモをそれぞれ紹介していきます。
なお、今回紹介するタスクの概要は公式実装の解説ページから抜粋しています。
テキスト分類の実装デモ
テキスト分類は、定義した特定のテキストにラベルまたはクラスを割り当てるタスクです。
主な使用例として、後ほど紹介する感情分析や自然言語推論、文法の正確性の評価などがあります。
以下の例では、2つの文章に対して、分類を実装してみます。
# 「text-classification(テキスト分類)」のパイプライン
from transformers import pipeline
classifier = pipeline("text-classification")
# 「Learning about natural language processing is a lot of fun(自然言語処理を学ぶのはとても楽しい)」を分類
result = classifier("Learning about natural language processing is a lot of fun")[0]
print(f"label: {result['label']}, with score: {round(result['score'], 4)}")
# 「The movie I saw yesterday was not very interesting(昨日見た映画はあまり面白くなかった)」を分類
result = classifier("The movie I saw yesterday was not very interesting")[0]
print(f"label: {result['label']}, with score: {round(result['score'], 4)}")
以下のような出力結果を得ます。
label: POSITIVE, with score: 0.9999
label: NEGATIVE, with score: 0.9998
「自然言語処理を学ぶのはとても楽しい」=positive、「昨日見た映画はあまり面白くなかった」=negativeという正しい分類結果を得ることができました。
同時にスコア(機械の判定の確信度)も表示されており、どちらも確信度が高い判定であることがわかります。
感情分析の実装デモ
テキスト分類の応用例として、感情分析があります。
文章を「positive」「negative」などの感情表現のラベルに分類することで、文章内の感情を把握することができます。
主な使用例として、SNSやカスタマーレビューなどから評価や満足度などの指標を分析することができます。
# 「sentiment-analysis(感情分析)」のパイプライン
from transformers import pipeline
classifier = pipeline("sentiment-analysis")
# 「I hate you(嫌い)」を感情分析
result = classifier("I hate you")[0]
print(f"label: {result['label']}, with score: {round(result['score'], 4)}")
# 「I love you(好き)」を感情分析
result = classifier("I love you")[0]
print(f"label: {result['label']}, with score: {round(result['score'], 4)}")
以下のような出力結果を得ます。
label: NEGATIVE, with score: 0.9991
label: POSITIVE, with score: 0.9999
「嫌い=ネガティブ」、「好き=ポジティブ」と正しく判定できています。
先ほどと同様に同時にスコア(機械の判定の確信度)も表示されており、どちらも確信度が高い判定であることがわかります。
質問応答の実装デモ
質問応答では、ある文章(コンテキスト)から質問に対する回答を出力することができます。
まずはコンテキスト(入力する文章)を与え、次に質問文を定義して、その回答を出力します。
# 「question-answering(質問応答)」のパイプライン
from transformers import pipeline
question_answerer = pipeline("question-answering")
# コンテキスト
context = r"""
Extractive Question Answering is the task of extracting an answer from a text given a question. An example of a
question answering dataset is the SQuAD dataset, which is entirely based on that task. If you would like to fine-tune
a model on a SQuAD task, you may leverage the examples/pytorch/question-answering/run_squad.py script.
"""
# 質問を定義
result = question_answerer(question="What is extractive question answering?", context=context)
# 回答を出力
print(
f"Answer: '{result['answer']}', score: {round(result['score'], 4)}, start: {result['start']}, end: {result['end']}"
)
# 質問を定義
result = question_answerer(question="What is a good example of a question answering dataset?", context=context)
# 回答を出力
print(
f"Answer: '{result['answer']}', score: {round(result['score'], 4)}, start: {result['start']}, end: {result['end']}"
)
以下のような出力結果を得ます。
Answer: 'the task of extracting an answer from a text given a question', score: 0.6177, start: 34, end: 95
Answer: 'SQuAD dataset', score: 0.5152, start: 147, end: 160
質問 | 回答 | |
抽出的質問応答とは? | → | 与えられた質問から答えを抽出するタスク |
質問応答データセットの良い例は何ですか? | → | SQuAD dataset |
「抽出的質問応答は、与えられた質問から回答を抽出するタスクです。 質問応答データセットの例として、 SQuAD データセットがあり、これは質疑応答のタスクに完全に基づいています。 微調整したい場合、SQuAD タスクのモデルでは、examples/pytorch/question-answering/run_squad.py スクリプトを利用できます。」という文章に対して、質問に対する回答を出力しています。
テキストから抽出された回答である信頼スコア(機械の判定の確信度)を、テキスト内の抽出された回答の位置である「開始」値と「終了」値とともに返します。
「抽出的質問応答とは」という1つめの質問に対して、「与えられた質問から答えを抽出するタスク」という結果を、「質問応答データセットの良い例は何ですか」という2つ目の質問に対して、「SQuAD dataset」という結果を得ました。
問いに対して、文章の内容をもとに、正しく回答を出力できていることがわかります。
マスク言語モデルの実装デモ
マスク言語モデリングは、文中の単語の一部をマスクし、それらのマスクを置き換える単語を予測するタスクです。
マスキング トークンを使用してシーケンス内のトークンをマスキングし、そのマスクを適切なトークンで埋めるようにモデルに指示することで、モデルは右側のコンテキスト (マスクの右側のトークン) と左側のコンテキスト (マスクの左側のトークン) の両方に対応できます。
以下の例では、「HuggingFace は、コミュニティが NLP タスクを解決するために使用する◯◯◯を作成しています」という文章の◯◯◯部分の穴埋めの候補を出力します。
# 「fill-mask(マスク言語モデル)」のパイプライン
from transformers import pipeline
unmasker = pipeline("fill-mask")
from pprint import pprint
# 以下の文章の空欄の穴埋めを実行
output = unmasker(f"HuggingFace is creating a {unmasker.tokenizer.mask_token} that the community uses to solve NLP tasks.")
pprint(output)
以下のような出力結果を得ます。
[{'score': 0.17927497625350952, 'sequence': 'HuggingFace is creating a tool that the community uses to solve ' 'NLP tasks.', 'token': 3944, 'token_str': ' tool'},
{'score': 0.11349403858184814, 'sequence': 'HuggingFace is creating a framework that the community uses to ' 'solve NLP tasks.', 'token': 7208, 'token_str': ' framework'},
{'score': 0.05243556201457977, 'sequence': 'HuggingFace is creating a library that the community uses to ' 'solve NLP tasks.', 'token': 5560, 'token_str': ' library'},
{'score': 0.03493537753820419, 'sequence': 'HuggingFace is creating a database that the community uses to ' 'solve NLP tasks.', 'token': 8503, 'token_str': ' database'},
{'score': 0.02860264666378498, 'sequence': 'HuggingFace is creating a prototype that the community uses to ' 'solve NLP tasks.', 'token': 17715, 'token_str': ' prototype'}]
「HuggingFace は、コミュニティが NLP タスクを解決するために使用する◯◯◯を作成しています」の穴埋め候補として、「tool 」、「framework」、「library」などを挙げています。
テキスト生成の実装デモ
テキスト生成 (オープンエンド テキスト生成とも呼ば れます) の目標は、特定のコンテキストからの継続であるテキストの一貫した部分を作成することです。
次の例は、パイプラインでGPT-2を使用してテキストを生成する方法を示しています。
「As far as I am concerned, I will(私としては、)」という文章の続きの文章を出力します。
# 「text-generation(テキスト生成)」のパイプライン
from transformers import pipeline
text_generator = pipeline("text-generation")
# 「As far as I am concerned, I will(私としては、)」の続きの文章を出力する
print(text_generator("As far as I am concerned, I will", max_length=50, do_sample=False))
以下のような出力結果を得ます。
[{'generated_text': 'As far as I am concerned, I will be the first to admit that I am not a fan of the idea of a "free market." I think that the idea of a free market is a bit of a stretch. I think that the idea'}]
# 私としては、"自由な市場 "という考え方には否定的です。自由市場という考え方は、ちょっと無理があると思うのです。私が思うに、その考え方は
「As far as I am concerned, I will(私としては、)」という文章の続きとして、「”自由な市場 “という考え方には否定的です。自由市場という考え方は、ちょっと無理があると思うのです。私が思うに、その考え方は〜」という文章を出力しています。
要約の実装デモ
要約は、重要な情報を保持しながらドキュメントや記事を短いテキストに要約するタスクです。
元の入力からテキストを抽出できるモデルもあれば、まったく新しいテキストを生成できるモデルもあります。
以下は、パイプラインを使用してニュース記事の要約を行う例です。
# 「summarization(要約)」のパイプライン
from transformers import pipeline
summarizer = pipeline("summarization")
# 入力する記事
ARTICLE = """ New York (CNN)When Liana Barrientos was 23 years old, she got married in Westchester County, New York.
A year later, she got married again in Westchester County, but to a different man and without divorcing her first husband.
Only 18 days after that marriage, she got hitched yet again. Then, Barrientos declared "I do" five more times, sometimes only within two weeks of each other.
In 2010, she married once more, this time in the Bronx. In an application for a marriage license, she stated it was her "first and only" marriage.
Barrientos, now 39, is facing two criminal counts of "offering a false instrument for filing in the first degree," referring to her false statements on the
2010 marriage license application, according to court documents.
Prosecutors said the marriages were part of an immigration scam.
On Friday, she pleaded not guilty at State Supreme Court in the Bronx, according to her attorney, Christopher Wright, who declined to comment further.
After leaving court, Barrientos was arrested and charged with theft of service and criminal trespass for allegedly sneaking into the New York subway through an emergency exit, said Detective
Annette Markowski, a police spokeswoman. In total, Barrientos has been married 10 times, with nine of her marriages occurring between 1999 and 2002.
All occurred either in Westchester County, Long Island, New Jersey or the Bronx. She is believed to still be married to four men, and at one time, she was married to eight men at once, prosecutors say.
Prosecutors said the immigration scam involved some of her husbands, who filed for permanent residence status shortly after the marriages.
Any divorces happened only after such filings were approved. It was unclear whether any of the men will be prosecuted.
The case was referred to the Bronx District Attorney\'s Office by Immigration and Customs Enforcement and the Department of Homeland Security\'s
Investigation Division. Seven of the men are from so-called "red-flagged" countries, including Egypt, Turkey, Georgia, Pakistan and Mali.
Her eighth husband, Rashid Rajput, was deported in 2006 to his native Pakistan after an investigation by the Joint Terrorism Task Force.
If convicted, Barrientos faces up to four years in prison. Her next court appearance is scheduled for May 18.
"""
# 入力した記事に対する要約文を出力
print(summarizer(ARTICLE, max_length=130, min_length=30, do_sample=False))
以下のような出力結果を得ます。
[{'summary_text': ' Liana Barrientos, 39, is charged with two counts of "offering a false instrument for filing in the first degree" In total, she has been married 10 times, with nine of her marriages occurring between 1999 and 2002 . At one time, she was married to eight men at once, prosecutors say .'}]
入力 |
ニューヨーク(CNN)リアナ・バリエントスさんは23歳のとき、ニューヨーク州ウエストチェスター郡で結婚した。 1年後、彼女はウエストチェスター郡で再婚したが、相手は別の男性で、最初の夫とは離婚せずに結婚した。 その結婚からわずか18日後、彼女はまたもや結婚した。その後、バリェントスはさらに5回「I do」と宣言し、時には2週間以内に結婚した。 2010年、彼女はもう一度、今度はブロンクスで結婚した。結婚許可証の申請書には、「最初で最後の」結婚であると書かれていた。 現在39歳のバリェントスは、「第一級虚偽提出物提供」の2つの刑事訴追を受けており、これは2010年の結婚許可申請における彼女の虚偽記載に言及している。 裁判資料によると、2010年の結婚許可証の申請書に虚偽の記載をしたことが原因だ。 検察は、結婚が移民詐欺の一部であると述べている。 金曜日にブロンクスの州最高裁判所で無罪を主張したと、彼女の弁護士であるクリストファー・ライトは述べた。 法廷を出た後、バリェントスは、非常口からニューヨークの地下鉄に忍び込んだという理由で、サービスの窃盗と不法侵入で逮捕・起訴されたと、アネット・マコウスキー刑事は語った。 警察の広報担当者であるアネット・マーコウスキー刑事は、次のように述べています。バリェントスさんは合計で10回結婚しており、そのうち9回は1999年から2002年にかけて結婚している。 いずれもウエストチェスター郡、ロングアイランド、ニュージャージー、ブロンクスのいずれかで行われた。彼女は現在も4人の男性と結婚していると思われ、一時期は8人の男性と同時に結婚していたと検察は述べている。 検察によると、移民詐欺には、結婚後すぐに永住権を申請した夫たちも含まれていた。 離婚は、その申請が承認された後に行われた。この中の誰かが起訴されるかどうかは不明である。 この事件は、移民税関捜査局と国土安全保障省捜査局によってブロンクス地方検事局に付託された。 捜査部門から照会があった このうち7人は、エジプト、トルコ、グルジア、パキスタン、マリなど、いわゆる「レッドフラッグ国」の出身です。 8番目の夫であるRashid Rajputは、Joint Terrorism Task Forceによる調査の後、2006年に母国パキスタンに強制送還されました。 有罪判決を受けた場合、Barrientosは最高4年の禁固刑に直面することになります。 次回の出廷は5月18日に予定されています。 |
↓ |
出力(要約結果) |
リアナ・バリエントス(39)は、「第一級虚偽提出書類提供」の2つの訴因で起訴された。彼女は合計10回結婚しており、そのうち9回は1999年から2002年の間に起こったものである。一時期は8人の男性と同時に結婚していたと、検察は述べている。 |
入力したニュース記事の内容を、要約して出力することができました。
翻訳の実装デモ
翻訳とは、テキストをある言語から別の言語に翻訳する作業です。
翻訳データセットの例として、WMT の英語からドイツ語へのデータセットがあります。
このデータセットには、英語の文が入力データとして含まれ、対応するドイツ語の文がターゲット データとして含まれています。
以下は、パイプラインを使用して英語からドイツ語へ翻訳を行う例です。
# 「translation_en_to_de(英語からドイツ語への翻訳)」のパイプライン
from transformers import pipeline
translator = pipeline("translation_en_to_de")
# 英語からドイツ語への翻訳結果を表示
print(translator("Hugging Face is a technology company based in New York and Paris", max_length=40))
以下のような出力結果を得ます。
[{'summary_text': ' Liana Barrientos, 39, is charged with two counts of "offering a false instrument for filing in the first degree" In total, she has been married 10 times, with nine of her marriages occurring between 1999 and 2002 . At one time, she was married to eight men at once, prosecutors say .'}]
英語からドイツ語への変換ができました。
自然言語処理以外の分野での活用事例
音声分類
オーディオ分類は、クラスをオーディオ信号に割り当てます。
自動音声認識
自動音声認識は、音声信号をテキストに変換します。
画像分類
テキストや音声の分類と同様に、画像の分類では画像にクラスが割り当てられます。
まとめ
最後までご覧いただきありがとうございました。
今回の記事ではHuggingface Transformersの入門として、概要と基本的なタスクのデモを紹介しました。
次回はより詳細なタスクを実装方法を紹介します。
このシリーズでは、自然言語処理全般に関するより詳細な実装や学習の方法を紹介しておりますので、是非ご覧ください。
【次回】