KLUE-benchmark / KLUE

📖 Korean NLU Benchmark

Home Page:https://klue-benchmark.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[KLUE-NER] unk 토큰이 있는 경우 제대로 character_preds 리스트가 제대로 생성되지 않는 문제가 있습니다.

khel-kim opened this issue · comments

Description

unk 토큰이 있는 경우 제대로 character_preds 리스트가 제대로 생성되지 않는 문제가 있습니다.
KLUE-baseline issue : KLUE-benchmark/KLUE-baseline#9

How to Reproduce(재현 방법) 🤔

예를 들어 "전문성운줄알았어여~ᄏ"를 토크나이징하면 (sample id : klue-ner-v1_dev_00236-nsmc)

['전문',
 '##성',
 '##운',
 '##줄',
 '##알',
 '##았',
 '##어',
 '##여',
 '~',
 '[UNK]']

이런 결과가 나오는데요.

이러한 input이 https://github.com/KLUE-benchmark/KLUE-baseline/blob/main/klue_baseline/models/named_entity_recognition.py#L98-L129 이 if문을 타게 되면,

character_preds가 원하는 형태로 생성되지 않게 됩니다.

이유는 unk가 있는 공백기준으로 분리뒨 어절을 토크나이징 했을 때에 unk가 아닌 토큰은 하나의 캐릭터일거라고 가정되어 코드작성이 되었기 때문인 것 같습니다.

이 때문에 '전문' 같은 경우에는 char 이 2개임에도 subword_pred가 캐릭터 하나에 대한 pred만 append 되는 상황이 됩니다.
(https://github.com/KLUE-benchmark/KLUE-baseline/blob/main/klue_baseline/models/named_entity_recognition.py#L125)

(Optional) Suggestion

How to solve (어떻게 해결할 수 있을까요) 🙋‍♀

                if self.tokenizer.unk_token in subwords:  # 뻥튀기가 필요한 case!
                    unk_aligned_subwords = self.tokenizer_out_aligner(
                        word, subwords, strip_char
                    )  # [UNK] -> [UNK, +UNK]
                    add_char_preds_idx = 0  # 추가된 부분
                    unk_flag = False
                    for subword in unk_aligned_subwords:
                        if character_preds_idx >= self.hparams.max_seq_length - 1:
                            break
                        subword_pred = subword_preds[character_preds_idx].tolist()
                        subword_pred_label = label_list[subword_pred]
                        if subword == self.tokenizer.unk_token:
                            unk_flag = True
                            character_preds.append(subword_pred)
                            add_char_preds_idx += 1  # 추가된 부분
                            continue
                        elif subword == self.in_unk_token:
                            if subword_pred_label == "O":
                                character_preds.append(subword_pred)
                            else:
                                _, entity_category = subword_pred_label.split("-")
                                character_pred_label = "I-" + entity_category
                                character_pred = label_list.index(character_pred_label)
                                character_preds.append(character_pred)
                            add_char_preds_idx += 1  # 추가된 부분
                            continue
                        else:
                            if unk_flag:
                                character_preds_idx += 1
                                subword_pred = subword_preds[character_preds_idx].tolist()
                                subword_pred = [subword_pred] * len(subword.lstrip(strip_char))  # 추가된 부분
                                character_preds.extend(subword_pred)  # 추가된 부분
                                unk_flag = False
                            else:
                                subword_pred = [subword_pred] * len(subword.lstrip(strip_char))    # 추가된 부분
                                character_preds.extend(subword_pred)    # 추가된 부분
                                character_preds_idx += 1  # `+UNK`가 끝나는 시점에서도 += 1 을 해줘야 다음 label로 넘어감
                    character_preds_idx += add_char_preds_idx    # 추가된 부분

코드를 우선 려프하게 작성하게 되었는데, 해당 부분을 검토해주셔서 더 좋은 코드(?)로 업데이트 되면 좋을 것 같습니다!

좋은 finetuning system을 만들어주셔서 감사합니다 🙇‍♂️