Skip to content

필사 모드: HuggingFace 생태계 완전 정복: Transformers, Datasets, PEFT, Accelerate 마스터하기

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

들어가며

HuggingFace는 현재 AI/ML 생태계에서 가장 중요한 플랫폼 중 하나입니다. 수십만 개의 사전학습 모델, 수만 개의 데이터셋, 그리고 실용적인 라이브러리들을 하나의 생태계로 제공합니다. 이 가이드에서는 HuggingFace의 핵심 구성 요소를 처음부터 끝까지 마스터하겠습니다.

1. HuggingFace 생태계 개요

1.1 HuggingFace Hub

HuggingFace Hub는 세 가지 핵심 요소로 구성됩니다.

**Model Hub**: 전 세계 연구자와 개발자들이 공유한 수십만 개의 사전학습 모델 저장소입니다. BERT, GPT-2, Llama, Mistral, Stable Diffusion 등 거의 모든 유명한 모델을 찾을 수 있습니다. 모델은 PyTorch, TensorFlow, JAX 형식으로 저장되며, 각 모델 페이지에서 사용법과 성능 벤치마크를 확인할 수 있습니다.

**Dataset Hub**: NLP, Vision, Audio, Multimodal 등 다양한 분야의 수천 개 데이터셋을 제공합니다. `datasets` 라이브러리와 완벽하게 통합되어 한 줄의 코드로 어느 데이터셋이든 불러올 수 있습니다.

**Spaces**: Gradio 또는 Streamlit 기반의 ML 데모 앱을 무료로 호스팅할 수 있습니다. CPU/GPU 환경에서 실행 가능하며, 커뮤니티와 모델을 공유하는 가장 쉬운 방법입니다.

1.2 주요 라이브러리 목록

| 라이브러리 | 용도 |

| --------------- | ----------------------------------- |

| transformers | 사전학습 모델 로딩 및 추론/파인튜닝 |

| datasets | 데이터셋 로딩 및 전처리 |

| tokenizers | 빠른 토크나이저 구현 |

| peft | 파라미터 효율적 파인튜닝 (LoRA 등) |

| accelerate | 멀티 GPU/TPU 학습 추상화 |

| trl | RLHF, SFT, DPO 파인튜닝 |

| diffusers | 이미지 생성 모델 |

| evaluate | 모델 평가 메트릭 |

| optimum | 하드웨어 최적화 |

| huggingface_hub | Hub API 클라이언트 |

1.3 계정 설정과 API 토큰

pip install transformers datasets tokenizers peft accelerate trl diffusers evaluate huggingface_hub

from huggingface_hub import login

방법 1: 직접 토큰 입력

login(token="hf_your_token_here")

방법 2: 환경 변수 (권장)

os.environ["HUGGINGFACE_TOKEN"] = "hf_your_token_here"

방법 3: CLI

huggingface-cli login

2. Transformers 라이브러리 완전 가이드

2.1 파이프라인 (Pipeline) API

파이프라인은 HuggingFace에서 가장 간단하게 모델을 사용하는 방법입니다. 내부적으로 토크나이저, 모델, 후처리까지 모두 처리해 줍니다.

from transformers import pipeline

텍스트 분류

classifier = pipeline("text-classification", model="snunlp/KR-FinBert-SC")

result = classifier("이 회사의 주가가 오를 것 같습니다.")

print(result)

[{'label': 'positive', 'score': 0.9876}]

텍스트 생성

generator = pipeline(

"text-generation",

model="meta-llama/Meta-Llama-3-8B-Instruct",

torch_dtype="auto",

device_map="auto"

)

output = generator(

"서울의 가장 유명한 관광지는",

max_new_tokens=100,

do_sample=True,

temperature=0.7

)

print(output[0]["generated_text"])

질의응답 (Extractive QA)

qa = pipeline("question-answering", model="monologg/koelectra-base-finetuned-korquad")

result = qa(

question="HuggingFace는 어디에 있나요?",

context="HuggingFace는 뉴욕에 본사를 두고 있으며 파리에도 사무소가 있습니다."

)

print(result)

{'score': 0.99, 'start': 13, 'end': 17, 'answer': '뉴욕'}

번역

translator = pipeline("translation", model="Helsinki-NLP/opus-mt-ko-en")

result = translator("안녕하세요, 저는 AI 연구자입니다.")

print(result)

요약

summarizer = pipeline("summarization", model="facebook/bart-large-cnn")

long_text = """HuggingFace는 2016년에 설립된 AI 회사로..."""

summary = summarizer(long_text, max_length=100, min_length=30)

print(summary)

토큰 분류 (NER)

ner = pipeline("ner", model="snunlp/KR-FinBert-SC", aggregation_strategy="simple")

result = ner("삼성전자가 반도체 사업을 확장합니다.")

print(result)

2.2 AutoTokenizer와 AutoModel

from transformers import AutoTokenizer, AutoModel

토크나이저 로딩

tokenizer = AutoTokenizer.from_pretrained("klue/roberta-base")

텍스트 인코딩

text = "HuggingFace는 정말 유용한 라이브러리입니다."

inputs = tokenizer(text, return_tensors="pt")

print(inputs)

{'input_ids': tensor([[...]]), 'attention_mask': tensor([[...]])}

토큰 디코딩

decoded = tokenizer.decode(inputs["input_ids"][0])

print(decoded)

특수 토큰 확인

print(f"BOS: {tokenizer.bos_token}") # [CLS]

print(f"EOS: {tokenizer.eos_token}") # [SEP]

print(f"PAD: {tokenizer.pad_token}") # [PAD]

print(f"UNK: {tokenizer.unk_token}") # [UNK]

print(f"어휘 크기: {tokenizer.vocab_size}")

배치 인코딩

texts = ["첫 번째 문장입니다.", "두 번째 문장은 조금 더 깁니다."]

batch_inputs = tokenizer(

texts,

padding=True,

truncation=True,

max_length=128,

return_tensors="pt"

)

print(batch_inputs["input_ids"].shape) # [2, 128]

모델 로딩

model = AutoModel.from_pretrained("klue/roberta-base")

model.eval()

with torch.no_grad():

outputs = model(**batch_inputs)

last_hidden_state: [batch, seq_len, hidden_dim]

print(outputs.last_hidden_state.shape)

pooler_output: [batch, hidden_dim]

print(outputs.pooler_output.shape)

2.3 태스크별 특화 모델

from transformers import (

AutoModelForSequenceClassification,

AutoModelForCausalLM,

AutoModelForSeq2SeqLM,

AutoModelForTokenClassification,

AutoModelForQuestionAnswering,

AutoModelForMaskedLM,

)

시퀀스 분류 모델 (감성 분석, 텍스트 분류)

clf_model = AutoModelForSequenceClassification.from_pretrained(

"klue/roberta-base",

num_labels=2

)

CausalLM (GPT 스타일 텍스트 생성)

causal_model = AutoModelForCausalLM.from_pretrained(

"meta-llama/Meta-Llama-3-8B",

torch_dtype=torch.bfloat16,

device_map="auto",

attn_implementation="flash_attention_2"

)

Seq2Seq (번역, 요약)

seq2seq_model = AutoModelForSeq2SeqLM.from_pretrained("facebook/bart-large-cnn")

토큰 분류 (NER, POS 태깅)

ner_model = AutoModelForTokenClassification.from_pretrained(

"klue/roberta-base",

num_labels=9 # 레이블 수에 맞게 조정

)

추출형 QA

qa_model = AutoModelForQuestionAnswering.from_pretrained("klue/roberta-large")

Masked LM (BERT 스타일 마스크 예측)

mlm_model = AutoModelForMaskedLM.from_pretrained("klue/roberta-base")

2.4 모델 추론 상세 예제

from transformers import AutoTokenizer, AutoModelForCausalLM

def load_model(model_name: str):

tokenizer = AutoTokenizer.from_pretrained(model_name)

model = AutoModelForCausalLM.from_pretrained(

model_name,

torch_dtype=torch.bfloat16,

device_map="auto"

)

return tokenizer, model

def generate_text(

model,

tokenizer,

prompt: str,

max_new_tokens: int = 200,

temperature: float = 0.7,

top_p: float = 0.9,

do_sample: bool = True

) -> str:

inputs = tokenizer(prompt, return_tensors="pt").to(model.device)

with torch.no_grad():

outputs = model.generate(

**inputs,

max_new_tokens=max_new_tokens,

temperature=temperature,

top_p=top_p,

do_sample=do_sample,

repetition_penalty=1.1,

eos_token_id=tokenizer.eos_token_id,

pad_token_id=tokenizer.pad_token_id,

)

입력 프롬프트 제외하고 생성된 텍스트만 반환

generated_ids = outputs[0][inputs["input_ids"].shape[1]:]

return tokenizer.decode(generated_ids, skip_special_tokens=True)

사용 예시

tokenizer, model = load_model("Qwen/Qwen2.5-7B-Instruct")

Chat template 적용

messages = [

{"role": "system", "content": "당신은 도움이 되는 AI 어시스턴트입니다."},

{"role": "user", "content": "파이썬으로 피보나치 수열을 구하는 코드를 작성해주세요."}

]

prompt = tokenizer.apply_chat_template(

messages,

tokenize=False,

add_generation_prompt=True

)

response = generate_text(model, tokenizer, prompt)

print(response)

2.5 토크나이저 심화

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("meta-llama/Meta-Llama-3-8B")

인코딩 옵션

text = "안녕하세요! HuggingFace를 배워봅시다."

기본 인코딩

ids = tokenizer.encode(text)

print(f"토큰 ID: {ids}")

print(f"토큰 수: {len(ids)}")

토큰 확인

tokens = tokenizer.tokenize(text)

print(f"토큰: {tokens}")

특수 토큰 포함/제외

ids_with_special = tokenizer.encode(text, add_special_tokens=True)

ids_without_special = tokenizer.encode(text, add_special_tokens=False)

print(f"특수 토큰 포함: {len(ids_with_special)}")

print(f"특수 토큰 제외: {len(ids_without_special)}")

배치 처리와 패딩

batch = [

"짧은 문장",

"이것은 조금 더 긴 문장입니다. 패딩이 적용됩니다."

]

encoded = tokenizer(

batch,

padding="max_length",

max_length=64,

truncation=True,

return_tensors="pt",

return_attention_mask=True

)

print("input_ids shape:", encoded["input_ids"].shape)

print("attention_mask shape:", encoded["attention_mask"].shape)

토큰 타입 ID (BERT 스타일 pair encoding)

bert_tokenizer = AutoTokenizer.from_pretrained("klue/roberta-base")

pair_encoded = bert_tokenizer(

"질문: AI는 무엇인가요?",

"문맥: AI는 인공지능의 약자입니다.",

return_tensors="pt"

)

print("token_type_ids:", pair_encoded.get("token_type_ids"))

특수 토큰 추가

special_tokens = {"additional_special_tokens": ["[DOMAIN]", "[ENTITY]", "[DATE]"]}

num_added = tokenizer.add_special_tokens(special_tokens)

print(f"추가된 특수 토큰 수: {num_added}")

3. Datasets 라이브러리

3.1 데이터셋 로딩

from datasets import load_dataset

Hub에서 데이터셋 로딩

dataset = load_dataset("klue", "sts")

print(dataset)

DatasetDict({train: Dataset({features: [...], num_rows: ...})})

특정 스플릿만 로딩

train_ds = load_dataset("klue", "sts", split="train")

val_ds = load_dataset("klue", "sts", split="validation")

로컬 파일 로딩

local_ds = load_dataset("json", data_files={"train": "train.jsonl", "test": "test.jsonl"})

csv_ds = load_dataset("csv", data_files="data.csv")

text_ds = load_dataset("text", data_files="corpus.txt")

스플릿 비율 지정

split_ds = load_dataset("klue", "sts", split="train[:80%]")

val_split = load_dataset("klue", "sts", split="train[80%:]")

데이터셋 정보 확인

print(train_ds.features)

print(train_ds.column_names)

print(train_ds.num_rows)

print(train_ds[0]) # 첫 번째 샘플

print(train_ds[:5]) # 처음 5개 샘플

3.2 데이터셋 전처리

from datasets import load_dataset

from transformers import AutoTokenizer

dataset = load_dataset("klue", "sts")

tokenizer = AutoTokenizer.from_pretrained("klue/roberta-base")

map 함수로 토크나이징

def tokenize_function(examples):

return tokenizer(

examples["sentence1"],

examples["sentence2"],

padding="max_length",

truncation=True,

max_length=128

)

tokenized_ds = dataset.map(

tokenize_function,

batched=True, # 배치 처리로 속도 향상

num_proc=4, # 멀티프로세싱

remove_columns=["sentence1", "sentence2", "guid"]

)

filter로 조건에 맞는 샘플만 선택

filtered_ds = dataset["train"].filter(

lambda x: x["label"] > 3.0

)

print(f"필터 후 크기: {len(filtered_ds)}")

select로 인덱스 기반 선택

small_ds = dataset["train"].select(range(1000))

sort

sorted_ds = dataset["train"].sort("label", reverse=True)

shuffle

shuffled_ds = dataset["train"].shuffle(seed=42)

rename_column

renamed_ds = dataset["train"].rename_column("label", "score")

컬럼 추가

def add_text_length(example):

example["text_length"] = len(example["sentence1"].split())

return example

ds_with_length = dataset["train"].map(add_text_length)

데이터셋 저장

tokenized_ds.save_to_disk("./tokenized_klue_sts")

저장된 데이터셋 로딩

from datasets import load_from_disk

loaded_ds = load_from_disk("./tokenized_klue_sts")

3.3 커스텀 데이터셋 생성과 업로드

from datasets import Dataset, DatasetDict, Features, Value, ClassLabel

pandas DataFrame에서 Dataset 생성

df = pd.DataFrame({

"text": ["긍정적인 문장입니다.", "부정적인 문장입니다.", "중립적인 문장입니다."],

"label": [1, 0, 2]

})

custom_ds = Dataset.from_pandas(df)

딕셔너리에서 Dataset 생성

data_dict = {

"text": ["sample 1", "sample 2"],

"score": [0.8, 0.3]

}

ds_from_dict = Dataset.from_dict(data_dict)

Features 정의

features = Features({

"text": Value("string"),

"label": ClassLabel(names=["negative", "positive", "neutral"]),

"score": Value("float32")

})

Hub에 업로드

from huggingface_hub import login

login()

custom_ds.push_to_hub("your-username/my-custom-dataset")

DatasetDict로 스플릿 포함 업로드

dataset_dict = DatasetDict({

"train": custom_ds,

"test": custom_ds

})

dataset_dict.push_to_hub("your-username/my-custom-dataset")

3.4 스트리밍 데이터셋

from datasets import load_dataset

스트리밍 모드로 로딩 (메모리에 전체 데이터를 올리지 않음)

streaming_ds = load_dataset(

"HuggingFaceFW/fineweb",

"sample-10BT",

split="train",

streaming=True

)

이터레이터로 순회

for i, example in enumerate(streaming_ds):

if i >= 5:

break

print(example["text"][:100])

map과 filter도 스트리밍에서 사용 가능

filtered_stream = streaming_ds.filter(lambda x: len(x["text"]) > 500)

mapped_stream = filtered_stream.map(lambda x: {"text_len": len(x["text"])})

배치 처리

def process_batch(batch):

return {"processed": [t.lower() for t in batch["text"]]}

batched_stream = streaming_ds.map(process_batch, batched=True, batch_size=16)

DataLoader로 변환

from torch.utils.data import DataLoader

dataloader = DataLoader(

list(streaming_ds.take(1000)), # 처음 1000개만 로딩

batch_size=8,

shuffle=True

)

3.5 DataCollator 활용

from transformers import DataCollatorWithPadding, DataCollatorForSeq2Seq, DataCollatorForLanguageModeling

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("klue/roberta-base")

동적 패딩 (배치 내 최대 길이에 맞게 패딩)

data_collator = DataCollatorWithPadding(tokenizer=tokenizer)

Seq2Seq 모델용 (디코더 인풋 자동 생성)

from transformers import AutoTokenizer as T5Tok

t5_tokenizer = T5Tok.from_pretrained("t5-base")

seq2seq_collator = DataCollatorForSeq2Seq(

tokenizer=t5_tokenizer,

padding=True,

return_tensors="pt"

)

Language Modeling (MLM)

mlm_collator = DataCollatorForLanguageModeling(

tokenizer=tokenizer,

mlm=True,

mlm_probability=0.15 # 15% 토큰 마스킹

)

CLM (Causal Language Modeling)

clm_collator = DataCollatorForLanguageModeling(

tokenizer=tokenizer,

mlm=False # CLM 모드

)

4. Tokenizers 라이브러리

4.1 빠른 토크나이저

HuggingFace `tokenizers` 라이브러리는 Rust로 구현된 초고속 토크나이저를 제공합니다. 기존 Python 토크나이저 대비 최대 100배 빠릅니다.

from tokenizers import Tokenizer, models, trainers, pre_tokenizers, decoders, processors

from tokenizers.models import BPE, WordPiece, Unigram

BPE 토크나이저 훈련

tokenizer = Tokenizer(BPE(unk_token="[UNK]"))

tokenizer.pre_tokenizer = pre_tokenizers.ByteLevel(add_prefix_space=False)

trainer = trainers.BpeTrainer(

vocab_size=30000,

min_frequency=2,

special_tokens=["[UNK]", "[CLS]", "[SEP]", "[PAD]", "[MASK]"]

)

파일에서 훈련

files = ["corpus.txt"]

tokenizer.train(files, trainer)

저장

tokenizer.save("my_tokenizer.json")

로딩

loaded_tokenizer = Tokenizer.load("my_tokenizer.json")

인코딩

output = tokenizer.encode("안녕하세요, HuggingFace!")

print(output.tokens)

print(output.ids)

배치 인코딩

batch_output = tokenizer.encode_batch(["문장 1", "문장 2"])

4.2 WordPiece 토크나이저 (BERT 스타일)

from tokenizers import Tokenizer

from tokenizers.models import WordPiece

from tokenizers.trainers import WordPieceTrainer

from tokenizers.pre_tokenizers import Whitespace

from tokenizers.processors import TemplateProcessing

WordPiece 초기화

tokenizer = Tokenizer(WordPiece(unk_token="[UNK]"))

tokenizer.pre_tokenizer = Whitespace()

trainer = WordPieceTrainer(

vocab_size=30522,

special_tokens=["[UNK]", "[CLS]", "[SEP]", "[PAD]", "[MASK]"]

)

tokenizer.train(["corpus.txt"], trainer)

BERT 스타일 후처리 추가

tokenizer.post_processor = TemplateProcessing(

single="[CLS] $A [SEP]",

pair="[CLS] $A [SEP] $B:1 [SEP]:1",

special_tokens=[

("[CLS]", tokenizer.token_to_id("[CLS]")),

("[SEP]", tokenizer.token_to_id("[SEP]")),

],

)

HuggingFace transformers와 통합

from transformers import PreTrainedTokenizerFast

fast_tokenizer = PreTrainedTokenizerFast(

tokenizer_object=tokenizer,

unk_token="[UNK]",

pad_token="[PAD]",

cls_token="[CLS]",

sep_token="[SEP]",

mask_token="[MASK]"

)

Hub에 업로드

fast_tokenizer.push_to_hub("your-username/my-tokenizer")

5. PEFT: 파라미터 효율적 파인튜닝

5.1 LoRA 기초

LoRA(Low-Rank Adaptation)는 기존 모델 가중치를 동결하고, 저랭크 행렬 두 개만 훈련하여 파라미터 수를 획기적으로 줄입니다.

from peft import LoraConfig, get_peft_model, TaskType

from transformers import AutoModelForCausalLM, AutoTokenizer

베이스 모델 로딩

model_name = "meta-llama/Meta-Llama-3-8B"

tokenizer = AutoTokenizer.from_pretrained(model_name)

model = AutoModelForCausalLM.from_pretrained(

model_name,

torch_dtype=torch.bfloat16,

device_map="auto"

)

LoRA 설정

lora_config = LoraConfig(

task_type=TaskType.CAUSAL_LM,

r=16, # 랭크 (낮을수록 파라미터 적음)

lora_alpha=32, # 스케일링 팩터

target_modules=[ # LoRA를 적용할 레이어

"q_proj", "v_proj", # Attention Q, V

"k_proj", "o_proj", # Attention K, Output

"gate_proj", "up_proj", # FFN

"down_proj"

],

lora_dropout=0.05,

bias="none",

inference_mode=False

)

LoRA 적용

peft_model = get_peft_model(model, lora_config)

peft_model.print_trainable_parameters()

trainable params: 41,943,040 || all params: 8,072,925,184 || trainable%: 0.5196

5.2 QLoRA: 4비트 양자화 + LoRA

from peft import prepare_model_for_kbit_training, LoraConfig, get_peft_model

from transformers import AutoModelForCausalLM, BitsAndBytesConfig

4비트 양자화 설정

bnb_config = BitsAndBytesConfig(

load_in_4bit=True,

bnb_4bit_use_double_quant=True, # 이중 양자화로 메모리 절약

bnb_4bit_quant_type="nf4", # Normal Float 4

bnb_4bit_compute_dtype=torch.bfloat16

)

양자화된 모델 로딩

model = AutoModelForCausalLM.from_pretrained(

"meta-llama/Meta-Llama-3-8B",

quantization_config=bnb_config,

device_map="auto"

)

kbit 훈련 준비 (그래디언트 체크포인팅 활성화)

model = prepare_model_for_kbit_training(model)

LoRA 설정 및 적용

lora_config = LoraConfig(

r=64,

lora_alpha=128,

target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],

lora_dropout=0.1,

bias="none",

task_type="CAUSAL_LM"

)

model = get_peft_model(model, lora_config)

model.print_trainable_parameters()

5.3 완전한 파인튜닝 예제 (SFTTrainer 활용)

from trl import SFTTrainer, SFTConfig

from peft import LoraConfig

from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig

from datasets import load_dataset

1. 데이터 준비

dataset = load_dataset("iamksh/kor_alpaca_data_v1.1", split="train")

def format_conversation(sample):

system = "당신은 도움이 되는 한국어 AI 어시스턴트입니다."

instruction = sample["instruction"]

inp = sample.get("input", "")

output = sample["output"]

if inp:

user_msg = f"{instruction}\n\n입력: {inp}"

else:

user_msg = instruction

return {

"text": f"<|system|>\n{system}\n<|user|>\n{user_msg}\n<|assistant|>\n{output}"

}

dataset = dataset.map(format_conversation)

2. 모델 설정

bnb_config = BitsAndBytesConfig(

load_in_4bit=True,

bnb_4bit_use_double_quant=True,

bnb_4bit_quant_type="nf4",

bnb_4bit_compute_dtype=torch.bfloat16

)

model = AutoModelForCausalLM.from_pretrained(

"meta-llama/Meta-Llama-3-8B",

quantization_config=bnb_config,

device_map="auto"

)

tokenizer = AutoTokenizer.from_pretrained("meta-llama/Meta-Llama-3-8B")

tokenizer.pad_token = tokenizer.eos_token

3. LoRA 설정

peft_config = LoraConfig(

r=32,

lora_alpha=64,

lora_dropout=0.05,

bias="none",

task_type="CAUSAL_LM",

target_modules=["q_proj", "v_proj", "k_proj", "o_proj"]

)

4. 훈련 설정

sft_config = SFTConfig(

output_dir="./qlora-llama3-ko",

num_train_epochs=3,

per_device_train_batch_size=2,

gradient_accumulation_steps=4,

learning_rate=2e-4,

fp16=False,

bf16=True,

logging_steps=10,

save_steps=100,

warmup_ratio=0.03,

lr_scheduler_type="cosine",

dataset_text_field="text",

max_seq_length=2048,

report_to="wandb"

)

5. 훈련

trainer = SFTTrainer(

model=model,

train_dataset=dataset,

peft_config=peft_config,

args=sft_config,

processing_class=tokenizer,

)

trainer.train()

trainer.save_model("./qlora-llama3-ko-final")

5.4 어댑터 저장, 로딩, 병합

from peft import PeftModel

from transformers import AutoModelForCausalLM, AutoTokenizer

LoRA 어댑터만 저장

peft_model.save_pretrained("./lora-adapter")

tokenizer.save_pretrained("./lora-adapter")

Hub에 어댑터 업로드

peft_model.push_to_hub("your-username/llama3-ko-lora")

어댑터 로딩 (베이스 모델 + 어댑터)

base_model = AutoModelForCausalLM.from_pretrained(

"meta-llama/Meta-Llama-3-8B",

torch_dtype=torch.bfloat16,

device_map="auto"

)

peft_model = PeftModel.from_pretrained(base_model, "./lora-adapter")

어댑터를 베이스 모델에 병합 (추론 속도 최적화)

merged_model = peft_model.merge_and_unload()

merged_model.save_pretrained("./merged-llama3-ko")

tokenizer.save_pretrained("./merged-llama3-ko")

6. Accelerate 라이브러리

6.1 Accelerate 설정

대화형 설정

accelerate config

단일 GPU 기본 설정

accelerate config --config_file ./accelerate_config.yaml

accelerate_config.yaml

compute_environment: LOCAL_MACHINE

distributed_type: MULTI_GPU

num_machines: 1

num_processes: 4

gpu_ids: all

mixed_precision: bf16

6.2 기본 Accelerate 학습 루프

from accelerate import Accelerator

from transformers import AutoModelForSequenceClassification, AutoTokenizer, AdamW

from datasets import load_dataset

from torch.utils.data import DataLoader

def training_function():

Accelerator 초기화

accelerator = Accelerator(

mixed_precision="bf16",

gradient_accumulation_steps=4,

log_with="wandb"

)

모델과 토크나이저

model_name = "klue/roberta-base"

tokenizer = AutoTokenizer.from_pretrained(model_name)

model = AutoModelForSequenceClassification.from_pretrained(model_name, num_labels=2)

데이터셋

dataset = load_dataset("klue", "ynat", split="train")

def tokenize(examples):

return tokenizer(examples["title"], truncation=True, max_length=128)

tokenized = dataset.map(tokenize, batched=True)

tokenized.set_format("torch", columns=["input_ids", "attention_mask", "label"])

dataloader = DataLoader(tokenized, batch_size=16, shuffle=True)

옵티마이저

optimizer = AdamW(model.parameters(), lr=2e-5)

Accelerate 준비 (모델, 옵티마이저, 데이터로더 모두 준비)

model, optimizer, dataloader = accelerator.prepare(model, optimizer, dataloader)

학습 루프

for epoch in range(3):

model.train()

for batch in dataloader:

with accelerator.accumulate(model):

outputs = model(**batch)

loss = outputs.loss

accelerator.backward(loss)

accelerator.clip_grad_norm_(model.parameters(), 1.0)

optimizer.step()

optimizer.zero_grad()

accelerator.print(f"Epoch {epoch} completed")

저장

accelerator.wait_for_everyone()

unwrapped_model = accelerator.unwrap_model(model)

unwrapped_model.save_pretrained("./output", save_function=accelerator.save)

멀티 GPU 실행: accelerate launch train.py

training_function()

6.3 DeepSpeed 통합

from accelerate import Accelerator

from accelerate.utils import DeepSpeedPlugin

DeepSpeed ZeRO-2 설정

ds_plugin = DeepSpeedPlugin(

hf_ds_config={

"zero_optimization": {

"stage": 2,

"allgather_partitions": True,

"allgather_bucket_size": 2e8,

"overlap_comm": True,

"reduce_scatter": True,

"reduce_bucket_size": 2e8,

"contiguous_gradients": True

},

"bf16": {"enabled": True},

"optimizer": {

"type": "AdamW",

"params": {

"lr": "auto",

"weight_decay": "auto"

}

}

}

)

accelerator = Accelerator(deepspeed_plugin=ds_plugin)

6.4 그래디언트 누적과 Mixed Precision

from accelerate import Accelerator

accelerator = Accelerator(

mixed_precision="bf16", # fp16, bf16, no 중 선택

gradient_accumulation_steps=8 # 8 스텝마다 실제 업데이트

)

학습 루프에서 accumulate 컨텍스트 매니저 사용

for batch in dataloader:

with accelerator.accumulate(model):

output = model(**batch)

loss = output.loss / accelerator.gradient_accumulation_steps

accelerator.backward(loss)

if accelerator.sync_gradients:

accelerator.clip_grad_norm_(model.parameters(), 1.0)

optimizer.step()

lr_scheduler.step()

optimizer.zero_grad()

7. TRL: Transformer Reinforcement Learning

7.1 SFTTrainer

from trl import SFTTrainer, SFTConfig

from transformers import AutoModelForCausalLM, AutoTokenizer

from datasets import load_dataset

model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-7B")

tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-7B")

dataset = load_dataset("HuggingFaceH4/ultrachat_200k", split="train_sft[:5%]")

training_args = SFTConfig(

output_dir="./sft-qwen",

max_seq_length=2048,

num_train_epochs=1,

per_device_train_batch_size=4,

gradient_accumulation_steps=2,

learning_rate=2e-5,

bf16=True,

save_strategy="epoch",

logging_steps=10,

dataset_text_field="messages", # chat 형식 컬럼

)

trainer = SFTTrainer(

model=model,

args=training_args,

train_dataset=dataset,

processing_class=tokenizer,

)

trainer.train()

7.2 DPOTrainer (Direct Preference Optimization)

from trl import DPOTrainer, DPOConfig

from transformers import AutoModelForCausalLM, AutoTokenizer

from datasets import load_dataset

DPO에는 reference 모델이 필요

model = AutoModelForCausalLM.from_pretrained("your-sft-model")

ref_model = AutoModelForCausalLM.from_pretrained("your-sft-model") # frozen

tokenizer = AutoTokenizer.from_pretrained("your-sft-model")

DPO 데이터셋: prompt, chosen, rejected 컬럼 필요

dpo_dataset = load_dataset("HuggingFaceH4/ultrafeedback_binarized", split="train_prefs")

dpo_config = DPOConfig(

output_dir="./dpo-model",

num_train_epochs=1,

per_device_train_batch_size=2,

gradient_accumulation_steps=4,

learning_rate=5e-7,

beta=0.1, # KL 패널티 강도

bf16=True,

loss_type="sigmoid", # sigmoid, hinge, ipo 등

)

trainer = DPOTrainer(

model=model,

ref_model=ref_model,

args=dpo_config,

train_dataset=dpo_dataset,

processing_class=tokenizer,

)

trainer.train()

7.3 RewardTrainer

from trl import RewardTrainer, RewardConfig

from transformers import AutoModelForSequenceClassification, AutoTokenizer

from datasets import load_dataset

리워드 모델 (시퀀스 분류 헤드 추가)

model = AutoModelForSequenceClassification.from_pretrained(

"klue/roberta-base",

num_labels=1 # 스칼라 리워드 출력

)

tokenizer = AutoTokenizer.from_pretrained("klue/roberta-base")

preference 데이터셋 필요

dataset = load_dataset("HuggingFaceH4/ultrafeedback_binarized", split="train_prefs")

reward_config = RewardConfig(

output_dir="./reward-model",

num_train_epochs=1,

per_device_train_batch_size=8,

learning_rate=1e-5,

max_length=512,

)

trainer = RewardTrainer(

model=model,

args=reward_config,

train_dataset=dataset,

processing_class=tokenizer,

)

trainer.train()

8. Diffusers 라이브러리

8.1 기본 이미지 생성

from diffusers import StableDiffusionPipeline, DPMSolverMultistepScheduler

Stable Diffusion 파이프라인 로딩

pipe = StableDiffusionPipeline.from_pretrained(

"runwayml/stable-diffusion-v1-5",

torch_dtype=torch.float16,

use_safetensors=True

)

더 빠른 스케줄러 사용

pipe.scheduler = DPMSolverMultistepScheduler.from_config(pipe.scheduler.config)

pipe = pipe.to("cuda")

메모리 최적화

pipe.enable_attention_slicing()

pipe.enable_xformers_memory_efficient_attention()

이미지 생성

image = pipe(

prompt="A beautiful Korean temple in autumn, photorealistic, 8k",

negative_prompt="blurry, low quality, cartoon",

num_inference_steps=20,

guidance_scale=7.5,

width=512,

height=512,

generator=torch.Generator("cuda").manual_seed(42)

).images[0]

image.save("temple.png")

SDXL 사용

from diffusers import StableDiffusionXLPipeline

xl_pipe = StableDiffusionXLPipeline.from_pretrained(

"stabilityai/stable-diffusion-xl-base-1.0",

torch_dtype=torch.float16,

variant="fp16"

).to("cuda")

image = xl_pipe(

prompt="A majestic mountain landscape, 4k photo",

num_inference_steps=30,

guidance_scale=5.0

).images[0]

8.2 LoRA for Diffusion

from diffusers import StableDiffusionPipeline

LoRA 어댑터가 포함된 파이프라인 로딩

pipe = StableDiffusionPipeline.from_pretrained(

"runwayml/stable-diffusion-v1-5",

torch_dtype=torch.float16

).to("cuda")

LoRA 웨이트 로딩

pipe.load_lora_weights("path/to/lora/weights", weight_name="lora.safetensors")

pipe.fuse_lora(lora_scale=0.8)

image = pipe(

"a photo of sks person in a fantasy world",

num_inference_steps=30

).images[0]

9. Evaluate 라이브러리

9.1 기본 메트릭 사용

BLEU 점수 (번역 품질)

bleu = evaluate.load("bleu")

result = bleu.compute(

predictions=["the cat is on the mat"],

references=[["the cat is on the mat", "there is a cat on the mat"]]

)

print(f"BLEU: {result['bleu']:.4f}")

ROUGE 점수 (요약 품질)

rouge = evaluate.load("rouge")

result = rouge.compute(

predictions=["매우 유용한 라이브러리입니다."],

references=["이것은 매우 유용한 라이브러리입니다."]

)

print(result) # rouge1, rouge2, rougeL, rougeLsum

BERTScore (의미 유사도)

bertscore = evaluate.load("bertscore")

result = bertscore.compute(

predictions=["AI가 세상을 바꾸고 있습니다."],

references=["인공지능이 세계를 변화시키고 있습니다."],

lang="ko"

)

print(f"BERTScore F1: {result['f1'][0]:.4f}")

Accuracy

accuracy = evaluate.load("accuracy")

result = accuracy.compute(predictions=[0, 1, 1, 0], references=[0, 1, 0, 0])

print(f"Accuracy: {result['accuracy']:.4f}")

Perplexity

perplexity = evaluate.load("perplexity", module_type="metric")

9.2 훈련 중 평가 통합

from transformers import Trainer, TrainingArguments

accuracy = evaluate.load("accuracy")

def compute_metrics(eval_pred):

logits, labels = eval_pred

predictions = np.argmax(logits, axis=-1)

return accuracy.compute(predictions=predictions, references=labels)

training_args = TrainingArguments(

output_dir="./model-output",

evaluation_strategy="epoch",

num_train_epochs=3,

per_device_train_batch_size=16,

per_device_eval_batch_size=32,

load_best_model_at_end=True,

metric_for_best_model="accuracy",

)

trainer = Trainer(

model=model,

args=training_args,

train_dataset=train_dataset,

eval_dataset=eval_dataset,

compute_metrics=compute_metrics,

)

10. Hub API와 자동화

10.1 huggingface_hub 클라이언트

from huggingface_hub import HfApi, hf_hub_download, snapshot_download

from huggingface_hub import create_repo, upload_file, upload_folder

api = HfApi()

모델 파일 다운로드

local_path = hf_hub_download(

repo_id="meta-llama/Meta-Llama-3-8B",

filename="config.json"

)

전체 저장소 다운로드

snapshot_download(

repo_id="meta-llama/Meta-Llama-3-8B",

local_dir="./llama3-8b",

ignore_patterns=["*.bin", "*.pt"] # safetensors만 다운로드

)

새 저장소 생성

create_repo("your-username/my-model", private=True)

create_repo("your-username/my-dataset", repo_type="dataset")

create_repo("your-username/my-space", repo_type="space", space_sdk="gradio")

파일 업로드

upload_file(

path_or_fileobj="./my_model.bin",

path_in_repo="pytorch_model.bin",

repo_id="your-username/my-model"

)

폴더 업로드

upload_folder(

folder_path="./output-model",

repo_id="your-username/my-model",

ignore_patterns=["*.log", "__pycache__"]

)

저장소 정보 조회

model_info = api.model_info("meta-llama/Meta-Llama-3-8B")

print(model_info.card_data)

print(model_info.safetensors)

모델 검색

models = api.list_models(

filter="text-generation",

language="ko",

sort="downloads",

limit=10

)

for m in models:

print(m.id, m.downloads)

10.2 모델 카드 자동 생성

from huggingface_hub import ModelCard, ModelCardData

card_data = ModelCardData(

language="ko",

license="apache-2.0",

library_name="transformers",

tags=["llama", "korean", "fine-tuned"],

datasets=["iamksh/kor_alpaca_data_v1.1"],

base_model="meta-llama/Meta-Llama-3-8B",

metrics=[{"type": "accuracy", "value": 0.95}]

)

card = ModelCard.from_template(

card_data,

template_str="""

{{ card_data }}

한국어 Llama-3-8B

이 모델은 한국어 명령 따르기를 위해 파인튜닝된 Llama-3-8B입니다.

사용법

from transformers import pipeline

generator = pipeline("text-generation", model="your-username/llama3-ko")

훈련 세부 사항

- 베이스 모델: meta-llama/Meta-Llama-3-8B

- 방법: QLoRA (4-bit)

- 데이터셋: 한국어 Alpaca

"""

)

card.push_to_hub("your-username/llama3-ko")

11. Optimum 라이브러리

11.1 ONNX 변환

from optimum.exporters.onnx import main_export

모델을 ONNX 형식으로 변환

main_export(

model_name_or_path="klue/roberta-base",

output="./roberta-onnx",

task="text-classification"

)

ONNX 모델 로딩 및 추론

from optimum.onnxruntime import ORTModelForSequenceClassification

from transformers import AutoTokenizer

ort_model = ORTModelForSequenceClassification.from_pretrained("./roberta-onnx")

tokenizer = AutoTokenizer.from_pretrained("klue/roberta-base")

inputs = tokenizer("이 영화는 정말 재미있었습니다!", return_tensors="pt")

outputs = ort_model(**inputs)

print(outputs.logits)

11.2 BetterTransformer

from optimum.bettertransformer import BetterTransformer

from transformers import AutoModelForSequenceClassification

model = AutoModelForSequenceClassification.from_pretrained("klue/roberta-base")

BetterTransformer로 변환 (PyTorch 2.0+ 최적화 활용)

model = BetterTransformer.transform(model)

추론 (자동으로 Flash Attention 등 최적화 사용)

model.eval()

with torch.no_grad():

outputs = model(**inputs)

12. 실전 프로젝트: 한국어 LLM 파인튜닝

12.1 한국어 데이터셋 준비

from datasets import load_dataset, concatenate_datasets

KLUE 벤치마크 데이터셋

klue_tc = load_dataset("klue", "ynat", split="train") # 주제 분류

klue_sts = load_dataset("klue", "sts", split="train") # 의미 유사도

klue_nli = load_dataset("klue", "nli", split="train") # 자연어 추론

klue_ner = load_dataset("klue", "ner", split="train") # 개체명 인식

klue_re = load_dataset("klue", "re", split="train") # 관계 추출

klue_dp = load_dataset("klue", "dp", split="train") # 의존 구문 분석

한국어 명령 데이터셋

ko_alpaca = load_dataset("iamksh/kor_alpaca_data_v1.1", split="train")

대화 데이터셋

ko_chat = load_dataset("heegyu/open-korean-instructions", split="train")

def format_instruction_dataset(example):

"""Alpaca 형식을 ChatML 형식으로 변환"""

instruction = example["instruction"]

inp = example.get("input", "").strip()

output = example["output"]

if inp:

user_content = f"{instruction}\n\n{inp}"

else:

user_content = instruction

messages = [

{"role": "system", "content": "당신은 도움이 되는 한국어 AI 어시스턴트입니다."},

{"role": "user", "content": user_content},

{"role": "assistant", "content": output}

]

return {"messages": messages}

formatted_dataset = ko_alpaca.map(format_instruction_dataset)

print(formatted_dataset[0])

12.2 전체 QLoRA 파인튜닝 파이프라인

from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig

from peft import LoraConfig, prepare_model_for_kbit_training, get_peft_model

from trl import SFTTrainer, SFTConfig

from datasets import load_dataset

─── 설정 ───────────────────────────────────────────────

MODEL_NAME = "meta-llama/Meta-Llama-3-8B"

OUTPUT_DIR = "./llama3-ko-qlora"

MAX_SEQ_LEN = 2048

NUM_EPOCHS = 2

BATCH_SIZE = 2

GRAD_ACCUM = 8

LR = 2e-4

─── 4bit 양자화 ─────────────────────────────────────────

bnb_config = BitsAndBytesConfig(

load_in_4bit=True,

bnb_4bit_use_double_quant=True,

bnb_4bit_quant_type="nf4",

bnb_4bit_compute_dtype=torch.bfloat16

)

─── 모델/토크나이저 로딩 ─────────────────────────────────

tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)

tokenizer.pad_token = tokenizer.eos_token

tokenizer.padding_side = "right"

model = AutoModelForCausalLM.from_pretrained(

MODEL_NAME,

quantization_config=bnb_config,

device_map="auto",

attn_implementation="flash_attention_2"

)

model = prepare_model_for_kbit_training(model)

─── LoRA 설정 ───────────────────────────────────────────

peft_config = LoraConfig(

r=64,

lora_alpha=128,

target_modules=[

"q_proj", "k_proj", "v_proj", "o_proj",

"gate_proj", "up_proj", "down_proj"

],

lora_dropout=0.05,

bias="none",

task_type="CAUSAL_LM"

)

─── 데이터셋 ────────────────────────────────────────────

dataset = load_dataset("iamksh/kor_alpaca_data_v1.1", split="train")

def format_sample(example):

messages = [

{"role": "system", "content": "당신은 도움이 되는 AI 어시스턴트입니다."},

{"role": "user", "content": example["instruction"]},

{"role": "assistant", "content": example["output"]}

]

text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=False)

return {"text": text}

dataset = dataset.map(format_sample)

─── 훈련 설정 ───────────────────────────────────────────

training_args = SFTConfig(

output_dir=OUTPUT_DIR,

num_train_epochs=NUM_EPOCHS,

per_device_train_batch_size=BATCH_SIZE,

gradient_accumulation_steps=GRAD_ACCUM,

learning_rate=LR,

bf16=True,

gradient_checkpointing=True,

optim="paged_adamw_8bit",

warmup_ratio=0.05,

lr_scheduler_type="cosine",

save_strategy="epoch",

logging_steps=10,

dataset_text_field="text",

max_seq_length=MAX_SEQ_LEN,

packing=True, # 여러 샘플을 하나의 시퀀스로 패킹

)

─── 훈련 ────────────────────────────────────────────────

trainer = SFTTrainer(

model=model,

train_dataset=dataset,

peft_config=peft_config,

args=training_args,

processing_class=tokenizer,

)

trainer.train()

─── 저장 ────────────────────────────────────────────────

trainer.model.save_pretrained(f"{OUTPUT_DIR}/adapter")

tokenizer.save_pretrained(f"{OUTPUT_DIR}/adapter")

print("훈련 완료!")

12.3 파인튜닝된 모델 평가

from peft import PeftModel

from transformers import AutoModelForCausalLM, AutoTokenizer

모델 로딩

base_model = AutoModelForCausalLM.from_pretrained(

"meta-llama/Meta-Llama-3-8B",

torch_dtype=torch.bfloat16,

device_map="auto"

)

model = PeftModel.from_pretrained(base_model, "./llama3-ko-qlora/adapter")

tokenizer = AutoTokenizer.from_pretrained("meta-llama/Meta-Llama-3-8B")

def chat(user_message: str, max_new_tokens: int = 512) -> str:

messages = [

{"role": "system", "content": "당신은 도움이 되는 AI 어시스턴트입니다."},

{"role": "user", "content": user_message}

]

prompt = tokenizer.apply_chat_template(

messages,

tokenize=False,

add_generation_prompt=True

)

inputs = tokenizer(prompt, return_tensors="pt").to(model.device)

with torch.no_grad():

outputs = model.generate(

**inputs,

max_new_tokens=max_new_tokens,

do_sample=True,

temperature=0.7,

top_p=0.9,

repetition_penalty=1.1

)

response = tokenizer.decode(

outputs[0][inputs["input_ids"].shape[1]:],

skip_special_tokens=True

)

return response

평가 테스트

test_questions = [

"파이썬으로 피보나치 수열을 출력하는 코드를 작성해주세요.",

"대한민국의 수도는 어디인가요?",

"머신러닝과 딥러닝의 차이점을 설명해주세요.",

]

for q in test_questions:

print(f"Q: {q}")

print(f"A: {chat(q)}")

print("-" * 50)

12.4 Gradio Spaces 배포

from transformers import pipeline

파이프라인 로딩

pipe = pipeline(

"text-generation",

model="./llama3-ko-qlora/merged",

torch_dtype=torch.bfloat16,

device_map="auto"

)

def respond(message, history, system_prompt, max_tokens, temperature):

messages = [{"role": "system", "content": system_prompt}]

for user, assistant in history:

messages.append({"role": "user", "content": user})

messages.append({"role": "assistant", "content": assistant})

messages.append({"role": "user", "content": message})

output = pipe(

messages,

max_new_tokens=max_tokens,

temperature=temperature,

do_sample=True

)

return output[0]["generated_text"][-1]["content"]

demo = gr.ChatInterface(

respond,

additional_inputs=[

gr.Textbox("당신은 도움이 되는 AI 어시스턴트입니다.", label="시스템 프롬프트"),

gr.Slider(50, 1000, 256, label="최대 토큰"),

gr.Slider(0.1, 2.0, 0.7, label="Temperature")

],

title="한국어 Llama-3 챗봇",

description="QLoRA로 파인튜닝된 한국어 LLM"

)

if __name__ == "__main__":

demo.launch()

마치며

이 가이드에서 HuggingFace 생태계의 핵심 구성 요소들을 살펴보았습니다.

- **transformers**: 파이프라인부터 세밀한 모델 제어까지 다양한 추상화 수준 제공

- **datasets**: 효율적인 데이터 로딩, 처리, 공유

- **tokenizers**: Rust 기반 초고속 토크나이징

- **peft**: LoRA/QLoRA로 대형 모델을 소비자 GPU에서도 파인튜닝

- **accelerate**: 멀티 GPU/TPU 학습을 코드 변경 없이 지원

- **trl**: SFT, DPO, RLHF 등 현대적 파인튜닝 기법

- **diffusers**: 이미지 생성 모델의 표준 라이브러리

- **evaluate**: 표준화된 모델 평가

HuggingFace 생태계는 빠르게 발전하고 있으므로 공식 문서와 블로그를 주기적으로 확인하는 것을 권장합니다.

참고 자료

- HuggingFace 공식 문서: https://huggingface.co/docs

- transformers 문서: https://huggingface.co/docs/transformers

- PEFT 문서: https://huggingface.co/docs/peft

- Accelerate 문서: https://huggingface.co/docs/accelerate

- TRL 문서: https://huggingface.co/docs/trl

- Diffusers 문서: https://huggingface.co/docs/diffusers

현재 단락 (1/992)

HuggingFace는 현재 AI/ML 생태계에서 가장 중요한 플랫폼 중 하나입니다. 수십만 개의 사전학습 모델, 수만 개의 데이터셋, 그리고 실용적인 라이브러리들을 하나의 생태계...

작성 글자: 0원문 글자: 33,297작성 단락: 0/992