단어장에 새로운 단어를 넣고 적용하려면 어떻게 해야 하는지 알 수 있을까요?

#2
by Gyeongmo - opened

안녕하세요?
이 모델을 한 달에도 몇 번씩 내려 받아 아주 잘 쓰고 있는 사용자입니다. 좋은 모델 만들어 주셔서 정말정말 감사합니다.
덕분에 학생들에게 과학 질문-답변 서비스를 제공하여 유용하게 잘 쓰고 있습니다. (주소는 https://acer2.snu.ac.kr 입니다.)
한 가지 질문이 있는데요, 단어장에 화학결합에서 쓰는 '옥텟' 규칙이란 단어가 들어가면 '옥텟'이란 단어가 없어서 그런지 엉뚱한 문장을 가장 유사하다고 판별합니다. 단어장에 새로운 단어를 넣고 적용하여 모델을 만들고, 이 모델을 불러와서 적용하여 사용하려면 어떻게 해야 하는지 알 수 있을까요?
감사합니다.

안녕하세요! 먼저 부족한 결과물에 관심을 가져주셔서 감사드립니다.

말씀주신 것처럼 현재 학습된 모델의 단어장에는 '옥텟'이라는 단어가 없는 것으로 확인되었습니다. ([UNK] 토큰은 unknown 을 의미합니다)

from transformers import AutoTokenizer, AutoModel
import torch


def mean_pooling(model_output, attention_mask):
        token_embeddings = model_output[0] #First element of model_output contains all token embeddings
        input_mask_expanded = attention_mask.unsqueeze(-1).expand(token_embeddings.size()).float()
        return torch.sum(token_embeddings * input_mask_expanded, 1) / torch.clamp(input_mask_expanded.sum(1), min=1e-9)


if __name__ == "__main__":

        tokenizer = AutoTokenizer.from_pretrained('jhgan/ko-sroberta-multitask')
        sentence = "옥텟 규칙에 대해서 설명해주세요"

        input_ids = tokenizer(sentence).get("input_ids")
        decoded_tokens = tokenizer.convert_ids_to_tokens(input_ids)
        print("토큰 추가 전")
        print("encoded tokens:", input_ids)
        print("decoded tokens:", decoded_tokens, end="\n\n")

        # 토큰 추가
        tokenizer.add_tokens("옥텟")
        input_ids = tokenizer(sentence).get("input_ids")
        decoded_tokens = tokenizer.convert_ids_to_tokens(input_ids)
        print("토큰 추가 후")
        print("encoded tokens:", input_ids)
        print("decoded tokens:", decoded_tokens)

        model = AutoModel.from_pretrained('jhgan/ko-sroberta-multitask')
        model.resize_token_embeddings(len(tokenizer))
        encoded_input = tokenizer(sentence, return_tensors='pt')
        with torch.no_grad():
                model_output = model(**encoded_input)
                sentence_embeddings = mean_pooling(model_output, encoded_input['attention_mask'])

#output
#토큰 추가 전
#encoded tokens: [0, 3, 6094, 2170, 3958, 3788, 2097, 2223, 5971, 2]
#decoded tokens: ['[CLS]', '[UNK]', '규칙', '##에', '대해서', '설명', '##해', '##주', '##세요', '[SEP]']

#토큰 추가 후
#encoded tokens: [0, 32000, 6094, 2170, 3958, 3788, 2097, 2223, 5971, 2]
#decoded tokens: ['[CLS]', '옥텟', '규칙', '##에', '대해서', '설명', '##해', '##주', '##세요', '[SEP]']

보시는 코드처럼 단어장에 새로운 단어를 추가하는 것이 가능하지만, 추가된 단어의 의미가 모델에 충분히 반영되도록 학습시켜 활용하시기는 쉽지 않을 것으로 예상됩니다. 이유는 다음과 같습니다.

  1. '옥텟'이라는 단어를 추가해 모델을 다시 학습시키기 위해서는 그 단어를 포함하는 텍스트 데이터가 충분히 많아야 하고, 적절한 형태의 레이블링까지 되어있어야 합니다. 본 모델에 사용된 레이블의 형식에 대해서는 카카오브레인의 KorNLU 데이터셋을 검색해보시면 이해가 쉬울 것 같습니다. 만약 레이블링은 되어있지 않지만 충분히 많은 수의 데이터를 확보하고 계시다면 SimCSE 와 같은 방법론으로 모델을 직접 학습키는 방법이 있을 것 같습니다.

  2. 본 모델은 대규모 텍스트 데이터를 사전학습한 언어모델에 추가적인 학습을 진행해 만들어졌으며, 사전학습 모델의 성능에 크게 영향을 받습니다. '옥텟'이라는 단어를 해당 단어를 포함하는 데이터 충분히 많이 준비해 추가 학습을 진행할 경우 해당 단어를 포함하는 케이스에 대해서는 성능이 개선되겠지만 사전학습 과정에서 학습된 단어가 아니기 때문에 성능 개선폭이 생각보다 크지 않을 수도 있고, 오히려 모델의 일반화 성능을 악화시킬 여지도 있어 보입니다.

이와 관련된 연구들이 많기는 할텐데,, 제가 팔로업하고 있지는 못한 상황입니다. 만약 사용하시는 영역에서 모델 성능을 좀더 개선하시길 원하신다면, language model domain adapdation 등의 키워드를 찾아보시면 관련된 자료들이 있을지도 모르겠습니다.

많은 도움 드리지 못해 죄송합니다 ㅠㅠ

답변 주셔서 정말정말 감사합니다. 이메일로 답변이 온 건 알고 있었는데요, 너무 정신이 없어서 못 보고 있었습니다.. 저는 컴퓨터과학 전공자는 아니다 보니 전문적인 내용은 잘 모릅니다만, 덕분에 SimCSE, language model domain adaptation 이라는 키워드를 알게 되었습니다. 감사합니다. 용어를 알아야 검색을 해볼 텐데요, 용어조차 있는지도 몰랐습니다. 이것도 한 번 시도해봐야겠습니다. 그러나 데이터가 수십, 수백만 개가 아니라 10000~20000개 수준이라 이게 충분히 큰 수의 데이터인지 판단이 안 됩니다. ㅎㅎ

저야말로 jhgan님 덕에 1년 가까이 이 챗봇 서비스를 한 것이지, 저 혼자는 못 만들었을 겁니다. 제가 도움을 더 못 드려 죄송합니다.

Sign up or log in to comment