※本記事は、スタンフォード大学のCS224N NLP with Deep Learning | 2023コースにおける、Eric Frankel氏によるHugging Face Transformersチュートリアルの内容を基に作成されています。このチュートリアルの詳細情報は https://www.youtube.com/watch?v=b80by3Xk_A8 でご覧いただけます。本記事では、チュートリアルの内容を要約・構造化しております。なお、本記事の内容は原著作者の見解を正確に反映するよう努めていますが、要約や解釈による誤りがある可能性もありますので、正確な情報や文脈については、オリジナルの動画をご覧いただくことをお勧めいたします。
スタンフォード大学の人工知能専門・大学院プログラムについての詳細は https://stanford.io/ai でご覧いただけます。また、このコースについての詳細は https://online.stanford.edu/courses/c... で、コーススケジュールとシラバスは http://web.stanford.edu/class/cs224n/ でご確認いただけます。
【講師紹介】 Christopher Manning教授:Thomas M. Siebel機械学習教授、言語学・コンピュータサイエンス教授、スタンフォード人工知能研究所(SAIL)所長
1. イントロダクション
1.1. Hugging Faceライブラリの概要
こんにちは皆さん、224n Hugging Face Transformersチュートリアルへようこそ。このチュートリアルは、Hugging Faceライブラリの使い方について説明します。このライブラリは、既製のNLPモデル、特にTransformerベースのモデルを効果的に活用する非常に便利な方法です。皆さんの最終プロジェクトやカスタムプロジェクト、あるいは将来の何かに使えるでしょう。これは本当に便利なパッケージで、特にPyTorchとうまく連携します。
Hugging Faceライブラリの主な魅力は、事前訓練済みのTransformerモデルを簡単に利用できることです。BERTやGPT-2、GoogleのT5 Smallなど、さまざまなモデルが利用可能です。これらのモデルの重みはすべてHugging Face Hubで公開されており、自由にダウンロードできます。特定のモデルに興味がある場合、おそらくそのバージョンをここで見つけることができるでしょう。
また、特定のタスク向けに最適化されたモデルも探せます。例えば、ゼロショット分類のような特定のタスクに優れたモデルもいくつか用意されています。探しているタスクが何であれ、それに適したHugging Faceモデルがオンラインで見つかるでしょう。
1.2. ドキュメンテーション紹介
まず最初に、このチュートリアルで取り上げきれない内容がある場合のために、Hugging Faceのドキュメントは非常に充実していることを伝えておきます。彼らは多くのチュートリアルやウォークスルー、さらに遊べるノートブックも提供しています。何か疑問があったら、そちらを見るのが本当に良い方法です。
Hugging Faceのドキュメントは、各機能の詳細な説明や使用例が豊富に含まれており、特にTransformersパッケージの各クラスやメソッドについて徹底的に解説されています。モデルのアーキテクチャ、トークナイザーの詳細、さまざまなタスク向けの具体的な実装例など、必要な情報がすべて揃っています。
具体的なタスクや機能について詳しく知りたい場合、例えばトークナイザーの特殊なオプションやトレーニング引数の設定など、ドキュメントを参照することで簡単に情報を得ることができます。このチュートリアルでは基本的な使い方を説明しますが、より深く掘り下げたい場合は、ぜひHugging Faceの公式ドキュメントを活用してください。
1.3. 必要なパッケージのインストール
Colabで最初にやることは、すでに実行しましたが、もう一度実行してみましょう。Transformersというpythonパッケージと、datasetsというpythonパッケージをインストールします。これらはHugging Face TransformersとDatasetsに対応しています。これらは非常に便利で、Transformersは多くの事前訓練済みモデルを取得できる場所であり、Datasetsはさまざまなタスクに使える便利なデータセットを提供してくれます。今回の場合は感情分析のためのデータセットなどが含まれています。
また、エンコーディングが実際にどのように行われているかを理解するための補助関数も使用します。これを実行して始めましょう。また、他にもいくつかの重要な要素をインポートします。
インストールが完了すると、Transformersとdatasetsパッケージを通じて、事前訓練されたモデルやデータセットに簡単にアクセスできるようになります。これにより、自然言語処理タスクを素早く開始することができます。
2. Hugging Faceの基本
2.1. モデルの探し方
まず最初に、Hugging Faceを使うためのステップバイステップの方法を説明します。最初にやることは、Hugging Face Hubからモデルを見つけることです。ここには様々な種類のモデルがあります。BERTやGPT2、GoogleのT5 Smallなどの言語モデルもあります。たくさんの異なるモデルがあり、それらの事前訓練済みの重みはすべてHugging Faceで自由にダウンロード可能です。
特定のモデルに興味がある場合、そのバージョンをおそらくここで見つけることができるでしょう。サイドバーには、特定のタスク向けのさまざまな種類のモデルも表示されています。例えば、ゼロショット分類のようなタスクをしたい場合、そのタスクに特に適したモデルがいくつかあります。
あなたが探しているタスクに基づいて、オンラインでダウンロード可能なHugging Faceモデルがおそらく存在します。つまり、まず最初にHugging Face Hubでモデルを見つけて、次に何をしたいかを決めます。今回の場合は感情分析を行いますが、皆さんが使いたいものは何でも構いません。
2.2. Hugging Face Hubの紹介
Hugging Face Hubとは、モデル、データセット、および関連リソースの包括的なリポジトリです。ここでは、膨大な数の事前訓練済みモデルにアクセスすることができます。サイドバーを使うと、特定のタスクに最適なモデルを簡単にフィルタリングできます。例えば、ゼロショット分類のようなタスクがあれば、それに特化したモデルを見つけることができます。
Hubでモデルを検索する際、各モデルには詳細なドキュメントがあり、その使用方法、パフォーマンス指標、トレーニングに使用されたデータセットについての情報が提供されています。これは、特定のユースケースに最適なモデルを選択する際に非常に役立ちます。
また、モデルを見つけたら、そのモデル名(例:sentiment-roberta-large-english)をコピーして、コードで直接使用することができます。これにより、必要なモデルの重みとアーキテクチャを自動的にダウンロードして初期化することができます。Hugging Face Hubは、NLPモデルのリソースとして非常に豊富で、必要なものがあれば、それを探して簡単に利用することができます。
2.3. Auto機能の利用
Hugging Faceでは、「Auto」クラスという非常に便利な機能を提供しています。これらは、モデルやトークナイザーの初期化プロセスを大幅に簡略化してくれます。例えば、AutoTokenizer
やAutoModel
というクラスがあります。
AutoTokenizer
を使うと、特定のモデルに対応する正しいトークナイザーを自動的に選択してくれます。これは非常に便利です。なぜなら、各モデルには特有のトークナイザーがあり、それらを手動で正確に一致させるのは面倒だからです。AutoTokenizer
を使えば、モデル名を指定するだけで、それに対応する適切なトークナイザーが自動的にロードされます。
同様に、AutoModel
を使うと、指定されたモデル名に基づいて適切なモデルクラスを自動的に選択し、初期化してくれます。例えば、BERTモデルを使いたい場合、AutoModel.from_pretrained("bert-base-uncased")
と書くだけで、正しいBERTモデルクラスがロードされます。
これにより、コードがより簡潔になり、モデルとトークナイザーの互換性について心配する必要がなくなります。特に、様々なモデルを試す場合や、モデルの詳細なアーキテクチャについてあまり気にしない場合に非常に便利です。基本的にAuto機能を使えば、オーバーヘッドをほとんど増やさずに初期化プロセスをシンプルに行うことができます。
3. トークナイザー
3.1. トークナイザーの役割と機能
トークナイザーは、どのモデルでも入力の前処理に使用されます。基本的に生の文字列を取り、モデルが取り込んで理解できる数値やIDへのマッピングを行います。トークナイザーは使用したいモデルに特化したものであるか、あるいはAutoTokenizer
を使うこともできます。AutoTokenizer
は便利なもので、使用するモデルタイプに対応する正しいトークナイザーを自動的に選択してくれます。
AutoTokenizer
の利点は、使用するモデルに合わせて正しいトークナイザーを選んでくれることです。これにより、モデルが訓練された正確なインデックスにすべてが正しくマッピングされていることを確認できます。
例として、トークナイザーがどのように機能するか見てみましょう。一般的なPyTorchモデルと同じように呼び出すことができますが、ここでは単に文字列に対して呼び出します。「hugging face transformers is great」という入力文字列があるとします。これをトークナイザーに関数のように渡すと、トークン化された結果が得られます。これには「input_ids」というセットが含まれ、これは各トークンを表す数値です。モデルはこれらを使用します。また、対応する特定のTransformerのための「attention_mask」も含まれています。
トークナイザーは、モデルへの入力を準備する重要なステップであり、テキストを処理してモデルが理解できる形式に変換する役割を果たします。また、トークナイザーは文字列をトークンに分割するだけでなく、モデルが必要とする特殊トークンの追加や、入力の長さの調整なども行います。
3.2. AutoTokenizerの利用
Hugging Faceでは、AutoTokenizer
というクラスを提供しており、これは使用するモデルに合わせて適切なトークナイザーを自動的に選択してくれます。モデルごとに対応するトークナイザーがあり、AutoTokenizer
を使うことでそのモデルタイプに必要な正しいトークナイザーを選んでくれます。
AutoTokenizer
を使用するには、以下のようにします:
from transformers import AutoTokenizertokenizer = AutoTokenizer.from_pretrained("sentiment-roberta-large-english")
ここでは、「sentiment-roberta-large-english」というモデル名を指定していますが、使用したいモデルの名前を指定すれば、それに対応するトークナイザーが自動的にロードされます。このように、AutoTokenizer
はモデル名を与えるだけで、そのモデルに対応する正しいトークナイザーを取得するという便利な方法を提供しています。
AutoTokenizer
を使うメリットは、モデルが訓練された正確なインデックスに全てが正しくマッピングされることを保証してくれる点です。これにより、モデルとトークナイザーの互換性について心配する必要がなくなります。特に様々なモデルを試す場合に非常に便利です。AutoTokenizer
は基本的に、その選択をあなたのために行い、オーバーヘッドをほとんど増やさずに正しいトークナイザーを確実に取得できるようにしています。
3.3. トークナイザーの種類(Python版とFast版)
トークナイザーには2種類あります。Pythonトークナイザーと、Rustで書かれた「Tokenizer Fast」と呼ばれるものです。一般的にAutoTokenizer
を使用すると、デフォルトではFast版が選択されます。この2つの間に大きな違いはなく、主に推論時間、つまりモデル出力を得るための時間の違いがあるだけです。
Fast版のトークナイザーは、その名前が示すように、処理速度が最適化されています。Rustで実装されているため、特に大量のテキストを処理する場合やバッチ処理を行う場合に、純粋なPython実装よりも高速に動作します。
また、Fast版のトークナイザーでは、追加のオプションとして文字とトークンのマッピングに関する詳細情報を取得することもできます。これは、入力の特定の文字がどのようにトークン化されているかを理解するのに役立ちます。
ほとんどの場合、AutoTokenizer
を使用すれば、特に指定しなくても自動的にFast版が選択されるため、この違いについて深く考える必要はありません。単にパフォーマンスの観点から、Fast版が利用可能な場合はそちらが選択されるということを知っておくと良いでしょう。
3.4. トークン化プロセスの詳細
トークン化プロセスがどのように機能するのか詳しく見ていきましょう。これにより、各ステップで何が起こっているのかについての洞察が得られます。例として、「hugging face transformers is great」という入力文字列を使用してみましょう。
トークン化の最初のステップでは、個々の単語に分割します。ここでは、トークン化ステップの出力として、これらの個々の分割されたトークンが得られます。その後、これらのトークンをIDに変換し、モデルが推論を実行するために必要な特殊トークンを追加します。
具体的には、入力文字列「hugging face transformers is great」に対して、トークナイザーは以下のような処理を行います:
- 単語分割:「hugging」「face」「transformers」「is」「great」
- サブワード分割:必要に応じて単語をさらに小さな単位に分割します
- ID変換:各トークンを数値IDに変換
- 特殊トークン追加:モデルが必要とする開始トークン([CLS])や終了トークン([SEP])などを追加
Fast版のトークナイザーを使用すると、追加のオプションとして文字とトークンのマッピング情報も得られます。たとえば、「char_to_word」は入力内の特定の文字が、どのトークンの一部になっているかを示します。これらの情報は、トークンが入力文字列からどのように使用されているかを理解するのに役立ちます。
トークン化プロセスは、モデルへの入力を準備する上で重要なステップであり、テキスト処理パイプラインの重要な部分です。これにより、生のテキストがモデルが処理できる数値表現に変換されます。
3.5. パディングと特殊トークンの処理
トークナイザーの出力を使用する方法はいくつかあります。一つの方法は、「return_tensors」を「pt」に設定してPyTorchテンソルを返すように指示することです。これは非常に便利で、おそらく一般的にはPyTorchテンソルが必要になるでしょう。
また、トークナイザーに複数のトークンを追加し、必要に応じてパディングを行うこともできます。例えば、「pad」トークンをこの種の括弧のようなものとして使用し、トークンIDを0に対応させることができます。これにより、与えた入力に対してパディングが追加されます。特定のタイプのモデルで出力が同じ長さである必要がある場合、これらのパディングトークンが追加され、それに応じてアテンションマスクにゼロが与えられます。
この処理を行うには、「padding=True」を設定します。また、「truncation=True」を設定することもできます。トークナイザーのその他の機能について詳しく知りたい場合は、Hugging Faceのドキュメントを確認してください。非常に詳細な説明があります。
トークナイザーはおそらく特定の方法でスペースや単語を処理しており、時には予期しない方法でトークン化されることもあるかもしれません。しかし一般的に、トークン化のプロセスは一貫しており、ほとんどの場合、Hugging Faceトークナイザーから直接得られる出力で十分です。
最後に、一度に複数の文を処理する場合、「batch_decode」メソッドを使用できます。トークナイザーに文を通して得たモデル入力があれば、その入力IDを「batch_decode」に渡すことでデコードできます。必要に応じて「skip_special_tokens=True」を設定することで、パディングトークンやその他の特殊トークンの存在を無視することもできます。
3.6. バッチ処理とデコード
トークナイザーには、複数の入力を一度に処理するためのバッチ処理機能があります。例えば、複数の文をトークナイザーに渡し、それらをパディングして同じ長さにすることができます。この場合、「padding=True」を設定することで、最も長い入力に合わせて他の入力にパディングが追加されます。
バッチ処理した結果をデコードする方法も提供されています。「batch_decode」メソッドを使えば、一度に複数の入力IDをデコードすることができます。例えば、複数の文をトークナイザーに通して得たモデル入力があれば、そのinput_idsを「batch_decode」に渡すことで、元の文字列に近い形に戻すことができます。
# バッチ処理の例sentences = ["hugging face is great", "transformers are awesome"]model_inputs = tokenizer(sentences, padding=True, return_tensors="pt")# デコードの例decoded_texts = tokenizer.batch_decode(model_inputs["input_ids"])
また、「skip_special_tokens=True」というオプションを設定することで、デコード時に[PAD]や[CLS]などの特殊トークンを無視することもできます。これにより、元の入力テキストにより近い形で結果を得ることができます。
バッチ処理とデコードの機能は、特に大量のテキストデータを扱う場合や、モデルの入出力を効率的に処理したい場合に非常に役立ちます。これがトークナイザーの使い方の高レベルな概要です。
4. モデルの使用
4.1. 事前訓練済みモデルのロード
トークナイザーの使い方と同様に、Hugging Faceのモデルを使用する方法も非常に簡単です。特定のモデルタイプを選択するか、またはAutoModel
クラスを使用します。AutoModel
は、トークナイザーのAutoTokenizer
と同様に、初期化プロセスを自動的に処理してくれます。オーバーヘッドをほとんど追加せずに便利な方法でモデルを初期化できます。
事前訓練済みモデルをロードするには、以下のようにします:
from transformers import AutoModelmodel = AutoModel.from_pretrained("bert-base-uncased")
また、特定のタスク用にカスタマイズされたモデルクラスを使用することもできます:
from transformers import AutoModelForSequenceClassificationmodel = AutoModelForSequenceClassification.from_pretrained("sentiment-roberta-large-english", num_labels=2)
シーケンス分類のようなコンテキストがある場合、Hugging Faceが提供する非常に特定のクラスを使用できます。例えば、シーケンス分類にDistilBERTを使用したい場合は「DistilBertForSequenceClassification」を使用し、マスク言語モデリング設定でDistilBERTを使用する場合は「DistilBertForMaskedLM」を使用します。さらに、DistilBERTから得られる表現のみを使用する場合は、基本的なモデルを使用します。
ここでの重要なポイントは、Hugging Faceから特定のタスク用のクラスを使用して初期化できるということです。AutoModel
も同様に、AutoTokenizer
と同じように機能します。デフォルトで特定のモデルをロードし、この場合は必要な基本的な重みを取得します。
4.2. モデル種類(エンコーダー、デコーダー、エンコーダー・デコーダー)
Hugging Faceでは、基本的に3つの異なるタイプのモデルを扱うことができます。エンコーダータイプのモデル(BERTなど)、デコーダータイプのモデル(GPT-2など)、そしてエンコーダー・デコーダーモデル(BARTやT5など)です。
エンコーダーモデルは、入力シーケンス全体を処理して各トークンの文脈を理解し、双方向のアテンションを使用します。BERTやRoBERTaがこのカテゴリに含まれます。これらは主に分類、固有表現認識、質問応答などのタスクに適しています。
デコーダーモデルは、自己回帰的に動作し、テキストを生成できます。GPT-2やGPT-3などがこれに当たります。これらは言語生成タスクに優れており、「テキストを生成する」という潜在的なタスクを実行できます。
エンコーダー・デコーダーモデル(シーケンス・ツー・シーケンスモデルとも呼ばれる)は、BARTやT5のようなモデルです。これらは翻訳、要約、複雑な質問応答など、入力テキストを処理してから新しいテキストを生成する必要があるタスクに適しています。
Hugging Face Hubに戻ると、さまざまな種類のモデルがあり、ドキュメントを見れば、どのようなクラスを使用すべきかについての情報も得られます。AutoTokenizer
や異なるタスク用の様々なAutoModel
クラスなどがあります。
重要なのは、モデルの選択がアーキテクチャのタイプと一致している必要があるということです。例えば、BERTやDistilBERTはエンコーダーのみで構成されているため、エンコーダーとデコーダーを必要とするシーケンス・ツー・シーケンスモデルとして使用することはできません。モデルの使用方法には、モデルアーキテクチャ自体に基づく制限があります。
4.3. タスク固有のモデルクラス
Hugging Faceでは、同じ基本的なアーキテクチャを持つ事前訓練済みTransformerモデルでも、異なるタスクに合わせて異なるヘッド(アテンションヘッド)を持つことがあります。例えばシーケンス分類や他のタスクを行う場合に特定のヘッドを使用します。Hugging Faceはこれを自動的に処理してくれます。
例えば、感情分析を行いたい場合、以下のようなコードを使います:
from transformers import AutoModelForSequenceClassificationmodel = AutoModelForSequenceClassification.from_pretrained("sentiment-roberta-large-english", num_labels=2)
ここではAutoModelForSequenceClassification
という特定のクラスを使用しています。これは私たちがシーケンス分類という特定のコンテキストで使用したいからです。同様に、マスク言語モデリングでDistilBERTを使用したい場合はDistilBertForMaskedLM
を使用し、単にDistilBERTの表現を取得したい場合は基本的なモデルを使用します。
別の例として、シーケンス分類にDistilBERTを使用したい場合、以下のように明示的にモデルを指定することもできます:
from transformers import DistilBertForSequenceClassificationmodel = DistilBertForSequenceClassification.from_pretrained("distilbert-base-uncased", num_labels=2)
あるいは、AutoModel
を使用して同様のことを実現することもできます:
from transformers import AutoModelForSequenceClassificationmodel = AutoModelForSequenceClassification.from_pretrained("distilbert-base-uncased", num_labels=2)
これら2つの方法は基本的に同じモデルを取得します。1つはAutoModel
を使用し、もう1つは明示的にDistilBERTを指定しています。分類を行うので、ラベルの数またはクラスの数を実際に指定する必要があります。
4.4. 入力データの渡し方
トークナイザーから得られた入力をモデルに渡す方法について説明します。トークナイザーからモデル入力を取得した後、それをモデルに渡す方法は2つあります。
1つ目の方法は、明示的に各パラメータを指定する方法です。以下のように、入力IDsとアテンションマスクを明示的に渡します:
# オプション1:明示的に引数を指定outputs = model( input_ids=model_inputs["input_ids"], attention_mask=model_inputs["attention_mask"])
2つ目の方法は、Pythonの「アンパック」機能を使う方法です。これにより、モデル入力の辞書キーが自動的に対応する引数にマッピングされます:
# オプション2:辞書をアンパックして渡すoutputs = model(**model_inputs)
この**
構文を使うと、辞書がアンパックされ、キーが同じ名前の引数に自動的にマッピングされます。つまり、input_ids
はinput_ids
引数に、attention_mask
はattention_mask
引数にマッピングされます。
両方の方法は同じ結果をもたらします。2つ目の方法は、コードをより簡潔にする便利な方法です。どちらの方法を選んでも、モデルは同じ入力を受け取り、同じ出力を生成します。
これらの方法を使うことで、トークナイザーの出力をシームレスにモデルに渡すことができ、事前訓練済みモデルを使った推論プロセスが非常にスムーズになります。
4.5. 出力の解釈
モデルからの出力がどのように見えるのか、実際に見てみましょう。入力(トークンIDとアテンションマスク)をモデルに渡すと、出力が得られます。この出力は「logits」と呼ばれるものを含んでいます。例えば、1つの例を渡して2つの潜在的なクラスに分類しようとしている場合、2つのlogitsが得られます。
# モデル出力の例print(outputs.logits)# 例: tensor([[-1.5393, 1.7643]], grad_fn=<AddmmBackward>)
これらのlogitsは、各クラスに対する未正規化のスコアを表しています。バイナリ分類タスクの場合、2つのクラスがあるのは少し奇妙に思えるかもしれませんが(1つのクラスを分類するかしないかを選ぶこともできるはずですが)、Hugging Faceモデルのセットアップ方法によるものです。
さらに、Hugging Faceからロードするモデルは基本的にPyTorchモジュールなので、以前と同じ方法でモデルを使用できます。つまり、loss.backward()
のようなものは、実際に入力に対応する損失に基づいてこの逆伝播ステップを実行します。
ラベル付きデータがあれば、PyTorchのクロスエントロピー関数を使用して損失を計算し、その損失を返してから逆伝播することができます。モデル内で更新されるパラメータを取得することさえできます。これは単に、実際の埋め込み重みの大きなテンソルになります。
Hugging Face自体には、モデルの損失を計算するための簡単な方法もあります。入力文字列をトークン化してモデル入力を取得し、「positive」と「negative」の2つのラベルがあり、それからモデル入力に割り当てるラベルを指定します。これを渡すと、Hugging Faceが提供するモデル出力にはこの損失が含まれています。PyTorchライブラリから追加のものを呼び出すことなく、Hugging Face内でネイティブに損失を計算する非常に簡単な方法です。
最後に、2つのラベル(例:positiveとnegative)がある場合、モデル出力を取得し、logitsを見て、どれが最大かを確認することで、モデルが実際に予測しているラベルを取得できます。argmax
を取ると、最大のインデックスが得られ、それがモデルが予測している出力ラベルになります。
このように、Hugging Face内から分類を行い、損失を取得し、実際のラベルを取得するための非常に簡単な方法が提供されています。
5. モデル内部の調査
5.1. 隠れ状態の確認
モデルの内部を調査する方法もあります。これはNLPモデル内で何が起こっているかを理解しようとしている場合に役立ちます。ここでは、Hugging Face Hubからの事前訓練済みモデルの重みをインポートするとき、「output_attentions=True」と「output_hidden_states=True」という重要な引数を設定します。これらはモデル内部で各時点で何が起きているかを調査するために使用できる重要な引数です。
model = AutoModel.from_pretrained("bert-base-uncased", output_attentions=True, output_hidden_states=True)
次に、モデルをeval(評価)モードに設定し、入力文字列をトークン化します。この場合、勾配について気にする必要はないため、逆伝播は行いません。そして、モデル入力をモデルに渡します。
これにより、モデルの隠れ状態を調査できるようになります。モデル出力の「hidden_states」というプロパティを表示すると、各層での隠れ状態のサイズを確認できます。これにより、各モデル層での形状が分かります。また、各層でのアテンションヘッドのサイズも確認できます。
モデル出力自体を見ると、これらの異なる隠れ状態が大量に出力されます。最後の隠れ状態も確認できます。モデル出力は、隠れ状態がどのように見えるか、そしてアテンション重みがどのように見えるかを示すために非常に堅牢です。特定のモデルを分析しようとしている場合、これは非常に役立つ方法です。
隠れ状態のサイズを理解するには、表示される形状を見るのが役立ちます。例えば、hidden_states[0].shape
を見ると、最初の隠れ層、バッチ、そして最後に768次元の表現が表示されます。これにより、モデルの各層で何が起きているかを詳細に把握することができます。
5.2. アテンション重みの可視化
モデル内の各層におけるアテンション重みを視覚化することもできます。これにより、モデルが各層で何に注目しているかを理解する上で役立ちます。同じモデル入力(例:「hugging face transformers is great」)を使用して、各層での表現がどのように見えるかを確認できます。
具体的には、モデル内の各層と各ヘッドについて、トークン間のアテンション重みを分析できます。これは、モデルの各層において、どのトークンに注目しているかを理解するための良い方法です。
# アテンション重みの可視化例for layer, attn_data in enumerate(model_output.attentions): for head in range(attn_data.size(1)): # 各層、各ヘッドでのアテンション重みを分析 # ...
可視化した結果では、Y軸は異なる層に対応し、X軸はモデル内の異なるアテンションヘッドに対応します。各ヘッドについて、各層でアテンション分布がどのように分布しているか、実際にどのトークンが注目されているかを把握できます。
色の濃淡はアテンション重みの強さを表しています。黄色は高い値(より強いアテンション)を示し、暗い色(ネイビーなど)は値が低い(ほぼゼロ)ことを示します。この視覚化により、モデルが入力の異なる部分にどのように注意を払っているかを直感的に理解することができます。
例えば、特定の層の特定のヘッドが文の特定の部分(例えば、文の主語や目的語)に集中していることがわかるかもしれません。あるいは、一部のヘッドが単語間の文法的関係を捉えている一方で、他のヘッドが意味的関連性を追跡していることなどが観察できるかもしれません。
このようなアテンション重みの可視化は、モデルがどのように決定を下しているかを理解するための貴重な洞察を提供し、モデルの挙動を解釈するのに役立ちます。
5.3. モデルの評価モード
モデルを調査する際に使用するmodel.eval()
について説明します。この関数は、任意のPyTorchモジュールやモデルに対して使用できるもので、モデルを「評価モード」に設定します。これは非常に重要な機能です。
評価モードでは、モデルはトレーニングモードとは異なる動作をします。具体的には、勾配の計算やパラメータの更新を行わないようにします。データを通して勾配を計算したり、モデルを更新したりする必要がない場合、つまり単にモデルを評価するだけの場合には、このモードに設定するのが適切です。
model.eval() # モデルを評価モードに設定
この設定により、トレーニング時に使用される一部の機能(ドロップアウトやバッチ正規化の振る舞いなど)が無効化され、推論時により効率的に動作するようになります。例えば、ドロップアウト層は評価モードでは無効になり、すべてのニューロンが活性化されます。
質問にあったように、事前訓練済みのモデルをそのまま評価できるのかという点については、はい、できます。これはすでに事前訓練されたモデルであり、ファインチューニングをしていなくても評価することは可能です。評価モードに設定することで、モデルの動作をより効率的に分析することができます。
モデルの調査を行う際には、通常、勾配の計算は必要ないため、model.eval()
を使用することでモデルの挙動をより正確に把握できます。特にアテンション重みや隠れ状態を分析する場合には、この設定が重要になります。
6. ファインチューニング
6.1. IMDbデータセットの準備
ここから、モデルのファインチューニングについて説明していきます。プロジェクトでは、モデルをファインチューニングしたいことが多いでしょう。その方法の例を紹介します。
Hugging Faceには、モデルだけでなく便利なデータセットも用意されています。これらを読み込んで使用することができます。ここでは、IMDbデータセットを使用した例を見ていきます。
まず、最初の50トークンだけを見るようにします。以下は、出力を切り詰めるためのヘルパー関数です:
def truncate_output(output): # 出力を最初の50トークンに制限するヘルパー関数 # ...
次に、データセットを作成するために、Hugging Faceのdatasets
ライブラリからDatasetDict
クラスを使用します。これにより、トレーニングデータセットと検証データセットを含む小さなデータセットを作成できます:
from datasets import DatasetDict# 小さなデータセットを作成mini_dataset = DatasetDict({ 'train': imdb_train.shuffle().select(range(128)), 'validation': imdb_train.shuffle().select(range(128, 128 + 32))})
このデモンストレーションでは、IMDbの訓練データセットからトレーニングと検証の両方のデータを取得します。データをシャッフルして、最初の128例をトレーニング用に、次の32例を検証用に選択します。また、効率的に実行できるように、また実際にCPUで実行できるように、これらの入力を切り詰めます。
次に、このデータセットがどのように見えるか確認できます。これは基本的に辞書のようなもので、トレーニングデータセットと検証データセットをラップしたクラスです。最初の10個のエントリを見ると、テキスト(映画レビュー)とそれに対応するラベル(ポジティブかネガティブか)が含まれた辞書が返されます。ラベルでは、1がポジティブレビュー、0がネガティブを表しています。これにより、感情分析に非常に簡単に使用できるようになっています。
6.2. データの前処理
データセットを準備した後、次はデータの前処理を行います。このステップでは、テキストデータをモデルが使用できる形式に変換します。Hugging Faceのデータセットには、データの前処理を簡単に行うためのmap
関数が用意されています。
# データセットを準備して16のバッチにするtokenized_dataset = mini_dataset.map( lambda examples: tokenizer( examples["text"], padding=True, truncation=True ), batched=True, batch_size=16)
ここでのmap
関数は、データセット内の各例に対してラムダ関数を適用します。このラムダ関数は、テキストをトークン化するものです。基本的に、各例のテキストをトークン化し、必要に応じてパディングと切り詰めを追加します。これをバッチ処理で行い、バッチサイズは16に設定しています。
次に、データセットの形式を少し修正します:
# 不要な列を削除し、ラベル列の名前を変更tokenized_dataset = tokenized_dataset.remove_columns(["text"])tokenized_dataset = tokenized_dataset.rename_column("label", "labels")# PyTorchテンソル形式に設定tokenized_dataset.set_format("torch")
ここでは、「text」列を削除しています。これは、すでにテキストを前処理してinput_idsに変換したため、元のテキスト列はもう必要ないからです。また、「label」という列名を「labels」に変更しています。最後に、データセットの形式をPyTorchに設定して、モデルに直接渡せるようにしています。
処理後のデータセットを確認すると、各レビューに対応する2つのラベルと入力IDsが含まれていることがわかります。また、アテンションマスクも含まれています。基本的に、トークナイザーから得られる結果がデータセットに追加され、モデルに簡単に渡せるようになっています。
これらの前処理ステップにより、生のテキストデータがモデルが処理できる形式に変換され、トレーニングの準備が整います。
6.3. バッチ処理の設定
データの前処理が完了したら、効率的なトレーニングのためにバッチ処理を設定する必要があります。先ほどの前処理ステップでは、すでにバッチサイズ16でデータをトークン化しましたが、ここではトレーニング時のバッチ処理について説明します。
バッチ処理には主に二つの考慮点があります。一つは、すべてのシーケンスが同じ長さになるようにパディングすることです。もう一つは、効率的なメモリ使用のためにデータをバッチに分けることです。
トークン化の際にpadding=True
を設定することで、各バッチ内で最も長いシーケンスに合わせて他のシーケンスにパディングが追加されます。これにより、バッチ内のすべての例が同じ長さになります。特定のバッチ内で処理するだけなので、データセット全体を同じ長さにパディングする必要はありません。
また、切り詰め(truncation)についても同様です。truncation=True
を設定することで、モデルの最大長を超えるシーケンスは自動的に切り詰められます。あるいは、手動で高い切り詰め制限を設定することもできます。
バッチサイズの選択は、使用可能なメモリとトレーニングの効率性のバランスによって決まります。大きなバッチサイズはより安定した勾配を提供しますが、より多くのメモリを必要とします。このデモでは16を選択していますが、実際のプロジェクトでは、ハードウェアやデータセットのサイズに基づいて調整する必要があるかもしれません。
パディングと入力IDの処理は自動的に行われるため、トークナイザーの出力からinput_idsとattention_maskを取得し、それをデータセットに追加するだけで済みます。これらはモデルトレーニング時に直接使用されます。
6.4. データローダーの作成
データセットの準備が完了したら、次はPyTorchのDataLoaderを使ってデータをトレーニングに適した形式に変換します。DataLoaderはバッチ単位でデータをロードし、トレーニングループで効率的に使用できるようにします。
from torch.utils.data import DataLoader# データローダーの作成train_dataloader = DataLoader( tokenized_dataset["train"], batch_size=16, shuffle=True)eval_dataloader = DataLoader( tokenized_dataset["validation"], batch_size=16)
ここでは、通常のPyTorchのDataLoaderをインポートし、先ほど作成したトークン化されたデータセットをロードしています。トレーニングデータセットと検証データセットの両方に対してDataLoaderを作成し、バッチサイズを16に指定しています。
トレーニングデータローダーではshuffle=True
を設定して、エポックごとにデータがランダムな順序で提供されるようにしています。これはモデルが特定の順序に過適合するのを防ぐのに役立ちます。一方、評価データローダーではシャッフルは必要ありません。
これらのDataLoaderを使用することで、トレーニングループ内でバッチを簡単に反復処理できます。各バッチには、入力IDs、アテンションマスク、およびラベルが含まれており、これらをモデルに直接渡すことができます。
DataLoaderはPyTorchのトレーニングパイプラインの重要な部分であり、大規模なデータセットでも効率的にメモリを使用しながらトレーニングを行うことができます。これで、モデルのトレーニングに必要なすべてのデータ準備ステップが完了しました。
7. モデルのトレーニング
7.1. PyTorchによる直接トレーニング
モデルのトレーニングは、通常のPyTorchでのトレーニングとまったく同じ方法で行うことができます。損失を計算し、逆伝播させるといった通常のプロセスを踏みます。トレーニングの設計方法は基本的にあなた次第です。
Hugging Faceのモデルは単なるPyTorchモジュールなので、標準的なPyTorchトレーニングループを使用できます。以下は基本的なトレーニングループの例です:
# シーケンス分類用のモデルをロードmodel = AutoModelForSequenceClassification.from_pretrained("distilbert-base-uncased", num_labels=2)# エポック数と訓練ステップ数を設定num_epochs = 3num_training_steps = num_epochs * len(train_dataloader)# オプティマイザと学習率スケジュールを初期化optimizer = AdamW(model.parameters(), lr=5e-5)lr_scheduler = get_linear_schedule_with_warmup( optimizer, num_warmup_steps=0, num_training_steps=num_training_steps)# トレーニングループmodel.train()for epoch in range(num_epochs): for batch in train_dataloader: # バッチをGPUに移動(必要に応じて) batch = {k: v.to(device) for k, v in batch.items()} # 順伝播 outputs = model(**batch) loss = outputs.loss # Hugging Faceモデルは自動的に損失を計算 # 逆伝播 loss.backward() # パラメータの更新 optimizer.step() lr_scheduler.step() optimizer.zero_grad()
この例では、Transformersパッケージから特定のオプティマイザータイプをインポートしています。ここではAdamW
を使用していますが、Transformersパッケージには他のオプティマイザも用意されています。また、学習率を時間とともに減少させる線形スケジュールも使用できます。
コードの構造を見ると、分類用のモデルをロードし、エポック数とトレーニングステップ数を設定して、オプティマイザと学習率スケジュールを初期化しています。その後、通常のPyTorchモデルと同様に、モデルをトレーニングモードにセットし、バッチをデータローダーから受け取り、逆伝播してオプティマイザを更新しています。
これは基本的に通常のPyTorchでの手順と同じであり、Hugging Faceモデルとの互換性があります。慣れているならPyTorchでのトレーニング方法をそのまま使用できるというのは大きな利点です。
7.2. Transformersのオプティマイザー
Transformersパッケージには、特定の種類のオプティマイザーをインポートすることができます。例えば、AdamW
というオプティマイザーがあります。これは重み減衰を行うAdamオプティマイザーのバージョンで、Transformerモデルのトレーニングに一般的に使用されます。
from transformers import AdamW# オプティマイザーの初期化optimizer = AdamW(model.parameters(), lr=5e-5)
このAdamW
オプティマイザーは、標準的なAdamオプティマイザーに重み減衰正則化を追加したものです。重み減衰はモデルの複雑さを減らし、過学習を防ぐのに役立ちます。
TransformersパッケージのAdamW
はPyTorchのAdam
と似ていますが、特にTransformerモデルのトレーニングに最適化されています。学習率、ベータ値、イプシロン、重み減衰など、様々なパラメータをカスタマイズできます。
optimizer = AdamW( model.parameters(), lr=5e-5, # 学習率 betas=(0.9, 0.999), # Adamのベータパラメータ eps=1e-8, # 数値安定性のための小さな値 weight_decay=0.01 # 重み減衰の強さ)
これらのパラメータは、モデルのサイズ、データセットの性質、トレーニングの目標に基づいて調整することができます。一般的には、Transformerモデルのファインチューニングには小さな学習率(1e-5から5e-5の範囲)が推奨されています。
AdamW
オプティマイザーはTransformerモデルのファインチューニングに広く使用されており、多くの場合、優れた結果を得ることができます。適切なオプティマイザーの選択と設定は、モデルのパフォーマンスに大きな影響を与えることがあります。
7.3. 学習率スケジューラー
Transformersパッケージからは、学習率スケジューラーをインポートすることもできます。学習率スケジューラーは、トレーニング中の各ステップで学習率を調整することができます。例えば、線形スケジューラーを使用すると、時間の経過とともに学習率を段階的に減少させることができます。
from transformers import get_linear_schedule_with_warmup# 学習率スケジューラーの初期化lr_scheduler = get_linear_schedule_with_warmup( optimizer, num_warmup_steps=0, num_training_steps=num_training_steps)
このget_linear_schedule_with_warmup
関数は、最初のウォームアップフェーズの後に線形に学習率を減少させるスケジューラーを作成します。num_warmup_steps
パラメータは、学習率が最大値に達するまでの訓練ステップ数を指定します。num_training_steps
は、トレーニングの総ステップ数で、通常はエポック数とバッチ数の積として計算されます。
ウォームアップフェーズでは、学習率は0から指定した最大値まで徐々に増加します。これにより、トレーニングの初期段階での急激なパラメータ更新が避けられ、より安定したトレーニングが可能になります。ウォームアップ後は、学習率は線形に減少し、トレーニングの終わりには0に近づきます。
このスケジューラーは、オプティマイザーのステップの後に以下のように呼び出されます:
# トレーニングループ内optimizer.step()lr_scheduler.step()optimizer.zero_grad()
適切な学習率スケジュールの使用は、トレーニングの収束を加速し、最終的なモデルのパフォーマンスを向上させるのに役立ちます。特に大規模なTransformerモデルでは、学習率のスケジューリングが重要です。
8. Trainerクラスの活用
8.1. トレーニング引数の設定
PyTorchが好きなら、前述の方法でトレーニングを行うことができますが、Hugging FaceにはTrainer
クラスという別のオプションもあります。これを使うとさらに簡単にトレーニングが行えます。先ほどのデータセット作成と同じ方法でデータを準備した後、Hugging FaceのTrainingArguments
クラスをインポートします。
このTrainingArguments
クラスは、トレーニング時に使用したいすべての設定をまとめた辞書のようなものです。さらに、トレーニングを自動的に処理してくれるTrainer
クラスもインポートします。
from transformers import TrainingArguments, Trainer# トレーニング引数の設定training_args = TrainingArguments( output_dir="./results", # 結果を保存するディレクトリ per_device_train_batch_size=16, # トレーニング時のバッチサイズ per_device_eval_batch_size=16, # 評価時のバッチサイズ num_train_epochs=3, # トレーニングのエポック数 evaluation_strategy="epoch", # エポックごとに評価を行う learning_rate=5e-5, # 学習率 weight_decay=0.01, # 重み減衰)
TrainingArguments
には、モデルのトレーニングに関するあらゆる側面を制御するための多数のパラメータがあります。例えば:
output_dir
: ログやチェックポイントを保存する場所per_device_train_batch_size
: トレーニング中のデバイスあたりのバッチサイズ(複数GPUを使用する場合に便利)num_train_epochs
: トレーニングするエポック数evaluation_strategy
: どのようにモデルを評価するか(エポックごと、ステップごとなど)learning_rate
: 学習率- その他多数の設定(ウォームアップステップ、ウォームアップ比率、重み減衰など)
ドキュメントを確認すると、設定できる様々な引数が紹介されています。基本的には、先ほどの明示的なPyTorchメソッドで使用したのと同じ引数をここでも使用できます。これらの引数をTrainer
に渡すことで、トレーニングプロセス全体が自動的に管理されます。
8.2. コールバック機能
Trainerクラスは、トレーニングプロセス中に特定の時点で追加の処理を実行するためのコールバック機能も提供しています。コールバックを使用すると、トレーニングプロセス中に何か特別なことを行いたい場合に役立ちます。例えば、各エポック後に検証セットでモデルを評価したり、何らかの出力を保存したりする場合などです。
# コールバックの例from transformers import TrainerCallbackclass LoggingCallback(TrainerCallback): def on_epoch_end(self, args, state, control, **kwargs): # エポック終了時に実行されるコード print(f"Epoch {state.epoch} completed")
このようなカスタムコールバックを作成したら、Trainerのインスタンス化時にコールバックとして渡すことができます:
trainer = Trainer( model=model, args=training_args, train_dataset=tokenized_dataset["train"], eval_dataset=tokenized_dataset["validation"], tokenizer=tokenizer, compute_metrics=compute_metrics, callbacks=[LoggingCallback()] # コールバックをリストとして渡す)
Hugging Faceには、すでに用意されているコールバックもいくつかあります。例えば、LoggingCallback
はトレーニングプロセス自体に関する情報をログに記録するだけのシンプルなものです。
これはあまり重要ではありませんが、トレーニング中にコールバックを使用して何か特別な処理を行いたい場合には、このような方法を使うことができます。コールバックは、トレーニングプロセスをより柔軟に制御したり、トレーニング中のモデルの状態を監視したりするための強力なツールです。
8.3. 早期停止の実装
トレーニング中に早期停止を実装することもできます。早期停止は、その名前が示す通り、モデルが何も学習していない場合や、複数のエポックが経過しても改善が見られない場合に、モデルのトレーニングを早期に終了させるものです。これにより、計算時間を無駄にすることなく、結果をより早く確認することができます。
from transformers import EarlyStoppingCallback# 早期停止コールバックの作成early_stopping_callback = EarlyStoppingCallback( early_stopping_patience=3, # 改善がなくても待機するエポック数 early_stopping_threshold=0.01 # 改善とみなすための最小変化量)# Trainerにコールバックとして追加trainer = Trainer( model=model, args=training_args, train_dataset=tokenized_dataset["train"], eval_dataset=tokenized_dataset["validation"], tokenizer=tokenizer, compute_metrics=compute_metrics, callbacks=[early_stopping_callback])
EarlyStoppingCallback
の主要なパラメータはearly_stopping_patience
で、これは改善がなくても何エポック待つかを指定します。例えば、値が3の場合、3エポック連続で評価メトリクス(通常は検証損失)に改善が見られなければ、トレーニングは停止します。
患者値の適切な選択については、モデルのアーキテクチャに依存するというよりは、かなり裁量に任されています。小さい値(例:2〜3)では、トレーニングが早く終了しますが、モデルが一時的な停滞を乗り越える前に停止してしまう可能性があります。大きい値(例:5〜10)では、モデルがより長く学習できますが、実際に必要以上にトレーニングする可能性があります。
早期停止は、モデルの過学習を防いだり、トレーニング時間を短縮したりするのに役立つ重要なテクニックです。特に、モデルのハイパーパラメータを調整する際や、複数のモデルをテストする際に便利です。
8.4. モデルの評価と予測
モデルのトレーニングが完了したら、簡単にモデルを評価することができます。トレーナークラスは、モデルを評価するための便利なメソッドを提供しています。
# モデルの評価eval_results = trainer.evaluate()print(f"Evaluation results: {eval_results}")
trainer.evaluate()
を呼び出すと、初期化時に指定した評価データセット(この場合は検証データセット)でモデルが評価されます。評価結果は、損失やその他のメトリクス(コンピュートメトリクス関数で定義したもの)を含む辞書として返されます。
また、新しいデータでの予測も非常に簡単です。trainer.predict()
メソッドを使用すると、指定したデータセットに対する予測を取得できます:
# 予測の実行
predictions = trainer.predict(tokenized_dataset["validation"])
このメソッドは、トークン化されたデータセット(ここでは検証データセット)に対する予測を返します。返される予測には、モデルからのログ、ラベルの真値、そして任意のメトリクスが含まれます。
# 予測結果の内容print(f"Predictions shape: {predictions.predictions.shape}")print(f"Label ids shape: {predictions.label_ids.shape}")print(f"Metrics: {predictions.metrics}")
これらの予測結果を使って、モデルの性能をさらに分析したり、特定の例での予測を確認したりすることができます。例えば、混同行列を作成したり、誤って分類された例を調査したりできます。
予測機能は、トレーニング済みモデルをデプロイしたり、新しいデータに対する推論を行ったりする際にも役立ちます。トレーナークラスはこれらの機能を簡単に利用できるようにし、機械学習ワークフローのこの部分を大幅に簡素化します。
8.5. チェックポイントの保存と読み込み
トレーニング中、Trainerクラスは自動的にチェックポイントを保存します。これらのチェックポイントは、TrainingArgumentsで指定したoutput_dir
に保存されます。トレーニングが進むにつれて、定期的にモデルの状態が保存されるため、トレーニングが途中で中断されても、後から再開することができます。
# トレーニング開始(チェックポイントは自動的に保存される)trainer.train()
トレーニング実行中は、output_dir
に様々なチェックポイントが保存されていることが確認できます。例えば、「checkpoint-8」というフォルダが見つかるかもしれません。これは、8番目のチェックポイントを表しています。
後でモデルを再度使用したい場合は、そのチェックポイントからモデルを簡単に読み込むことができます:
# 保存したチェックポイントからモデルを読み込むfrom transformers import AutoModelForSequenceClassificationcheckpoint_path = "./results/checkpoint-8" # チェックポイントへのパスloaded_model = AutoModelForSequenceClassification.from_pretrained(checkpoint_path)loaded_tokenizer = AutoTokenizer.from_pretrained(checkpoint_path)
このコードでは、チェックポイントフォルダへのパスを指定して、そこからモデルとトークナイザーを読み込んでいます。これにより、前回のトレーニング状態から正確にモデルを復元できます。
チェックポイントの保存と読み込みは、長時間のトレーニングを行う場合や、トレーニング済みモデルを共有したい場合に特に重要です。また、異なるハイパーパラメータで複数のモデルをトレーニングし、最良の結果を選択する際にも役立ちます。
9. 補足情報
9.1. テキスト生成
Hugging Faceライブラリでは、テキスト生成に関する追加の機能も提供されています。テキスト生成は、GPT-2のようなデコーダーベースのモデルや、BARTやT5のようなエンコーダー・デコーダーモデルで実行できます。
テキスト生成のためには、専用のモデルクラスを使用します。例えば、GPT-2モデルを使ったテキスト生成は以下のように行えます:
from transformers import GPT2LMHeadModel, GPT2Tokenizer# モデルとトークナイザーのロードmodel = GPT2LMHeadModel.from_pretrained("gpt2")tokenizer = GPT2Tokenizer.from_pretrained("gpt2")# 入力テキストのトークン化input_text = "Once upon a time,"input_ids = tokenizer.encode(input_text, return_tensors="pt")# テキスト生成output = model.generate( input_ids, max_length=50, num_return_sequences=1, no_repeat_ngram_size=2, temperature=0.7)# 生成されたテキストのデコードgenerated_text = tokenizer.decode(output[0], skip_special_tokens=True)print(generated_text)
テキスト生成では、様々なパラメータを調整することができます:
max_length
: 生成するテキストの最大長num_return_sequences
: 返す生成シーケンスの数no_repeat_ngram_size
: 繰り返しを防ぐためのn-gramサイズtemperature
: 生成の多様性を制御(高い値=より多様、低い値=より決定論的)top_p
/top_k
: 次のトークンの選択肢を制限するためのサンプリング戦略
テキスト生成は、ストーリーの続きを書く、質問に回答する、対話システムを作成するなど、様々な用途に活用できます。Hugging Faceの生成APIは柔軟で、多様なテキスト生成タスクに対応できるよう設計されています。
9.2. カスタムデータセットの定義
Hugging Faceでは、独自のカスタムデータセットを定義して使用することもできます。標準的なデータセットだけでなく、特定のニーズに合わせた独自のデータを使用したい場合に役立ちます。
カスタムデータセットを作成するには、基本的にPyTorchのDataset
クラスを拡張するか、Hugging Faceのdatasets
ライブラリを使用します。以下は、カスタムデータセットを作成する例です:
from torch.utils.data import Datasetclass CustomTextDataset(Dataset): def __init__(self, texts, labels, tokenizer, max_length): self.texts = texts self.labels = labels self.tokenizer = tokenizer self.max_length = max_length def __len__(self): return len(self.texts) def __getitem__(self, idx): text = self.texts[idx] label = self.labels[idx] encoding = self.tokenizer( text, truncation=True, max_length=self.max_length, padding="max_length", return_tensors="pt" ) # バッチ次元を削除 return { "input_ids": encoding["input_ids"].squeeze(), "attention_mask": encoding["attention_mask"].squeeze(), "labels": label }
このカスタムデータセットを使用するには、テキストとラベルのリスト、トークナイザー、最大長を渡して初期化します:
# カスタムデータセットの作成
custom_dataset = CustomTextDataset(
texts=["I love this movie", "This movie is terrible"],
labels=[1, 0], # 1=ポジティブ、0=ネガティブ
tokenizer=tokenizer,
max_length=128
)
あるいは、CSVファイルやJSONファイルなどから直接データを読み込むこともできます:
import pandas as pd# CSVからデータを読み込むdf = pd.read_csv("my_data.csv")texts = df["text"].tolist()labels = df["label"].tolist()custom_dataset = CustomTextDataset(texts, labels, tokenizer, max_length=128)
カスタムデータセットを定義することで、自分のドメイン固有のデータを使用してモデルをトレーニングしたり、特定のタスクに合わせてデータを前処理したりすることができます。これは、実世界の問題に取り組む際に特に重要です。
9.3. パイプラインインターフェース
Hugging Faceには、「パイプライン」と呼ばれる、さらに簡単にモデルを使用するためのインターフェースがあります。パイプラインは、事前訓練済みモデルを使って様々なNLPタスクを非常に簡単に実行するための抽象化レイヤーです。
パイプラインインターフェースを使用すると、トークナイザーの設定やモデルへの入力の渡し方などの低レベルな詳細を気にすることなく、高レベルのAPIでモデルを使用できます。以下は、感情分析のためのパイプラインの例です:
from transformers import pipeline# 感情分析パイプラインの作成sentiment_analyzer = pipeline("sentiment-analysis")# テキストの分析result = sentiment_analyzer("I really enjoyed this movie, it was fantastic!")print(result)# 出力例: [{'label': 'POSITIVE', 'score': 0.9998}]
パイプラインは多くのタスクに対応しています:
- テキスト分類(「sentiment-analysis」など)
- トークン分類(「ner」=固有表現認識など)
- 質問応答(「question-answering」)
- テキスト生成(「text-generation」)
- テキスト補完(「text-infilling」)
- 要約(「summarization」)
- 翻訳(「translation」)
- 特徴抽出(「feature-extraction」)
特定のモデルを使いたい場合は、パイプラインにモデル名を指定することもできます:
classifier = pipeline( "sentiment-analysis", model="distilbert-base-uncased-finetuned-sst-2-english")
パイプラインインターフェースは、特にプロトタイピングやクイックテストに非常に便利です。複雑なコードを書かなくても、すぐにモデルの能力を試すことができます。また、実験からプロダクションへの移行をスムーズにするためのブリッジとしても機能します。
9.4. マスク言語モデリング
Hugging Faceでは、マスク言語モデリング(MLM)のような特定のタスクにも対応しています。マスク言語モデリングは、BERTのような双方向エンコーダーモデルのプレトレーニングに使用された手法で、テキスト内の一部の単語をマスクし、モデルにそれを予測させるというものです。
マスク言語モデリングをHugging Faceで実行するには、専用のモデルクラスを使用します:
from transformers import BertForMaskedLM, BertTokenizer# モデルとトークナイザーのロードmodel = BertForMaskedLM.from_pretrained("bert-base-uncased")tokenizer = BertTokenizer.from_pretrained("bert-base-uncased")# テキストの準備([MASK]トークンを含む)text = "The capital of France is [MASK]."inputs = tokenizer(text, return_tensors="pt")# マスクされた位置の予測outputs = model(**inputs)prediction_scores = outputs.logits# マスクトークンの位置を特定mask_token_index = (inputs.input_ids == tokenizer.mask_token_id)[0].nonzero(as_tuple=True)[0]# 最も可能性の高いトークンを取得predicted_token_id = prediction_scores[0, mask_token_index].argmax(axis=-1)predicted_token = tokenizer.decode(predicted_token_id)print(f"予測された単語: {predicted_token}")# 出力例: 予測された単語: paris
マスク言語モデリングは以下のような用途に活用できます:
- テキスト補完や候補の提案
- 文脈に基づく単語の選択肢の生成
- 言語理解能力のテスト
- データ拡張(テキストの一部をモデルの予測で置き換える)
また、パイプラインインターフェースを使って、さらに簡単にマスク言語モデリングを実行することもできます:
from transformers import pipelinefill_mask = pipeline("fill-mask")results = fill_mask("The capital of France is <mask>.")for result in results: print(f"トークン: {result['token_str']}, スコア: {result['score']:.4f}")
マスク言語モデリングは、テキストの理解や生成において基本的かつ強力なツールであり、Hugging Faceの柔軟なAPIを通じて簡単にアクセスできます。