Hugging Face Transformersの使い方と実践ガイド

Hugging Face Transformersは、事前学習済みの言語モデルを簡単に利用できるライブラリです。BERT、GPT、T5など、数千のモデルにアクセスでき、推論からファインチューニングまで幅広く対応しています。

本記事では、Transformersライブラリの基本的な使い方を解説します。

本記事の内容

  • Hugging Face Transformersの概要
  • 事前学習モデルの読み込みと推論
  • Pipelineによる簡単な利用
  • テキスト分類のファインチューニング
  • テキスト生成

前提知識

この記事を読む前に、以下の記事を読んでおくと理解が深まります。

Hugging Face Transformersの概要

主要コンポーネント

コンポーネント 説明
Model Transformer モデル(BERT, GPT, T5等)
Tokenizer テキストをトークンに変換
Pipeline 高レベルの推論API
Trainer 訓練ユーティリティ
Dataset データセット管理

インストール

pip install transformers
pip install datasets  # データセット用
pip install accelerate  # 高速化・分散学習用

モデルとトークナイザーの読み込み

基本的な読み込み

from transformers import AutoModel, AutoTokenizer

# モデル名を指定して読み込み
model_name = "bert-base-uncased"

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

# テキストをトークン化
text = "Hello, how are you?"
inputs = tokenizer(text, return_tensors="pt")
print(inputs)
# {'input_ids': tensor([[...]]), 'attention_mask': tensor([[...]])}

# モデルで推論
outputs = model(**inputs)
print(outputs.last_hidden_state.shape)  # (batch_size, seq_len, hidden_size)

様々なモデルタイプ

from transformers import (
    AutoModelForSequenceClassification,
    AutoModelForTokenClassification,
    AutoModelForQuestionAnswering,
    AutoModelForCausalLM,
    AutoModelForSeq2SeqLM,
)

# テキスト分類
classifier = AutoModelForSequenceClassification.from_pretrained(
    "bert-base-uncased",
    num_labels=2
)

# トークン分類(NER等)
ner_model = AutoModelForTokenClassification.from_pretrained(
    "bert-base-uncased",
    num_labels=9
)

# 質問応答
qa_model = AutoModelForQuestionAnswering.from_pretrained(
    "bert-base-uncased"
)

# テキスト生成(因果言語モデル)
generator = AutoModelForCausalLM.from_pretrained("gpt2")

# Seq2Seq(翻訳、要約等)
seq2seq = AutoModelForSeq2SeqLM.from_pretrained("t5-small")

トークナイザーの詳細

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")

# 基本的なトークン化
text = "Hello, world! This is a test."
tokens = tokenizer.tokenize(text)
print(tokens)  # ['hello', ',', 'world', '!', 'this', 'is', 'a', 'test', '.']

# IDに変換
ids = tokenizer.convert_tokens_to_ids(tokens)
print(ids)

# 一括処理
encoded = tokenizer(
    text,
    padding=True,           # パディング
    truncation=True,        # 切り詰め
    max_length=128,         # 最大長
    return_tensors="pt"     # PyTorchテンソルで返す
)

# バッチ処理
texts = ["Hello world", "How are you?", "This is a longer sentence."]
batch = tokenizer(
    texts,
    padding=True,
    truncation=True,
    max_length=128,
    return_tensors="pt"
)

# デコード
decoded = tokenizer.decode(encoded["input_ids"][0])
print(decoded)  # [CLS] hello, world! this is a test. [SEP]

# 特殊トークン
print(f"CLS token: {tokenizer.cls_token}, ID: {tokenizer.cls_token_id}")
print(f"SEP token: {tokenizer.sep_token}, ID: {tokenizer.sep_token_id}")
print(f"PAD token: {tokenizer.pad_token}, ID: {tokenizer.pad_token_id}")

Pipelineによる簡単な推論

利用可能なパイプライン

from transformers import pipeline

# テキスト分類
classifier = pipeline("sentiment-analysis")
result = classifier("I love this movie!")
print(result)  # [{'label': 'POSITIVE', 'score': 0.99}]

# 複数テキスト
results = classifier([
    "I love this movie!",
    "This is terrible.",
    "It's okay, I guess."
])

# 固有表現抽出(NER)
ner = pipeline("ner", aggregation_strategy="simple")
result = ner("My name is John and I live in New York.")
print(result)
# [{'entity_group': 'PER', 'word': 'John', ...},
#  {'entity_group': 'LOC', 'word': 'New York', ...}]

# 質問応答
qa = pipeline("question-answering")
result = qa(
    question="What is the capital of France?",
    context="Paris is the capital of France. It is known for the Eiffel Tower."
)
print(result)  # {'answer': 'Paris', 'score': 0.99, ...}

# テキスト生成
generator = pipeline("text-generation", model="gpt2")
result = generator("Once upon a time", max_length=50, num_return_sequences=1)
print(result[0]["generated_text"])

# 翻訳
translator = pipeline("translation_en_to_fr", model="t5-small")
result = translator("Hello, how are you?")
print(result)

# 要約
summarizer = pipeline("summarization", model="t5-small")
article = """
Artificial intelligence is transforming the world. From healthcare to
transportation, AI is being applied to solve complex problems. Machine
learning, a subset of AI, enables computers to learn from data without
being explicitly programmed.
"""
result = summarizer(article, max_length=50, min_length=10)
print(result[0]["summary_text"])

# Fill-mask(BERT)
fill_mask = pipeline("fill-mask", model="bert-base-uncased")
result = fill_mask("Paris is the [MASK] of France.")
print(result)

GPUの利用

import torch

# GPU利用可能な場合
device = 0 if torch.cuda.is_available() else -1

classifier = pipeline("sentiment-analysis", device=device)
result = classifier("This is great!")

テキスト分類のファインチューニング

データセットの準備

from datasets import load_dataset, Dataset
import pandas as pd

# Hugging Faceのデータセットを読み込み
dataset = load_dataset("imdb")
print(dataset)
# DatasetDict({
#     'train': Dataset({features: ['text', 'label'], num_rows: 25000}),
#     'test': Dataset({features: ['text', 'label'], num_rows: 25000})
# })

# サンプルを確認
print(dataset['train'][0])

# カスタムデータからDatasetを作成
df = pd.DataFrame({
    'text': ['Great product!', 'Terrible experience', 'It was okay'],
    'label': [1, 0, 0]
})
custom_dataset = Dataset.from_pandas(df)

データの前処理

from transformers import AutoTokenizer

model_name = "bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_name)

def tokenize_function(examples):
    return tokenizer(
        examples["text"],
        padding="max_length",
        truncation=True,
        max_length=256
    )

# データセット全体をトークン化
tokenized_datasets = dataset.map(tokenize_function, batched=True)

# 不要なカラムを削除
tokenized_datasets = tokenized_datasets.remove_columns(["text"])
tokenized_datasets = tokenized_datasets.rename_column("label", "labels")
tokenized_datasets.set_format("torch")

# サブセットを使用(テスト用)
small_train = tokenized_datasets["train"].shuffle(seed=42).select(range(1000))
small_test = tokenized_datasets["test"].shuffle(seed=42).select(range(200))

Trainerを使った訓練

from transformers import (
    AutoModelForSequenceClassification,
    TrainingArguments,
    Trainer,
)
import numpy as np
from datasets import load_metric

# モデル
model = AutoModelForSequenceClassification.from_pretrained(
    model_name,
    num_labels=2
)

# 評価関数
def compute_metrics(eval_pred):
    logits, labels = eval_pred
    predictions = np.argmax(logits, axis=-1)
    accuracy = (predictions == labels).mean()
    return {"accuracy": accuracy}

# 訓練設定
training_args = TrainingArguments(
    output_dir="./results",
    evaluation_strategy="epoch",
    save_strategy="epoch",
    learning_rate=2e-5,
    per_device_train_batch_size=16,
    per_device_eval_batch_size=16,
    num_train_epochs=3,
    weight_decay=0.01,
    load_best_model_at_end=True,
    metric_for_best_model="accuracy",
    logging_dir="./logs",
    logging_steps=100,
    fp16=True,  # 混合精度
)

# Trainer
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=small_train,
    eval_dataset=small_test,
    compute_metrics=compute_metrics,
)

# 訓練
# trainer.train()

# 評価
# results = trainer.evaluate()
# print(results)

# モデルの保存
# trainer.save_model("./my_model")
# tokenizer.save_pretrained("./my_model")

カスタム訓練ループ

import torch
from torch.utils.data import DataLoader
from transformers import AutoModelForSequenceClassification, AdamW, get_scheduler
from tqdm import tqdm

# データローダー
train_dataloader = DataLoader(small_train, shuffle=True, batch_size=16)
eval_dataloader = DataLoader(small_test, batch_size=16)

# モデルとオプティマイザ
model = AutoModelForSequenceClassification.from_pretrained(model_name, num_labels=2)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)

optimizer = AdamW(model.parameters(), lr=2e-5)
num_epochs = 3
num_training_steps = num_epochs * len(train_dataloader)
lr_scheduler = get_scheduler(
    "linear",
    optimizer=optimizer,
    num_warmup_steps=0,
    num_training_steps=num_training_steps
)

# 訓練ループ
model.train()
for epoch in range(num_epochs):
    total_loss = 0
    progress_bar = tqdm(train_dataloader, desc=f"Epoch {epoch+1}")

    for batch in progress_bar:
        batch = {k: v.to(device) for k, v in batch.items()}
        outputs = model(**batch)
        loss = outputs.loss

        loss.backward()
        optimizer.step()
        lr_scheduler.step()
        optimizer.zero_grad()

        total_loss += loss.item()
        progress_bar.set_postfix({"loss": loss.item()})

    print(f"Epoch {epoch+1}: avg_loss = {total_loss / len(train_dataloader):.4f}")

# 評価
model.eval()
correct = 0
total = 0

with torch.no_grad():
    for batch in eval_dataloader:
        batch = {k: v.to(device) for k, v in batch.items()}
        outputs = model(**batch)
        predictions = torch.argmax(outputs.logits, dim=-1)
        correct += (predictions == batch["labels"]).sum().item()
        total += batch["labels"].size(0)

print(f"Accuracy: {correct / total:.4f}")

テキスト生成

GPT-2による生成

from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

model_name = "gpt2"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name)

# GPT-2にはpad_tokenがないので設定
tokenizer.pad_token = tokenizer.eos_token

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)

# テキスト生成
prompt = "The future of artificial intelligence is"
inputs = tokenizer(prompt, return_tensors="pt").to(device)

# 基本的な生成
outputs = model.generate(
    **inputs,
    max_new_tokens=50,
    do_sample=True,           # サンプリングを有効化
    temperature=0.7,           # 温度(低いほど確定的)
    top_k=50,                  # Top-K サンプリング
    top_p=0.95,                # Top-p (nucleus) サンプリング
    num_return_sequences=3,    # 生成する文の数
    pad_token_id=tokenizer.eos_token_id
)

# デコード
for i, output in enumerate(outputs):
    generated_text = tokenizer.decode(output, skip_special_tokens=True)
    print(f"Generated {i+1}: {generated_text}\n")

生成パラメータの解説

# Greedy Search(最も確率の高いトークンを選択)
outputs = model.generate(
    **inputs,
    max_new_tokens=50,
    do_sample=False  # Greedy
)

# Beam Search(複数の候補を探索)
outputs = model.generate(
    **inputs,
    max_new_tokens=50,
    num_beams=5,           # ビーム数
    early_stopping=True,
    no_repeat_ngram_size=2  # 同じn-gramの繰り返しを防ぐ
)

# Top-K Sampling
outputs = model.generate(
    **inputs,
    max_new_tokens=50,
    do_sample=True,
    top_k=50,
    temperature=0.8
)

# Top-p (Nucleus) Sampling
outputs = model.generate(
    **inputs,
    max_new_tokens=50,
    do_sample=True,
    top_p=0.92,
    temperature=0.8
)

# 組み合わせ
outputs = model.generate(
    **inputs,
    max_new_tokens=100,
    do_sample=True,
    top_k=50,
    top_p=0.95,
    temperature=0.8,
    repetition_penalty=1.2,  # 繰り返しにペナルティ
    num_return_sequences=1
)

ストリーミング生成

from transformers import TextStreamer

# ストリーミング出力
streamer = TextStreamer(tokenizer, skip_special_tokens=True)

outputs = model.generate(
    **inputs,
    max_new_tokens=100,
    do_sample=True,
    temperature=0.7,
    streamer=streamer  # リアルタイムで出力
)

モデルの保存と読み込み

# ローカルに保存
model.save_pretrained("./my_model")
tokenizer.save_pretrained("./my_model")

# ローカルから読み込み
model = AutoModelForCausalLM.from_pretrained("./my_model")
tokenizer = AutoTokenizer.from_pretrained("./my_model")

# Hugging Face Hubにアップロード
# まずログイン: huggingface-cli login
model.push_to_hub("my-username/my-model")
tokenizer.push_to_hub("my-username/my-model")

量子化モデルの使用

from transformers import AutoModelForCausalLM, BitsAndBytesConfig
import torch

# 4-bit量子化
quantization_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_compute_dtype=torch.float16
)

model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-2-7b-hf",
    quantization_config=quantization_config,
    device_map="auto"
)

# 8-bit量子化
model_8bit = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-2-7b-hf",
    load_in_8bit=True,
    device_map="auto"
)

まとめ

本記事では、Hugging Face Transformersライブラリについて解説しました。

  • 基本構成: Model、Tokenizer、Pipeline、Trainer
  • Pipeline: 高レベルAPIで簡単に推論
  • ファインチューニング: Trainerで効率的に訓練
  • テキスト生成: 様々なサンプリング手法
  • 量子化: メモリ効率の良いモデル利用

Transformersライブラリは、NLPタスクを素早くプロトタイピングし、本番環境に展開するための強力なツールです。

次のステップとして、以下の記事も参考にしてください。