#2 KoAlpaca Finetuning

daegeon kim·2024년 2월 10일

대회

목록 보기
2/4

1. 베이스라인 실습

모델 : KoGPT2
태스크 : CausalLM(Q&A)

# 모델 로드
model = GPT2LMHeadModel.from_pretrained('skt/kogpt2-base-v2')
model.to(device) # 모델을 GPU단으로 이동

# 모델 학습 하이퍼파라미터(Hyperparameter) 세팅
# 실제 필요에 따라 조정하세요.
CFG = {
    'LR' : 2e-5, # Learning Rate
    'EPOCHS' : 10, # 학습 Epoch
}

결과 : 제출결과 성능은 60이었다.

# 데이터 로드
data = pd.read_csv(cfg.traindata)

# 토크나이저 로드
tokenizer = PreTrainedTokenizerFast.from_pretrained('skt/kogpt2-base-v2', eos_token='</s>')

# 데이터 포맷팅 및 토크나이징
formatted_data = []
for _, row in tqdm(data.iterrows()):
    for q_col in ['질문_1', '질문_2']:
        for a_col in ['답변_1', '답변_2', '답변_3', '답변_4', '답변_5']:
            # 질문과 답변 쌍을 </s> token으로 연결
            input_text = row[q_col] + tokenizer.eos_token + row[a_col]
            input_ids = tokenizer.encode(input_text, return_tensors='pt')
            formatted_data.append(input_ids)
print('Done.')

데이터가 들어갈때 {질문<스페셜토큰>답변}의 형식으로 들어간다
한 질문에 답변 5개가 있으며, 같은 내용의 다른 형식의 질문이 2개다. 그래서 한 내용의 짝은 10개이다.

2 LLM Finetuning

시도해본 모델
beomi/KoAlpaca-Polyglot-5.8B(최종선정)
beomi/KoAlpaca-KoRWKV-1.5B
beomi/llama-2-ko-7b
beomi/polyglot-ko-12.8b-safetensors
태스크 : CausalLM(Q&A)

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig

# model_id = "beomi/KoAlpaca-KoRWKV-1.5B"  #
# tokenizer = AutoTokenizer.from_pretrained(model_id)
# model = AutoModelForCausalLM.from_pretrained(model_id).to(device)

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig

model_id = "beomi/KoAlpaca-Polyglot-5.8B"  # safetensors 컨버팅된 레포
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_id)
model = AutoModelForCausalLM.from_pretrained(model_id, quantization_config=bnb_config, device_map={"":0})

문제점 : 모두 모델에 올려봤는데 자꾸 실패했다. 아마도 RAM이 작아서 였다.
해결방법 : 모델 양자화를 통해 올릴 수 있었다. (https://huggingface.co/docs/transformers/main_classes/quantization)
추가 해결방법 : 학습할 때 LoRA 사용

context_length=128
def tokenize(element):
    outputs = tokenizer(
        element['text'],
        truncation=True,
        max_length=context_length,
        return_overflowing_tokens=True,
        return_length=True,
    )
    input_batch = []
    for length, input_ids in zip(outputs['length'], outputs['input_ids']):
        if length == context_length:
            input_batch.append(input_ids)
    return {"input_ids": input_batch}


tokenized_datasets = dataset.map(
    tokenize, batched=True, remove_columns=dataset["train"].column_names)
tokenized_datasets

여기서 map함수를 적용하려니 어떻게 동작하는지 이해가 안갔다. 알고보니 dataset이라는 라이브러리 안에 있던 메소드였다

  • map() 메서드는 데이터셋의 개별 요소에 함수(function)를 적용하여 작동

해결방법 : datasets 라이브러리에 localdata를 넣어줬다. 해당 코드에서는 huggingface Trainer 클래스를 사용할 예정이라 이방법이 호환하기 쉬울거같다.

from transformers import Trainer, TrainingArguments

args = TrainingArguments(
    output_dir='results',
    logging_steps=10,
    per_device_train_batch_size=2,
    # evaluation_strategy="steps",
    gradient_accumulation_steps=2,
    num_train_epochs=5,
    weight_decay=0.1,
    warmup_steps=10,
    lr_scheduler_type="cosine",
    learning_rate=1e-4,
    save_steps=10,
    fp16=True,
    push_to_hub=True,
    optim="paged_adamw_8bit"
)


trainer = Trainer(
    model=model,
    tokenizer=tokenizer,
    args=args,
    data_collator=data_collator,
    train_dataset=tokenized_datasets["train"],
)
model.config.use_cache = False

문제 : fp16에서 자꾸 에러
해결방법 : 제대로 양자화 하지 않았었다.. 그래서 양자화 다시 제대로 해주니 오류없이 돌아간다.(bitandbytes)

문제 :허깅페이스 trainer를 사용하면 자동으로 git을 심어서 에러가 발생
해결 방법: 내가사용하던 폴더가 이미 깃을 심어놓은 로컬 저장소여서 그런 것 같아서 코랩에서 학습시켰더니 잘된다.

Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.
  0%|          | 0/130 [00:00<?, ?it/s]Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.
A decoder-only architecture is being used, but right-padding was detected! For correct generation results, please set `padding_side='left'` when initializing the tokenizer.

이거는 경고메시지인데 뭔가 토크나이저 호환이 안맞는거같다..

모두 돌려본 결과 베이스라인보다 성능이 좋지않다;(60->47)
당연히 더 최근에 나온 모델이라고해서 좋은건 아니지만 충격적이었다.
그래서 내가생각해본 원인은
1. 데이터 하이퍼파라미터의 문제
2. 학습이 덜됨
3. eos토큰만 주는게아니라 {질문 : 답변: }이런식으로 짜야할 거같음

  • 해당모델 베이스라인 꿀팁중 "만약 학습이 충분히 되지 않으면 <|endoftext|> 토큰이 잘 생성되지 않을 수 있습니다
    이럴떈 충분히 긴 max_new_tokens를 준 뒤, ###으로 잘라서 써보세요. ex) output.split('###')[0]" 이런 얘기가 있었다. 뭔가 잘 조정해보면 좋을거같다.
profile
AI Engineer

0개의 댓글