Skip to content

[2021 훈민정음 한국어 음성•자연어 인공지능 경진대회] 대화요약 부문 알라꿍달라꿍 팀의 대화요약 학습 및 추론 코드를 공유하기 위한 레포입니다.

License

Notifications You must be signed in to change notification settings

seoy119/summary

This branch is 1 commit behind cosmoquester/2021-dialogue-summary-competition:master.

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Mar 3, 2022
7165925 · Mar 3, 2022

History

55 Commits
Dec 21, 2021
Dec 17, 2021
Dec 21, 2021
Dec 26, 2021
Jan 11, 2022
Mar 3, 2022
Dec 20, 2021
Dec 21, 2021
Jan 9, 2022
Jan 23, 2022
Jan 14, 2022
Jan 14, 2022
Jan 14, 2022
Dec 17, 2021
Dec 17, 2021
Mar 3, 2022
Mar 3, 2022

Repository files navigation

2021 Dialogue Summary Competition

Code style: black Imports: isort cosmoquester codecov

Please Click here for English README.

[2021 훈민정음 한국어 음성•자연어 인공지능 경진대회] 대화요약 부문 알라꿍달라꿍 팀의 대화요약 학습 및 추론 코드를 공유하기 위한 레포입니다.

팀원: 박상준(cosmoquester), 최기원(ckw1140), 오혜린(Hyerin-oh)

저희 팀은 이렇게 세 명으로 구성되어 있습니다.

최종 리더보드는 아래와 같고, 대화요약 부문에서 1등을 해내 네이버 대표상을 수상하였습니다.

Rank Name Score
1 알라꿍달라꿍 0.34286246
2 ... 0.3330445
3 ... 0.33254071

Quick Start

대회에서 사용한 기법대로 외부데이터없이 AIHub 데이터만을 이용해 학습한 모델을 쉽게 사용해볼 수 있습니다.

$ pip install transformers
from transformers import pipeline

model_name = "alaggung/bart-r3f"
max_length = 64
dialogue = ["밥 ㄱ?", "고고고고 뭐 먹을까?", "어제 김치찌개 먹어서 한식말고 딴 거", "그럼 돈까스 어때?", "오 좋다 1시 학관 앞으로 오셈", "ㅇㅋ"]

summarizer = pipeline("summarization", model=model_name)
summarization = summarizer("[BOS]" + "[SEP]".join(dialogue) + "[EOS]", max_length=max_length)

print(summarization)
# Your max_length is set to 64, but you input_length is only 51. You might consider decreasing max_length manually, e.g. summarizer('...', max_length=25)
# [{'summary_text': '어제 김치찌개를 먹어서 한식 말고 돈가스를 먹기로 했다.'}]
  • 위와 같이 pipeline을 이용하면 간단하게 실행할 수 있습니다.
from transformers import AutoTokenizer, BartForConditionalGeneration

model_name = "alaggung/bart-r3f"
max_length = 64
num_beams = 5
length_penalty = 1.2
dialogue = ["밥 ㄱ?", "고고고고 뭐 먹을까?", "어제 김치찌개 먹어서 한식말고 딴 거", "그럼 돈까스 어때?", "오 좋다 1시 학관 앞으로 오셈", "ㅇㅋ"]

tokenizer = AutoTokenizer.from_pretrained(model_name)
model = BartForConditionalGeneration.from_pretrained(model_name)
model.eval()

inputs = tokenizer("[BOS]" + "[SEP]".join(dialogue) + "[EOS]", return_tensors="pt")
outputs = model.generate(
    inputs.input_ids,
    attention_mask=inputs.attention_mask,
    num_beams=num_beams,
    length_penalty=length_penalty,
    max_length=max_length,
    use_cache=True,
)
summarization = tokenizer.decode(outputs[0], skip_special_tokens=True)

print(summarization)
# 어제 김치찌개를 먹어서 한식 말고 돈가스를 먹기로 했다.
  • 이렇게 그냥 불러와 추론할 수도 있습니다.

Directory Structure

# run 디렉토리에는 실행할 수 있는 스크립트들이 들어있습니다.
run
├── inference.py
├── interactive.py
├── train.py
└── train_tokenizer.py

# summarizer 디렉토리에는 데이터로더와 학습로직이 들어있습니다.
summarizer
├── data.py
├── method
│   ├── default.py
│   ├── r3f.py
│   ├── rdrop.py
│   └── rl.py
├── scheduler.py
└── utils.py

Process

최종제출에 사용했던 대화요약 모델을 학습하는 절차는 다음과 같습니다. 첨부된 실행 예시에서 하이퍼파라미터는 실제로 대회에서 사용했던 것과 동일합니다. 해당 파라미터들은 V100 32GB GPU 1대 기준으로 타 환경에서는 조절이 필요할 수 있습니다.

1. Tokenizer training

저희 팀은 토크나이저를 대회에서 제공한 학습데이터로 직접 학습해 사용하였습니다. 토크나이저의 학습은 학습데이터의 발화와 요약문을 mecab으로 1차분절한 후에 unigram 방법으로 학습해 사용하였습니다. (run/train_tokenizer.py 참고)

2. BART pretraining

저희는 모델 아키텍쳐로는 BART를 사용했습니다. 외부 데이터를 사용할 수 없기 때문에 학습 데이터셋의 대화 텍스트로 사전학습을 수행했으며 노이즈는 Text infilling과 Sentence Permutation을 적용했습니다. Sentence Permutation은 턴 단위로 수행하였습니다.

$ python -m run train \
    --output-dir outputs/pretrain \
    --method pretrain \
    --tokenizer resources/tokenizers/unigram_4K \
    --train-dataset-pattern "data/Training/*.json" \
    --valid-dataset-pattern "data/Validation/*.json" \
    --epochs 50 --seed 42 --max-learning-rate 2e-4 --batch-size 64 --gpus 1 \
    --model-config-path resources/configs/default.json
  • 이 학습의 학습추이는 Wandb에서 볼 수 있습니다.
  • 이 단계를 학습한 모델은 alaggung/bart-pretrained에서 사용할 수 있습니다.

3. Dialogue Summarization finetune (R3F)

사전학습 후에는 Dialogue Summarization task를 학습시켰습니다. 이때 Abstract Summarization에서 좋은 효과를 보이는 R3F 기법을 적용하였습니다.

$ python -m run train \
    --output-dir outputs/r3f \
    --method r3f \
    --tokenizer resources/tokenizers/unigram_4K \
    --train-dataset-pattern "data/Training/*.json" \
    --valid-dataset-pattern "data/Validation/*.json" \
    --epochs 10 --seed 42 --batch-size 64 --max-learning-rate 2e-4 --gpus 1 \
    --model-config-path resources/configs/default.json \
    --pretrained-ckpt-path outputs/pretrain/models/model-49epoch-218374steps-0.6568loss-0.8601acc
  • 이 학습의 학습추이는 Wandb에서 볼 수 있습니다.
  • 이 단계를 학습한 모델은 alaggung/bart-r3f에서 사용할 수 있습니다.

4. Dialogue Summarization finetune (RL)

마지막으로 학습의 목표를 대회의 평가지표인 ROUGE-L F1 score와 align시키기 위해서 고전적인 RL을 적용했습니다. target metric은 모델이 생성한 요약문과 실제 요약문간의 mecab분절 기준 ROUGE-L F1 score를 사용하였습니다.

$ python -m run train \
    --output-dir outputs/rl \
    --method rl \
    --tokenizer resources/tokenizers/unigram_4K \
    --train-dataset-pattern "data/Training/*.json" \
    --valid-dataset-pattern "data/Validation/*.json" \
    --epochs 1 --seed 42 --max-learning-rate 2e-5 --batch-size 20 --valid-batch-size 32 --accumulate-grad-batches 6 --gpus 1 \
    --model-config-path resources/configs/default.json \
    --pretrained-ckpt-path outputs/r3f/models/model-09epoch-43374steps-1.2955loss-0.6779acc
  • 이 학습의 학습추이는 Wandb에서 볼 수 있습니다.
  • 이 단계를 학습한 모델은 alaggung/bart-rl에서 사용할 수 있습니다.

Run

Train

$ python -m run train \
    --output-dir outputs/default-training \
    --method default \
    --model-config-path resources/configs/default.json \
    --tokenizer resources/tokenizers/unigram_4K \
    --train-dataset-pattern "data/Training/*.json" \
    --valid-dataset-pattern "data/Validation/*.json" \
    --gpus 1
  • 위와 같이 데이터와 config, tokenizer 경로를 주고 학습스크립트를 실행할 수 있습니다.
  • method 인자는 학습 방법을 설정하는 것이며 default, pretrain, r3f, rdrop, rl 중에 하나를 택해야합니다. method에 따라 해당 학습 기법으로 학습합니다.
  • pretrain은 BART pretrain이라서 대화요약 task를 학습하지 않습니다.
  • rl은 학습에서 target summary와의 ROUGE-L F1 점수를 계산해 사용하는데 이때 mecab을 이용해 형태소를 분절하기 때문에 mecab이 설치되어야 하며 docker/dialogue-summary-specials.csv 파일을 사용자 사전에 추가해주면 좋습니다.
  • 학습스크립트는 매 validation마다 체크포인트를 저장합니다. 모든 결과물은 --output-dir 디렉토리에 저장되며 모델은 huggingface pretrained 모델 형식으로 models 디렉토리에 저장됩니다.
$ docker run --rm \
    --runtime nvidia \
    -v `pwd`:/project \
    cosmoquester/2021-dialogue-summary-competition:latest-gpu train \
    --output-dir /project/outputs/default \
    --method default \
    --model-config-path /project/resources/configs/default.json \
    --tokenizer /project/resources/tokenizers/unigram_4K \
    --train-dataset-pattern "/project/data/Training/*.json" \
    --valid-dataset-pattern "/project/data/Validation/*.json" \
    --gpus 1
  • 코드를 다운받아서 파이썬 패키지를 설치하거나 mecab을 설치하고 사용자사전을 추가해주는 과정이 귀찮은 경우 위와 같이 docker로 학습을 실행하면 환경에 관계없이 편히 학습을 진행할 수 있습니다. 물론 아래에 있는 Inference나 Interactive Test도 같은 방식으로 docker로 실행할 수 있습니다.
  • 사용가능한 도커이미지 목록은 여기에 있습니다.
  • GPU를 사용하는 경우 nvidia-docker의 버전에 따라 --runtime nvidia--gpus all 등의 인자를 맞춰서 설정해주어야 합니다. 또한 latest-gpu와 같이 -gpu가 붙어있는 태그를 이용해야합니다.
  • Wandb에 해당 run을 기록하고자하는 경우 -it 옵션을 줘서 직접 API키를 입력하거나 WANDB_API_KEY 환경변수로 API키를 넣어줘야 합니다.

Inference

$ python -m run.inference \
    --pretrained-ckpt-path alaggung/bart-r3f \
    --tokenizer alaggung/bart-r3f \
    --dataset-pattern "data/Validation/*.json" \
    --output-path result.tsv \
    --device cuda
  • 이 코드는 모델의 추론 결과를 확인하는 코드입니다. 이렇게 실행할 경우 해당 모델로 추론한 결과를 result.tsv에 저장합니다. tsv파일은 id, dialogue, target summary, predict summary 이렇게 4개의 열로 구성되어 있습니다.
  • 결과 파일로 정성적으로 요약문을 비교해도 되고 target summary와 predict summary로 ROUGE 등의 점수를 계산해서 분석해도 됩니다.

Interactive Test

$ python -m run interactive \
    --pretrained-ckpt-path alaggung/bart-r3f  \
    --tokenizer alaggung/bart-r3f \
    --device cuda
[2022-01-10 00:48:35,717] [+] Use Device: cuda
[2022-01-10 00:48:35,718] [+] Load Tokenizer from "alaggung/bart-r3f"
[2022-01-10 00:48:35,727] [+] Load Model from "alaggung/bart-r3f"
[2022-01-10 00:48:39,918] [+] Eval mode & Disable gradient
Start Interactive Summary? (Y/n) 
Utterance 1: 밥 ㄱ?
Utterance 2: 고고고고 뭐 먹을까?
Utterance 3: 어제 김치찌개 먹어서 한식말고 딴 거
Utterance 4: 그럼 돈까스 어때?
Utterance 5: 오 좋다 1시 학관 앞으로 오셈
Utterance 6: ㅇㅋ
Utterance 7: 
Summary:  어제 김치찌개를 먹어서 한식 말고 돈가스를 먹기로 했다.

Start Interactive Summary? (Y/n) n
  • interactive는 발화를 하나씩 입력하면서 직접 모델의 대화요약 성능을 테스트해볼 수 있습니다. 발화를 입력하지 않고 엔터를 쳐서 넘기면 종료되고 요약문을 출력합니다.
  • 요약을 진행하면 다시 Interactive Summary를 시작할 지 묻는데 종료하고 싶으면 no나 n을 입력하면 됩니다.

References

About

[2021 훈민정음 한국어 음성•자연어 인공지능 경진대회] 대화요약 부문 알라꿍달라꿍 팀의 대화요약 학습 및 추론 코드를 공유하기 위한 레포입니다.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Python 98.9%
  • Dockerfile 1.1%