Fine-Tuning

[Fine-Tuning] Restoring obfuscation LLM 프로젝트 회고

dong_seok 2025. 4. 23. 22:17
728x90
반응형

이전 글에서 Unsloth와 엘리스 클라우드 등 기술적인 부분에 대해 설명했다면, 이번에는 DACON 난독화 한글 리뷰 복원 프로젝트를 진행하면서 겪었던 전체적인 경험과 시행착오를 공유하려 합니다. 

 

대회 개요

DACON에서 진행된 이 대회는 의도적으로 난독화된 한글 텍스트를 원래 형태로 복원하는 과제로, 오픈 소스 LLM(Large Language Model)을 활용해 해결하는 것이 핵심이었습니다.

 

처음에는 같은 경진대회에 참여한 사람이 공유해준 Gemma-2-B-it Full Fint-tuning 모델을 사용하였습니다. 

 

model_name = "mindw96/Gemma-2-2B-it-DACON-LLM"
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    torch_dtype=torch.bfloat16,
    device_map="auto",
    trust_remote_code=True,
)

 

2B 파라미터 규모의 작은 모델이었지만, Full-Fine-tuning이라서그런지 0.75의 정확도로 생각보다 높은 수치를 보여줬습니다. 하지만 저는 단순히 다른 사람의 모델을 추론에만 사용하는 것이 아니라, 직접 파인튜닝 과정을 경험하고 더 높은 정확도를 달성하고 싶다는 마음으로 대회를 진행하였습니다.

 

도전 과제: 제한된 컴퓨팅 자원

정확도 향상을 위해 2B보다 더 큰 모델로 풀 파인튜닝을 시도했으나, Colab 무료 환경에서는 지속적으로 OOM(Out Of Memory) 에러가 발생했습니다. 이를 해결하기 위해 배치 사이즈 감소와 양자화 등 여러 메모리 최적화 기법을 시도했지만, 기본적인 메모리가 너무 부족한 상황이었습니다.

 

모델 크기를 낮추어 학습을 시작했지만, 이번에는 학습 시간이 너무 오래 걸리는 문제에 직면했습니다. 결국 제한된 컴퓨팅 자원과 긴 학습 시간이라는 두 가지 문제를 모두 해결해야 했습니다.

 

해결책: 엘리스 클라우드와 Unsloth 라이브러리

1) 클라우드 환경으로 전환

근본적인 메모리 부족 문제를 해결하기 위해 엘리스 클라우드의 "A100 80GB PCle MIG 3g-40GB" 인스턴스를 활용하기로 했습니다. 대부분의 연구자들이 RunPod와 같은 플랫폼을 사용하는 경우가 많지만, 엘리스 클라우드는 출시된 지 얼마 되지 않았고 이벤트로 대여 비용을 지원해주어 비용 효율적인 선택이었습니다.

 

2) Unsloth 라이브러리 도입

메모리 사용 효율성과 학습 속도를 개선하기 위해 Unsloth 라이브러리를 활용했습니다. Unsloth는 사전에 통합(integration)된 모델만 지원하므로, Llama-3B 모델을 새롭게 선택하여 학습을 진행했습니다.

 

from unsloth import FastLanguageModel
import torch

# 모델 및 토크나이저 로드
model, tokenizer = FastLanguageModel.from_pretrained(
    model_name="unsloth/Llama-3.2-3B-Instruct-bnb-4bit",
    max_seq_length=2048,
    dtype=None,  # 자동 감지
    load_in_4bit=True,  # 4비트 양자화
)

# LoRA 설정으로 효율적인 파인튜닝
model = FastLanguageModel.get_peft_model(
    model,
    r=128,  # LoRA 랭크
    target_modules=[
        "q_proj", "k_proj", "v_proj", "o_proj", 
        "gate_proj", "up_proj", "down_proj", 
        "embed_tokens", "lm_head"
    ],
    lora_alpha=32,
    use_gradient_checkpointing="unsloth",  # 메모리 효율성
    use_rslora=True,  # 랭크 안정화 LoRA
)

 

 

 

이후에 학습에 적합한 형태로 데이터를 구성해주는 절차를 거쳤습니다.

 

 

# 난독화된 입력을 복원하는 작업을 위한 템플릿 정의
restore_prompt = """다음은 난독화 된 입력을 복원하는 작업입니다.

### 난독화 입력:
{}

### 복원된 출력:
{}"""

EOS_TOKEN = tokenizer.eos_token  # 반드시 EOS_TOKEN 추가 (생성 종료를 위해)

def combine_input_output(example):
    # 입력과 출력 정보를 템플릿에 맞게 합치고 EOS_TOKEN을 추가
    example["text"] = (
        restore_prompt.format(example["input"], example["output"]) + EOS_TOKEN
    )
    return example


# 데이터셋에 대해 map 적용
dataset = dataset.map(combine_input_output)

 

 

그 후 UnslothTrainer를 활용해 효율적인 학습을 진행했습니다.

 

trainer = UnslothTrainer(
    model=model,
    tokenizer=tokenizer,
    train_dataset=dataset,
    dataset_text_field="text",
    max_seq_length=2048,
    dataset_num_proc=2,
    args=UnslothTrainingArguments(
        per_device_train_batch_size=2,
        gradient_accumulation_steps=8,
        warmup_steps=10,
        num_train_epochs=1,
        learning_rate=5e-5,
        embedding_learning_rate=1e-5,  # 임베딩 레이어에 더 낮은 학습률 적용
        fp16=not is_bfloat16_supported(),
        bf16=is_bfloat16_supported(),
        logging_steps=1,
        optim="adamw_8bit",
        weight_decay=0.01,
        lr_scheduler_type="linear",
        output_dir="outputs",
    ),
)

# 학습 실행
trainer.train()

 

결과 및 성과

Unsloth 라이브러리와 4비트 양자화 기법을 활용한 Llama-3.2-3B 모델 학습으로 0.8의 정확도를 달성했습니다. 이는 초기 접근법보다 약 6.7% 향상된 결과입니다.

 

1) 이 접근법의 주요 이점

  • 메모리 효율성: 4비트 양자화로 메모리 사용량을 크게 줄임
  • 학습 속도 향상: Unsloth의 최적화로 일반적인 방법보다 2-4배 빠른 학습
  • 유연성: LoRA를 통해 모든 주요 모듈을 효율적으로 파인튜닝

기술적 인사이트

1) LoRA를 이용한 효율적인 파인튜닝

LoRA(Low-Rank Adaptation)는 전체 모델을 학습하는 대신 저차원 업데이트를 통해 파라미터를 효율적으로 학습합니다. r=128이라는 비교적 큰 랭크 값을 사용해 모델의 표현력을 극대화했습니다.

 

target_modules=[
    "q_proj", "k_proj", "v_proj", "o_proj",  # 어텐션 관련
    "gate_proj", "up_proj", "down_proj",     # MLP 관련
    "embed_tokens", "lm_head"                # 임베딩 및 출력
]

 

이렇게 모든 주요 모듈을 대상으로 함으로써 모델이 난독화 패턴을 더 깊이 이해하고 복원할 수 있었습니다.

 

2) 4비트 양자화의 효과

처음엔 16비트 형식의 모델을 양자화 하면 메모리 사용량이 줄어드는 대신 정확도가 크게 떨어질것이라고 예상해서 양자화를 선호하지 않았는데, 줄어든 메모리 사용량 대비 성능이 크게 떨어지지않은 것 같아서 양자화가 정확도 손실을 최소화하면서도 큰 모델을 효율적으로 사용하게 해준다는 긍정적인 인식을 얻게 되었습니다.