본문 바로가기
IT/python

허깅페이스 이용하기 - 기계번역, 생성형텍스트, 검색, 그림생성

by 가능성1g 2025. 1. 1.
반응형

** 환경 구성

윈도우즈11

miniconda

- 지금까지 경험으로 miniconda 를 설치해서 환경 구성하는게 가장 편하다!

설치

Miniconda — Anaconda documentation

 

Miniconda — Anaconda documentation

The Anaconda or Miniconda page lists some reasons why you might want one installation over the other.

docs.anaconda.com

 

가상환경 설정

conda create -n hug python=3.10 # 3.10 파이썬 고수중...
conda activate hug

 

패키지 설치

requirements.txt
0.00MB

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))

모델 크기는 줄어듬

바보가 됨...

반응형