はじめに
今回は [LLMのFinetuningのための基礎] transformersのAutoClassesの基本を理解する 1 と題しまして、transformersのAutoTokenizer・AutoConfigに関して学習したことをまとめました。
もともとはAutoTokenizerだけにしようかと思っていましたが、AutoConfigは切って離せずの関係性だったのでまとめて記事にしました。
今回メインで使用する教材はTransformersのAutoClassesのAPI referenceです。
個人的アウトプットのイメージですが、せっかく前回、前々回とアウトプットとしてqiita記事にしていたのでシリーズ化にでもしようかなと思っています。(どこまで読者の方の参考になるかは分かりませんが、、、)
以下、現段階でのアウトプットの記事のイメージ図です。
AutoClassの基本的内容を抑えた記事を書いたあとにどのようなことを書くのかはまだ検討中です。。。
(無理のない範囲で学習目的で書いていこうかなと思っています。)
LLM事前知識・datasetsの基本の理解については下記記事に記載されています。よろしければ是非一読お願いいたします。
おことわり
本記事はあくまでもLLM初学者である私の学習のアウトプットなので不正確・不十分な説明の可能性もあるため参考にされる場合は十分にご注意ください。
目次
- 1. AutoClassesとは
- 2. AutoConfigとは
- 3. AutoTokenizerとは
- 4. おわりに
AutoClassesとは
AutoClassesとはTransformers APIが提供している主要なクラスの一つです。
HuggingFace上に公開されているほとんどの事前学習済みモデルを、MODEL IDを指定するだけでそのモデルの情報を自動的にロードし、すぐに使える状態にすることができます。
AutoClassesは大きく3つのコンポーネントに分けられます。
- 1. AutoConfig
- 2. AutoTokenizer
- 3. AutoModel
それぞれが何をロードするものなのかを簡単に説明すると、
- AutoConfig --> モデルのアーキテクチャ(構造)を定義するための設定情報
- AutoTokenizer --> トークナイザーの構造
- AutoModel --> モデルの構造
上記は非常に簡易的説明ですが、次以降でより詳しく見ていきます。
注意1
本記事で触れるのはAutoConfigとAutoTokenizerのみです。
AutoModelについては次回触れます。
注意2
上記では簡単に、「MODEL IDを指定するだけで」 と述べていますがその他にも、モデルの情報へのローカルパスなどでもロードすることができます。
ロード対象
ロードする対象はHuggingFace hubのモデルカードで確認できます。
例えば google-bert/bert-base-uncased の場合はこちらで確認できます。
AutoConfigとは
AutoConfigとは、MODEL ID もしくは ローカルパスの情報から、関連するモデルの config.json ファイルを特定・ロードし、その内容に基づいて適切な PretrainedConfig のサブクラスのインスタンス(設定オブジェクト)を生成・返却するクラスです。
つまり、AutoConfig が提供するのは、PretrainedConfigクラスを継承した具体的な設定クラス(例: BertConfig, GPT2Config)のインスタンスです。
PretrainedConfigとは何か。
これは、事前学習済みモデルのアーキテクチャやハイパーパラメータといった構成情報を扱うための抽象化クラスです。設定情報をファイル (config.json) からロードしたり、ファイルへ保存したり、Pythonの辞書形式に変換したりするための共通メソッドを実装しています。
これを継承した各Configクラスは各モデルごとの固有の属性を付与することが可能になっています。
基本的に全てのConfigで共通の属性としてはhidden_size、num_attention_heads、num_hidden_layersの3つであり、テキストモデルの場合はvocab_sizeが加わります。
各モデルごとの固有の属性とは?
AutoClassesのreferenceには、次の様に記載があります。
各タスクごと、そして各バックエンド(PyTorch、TensorFlow、またはFlax)ごとにAutoModelのクラスが存在します。
この説明通り、Transformersで扱うことのできるモデルにはそれぞれに異なる背景が存在し、それらを各モデルごとの固有の属性とここでは読んでいます。
この様な実装がされていることはPretrainedConfigの Parameters の部分に PyTorch specific parameters や TensorFlow specific parameters といった記載があることからも確認ができます。
実際に見てみる
説明文を見ただけではなかなか理解しにくいです。
実際にロードして中身を確かめてみます。
今回扱う環境はGoogle Colabで、モデルにはgoogle-bert/bert-base-uncasedを使用します。
from transformers import AutoConfig
model_name = "google-bert/bert-base-uncased"
config = AutoConfig.from_pretrained(model_name)
実行するとプログレスバーが表示され、config.jsonがロードされていることが分かります。

中身を確認してみます。
print(config)
# 出力結果:
#
# BertConfig {
# "architectures": [
# "BertForMaskedLM"
# ],
# "attention_probs_dropout_prob": 0.1,
# "classifier_dropout": null,
# "gradient_checkpointing": false,
# "hidden_act": "gelu",
# "hidden_dropout_prob": 0.1,
# "hidden_size": 768,
# "initializer_range": 0.02,
# "intermediate_size": 3072,
# "layer_norm_eps": 1e-12,
# "max_position_embeddings": 512,
# "model_type": "bert",
# "num_attention_heads": 12,
# "num_hidden_layers": 12,
# "pad_token_id": 0,
# "position_embedding_type": "absolute",
# "transformers_version": "4.51.3",
# "type_vocab_size": 2,
# "use_cache": true,
# "vocab_size": 30522
# }
この出力結果をみると、BertConfigというクラスであり、その中にはnum_attention_headsやvocab_sizeと言ったようなモデルの構成情報が含まれていることが分かります。
また、上記の結果からは分かりませんがdir(config)などを実行すると、push_to_hub()などの関数も実装されていることが分かり、PretrainedConfigを継承していると理解できます。
AutoTokenizerとは
AutoTokenizerはテキストの前処理(トークン化やトークンID化など)を行う為のルールや語彙、それを行うトークナイザーをロードします。
AutoTokenizerについて理解するために次の段階を踏んで確認を行います。
- 1. 何がロードされるのか
- 2. どう使うのか
- 3. 何が出力されるのか
何がロードされるのか
実際にコードを実行してロードされるものを確認してみます。
from transformers import AutoTokenizer
model_name = "google-bert/bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_name)
結果:
セルの出力から今回の場合は、tokenizer_config.json、vocab.txt、tokenizer.jsonの3つがロードされていることが分かります。
それぞれの中身を軽く確認してみます。コメントアウト部分が標準出力の結果です。
import json
with open("/root/.cache/huggingface/hub/models--google-bert--bert-base-uncased/snapshots/86b5e0934494bd15c9632b12f734a8a67f723594/vocab.txt", "r") as f:
vocab_txt = f.read()
with open("/root/.cache/huggingface/hub/models--google-bert--bert-base-uncased/snapshots/86b5e0934494bd15c9632b12f734a8a67f723594/tokenizer.json", "r") as f:
tokenizer_json = json.load(f)
with open("/root/.cache/huggingface/hub/models--google-bert--bert-base-uncased/snapshots/86b5e0934494bd15c9632b12f734a8a67f723594/tokenizer_config.json", "r") as f:
tokenizer_config_json = json.load(f)
print(vocab_txt[:100])
# [PAD]
# [unused0]
# [unused1]
# [unused2]
# [unused3]
# [unused4]
# [unused5]
# [unused6]
# [unused7]
# [unused8]
# [unu
print(tokenizer_json.keys())
# dict_keys(['version', 'truncation', 'padding', 'added_tokens', 'normalizer', 'pre_tokenizer', 'post_processor', 'decoder', 'model'])
print(tokenizer_config_json.keys())
# dict_keys(['do_lower_case', 'model_max_length'])
これらは前処理用のトークナイザーに関連する重要な情報を含んだファイルです。
vocab.txt
vocab.txtはWordPieceに合わせた語彙情報テキストファイルであり、この部分はTransformers で使用される3つの主要なトークナイザーByte-Pair Encoding (BPE)、WordPiece、SentencePieceで若干変わってきます。
例えば、GPT2ではBPEが使用されており、この場合はvocab.txtではなくvocab.josnとmerges.txtが使用されています。
tokenizer.json
tokenizer.jsonはトークナイザーパイプラインの一連の処理に関する情報を含んだファイルです。
中身をもう少し詳しく見てみます。
from pprint import pprint
pprint(tokenizer_json["version"])
# 1.0
pprint(tokenizer_json["truncation"])
# null
pprint(tokenizer_json["padding"])
# null
pprint(tokenizer_json["added_tokens"])
# [{'id': 0,
# 'special': True,
# 'content': '[PAD]',
# 'single_word': False,
# 'lstrip': False,
# 'rstrip': False,
# 'normalized': False},
# {'id': 100,
# 'special': True,
# 'content': '[UNK]',
# 'single_word': False,
# 'lstrip': False,
# 'rstrip': False,
# 'normalized': False},
# {'id': 101,
# 'special': True,
# 'content': '[CLS]',
# 'single_word': False,
# 'lstrip': False,
# 'rstrip': False,
# 'normalized': False},
# {'id': 102,
# 'special': True,
# 'content': '[SEP]',
# 'single_word': False,
# 'lstrip': False,
# 'rstrip': False,
# 'normalized': False},
# {'id': 103,
# 'special': True,
# 'content': '[MASK]',
# 'single_word': False,
# 'lstrip': False,
# 'rstrip': False,
# 'normalized': False}]
pprint(tokenizer_json["normalizer"])
# {'type': 'BertNormalizer',
# 'clean_text': True,
# 'handle_chinese_chars': True,
# 'strip_accents': None,
# 'lowercase': True}
pprint(tokenizer_json["pre_tokenizer"])
# {'type': 'BertPreTokenizer'}
pprint(tokenizer_json["post_processor"])
# {'pair': [{'SpecialToken': {'id': '[CLS]', 'type_id': 0}},
# {'Sequence': {'id': 'A', 'type_id': 0}},
# {'SpecialToken': {'id': '[SEP]', 'type_id': 0}},
# {'Sequence': {'id': 'B', 'type_id': 1}},
# {'SpecialToken': {'id': '[SEP]', 'type_id': 1}}],
# 'single': [{'SpecialToken': {'id': '[CLS]', 'type_id': 0}},
# {'Sequence': {'id': 'A', 'type_id': 0}},
# {'SpecialToken': {'id': '[SEP]', 'type_id': 0}}],
# 'special_tokens': {'[CLS]': {'id': '[CLS]', 'ids': [101], 'tokens': ['[CLS]']},
# '[SEP]': {'id': '[SEP]',
# 'ids': [102],
# 'tokens': ['[SEP]']}},
# 'type': 'TemplateProcessing'}
pprint(tokenizer_json["decoder"])
# {'type': 'WordPiece', 'prefix': '##', 'cleanup': True}
pprint(tokenizer_json["model"].keys()) # vocabの量が多すぎるので keys()
# dict_keys(['unk_token', 'continuing_subword_prefix', 'max_input_chars_per_word', 'vocab'])
ご覧の通り、正規化やpre-tokenization等の情報が含まれていることが分かります。
tokenizer_config.json
tokenizer.jsonの補足にちk情報を含んだ情報です。
こちらも軽く中身を確認してみます。
print(tokenizer_config_json['do_lower_case'])
# True
print(tokenizer_config_json['model_max_length'])
# 512
小文字に直すかどうかや最大長に関する情報が含まれていることが分かります。
私の理解ではこれらは後述するtokenizerを使うする際のデフォルトのふるまいを指定しているものだと考えられます。
トークナイズの一連処理
Transformersの裏側で行われているトークナイズの一連の処理パイプラインについてより深く理解したい方は以下のページをご覧ください。
Hugging Face: Understanding tokenizers
トークナイザーの概要
ロードされる各ファイルの詳細
ここではロードされたファイルたちをかなり簡潔に説明させていただきましたが、より詳しく調べてまとめてくださった方がQiitaにいらっしゃったのでこちらもご確認することをお勧めさせていただきます。
どう使うのか
from_pretrained()でインスタンス化したインスタンスに直接引数を与えて使用します。
内部的には__call__で定義されています。
PreTrainedTokenizer._call_をご覧ください。
from transformers import AutoTokenizer
model_name = "google-bert/bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_name)
outputs = tokenizer("ここにいれる")
__call__にはいくつか引数が用意されていますが、ここでは代表的なものをまとめます。
入力テキスト
入力テキストの引数としてよく見るのはtextとtext_pairです。
textはトークナイズしたいテキスト本体。text_pairの場合はQandAタスクなどのsequenceペアが必要な際に使用します。
outputs = tokenizer(text="質問", text_pair="これを基に回答してもらう")
処理制御
トークナイズ処理における制御を行う引数として4つおさえておきます。
-
add_special_tokens
この引数はbool値を取ります。デフォルトはTrueです。
モデルが必要とする特殊トークン(BERTの場合は[CLS]や[SEP])を自動的に付与します。 -
padding
この引数はUnion[bool, str, PaddingStrategy]を取りますが、筆者はboolかstrしか意識したことがありません。デフォルトはFalseです。
Trueもしくは"longest"の場合は、バッチ内で最も長いsequenceに合わせてPaddingします。
"max_length"の場合は後述のmax_lenghtに合わせてPaddingします。基本的にモデルに渡すsequence長は揃える必要性があるため、
Trueもしくは"max_length"を指定します。 -
truncation
この引数はUnion[bool, str, PaddingStrategy]を取りますが、筆者はboolしか意識したことがありません。デフォルトはFalseです。
基本的にはモデルが扱えるsequence長には限界があるためTrueにしておくべき値です。 -
max_length
この引数はintを取ります。
PaddingやTruncationの基準となる最大長です。
デフォルトはNoneです。
出力形式の制御
__call__の出力形式を制御するために、retunr_tensorsがあります。
引数としてはUnion[str, TensorType, NoneType]ですが、基本的には文字列で打ち込むことが多い印象です。
戻り値のテンソル型を指定するため非常に重要な引数です。
後の作業でエラーを起こさないためにも明示的に指定すべき引数かと思います。
引数として、"pt"ならばPyTorchのテンソル、"tf"ならばTensorFlowのテンソル、"np"ならばNumPyの配列を返してきます。
その他の引数
その他に各モデルが必要とする情報に関数引数もあります。
以下一例です。
-
return_attention_mask
引数としてはbool値を取ります。
Trueの場合は戻り値にAttention Maskも含まれます。 -
return_token_type_ids
引数としてはbool値を取ります。
Trueの場合は戻り値にToken Type IDも含まれます。
input_text = "Hello, How are you ?"
outputs = tokenizer(
input_text,
padding=True,
truncation=True,
max_length=512,
return_tensors="pt"
)
何が出力されるのか
先ほどのAPI referenceを見ると分かるのですが、戻り値としてはBatchEncodingを返します。
更に言うと、input_idsやtoken_type_idsをフィールドに持つBatchEncodingです。
どんなフィールドをどんな時に持つのかはBatchEncodingのreferenceに記載があります。一読ください。
実際に確認してみます。
input_text = "Hello, How are you ?"
outputs = tokenizer(
input_text,
padding=True,
truncation=True,
max_length=512,
return_tensors="pt"
)
print(outputs)
# {'input_ids': tensor([[ 101, 7592, 1010, 2129, 2024, 2017, 1029, 102]]), 'token_type_ids': tensor([[0, 0, 0, 0, 0, 0, 0, 0]]), 'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1]])}
outputsはinput_ids、token_type_ids、attention_maskのフィールドを持つことが確認できました。
おわりに
今回はAutoClassesの内、AutoConfigとAutoTokenizerについて学習しました。
これらはモデルを構築、使用するうえで重要な情報を提供するクラスです。
是非一度、API referenceなどを一読の上ご理解いただけますと幸いです。
次回はAutoModelの基本について学習しようかと思います。

