Communityコーディング&開発github.com

huggingface-transformers

Hugging Face Transformersのベストプラクティス。モデル読み込み、トークナイゼーション、ファインチューニングワークフロー、推論最適化を網羅。トランスフォーマーモデルの操作、LLMのファインチューニング、NLPタスクの実装、推論の最適化に使用します。

huggingface-transformers とは?

このスキルは、Hugging Face Transformersライブラリを使用する際の包括的なベストプラクティスを提供します。モデル読み込み、トークナイゼーション、ファインチューニング、パイプライン使用法、推論最適化など、主要なトピックをカバーしています。BERT、GPT、T5、LLaMAなどの事前学習済みモデルをロードして使用する方法、カスタムデータでのファインチューニング、分類や質問応答などのNLPタスクの実装、量子化やONNXエクスポートによる推論最適化について詳細なガイドを提供します。Claude Code、Cursor、CodexなどのAIエージェントツールと統合することで、開発者は効率的にトランスフォーマーモデルを操作できるようになります。本スキルは、PyTorchベースの環境を前提としており、メモリ効率の高い手法(8ビット/4ビット量子化、LoRA)やトラブルシューティングのヒントも含まれているため、初心者から上級者まで幅広く役立ちます。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/applied-artificial-intelligence/claude-code-toolkit/tree/main/skills/huggingface-transformers

Installed? Explore more コーディング&開発 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

Hugging Face Transformers ベストプラクティス

Hugging Face Transformers ライブラリを効果的に使用するための包括的なガイドです。モデルの読み込み、トークナイゼーション、ファインチューニングのワークフロー、パイプラインの使用、カスタムデータセット、デプロイメントの最適化について説明します。


クイックリファレンス

このスキルを使用すべきタイミング:

  • 事前学習済みトランスフォーマー(BERT、GPT、T5、LLaMAなど)の読み込みと使用
  • カスタムデータでのモデルのファインチューニング
  • NLPタスク(分類、QA、生成など)の実装
  • 推論の最適化(量子化、ONNXなど)
  • トークナイゼーションの問題のデバッグ
  • Hugging Face パイプラインの使用
  • Transformers の本番環境へのデプロイ

対象モデル:

  • エンコーダー: BERT, RoBERTa, DeBERTa, ALBERT
  • デコーダー: GPT-2, GPT-Neo, LLaMA, Mistral
  • エンコーダー-デコーダー: T5, BART, Flan-T5
  • ビジョン: ViT, CLIP, Stable Diffusion

パート1: モデル読み込みパターン

パターン1: 基本的なモデル読み込み

from transformers import AutoModel, AutoTokenizer

# モデルとトークナイザーを読み込む
model_name = "bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name)

# 特定のタスク用
from transformers import AutoModelForSequenceClassification
model = AutoModelForSequenceClassification.from_pretrained(
    model_name,
    num_labels=3  # 3クラス分類用
)

パターン2: 特定の設定で読み込む

from transformers import AutoConfig, AutoModel

# 設定を変更
config = AutoConfig.from_pretrained("bert-base-uncased")
config.hidden_dropout_prob = 0.2  # カスタムドロップアウト
config.attention_probs_dropout_prob = 0.2

# カスタム設定でモデルを読み込み
model = AutoModel.from_pretrained("bert-base-uncased", config=config)

# 設定からモデルを新規作成
model = AutoModel.from_config(config)

パターン3: 量子化モデルの読み込み(メモリ効率重視)

from transformers import AutoModel, BitsAndBytesConfig
import torch

# 8ビット量子化(メモリ使用量50%削減)
quantization_config = BitsAndBytesConfig(load_in_8bit=True)

model = AutoModel.from_pretrained(
    "meta-llama/Llama-2-7b-hf",
    quantization_config=quantization_config,
    device_map="auto"  # 自動デバイス配置
)

# 4ビット量子化(メモリ使用量75%削減)
quantization_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_compute_dtype=torch.float16,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_use_double_quant=True
)

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

パターン4: ローカルパスからの読み込み

# モデルをローカルに保存
model.save_pretrained("./my-model")
tokenizer.save_pretrained("./my-model")

# ローカルパスから読み込み
model = AutoModel.from_pretrained("./my-model")
tokenizer = AutoTokenizer.from_pretrained("./my-model")

パート2: トークナイゼーションのベストプラクティス

重要なトークナイゼーションパターン

from transformers import AutoTokenizer

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

# ✅ 正しい: 全ての必須引数が指定されている
tokens = tokenizer(
    text,
    padding=True,  # バッチ内で最長にパディング
    truncation=True,  # max_lengthに切り詰め
    max_length=512,  # 最大シーケンス長
    return_tensors="pt"  # PyTorchテンソルを返す
)

# コンポーネントにアクセス
input_ids = tokens['input_ids']  # トークンID
attention_mask = tokens['attention_mask']  # パディングマスク
token_type_ids = tokens.get('token_type_ids')  # セグメントID (BERT)

# ❌ 間違い: 重要な引数が不足
tokens = tokenizer(text)  # パディング、切り詰め、テンソル形式がない!

バッチトークナイゼーション

# 複数テキストを効率的にトークナイズ
texts = ["最初のテキスト", "2番目のテキスト", "3番目のテキスト"]

tokens = tokenizer(
    texts,
    padding=True,  # バッチ内で最長にパディング
    truncation=True,
    max_length=128,
    return_tensors="pt"
)

# 結果の形状: [batch_size, max_length]
print(tokens['input_ids'].shape)  # torch.Size([3, max_len_in_batch])

特殊トークンの処理

# 特殊トークンを追加
tokenizer.add_special_tokens({
    'additional_special_tokens': ['[CUSTOM]', '[MARKER]']
})

# モデルの埋め込みサイズを変更
model.resize_token_embeddings(len(tokenizer))

# 特殊トークンを保持してエンコード
text = "Hello [CUSTOM] world"
tokens = tokenizer(text, add_special_tokens=True)

# デコード
decoded = tokenizer.decode(tokens['input_ids'][0], skip_special_tokens=False)

タスク別トークナイゼーション

# テキスト分類(単一シーケンス)
tokens = tokenizer(
    "This movie was great!",
    padding="max_length",
    truncation=True,
    max_length=128,
    return_tensors="pt"
)

# 質問応答(シーケンスペア)
question = "What is the capital of France?"
context = "France is a country in Europe. Paris is its capital."

tokens = tokenizer(
    question,
    context,
    padding="max_length",
    truncation="only_second",  # contextのみを切り詰め
    max_length=384,
    return_tensors="pt"
)

# テキスト生成(デコーダーのみのモデル)
prompt = "Once upon a time"
tokens = tokenizer(prompt, return_tensors="pt")
# 生成入力にはパディング不要

パート3: ファインチューニングワークフロー

パターン1: Trainerを使用したシンプルなファインチューニング

from transformers import (
    AutoModelForSequenceClassification,
    AutoTokenizer,
    Trainer,
    TrainingArguments
)
from datasets import load_dataset

# 1. データセットを読み込み
dataset = load_dataset("glue", "mrpc")

# 2. モデルを読み込み
model = AutoModelForSequenceClassification.from_pretrained(
    "bert-base-uncased",
    num_labels=2
)
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")

# 3. データセットをトークナイズ
def tokenize_function(examples):
    return tokenizer(
        examples["sentence1"],
        examples["sentence2"],
        padding="max_length",
        truncation=True,
        max_length=128
    )

tokenized_datasets = dataset.map(tokenize_function, batched=True)

# 4. トレーニング引数を定義
training_args = TrainingArguments(
    output_dir="./results",
    evaluation_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,
    logging_dir="./logs",
    logging_steps=100,
    save_strategy="epoch",
    load_best_model_at_end=True,
    metric_for_best_model="accuracy",
)

# 5. 評価指標を定義
from datasets import load_metric
import numpy as np

metric = load_metric("accuracy")

def compute_metrics(eval_pred):
    logits, labels = eval_pred
    predictions = np.argmax(logits, axis=-1)
    return metric.compute(predictions=predictions, references=labels)

# 6. Trainerを作成
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_datasets["train"],
    eval_dataset=tokenized_datasets["validation"],
    compute_metrics=compute_metrics,
)

# 7. トレーニング
trainer.train()

# 8. 保存
trainer.save_model("./fine-tuned-model")

パターン2: LoRAファインチューニング(パラメータ効率重視)

from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import LoraConfig, get_peft_model, TaskType

# ベースモデルを読み込み
model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-2-7b-hf",
    load_in_8bit=True,  # メモリ効率のため8ビット
    device_map="auto"
)

# LoRA設定を構成
lora_config = LoraConfig(
    task_type=TaskType.CAUSAL_LM,
    r=8,  # LoRAランク
    lora_alpha=32,  # LoRAアルファ
    lora_dropout=0.1,
    target_modules=["q_proj", "v_proj"],  # 適合させるレイヤー
)

# LoRAを適用
model = get_peft_model(model, lora_config)

# 学習可能パラメータを確認
model.print_trainable_parameters()
# 出力: trainable params: 4.2M || all params: 6.7B || trainable%: 0.062%

# Trainerでトレーニング(上と同じ)
# LoRAパラメータのみが更新される!

パターン3: カスタムトレーニングループ

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

# データローダーの準備
train_dataloader = DataLoader(tokenized_datasets["train"], batch_size=16, shuffle=True)
eval_dataloader = DataLoader(tokenized_datasets["validation"], batch_size=16)

# オプティマイザ
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=500,
    num_training_steps=num_training_steps
)

# トレーニングループ
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)

for epoch in range(num_epochs):
    model.train()
    for batch in train_dataloader:
        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()

    # 評価
    model.eval()
    for batch in eval_dataloader:
        batch = {k: v.to(device) for k, v in batch.items()}
        with torch.no_grad():
            outputs = model(**batch)
        # 指標を計算

パート4: パイプラインの使用(高レベルAPI)

テキスト分類パイプライン

from transformers import pipeline

# パイプラインを読み込み
classifier = pipeline(
    "text-classification",
    model="distilbert-base-uncased-finetuned-sst-2-english"
)

# 単一予測
result = classifier("I love this product!")
# [{'label': 'POSITIVE', 'score': 0.9998}]

# バッチ予測
results = classifier([
    "Great service!",
    "Terrible experience",
    "Average quality"
])

質問応答パイプライン

qa_pipeline = pipeline("question-answering", model="distilbert-base-uncased-distilled-squad")

result = qa_pipeline(
    question="What is the capital of France?",
    context="France is a country in Europe. Its capital is Paris, a beautiful city."
)
# {'score': 0.98, 'start': 49, 'end': 54, 'answer': 'Paris'}

テキスト生成パイプライン

generator = pipeline("text-generation", model="gpt2")

outputs = generator(
    "Once upon a time",
    max_length=50,
    num_return_sequences=3,
    temperature=0.7,
    top_k=50,
    top_p=0.95,
    do_sample=True
)

for output in outputs:
    print(output['generated_text'])

ゼロショット分類パイプライン

classifier = pipeline("zero-shot-classification", model="facebook/bart-large-mnli")

result = classifier(
    "This is a course about Python programming.",
    candidate_labels=["education", "technology", "business", "sports"]
)
# {'sequence': '...', 'labels': ['education', 'technology', ...], 'scores': [0.85, 0.12, ...]}

パート5: 推論最適化

最適化1: バッチ処理

# ❌ 低速: 一つずつ処理
for text in texts:
    output = model(**tokenizer(text, return_tensors="pt"))

# ✅ 高速: バッチで処理
batch_size = 32
for i in range(0, len(texts), batch_size):
    batch = texts[i:i+batch_size]
    inputs = tokenizer(batch, padding=True, truncation=True, return_tensors="pt")
    outputs = model(**inputs)

最適化2: 混合精度(AMP)

from torch.cuda.amp import autocast, GradScaler

scaler = GradScaler()

for batch in dataloader:
    optimizer.zero_grad()

    # 混合精度で順伝播
    with autocast():
        outputs = model(**batch)
        loss = outputs.loss

    # スケーリングされた勾配で逆伝播
    scaler.scale(loss).backward()
    scaler.step(optimizer)
    scaler.update()

最適化3: ONNXエクスポート

from transformers import AutoModelForSequenceClassification, AutoTokenizer
from optimum.onnxruntime import ORTModelForSequenceClassification

# ONNXにエクスポート
model = AutoModelForSequenceClassification.from_pretrained("bert-base-uncased")
model.save_pretrained("./onnx-model", export=True)

# ONNXモデルを読み込み(より高速な推論)
ort_model = ORTModelForSequenceClassification.from_pretrained("./onnx-model")

# 推論(2-3倍高速)
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
inputs = tokenizer("Hello world", return_tensors="pt")
outputs = ort_model(**inputs)

最適化4: 動的量子化

import torch

# モデルをint8に量子化
quantized_model = torch.quantization.quantize_dynamic(
    model,
    {torch.nn.Linear},  # Linearレイヤーを量子化
    dtype=torch.qint8
)

# モデルサイズ1/4、CPUでの推論が2-3倍高速

パート6: 一般的な問題と解決策

問題1: CUDAメモリ不足

問題: RuntimeError: CUDA out of memory

解決策:

# 解決策1: バッチサイズを減らす
training_args = TrainingArguments(
    per_device_train_batch_size=8,  # 以前は32
    gradient_accumulation_steps=4,  # 実効バッチ = 8*4 = 32
)

# 解決策2: 勾配チェックポイントを使用
model.gradient_checkpointing_enable()

# 解決策3: 8ビットモデルを使用
from transformers import BitsAndBytesConfig
quantization_config = BitsAndBytesConfig(load_in_8bit=True)
model = AutoModel.from_pretrained("model-name", quantization_config=quantization_config)

# 解決策4: キャッシュをクリア
import torch
torch.cuda.empty_cache()

問題2: トークナイゼーションの低速化

問題: トークナイゼーションがボトルネックになる

解決策:

# 解決策1: 高速トークナイザーを使用
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased", use_fast=True)

# 解決策2: データセットを一度トークナイズしてキャッシュ
 tokenized_dataset = dataset.map(
    tokenize_function,
    batched=True,
    num_proc=4,  # 並列処理
    remove_columns=dataset.column_names,
    load_from_cache_file=True  # 結果をキャッシュ
)

# 解決策3: トークナイゼーションに大きなバッチを使用
tokenizer(
    texts,
    padding=True,
    truncation=True,
    max_length=512,
    return_tensors="pt",
    batched=True,  # 複数テキストを同時に処理
    batch_size=1000
)

問題3: 結果の不一致

問題: 同じ入力に対してモデルが異なる結果を出力する

解決策:

# 再現性のためにシードを設定
import random

...[truncated for translation]

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

関連スキル