yangoos57 / Electra_for_Domain_Adaptation

Electra 학습 구조를 구현하고 Domain Adaptation 수행
0 stars 0 forks source link

추가 fine-tuning #1

Open polyn0 opened 1 year ago

polyn0 commented 1 year ago

안녕하세요!

adaptive pretraining 후에 discriminator만 사용하여 fine-tuning에 사용하게 되는데 checkpoint 파일에서 discriminator만 사용하는 방법을 알 수 있을까요?

yangoos57 commented 1 year ago

안녕하세요~

튜토리얼에서 소개하는 electra class에서 discriminator를 추출하는 방법에 대해서 물어보시는 것 같은데 맞을까요?

그런 경우라면 check_point를 불러오신 다음 아래 코드를 사용하시면 discriminator만 사용하실 수 있습니다.

# model = Electra(generator=generator,discriminator=discriminator,tokenizer=tokenizer)
discriminator = model.discriminator
polyn0 commented 1 year ago

빠른 답변 감사드립니다!

네 학습된 outputs/checkpoint-100000에서 모델을 불러와서 discriminator만 사용하고자 합니다. checkpoint를 아래와 같이 부르게 되면 checkpoint-100000에 config.json 파일이 없어 인식을 못하는데 어떻게 model을 부르는 건가요?

generator = ElectraForMaskedLM.from_pretrained("./outputs/checkpoint-100000")
discriminator = ElectraForPreTraining.from_pretrained("./outputs/checkpoint-100000")
yangoos57 commented 1 year ago

맞네요. 저도 처음 trainer를 사용했을때 이 부분에서 막혔거든요.

저장하고 불러오는 방법도 tutorial에 추가해야겠네요.


먼저 check_point로 자동 저장된 모델을 불러오는 방법에 대해서 말씀드릴께요.

checkpoint-100000 폴더 내부를 보시면 pytorch_model.bin라는 파일이 있는데, 이 파일을 이용하는 방법이에요.

pytorch_model.bin은 모델의 weight 값을 보관하고 있는 OrderedDict 자료구조의 파일이에요.

pytorch는 기존 모델을 불러온 다음 그 위에 weight를 교체하는 방법으로 새로운 모델을 불러오는 방식을 지원하는데, pytorch_model.bin은 이런 용도에 사용되는거죠.

설명은 복잡해 보이는데 코드로 보면 직관적으로 이해하실 수 있어요.

from transformers import ElectraForPreTraining, ElectraTokenizer, ElectraForMaskedLM

# 기본 모델 불러오기
tokenizer = ElectraTokenizer.from_pretrained("monologg/koelectra-base-v3-generator")
generator = ElectraForMaskedLM.from_pretrained('monologg/koelectra-base-v3-generator')
discriminator = ElectraForPreTraining.from_pretrained("monologg/koelectra-base-v3-discriminator")

model = Electra(generator=generator,discriminator=discriminator,tokenizer=tokenizer)

# 모델 weight 교체하기
weight_dict = torch.load('./outputs/checkpoint-100000/pytorch_model.bin',map_location=torch.device('cpu'))
model.load_state_dict(state_dict=weight_dict)

>>> <All keys matched successfully>


weight_dict = torch.load(...) 부분에서 에러가 발생하면 아래 코드로 바꿔서 시도하세요. gpu를 사용해 학습한 모델을 gpu가 없는 local에서 사용할 때 발생하는 에러에요.

weight_dict = torch.load('model/checkpoint-100/pytorch_model.bin',map_location=torch.device('cpu'))


모델을 제대로 불러온게 맞는지 궁금하다면 아래 코드를 사용해서 점검해보세요.

old_discriminator = ElectraForPreTraining.from_pretrained("monologg/koelectra-base-v3-discriminator")

new_discriminator = model.discriminator

old_param = list(old_discriminator.parameters())
new_param = list(new_discriminator.parameters())

not_updated_params = []
for i in range(len(old_param)) :
    x = old_param[i] - new_param[i]
    if torch.sum(x.reshape(-1)).item() == 0 :
        not_updated_params.append(i)

print(not_updated_params)


ELECTRA 모델을 정상적으로 불러왔으면 이제 discriminator의 base 모델만 따로 저장해야해요.

왜 base_model만 저장하는지는 이미 아실거라 생각하기에 넘어가겠습니다. 참고자료가 필요하시면 링크를 읽어주세요.

# 모델 저장
model.discriminator.base_model.save_pretrained('model/electraModel')

# 모델 불러오기
ElectraForMaskedLM.from_pretrained('model/electraModel')
ElectraForSequenceClassification.from_pre_trained('model/electraModel')
# ... 등등 Huggingface에서 지원하는 다양한 모듈과 연계 가능


Trainer를 활용해서 Fine-tuning을 하실 예정이라면 학습 완료된 모델을 저장하는 방법에 대해서도 설명드릴게요.

아래 코드를 사용하면 fine-tuning한 모델을 간단하게 저장할 수 있고 from_pretrained로 쉽게 불러올 수 있어요.

Trainer.save_model('경로')

여기서 주의할 점은 tutorial에서 소개하는 ELECTRA Class 같은 경우는 save_model로 저장할 수 없다는 거에요. ELECTRA Class는 학습을 수행하기 위한 구조일 뿐이지 ELECTRA Class 자체가 모델이 아니기 때문에 save_model 매서드를 사용할 수 없어요. (Bert의 경우 ELECTRA 처럼 특이한 학습구조를 사용하지 않기 때문에 Trainer.save_model('경로') 매서드를 사용해서 모델을 저장할 수 있어요.)

따라서 이와 같이 discriminator를 class에서 떼어낸 다음 save_pretrained 매서드로 저장해야해요.

discriminator = model.discriminator
discriminator.base_model.save_pretrained('model/electraModel')