반응형
** 환경 구성
윈도우즈11
miniconda
- 지금까지 경험으로 miniconda 를 설치해서 환경 구성하는게 가장 편하다!
설치
Miniconda — Anaconda documentation
가상환경 설정
conda create -n hug python=3.10 # 3.10 파이썬 고수중...
conda activate hug
패키지 설치
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu124
# pytorch 정상확인
# python 실행해서 repl 상태
>>> import torch
>>> torch.__version__
'2.5.1+cu124'
>>> torch.cuda.is_available()
True
# 허깅페이스 라이브러리 설치
pip install transformers[torch]==4.47.1 datasets==2.20.0
# 양자화를 위한 라이브러리
pip install bitsandbytes
# 강화학습을 위한 TRL/PEFT 라이브러리 설치
pip install trl peft -U accelerate
# 평가를 위한 라이브러리
pip install rouge_score
** 허깅페이스 파이프라인 설명
입력 -(raw text) - 토크나이저 - (input_ids) - 모델 - (logits) - 후처리 - (prediction) - 출력
자연어 처리 : 토크나이저 - 모델 - 후처리
컴퓨터 비전 : 이미지 프로세서 - 모델 - 후처리
오디오 : 오디오 프로세서 - 모델 - 후처리
** 유용한 모델
기계번역 : T5 ( Text-To-Text Transfer Transformer ) - 구글개발 Sequence - to sequence 모델
텍스트 생성 : LlaMA - 메타 개발 인과적 언어 모델 ( Causal language model )
문서 시각질의 응답 수행 : LayoutLMv3 추출기 - 마이크로소프트 microsoft/layoutlmv3-base
그림 생성 : Stable-Diffusion 3
** 예제 소스
- T5 테스뚜
from transformers import DataCollatorForSeq2Seq
from transformers import Seq2SeqTrainingArguments, Seq2SeqTrainer
from transformers import T5TokenizerFast, T5ForConditionalGeneration
from datasets import load_dataset
model_name = "KETI-AIR/long-ke-t5-small"
tokenizer = T5TokenizerFast.from_pretrained(model_name)
model = T5ForConditionalGeneration.from_pretrained(model_name)
def preprocess_data(example, tokenizer):
translation = example["translation"]
translation_source = ["en: "+ instance["en"] for instance in translation]
translation_target = ["ko: "+ instance["ko"] for instance in translation]
tokenized = tokenizer(
translation_source, text_target = translation_target, truncation=True
)
return tokenized
dataset = load_dataset("Helsinki-NLP/opus-100", "en-ko") # 병렬 망뭉지 영어-한국어 번역 쌍
processed_dataset = dataset.map(
lambda example: preprocess_data(example, tokenizer),
batched=True,
remove_columns=dataset["train"].column_names
)
seq2seq_collator = DataCollatorForSeq2Seq(
tokenizer=tokenizer,
padding="longest",
return_tensors="pt",
)
training_arguments = Seq2SeqTrainingArguments(
output_dir="output",
per_device_train_batch_size=8,
per_device_eval_batch_size=16,
learning_rate=5e-5,
num_train_epochs=1,
eval_steps=2500,
logging_steps=2500,
seed=42
)
trainer = Seq2SeqTrainer(
model=model,
args=training_arguments,
data_collator=seq2seq_collator,
train_dataset=processed_dataset["train"].select(range(100000)),
eval_dataset=processed_dataset["validation"].select(range(1000)),
)
trainer.train()
## 번역 테스트
import torch
model.eval()
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
data = "en: It's always greate to acquire new knowledge."
inputs = tokenizer(data, return_tensors="pt").to(device)
with torch.no_grad():
outputs = model.generate(
**inputs,
max_length=512,
num_beams=4,
no_repeat_ngram_size=2,
early_stopping=True,
)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
## 평가
import evaluate
from torch.utils.data import DataLoader
dataloader = DataLoader(
processed_dataset["test"].select(range(100)),
collate_fn=seq2seq_collator,
batch_size=4,
shuffle=False,
)
generated_translated = []
true_translated_ids = processed_dataset["test"].select(range(100))["labels"]
true_translated = tokenizer.batch_decode(true_translated_ids, skip_special_tokens=True)
with torch.no_grad():
for batch in dataloader:
batch = batch.to(device)
output = model.generate(
**batch,
max_length=1026,
num_beams=4,
no_repeat_ngram_size=2,
early_stopping=True,
)
batch_translated = tokenizer.batch_decode(output, skip_special_tokens=True)
generated_translated.extend(batch_translated)
metric = evalute.load("bleu")
bleu_scores = metric.compute(
predictions=generated_translated,
references=true_translated
)
print(bleu_scores)
- LlaMA 3.1 테스뚜
# model_download.py 모델다운로드
from huggingface_hub import snapshot_download
model_name = "meta-llama/Llama-3.1-8B-Instruct"
local_model_path = "./models/llama-3.1-8b-instruct"
token = ""
# 모델 다운로드
snapshot_download(repo_id=model_name, local_dir=local_model_path, token=token)
# main.py 간단한 활용
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig
local_model_path = "./models/llama-3.1-8b-instruct"
quantization_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.float16,
bnb_4bit_use_double_quant=False
)
tokenizer = AutoTokenizer.from_pretrained(
local_model_path,
trust_remote_code=True,
)
model = AutoModelForCausalLM.from_pretrained(
local_model_path,
quantization_config=quantization_config,
device_map="auto", # "auto"로 변경
rope_scaling={"type": "dynamic", "factor": 8.0},
)
model.eval()
"""messages = [
{"role": "user", "content": "안녕하세요."}
]"""
"""messages = [
{"role": "system", "content": "저는 주인님의 충실한 종 로봇입니다."},
{"role": "user", "content": "안녕하세요, 당신은 누구인가요?"}
]"""
messages = [
{"role": "system", "content": "저는 주인님의 충실한 종 로봇입니다."},
{"role": "user", "content": "안녕하세요, 제이름은 HanTJ입니다."},
{"role": "assistant", "content": "안녕하세요. 저는 주인님의 충실한 종 로봇입니다. 주인님의 서비스와 편의를 위해 설계되었습니다. 주인님의 명령을 받들며, 주인님의 삶을 편리하게 도와드리겠습니다. 무엇을 도와드릴까요?"},
{"role": "user", "content": "제 이름을 알고 있나요?"}
]
input_ids = tokenizer.apply_chat_template(
messages,
add_generation_prompt=True,
return_tensors="pt"
).to(model.device)
with torch.no_grad():
outputs = model.generate(
input_ids,
max_new_tokens=256,
do_sample=True,
temperature=0.7, # 무작위성 조절
top_p=0.9, # 핵심 샘플링 ( 상위-p 샘플링 )
)
response = outputs[0][input_ids.shape[-1]:]
print(tokenizer.decode(response, skip_special_tokens=True))
# train.py 훈련 예제
from transformers import TrainingArguments, DataCollatorForLanguageModeling
from trl import SFTTrainer
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig
from peft import LoraConfig
from datasets import load_dataset
## 모델 로드
local_model_path = "./models/llama-3.1-8b-instruct"
quantization_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.float16,
bnb_4bit_use_double_quant=False
)
model = AutoModelForCausalLM.from_pretrained(
local_model_path,
quantization_config=quantization_config,
device_map="auto", # "auto"로 변경
rope_scaling={"type": "dynamic", "factor": 8.0},
)
tokenizer = AutoTokenizer.from_pretrained(
local_model_path,
trust_remote_code=True,
)
## 훈련용 Lora Config
peft_config = LoraConfig(
r=128, # 어텐션 차원
lora_alpha=4, # Lora의 영향력
lora_dropout=0.1,
task_type="CAUSAL_LM",
)
# 파인튜닝용 데이터 로드
dataset = load_dataset("s076923/llama3-wikibook-ko")
tokenizer.pad_token = tokenizer.eos_token
tokenizer.model_max_length = 64
model.config.use_cache = False
# 훈련 설정
training_args = TrainingArguments(
output_dir="output",
per_device_train_batch_size=1,
gradient_accumulation_steps=5,
learning_rate=2e-4,
max_steps=500,
warmup_steps=100,
logging_steps=100,
fp16=True,
optim="paged_adamw_8bit",
seed=42,
)
data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False)
# formatting_func 정의
def formatting_func(example):
return example["text"]
trainer = SFTTrainer(
model=model,
preprocessing_class=AutoTokenizer, # tokenizer 대신 preprocessing_class 사용
preprocessing_kwargs={"trust_remote_code": True}, # tokenizer 초기화 시 사용한 인자
args=training_args,
peft_config=peft_config,
train_dataset=dataset["train"],
formatting_func=formatting_func, # dataset_text_field 대신 formatting_func 사용
)
trainer.train()
RTX 2060 SUPER 훈련시간 35분 걸림
# test.py 테스트 샘플
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig
local_model_path = "./output/checkpoint-500"
quantization_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.float16,
bnb_4bit_use_double_quant=False
)
tokenizer = AutoTokenizer.from_pretrained(
local_model_path,
trust_remote_code=True,
)
model = AutoModelForCausalLM.from_pretrained(
local_model_path,
quantization_config=quantization_config,
device_map="auto", # "auto"로 변경
rope_scaling={"type": "dynamic", "factor": 8.0},
)
model.eval()
messages = [
{"role": "user", "content": "위키북스의 대표 저자는 누구에요?"}
]
input_ids = tokenizer.apply_chat_template(
messages,
add_generation_prompt=True,
return_tensors="pt"
).to(model.device)
with torch.no_grad():
outputs = model.generate(
input_ids,
max_new_tokens=64,
do_sample=True,
temperature=0.2, # 무작위성 조절
top_p=0.95, # 핵심 샘플링 ( 상위-p 샘플링 )
no_repeat_ngram_size=2,
)
response = outputs[0][input_ids.shape[-1]:]
print(tokenizer.decode(response, skip_special_tokens=True))
모델 크기는 줄어듬
바보가 됨...
반응형