모델 : 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개이다.
시도해본 모델
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이라는 라이브러리 안에 있던 메소드였다
해결방법 : 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토큰만 주는게아니라 {질문 : 답변: }이런식으로 짜야할 거같음