Community코딩 & 개발github.com

huggingface-transformers

허깅페이스 트랜스포머(Transformers) 모델 로딩, 토크나이제이션, 파인튜닝 워크플로우 및 추론 최적화 모범 사례. 트랜스포머 모델을 사용하거나, LLM 파인튜닝, NLP 태스크 구현, 또는 트랜스포머 추론 최적화가 필요할 때 활용하세요.

huggingface-transformers란 무엇인가요?

이 스킬은 Hugging Face Transformers 라이브러리를 사용하는 개발자를 위한 종합 모범 사례 가이드입니다. 주로 BERT, GPT, T5, LLaMA, Mistral과 같은 널리 알려진 트랜스포머 아키텍처를 다루며, 모델 로딩 패턴, 토크나이제이션 모범 사례, Trainer 및 LoRA를 사용한 파인튜닝, Pipeline 고수준 API, ONNX 내보내기 및 양자화와 같은 추론 최적화 기법을 다룹니다. 이 스킬은 Claude Code, Cursor, Codex와 같은 모든 AI 에이전트 플랫폼과 호환되며, 메모리 문제 해결, 토크나이제이션 병목, 결과 재현성 등 일반적인 문제를 방지하는 데 중점을 둡니다. 로컬 파일 경로, 양자화 설정, 사용자 정의 훈련 루프 등 다양한 시나리오를 위한 실용적인 코드 예제를 제공하므로, 초보자와 숙련된 실무자 모두가 프로덕션 환경에서 트랜스포머를 최적의 방식으로 사용할 수 있도록 돕습니다.

지원 대상~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 모범 사례

허깅페이스 트랜스포머(Transformers) 라이브러리 사용에 대한 종합 가이드로, 모델 로딩, 토크나이제이션, 파인튜닝 워크플로우, 파이프라인 사용법, 사용자 정의 데이터셋 및 배포 최적화를 다룹니다.


빠른 참조

이 스킬을 사용해야 할 때:

  • 사전 훈련된 트랜스포머 로딩 및 사용 (BERT, GPT, T5, LLaMA 등)
  • 사용자 정의 데이터로 모델 파인튜닝
  • NLP 태스크 구현 (분류, QA, 생성 등)
  • 추론 최적화 (양자화, ONNX 등)
  • 토크나이제이션 문제 디버깅
  • Hugging Face 파이프라인 사용
  • 트랜스포머를 프로덕션에 배포

다루는 모델:

  • 인코더: 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 = ["첫 번째 텍스트", "두 번째 텍스트", "세 번째 텍스트"]

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(
    "이 영화는 훌륭했습니다!",
    padding="max_length",
    truncation=True,
    max_length=128,
    return_tensors="pt"
)

# 질문 답변 (시퀀스 쌍)
question = "프랑스의 수도는 무엇입니까?"
context = "프랑스는 유럽의 한 국가입니다. 파리가 그 수도입니다."

tokens = tokenizer(
    question,
    context,
    padding="max_length",
    truncation="only_second",  # 컨텍스트만 자르기
    max_length=384,
    return_tensors="pt"
)

# 텍스트 생성 (디코더 전용 모델)
prompt = "옛날옛적에"
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: Pipeline 사용법 (고수준 API)

텍스트 분류 Pipeline

from transformers import pipeline

# Pipeline 로딩
classifier = pipeline(
    "text-classification",
    model="distilbert-base-uncased-finetuned-sst-2-english"
)

# 단일 예측
result = classifier("나는 이 제품이 정말 마음에 듭니다!")
# [{'label': 'POSITIVE', 'score': 0.9998}]

# 배치 예측
results = classifier([
    "훌륭한 서비스!",
    "끔찍한 경험이었습니다",
    "평균적인 품질"
])

질문 답변 Pipeline

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

result = qa_pipeline(
    question="프랑스의 수도는 무엇입니까?",
    context="프랑스는 유럽의 한 국가입니다. 수도는 파리이며, 아름다운 도시입니다."
)
# {'score': 0.98, 'start': 49, 'end': 54, 'answer': 'Paris'}

텍스트 생성 Pipeline

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

outputs = generator(
    "옛날옛적에",
    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'])

제로샷 분류 Pipeline

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

result = classifier(
    "이것은 파이썬 프로그래밍에 관한 강좌입니다.",
    candidate_labels=["교육", "기술", "비즈니스", "스포츠"]
)
# {'sequence': '...', 'labels': ['교육', '기술', ...], '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},  # 선형 레이어만 양자화
    dtype=torch.qint8
)

# 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
import numpy as np
import torch

def set_seed(seed: int):
    random.seed(seed)
    np.random.seed(seed)
    torch.manual_seed(seed)
    torch.cuda.manual_seed_all(seed)
    torch.backends.cudnn.deterministic = True
    torch.backends.cudnn.benchmark = False

set_seed(42)

Individual skills in this repo

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

관련 스킬