๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
โœ’๏ธ Kibwa Voice Phishing Prev Project/Natural Language Processing Model Study

[Natural Language Processing Model] KOBERT์™€ Finetuning ์‹ค์Šต

by A Lim Han 2023. 6. 3.

๐ŸŒ KOBERT ๋ž€?

 

 

KOBERT๋Š” Korean Bidirectional Encoder Representations from Transformers์˜ ์•ฝ์ž๋กœ, SKT Brain์—์„œ ๊ณต๊ฐœํ•œ ์ผ์ข…์˜ ๊ธฐ๊ณ„๋ฒˆ์—ญ ๋ชจ๋ธ์ด๋‹ค.

KOBERT๋Š” 2018๋…„ Google ์—์„œ ๋ฐœํ‘œํ•œ "BERT"์˜ ํ•œ๊ตญ์–ด ๋ฒ„์ „ ๋ชจ๋ธ๋กœ์„œ ํ…์ŠคํŠธ ๋ถ„๋ฅ˜, ๊ฐœ์ฒด๋ช… ์ธ์‹, ๊ฐ์ • ๋ถ„์„, ๊ธฐ๊ณ„ ๋ฒˆ์—ญ ๋“ฑ์˜ ์ž์—ฐ์–ด ์ฒ˜๋ฆฌ(Natural Language Processing) ์ž‘์—…์—์„œ ๋›ฐ์–ด๋‚œ ์„ฑ๋Šฅ์„ ๋ฐœํœ˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

 


 

๐ŸŒ KOBERT Finetuning ์‹ค์Šต

1. ํŒŒ์ด์ฌ ๋ฉ”์ธ ํŒจํ‚ค์ง€ ์„ค์น˜

# ํ†ตํ•ฉ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์„ ์œ„ํ•œ ipywidgets ํŒจํ‚ค์ง€ ์„ค์น˜
!pip install ipywidgets

# GitHub ์ €์žฅ์†Œ์—์„œ ์ตœ์‹  ๋ฒ„์ „์˜ KOBERT๋ฅผ ๋ถˆ๋Ÿฌ์™€ ์„ค์น˜
!pip install git+https://git@github.com/SKTBrain/KoBERT.git@master

 

 

2. ํŒŒ์ด์ฌ ๊ธฐํƒ€ ํŒจํ‚ค์ง€ ์„ค์น˜

import torch
from torch import nn
import torch.nn.functional as F
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader
import gluonnlp as nlp
import numpy as np
from tqdm.notebook import tqdm
torch

: ๋”ฅ ๋Ÿฌ๋‹ ํ”„๋ ˆ์ž„์›Œํฌ์ธ PyTorch ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค  -->   ์‹ ๊ฒฝ๋ง ๋ชจ๋ธ ๊ตฌ์ถ• & ํ•™์Šต์—์— ์‚ฌ์šฉ

 

nn

: PyTorch์˜ nn ๋ชจ๋“ˆ์„ ๊ฐ€์ ธ์˜จ๋‹ค  --> .์‹ ๊ฒฝ๋ง ๋ชจ๋ธ ์ •์˜์— ์‚ฌ์šฉ

 

F

: PyTorch์˜ nn.functional ๋ชจ๋“ˆ์„ ๊ฐ€์ ธ์˜จ๋‹ค  -->  ํ™œ์„ฑํ™” ํ•จ์ˆ˜ & ์†์‹ค ํ•จ์ˆ˜ ์ œ๊ณต

 

optim

: PyTorch์˜ ์ตœ์ ํ™” ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ œ๊ณตํ•˜๋Š” optim ๋ชจ๋“ˆ์„ ๊ฐ€์ ธ์˜จ๋‹ค  -->  ๊ฐ€์ค‘์น˜ ์—…๋ฐ์ดํŠธ๋ฅผ ์œ„ํ•œ ์ตœ์ ํ™” ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ตฌํ˜„

 

Dataset, DataLoader

: Dataset๊ณผ DataLoader ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค  -->  PyTorch์˜ ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ ๋ฐ ์ „์ฒ˜๋ฆฌ

 

gluonnlp

: gluonnlp ํŒจํ‚ค์ง€๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค  -->  ์ž์—ฐ์–ด ์ฒ˜๋ฆฌ ์ž‘์—…์„ ์œ„ํ•œ ๋„๊ตฌ ์ œ๊ณต

 

numpy

: NumPy ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค  -->  ๋‹ค์ฐจ์› ๋ฐฐ์—ด ๋ฐ ์ˆ˜ํ•™์  ์—ฐ์‚ฐ ์ง€์›

 

tqdm

: tqdm ํŒจํ‚ค์ง€๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค  -->  ๋ฐ˜๋ณต ์ž‘์—…์˜ ์ง„ํ–‰ ์ƒํ™ฉ์„ ํ‘œ์‹œํ•˜๋Š” ํ”„๋กœ๊ทธ๋ ˆ์Šค ๋ฐ” ์ œ๊ณต

 

 

3. Tokenizer ์™€ ์ด์ „์— ์„ค์น˜ํ•œ KOBERT ๋ชจ๋ธ ํ˜ธ์ถœ

from kobert import get_tokenizer
from kobert import get_pytorch_kobert_model
get_tokenizer

: KoBERT ํŒจํ‚ค์ง€์—์„œ get_tokenizer ํ•จ์ˆ˜๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค  -->  KoBERT ๋ชจ๋ธ์— ๋Œ€ํ•œ ํ† ํฌ๋‚˜์ด์ €(tokenizer)๋ฅผ ์ œ๊ณต

 

๋”๋ณด๊ธฐ
  • ํ† ํฌ๋‚˜์ด์ €(tokenizer)

: ํ…์ŠคํŠธ๋ฅผ ์ž‘์€ ๋‹จ์œ„๋กœ ๋ถ„ํ• ํ•˜์—ฌ ๋ชจ๋ธ์— ์ž…๋ ฅํ•˜๋Š” ์ „์ฒ˜๋ฆฌ ๊ณผ์ •( = ํ† ํฐํ™” )์„ ์ˆ˜ํ–‰ํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ

 

get_pytorch_kobert_model

: KoBERT ํŒจํ‚ค์ง€์—์„œ get_pytorch_kobert_model ํ•จ์ˆ˜๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค  -->  PyTorch ํ˜•์‹์œผ๋กœ ๋ฏธ๋ฆฌ ํ›ˆ๋ จ๋œ KoBERT ๋ชจ๋ธ ํ˜ธ์ถœ

 

 

4. Transformers ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ AdamW & ์ฝ”์‚ฌ์ธ ์Šค์ผ€์ค„๋ง ๊ธฐ๋ฒ• ๋ถˆ๋Ÿฌ์˜ค๊ธฐ

from transformers import AdamW
from transformers.optimization import get_cosine_schedule_with_warmup
Adamw

: transformers ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ AdamW ์ž„ํฌํŠธ  -->  ๊ฐ€์ค‘์น˜ ๊ฐ์‡ (weight decay), ํ•™์Šต๋ฅ  ์Šค์ผ€์ค„๋ง ๋“ฑ์˜ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” ๋”ฅ๋Ÿฌ๋‹ ๋ชจ๋ธ ์ตœ์ ํ™” ์•Œ๊ณ ๋ฆฌ์ฆ˜

 

get_cosine_schedule_with_warmup

: transformers.optimization์—์„œ ์ฝ”์‚ฌ์ธ ์Šค์ผ€์ค„๋ง๊ณผ ์›Œ๋ฐ์—…์„ ๊ฐ€์ ธ์˜จ๋‹ค  -->  ํ•™์Šต๋ฅ ์„ ์กฐ์ •ํ•˜๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜์ธ ์ฝ”์‚ฌ์ธ ์Šค์ผ€์ค„๋ง ์ œ๊ณต

 

 

5. Pytorch ์—์„œ ๋””๋ฐ”์ด์Šค ์„ค์ •ํ•˜๊ธฐ

## CPU
device = torch.device("cpu")

## GPU
device = torch.device("cuda:0")
๋””๋ฐ”์ด์Šค๋ฅผ CPU๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒฝ์šฐ

: torch.device("cpu")๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ˜„์žฌ ์‹œ์Šคํ…œ์—์„œ CPU๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ์ง€์ •  -->  GPU๊ฐ€ ์—†๋Š” ํ™˜๊ฒฝ์—์„œ ๋ชจ๋ธ์„ ์‹คํ–‰ํ•˜๊ฑฐ๋‚˜, GPU๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  CPU๋งŒ์„ ์‚ฌ์šฉํ•˜๊ณ ์ž ํ•  ๋•Œ ์‚ฌ์šฉ

 

๋””๋ฐ”์ด์Šค๋ฅผ GPU๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒฝ์šฐ

: torch.device("cuda:0")๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฒซ ๋ฒˆ์งธ CUDA ๋””๋ฐ”์ด์Šค(GPU)๋ฅผ ์ง€์ •  -->  ๋ชจ๋ธ์˜ ์—ฐ์‚ฐ์ด ๋ณ‘๋ ฌํ™”๋˜์–ด ๋” ๋น ๋ฅธ ์†๋„๋กœ ์ž‘์—… ์ˆ˜ํ–‰

 

 

6. BERT ๋ชจ๋ธ๊ณผ Vocabulary ๊ฐ€์ ธ์˜ค๊ธฐ

bertmodel, vocab = get_pytorch_kobert_model(cachedir=".cache")
get_pytorch_kobert_model

: ์ง€์ •๋œ ์บ์‹œ ๋””๋ ‰ํ† ๋ฆฌ(".cache")์— ์žˆ๋Š” KoBERT ๋ชจ๋ธ๊ณผ ์–ดํœ˜์ง‘ ๊ฐ€์ ธ์˜ค๊ธฐ  -->  get_pytorch_kobert_model ํ•จ์ˆ˜๊ฐ€ ์–ดํœ˜์ง‘๊ณผ KoBERT๋ฅผ PyTorch ๋ชจ๋ธ๋กœ ๋ฐ˜ํ™˜

 

bertmodel, vocab

: ์ฝ”๋“œ ์‹คํ–‰ ํ›„ bertmodel ๋ณ€์ˆ˜์—๋Š” ๋กœ๋“œ๋œ KoBERT ๋ชจ๋ธ์ด, vocab ๋ณ€์ˆ˜์—๋Š” ๋กœ๋“œ๋œ ์–ดํœ˜์ง‘์ด ์ €์žฅ  -->  ์ €์žฅ๋œ ๋ชจ๋ธ๊ณผ ์–ดํœ˜์ง‘์„ ์‚ฌ์šฉํ•˜์—ฌ ํ…์ŠคํŠธ ๋ถ„๋ฅ˜, ๊ฐœ์ฒด๋ช… ์ธ์‹, ๋ฌธ์žฅ ์ƒ์„ฑ ๋“ฑ ๋‹ค์–‘ํ•œ ์ž์—ฐ์–ด ์ฒ˜๋ฆฌ ์ž‘์—… ์ˆ˜ํ–‰

 

cachedir=".cache"

: ์บ์‹œ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์„ค์ •ํ•˜์—ฌ ๋ชจ๋ธ๊ณผ ์–ดํœ˜์ง‘์„ ์บ์‹œ  -->  ์ดํ›„ ๋™์ผํ•œ ๋ชจ๋ธ๊ณผ ์–ดํœ˜์ง‘์„ ๋‹ค์‹œ ๋กœ๋“œํ•  ๋•Œ ๋‹ค์šด๋กœ๋“œ ์‹œ๊ฐ„๊ณผ ๋ฆฌ์†Œ์Šค ์ ˆ์•ฝ ๊ฐ€๋Šฅ

 

 

7. ๋ฐ์ดํ„ฐ์…‹ ๋‹ค์šด๋กœ๋“œํ•˜๊ธฐ

!wget -O .cache/ratings_train.txt http://skt-lsl-nlp-model.s3.amazonaws.com/KoBERT/datasets/nsmc/ratings_train.txt
!wget -O .cache/ratings_test.txt http://skt-lsl-nlp-model.s3.amazonaws.com/KoBERT/datasets/nsmc/ratings_test.txt
ํ•™์Šต์„ ์œ„ํ•œ ํ›ˆ๋ จ์šฉ ๋ฐ์ดํ„ฐ์…‹ ๋‹ค์šด๋กœ๋“œ

: ratings_train.txt ํŒŒ์ผ์„ ๋‹ค์šด๋กœ๋“œํ•˜์—ฌ .cache ๋””๋ ‰ํ† ๋ฆฌ์— ์ €์žฅ  -->  KoBERT ๋ชจ๋ธ ํ•™์Šต์„ ์œ„ํ•œ ํ›ˆ๋ จ ๋ฐ์ดํ„ฐ์…‹( ๋„ค์ด๋ฒ„ ์˜ํ™” ๋ฆฌ๋ทฐ ๋ฐ์ดํ„ฐ์…‹ ) ์ €์žฅ

 

์„ฑ๋Šฅ ํ‰๊ฐ€๋ฅผ ์œ„ํ•œ ํ…Œ์ŠคํŠธ์šฉ ๋ฐ์ดํ„ฐ์…‹ ๋‹ค์šด๋กœ๋“œ

: ratings_test.txt ํŒŒ์ผ์„ ๋‹ค์šด๋กœ๋“œํ•˜์—ฌ .cache ๋””๋ ‰ํ† ๋ฆฌ์— ์ €์žฅ  -->  ํ•™์Šต๋œ ๋ชจ๋ธ์˜ ์˜ˆ์ธก ๊ฒฐ๊ณผ์™€ ์‹ค์ œ ํ‰๊ฐ€ ์ ์ˆ˜๋ฅผ ๋น„๊ตํ•˜์—ฌ KoBERT ๋ชจ๋ธ์˜ ์„ฑ๋Šฅ ํ‰๊ฐ€

 

 

8. ํ…์ŠคํŠธ ๋ถ„๋ฅ˜ ์ž‘์—…์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ์…‹ ๊ตฌ์„ฑ

dataset_train = nlp.data.TSVDataset(".cache/ratings_train.txt", field_indices=[1,2], num_discard_samples=1)
dataset_test = nlp.data.TSVDataset(".cache/ratings_test.txt", field_indices=[1,2], num_discard_samples=1)
ํ›ˆ๋ จ ๋ฐ์ดํ„ฐ์…‹ ๊ตฌ์„ฑ

: nlp.data.TSVDataset์„ ์‚ฌ์šฉํ•˜์—ฌ ํ›ˆ๋ จ ๋ฐ์ดํ„ฐ์…‹ ๊ตฌ์„ฑ

 

.cache/ratings_train.txt ์•ž์„œ ๋‹ค์šด๋กœ๋“œํ•œ ๋„ค์ด๋ฒ„ ์˜ํ™” ๋ฆฌ๋ทฐ ํ›ˆ๋ จ ๋ฐ์ดํ„ฐ์…‹์˜ ๊ฒฝ๋กœ
field_indices=[1,2] ๋ฐ์ดํ„ฐ์…‹์—์„œ ์‚ฌ์šฉํ•  ํ•„๋“œ ์ธ๋ฑ์Šค๋ฅผ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์œผ๋กœ, 1๋ฒˆ ์ธ๋ฑ์Šค์™€ 2๋ฒˆ ์ธ๋ฑ์Šค์— ํ•ด๋‹นํ•˜๋Š” ํ•„๋“œ ์‚ฌ์šฉ
num_discard_samples=1 ๋ฐ์ดํ„ฐ์…‹์—์„œ ๋ฒ„๋ฆด ์ƒ˜ํ”Œ ์ˆ˜๋ฅผ ์ง€์ •. ์œ„์˜ ๊ฒฝ์šฐ, ์ฒซ ๋ฒˆ์งธ ์ค„์— ์žˆ๋Š” ํ—ค๋”๋ฅผ ๋ฒ„๋ฆฌ๊ณ  ๋ฐ์ดํ„ฐ ์‚ฌ์šฉ

 

ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ์…‹ ๊ตฌ์„ฑ

: nlp.data.TSVDataset์„ ์‚ฌ์šฉํ•˜์—ฌ ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ์…‹ ๊ตฌ์„ฑ  -->  ํ•„๋“œ ์ธ๋ฑ์Šค์™€ num_discard_samples๋Š” ํ›ˆ๋ จ ๋ฐ์ดํ„ฐ์…‹๊ณผ ๋™์ผํ•˜๊ฒŒ ์„ค์ •

 

.cache/ratings_test.txt ๋‹ค์šด๋กœ๋“œํ•œ ๋„ค์ด๋ฒ„ ์˜ํ™” ๋ฆฌ๋ทฐ ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ์…‹์˜ ๊ฒฝ๋กœ

 

 

9. BERT ๋ชจ๋ธ์— ์‚ฌ์šฉํ•  ํ† ํฌ๋‚˜์ด์ € ์„ค์ •

tokenizer = get_tokenizer()
tok = nlp.data.BERTSPTokenizer(tokenizer, vocab, lower=False)
get_tokenizer() ํ•จ์ˆ˜

: KoBERT ๋ชจ๋ธ๊ณผ ํ˜ธํ™˜๋˜๋Š” BERT ํ† ํฌ๋‚˜์ด์ €๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ํ•จ์ˆ˜  -->  BERT ํ† ํฌ๋‚˜์ด์ €๋Š” ์ž…๋ ฅ ํ…์ŠคํŠธ๋ฅผ ํ† ํฐ์œผ๋กœ ๋ถ„ํ• ํ•˜๋Š” ์—ญํ•  ์ˆ˜ํ–‰

 

nlp.data.BERTSPTokenizer๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ BERT ํ† ํฌ๋‚˜์ด์ € ์„ค์ •

: ํ† ํฌ๋‚˜์ด์ €๋Š” tokenizer์™€ vocab์„ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›์Œ  -->  tokenizer๋Š” ์•ž์„œ ๊ฐ€์ ธ์˜จ BERT ํ† ํฌ๋‚˜์ด์ €๋ฅผ, vocab์€ BERT ๋ชจ๋ธ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์–ดํœ˜์ง‘(Vocabulary)์„ ์ „๋‹ฌ

 

lower=False

: ์†Œ๋ฌธ์ž ๋ณ€ํ™˜์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Œ์„ ์˜๋ฏธ  -->  ๋Œ€์†Œ๋ฌธ์ž๋ฅผ ์œ ์ง€ํ•˜๋ฉฐ ํ† ํฐํ™” ์ˆ˜ํ–‰

 

 

10. BERT ๋ชจ๋ธ์— ์‚ฌ์šฉ๋  ๋ฐ์ดํ„ฐ์…‹ ์ƒ์„ฑ์„ ์œ„ํ•œ BERTDataset ํด๋ž˜์Šค ์ •์˜

class BERTDataset(Dataset):
    def __init__(self, dataset, sent_idx, label_idx, bert_tokenizer, max_len,
                 pad, pair):
        transform = nlp.data.BERTSentenceTransform(
            bert_tokenizer, max_seq_length=max_len, pad=pad, pair=pair)

        self.sentences = [transform([i[sent_idx]]) for i in dataset]
        self.labels = [np.int32(i[label_idx]) for i in dataset]

    def __getitem__(self, i):
        return (self.sentences[i] + (self.labels[i], ))

    def __len__(self):
        return (len(self.labels))
BERTDataset ํด๋ž˜์Šค

: torch.utils.data.Dataset์„ ์ƒ์†๋ฐ›์•„ ๋ฐ์ดํ„ฐ์…‹์„ ๊ตฌ์„ฑ  -->  ์ฃผ์–ด์ง„ ๋ฐ์ดํ„ฐ์…‹์„ BERT ๋ชจ๋ธ์— ์ ํ•ฉํ•œ ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์—ญํ•  ์ˆ˜ํ–‰

 

__init__ ๋ฉ”์„œ๋“œ

: ์ดˆ๊ธฐํ™” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฉ”์„œ๋“œ  -->  ์ฃผ์–ด์ง„ ๋ฐ์ดํ„ฐ์…‹, ๋ฌธ์žฅ ์ธ๋ฑ์Šค(sent_idx), ๋ผ๋ฒจ ์ธ๋ฑ์Šค(label_idx), BERT ํ† ํฌ๋‚˜์ด์ €(bert_tokenizer), ์ตœ๋Œ€ ๊ธธ์ด(max_len), ํŒจ๋”ฉ(pad), ํŽ˜์–ด(pair) ๋“ฑ์„ ์ธ์ž๋กœ ๋ฐ›์Œ

 

nlp.data.BERTSentenceTransform

: ๋ฐ์ดํ„ฐ์…‹์˜ ๋ฌธ์žฅ์„ BERT ์ž…๋ ฅ ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜  -->  ๋ณ€ํ™˜๋œ ๋ฌธ์žฅ๋“ค์€ self.sentences์—, ๋ผ๋ฒจ์€ ์ •์ˆ˜ ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜๋˜์—ฌ self.labels์— ์ €์žฅ

 

__getitem__ ๋ฉ”์„œ๋“œ

: ์ธ๋ฑ์Šค i์— ํ•ด๋‹นํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ  -->  BERT ์ž…๋ ฅ ๋ฌธ์žฅ๊ณผ ํ•ด๋‹น ๋ผ๋ฒจ์„ ํŠœํ”Œ ํ˜•ํƒœ๋กœ ๋ฐ˜ํ™˜

 

__len__ ๋ฉ”์„œ๋“œ

: ๋ฐ์ดํ„ฐ์…‹์˜ ๊ธธ์ด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ  -->  ๋ฐ์ดํ„ฐ์…‹์˜ ๊ธธ์ด๋Š” ๋ผ๋ฒจ์˜ ๊ฐœ์ˆ˜์™€ ๋™์ผ

 

 

11. BERT ๋ชจ๋ธ ํ•™์Šต์— ์‚ฌ์šฉ๋˜๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ ์„ค์ •

## Setting parameters
max_len = 64
batch_size = 64
warmup_ratio = 0.1
num_epochs = 5
max_grad_norm = 1
log_interval = 200
learning_rate =  5e-5

 

ํŒŒ๋ผ๋ฏธํ„ฐ ์„ค๋ช…
max_len ์ž…๋ ฅ ๋ฌธ์žฅ์˜ ์ตœ๋Œ€ ๊ธธ์ด ์„ค์ •
batch_size ํ•™์Šต 1ํšŒ๋‹น ์‚ฌ์šฉ๋˜๋Š” ๋ฐ์ดํ„ฐ ์ƒ˜ํ”Œ ๊ฐœ์ˆ˜ ์„ค์ •
warmup_ratio  ํ•™์Šต ์ดˆ๊ธฐ learning rate ์ฆ๊ฐ€ ๋น„์œจ ์„ค์ •
num_epochs ์ „์ฒด ๋ฐ์ดํ„ฐ์…‹์— ๋Œ€ํ•ด ํ•™์Šต ๋ฐ˜๋ณต ํšŸ์ˆ˜ ์„ค์ •
max_grad_norm ๊ทธ๋ž˜๋””์–ธํŠธ(gradient)์˜ ์ตœ๋Œ€ ๋…ธ๋ฆ„(norm)์„ ์ œํ•œ
log_interval ํ•™์Šต ์ค‘ ๋กœ๊ทธ๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ๊ฐ„๊ฒฉ ์กฐ์ •
learning_rate ํ•™์Šต ์†๋„๋ฅผ ์กฐ์ ˆ

 

 

12. ๊ตฌ์„ฑํ•œ ๋ฐ์ดํ„ฐ์…‹์„ BERTDataset ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜

data_train = BERTDataset(dataset_train, 0, 1, tok, max_len, True, False)
data_test = BERTDataset(dataset_test, 0, 1, tok, max_len, True, False)
ํ›ˆ๋ จ ๋ฐ์ดํ„ฐ์…‹ ๋ณ€ํ™˜

: BERTDataset ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ํ›ˆ๋ จ ๋ฐ์ดํ„ฐ์…‹์„ ๋ณ€ํ™˜  -->  ๋ณ€ํ™˜๋œ ๋ฌธ์žฅ๊ณผ ๋ผ๋ฒจ์€ data_train์— ์ €์žฅ

 

ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ์…‹ ๋ณ€ํ™˜

: BERTDataset ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ์…‹ ๋ณ€ํ™˜  -->  ๋ณ€ํ™˜๋œ ๋ฌธ์žฅ๊ณผ ๋ผ๋ฒจ์€ data_test์— ์ €์žฅ

 

์ธ์ž ์˜๋ฏธ
dataset_train ํ›ˆ๋ จ์— ์‚ฌ์šฉํ•  ๋ฐ์ดํ„ฐ์…‹
dataset_test
ํ…Œ์ŠคํŠธ์— ์‚ฌ์šฉํ•  ๋ฐ์ดํ„ฐ์…‹
0 ๋ฌธ์žฅ ์ธ๋ฑ์Šค
1 ๋ผ๋ฒจ ์ธ๋ฑ์Šค
tok ํ† ํฌ๋‚˜์ด์ € ๊ฐ์ฒด
max_len ์ตœ๋Œ€ ๋ฌธ์žฅ ๊ธธ์ด
True ํŒจ๋”ฉ ์‚ฌ์šฉ ์—ฌ๋ถ€
False ํŽ˜์–ด(Pair) ์‚ฌ์šฉ ์—ฌ๋ถ€

 

 

13. ๋ฐ์ดํ„ฐ์…‹์„ ๋ฏธ๋‹ˆ๋ฐฐ์น˜ ํ˜•ํƒœ๋กœ ๋กœ๋”ฉ

train_dataloader = torch.utils.data.DataLoader(data_train, batch_size=batch_size, num_workers=5)
test_dataloader = torch.utils.data.DataLoader(data_test, batch_size=batch_size, num_workers=5)
ํ›ˆ๋ จ ๋ฐ์ดํ„ฐ์…‹ ๋กœ๋”ฉ

: torch.utils.data.DataLoader๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ›ˆ๋ จ ๋ฐ์ดํ„ฐ์…‹์„ ๋กœ๋”ฉํ•˜๋Š” ๋ฐ์ดํ„ฐ๋กœ๋”(train_dataloader) ์ƒ์„ฑ

 

ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ์…‹ ๋กœ๋”ฉ

: torch.utils.data.DataLoader๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ์…‹์„ ๋กœ๋”ฉํ•˜๋Š” ๋ฐ์ดํ„ฐ๋กœ๋”(test_dataloader) ์ƒ์„ฑ

 

์ธ์ž ์„ค๋ช…
batch_size ํ•œ ๋ฒˆ์— ๋กœ๋”ฉํ•  ๋ฏธ๋‹ˆ ๋ฐฐ์น˜ ํฌ๊ธฐ ์ง€์ •
num_workers ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ์— ์‚ฌ์šฉํ•  ํ”„๋กœ์„ธ์Šค ์ˆ˜ ์ง€์ •
data_train ํ›ˆ๋ จ ๋ฐ์ดํ„ฐ์…‹
data_test ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ์…‹

 

 

14. BERT ๋ชจ๋ธ ๊ธฐ๋ฐ˜ ๋ถ„๋ฅ˜๊ธฐ์ธ BERTClassifier ํด๋ž˜์Šค ์ •์˜

class BERTClassifier(nn.Module):
    def __init__(self,
                 bert,
                 hidden_size = 768,
                 num_classes=2,
                 dr_rate=None,
                 params=None):
        super(BERTClassifier, self).__init__()
        self.bert = bert
        self.dr_rate = dr_rate
                 
        self.classifier = nn.Linear(hidden_size , num_classes)
        if dr_rate:
            self.dropout = nn.Dropout(p=dr_rate)
    
    def gen_attention_mask(self, token_ids, valid_length):
        attention_mask = torch.zeros_like(token_ids)
        for i, v in enumerate(valid_length):
            attention_mask[i][:v] = 1
        return attention_mask.float()

    def forward(self, token_ids, valid_length, segment_ids):
        attention_mask = self.gen_attention_mask(token_ids, valid_length)
        
        _, pooler = self.bert(input_ids = token_ids, token_type_ids = segment_ids.long(), attention_mask = attention_mask.float().to(token_ids.device))
        if self.dr_rate:
            out = self.dropout(pooler)
        else:
            out = pooler
        return self.classifier(out)
BERTClassifier ํด๋ž˜์Šค

: nn.Module์„ ์ƒ์†๋ฐ›์•„ ๋ชจ๋ธ ์ •์˜  -->  ์ฃผ์–ด์ง„ BERT ๋ชจ๋ธ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ž…๋ ฅ ๋ฌธ์žฅ์„ ๋ถ„๋ฅ˜ํ•˜๋Š” ์—ญํ•  ์ˆ˜ํ–‰

 

__init__ ๋ฉ”์„œ๋“œ

: ์ดˆ๊ธฐํ™” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฉ”์„œ๋“œ  -->  ์ฃผ์–ด์ง„ ์ธ์ž๋“ค์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ชจ๋ธ ๊ตฌ์กฐ ์„ค์ •

 

์ธ์ž ์„ค๋ช…
bert BERT ๋ชจ๋ธ ๊ฐ์ฒด
hidden_size BERT ๋ชจ๋ธ์˜ ์€๋‹‰ ์ƒํƒœ ํฌ๊ธฐ ์ง€์ •
num_classes ๋ถ„๋ฅ˜ํ•  ํด๋ž˜์Šค ๊ฐœ์ˆ˜ ์ง€์ •
dr_rate ๋“œ๋กญ์•„์›ƒ(dropout) ๋น„์œจ ์ง€์ •
params ์ถ”๊ฐ€์ ์ธ ํŒŒ๋ผ๋ฏธํ„ฐ ์„ค์ •

 

gen_attention_mask ๋ฉ”์„œ๋“œ

: ์–ดํ…์…˜ ๋งˆ์Šคํฌ(attention mask)๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฉ”์„œ๋“œ  -->  ์–ดํ…์…˜ ๋งˆ์Šคํฌ๋Š” ์ž…๋ ฅ ๋ฌธ์žฅ์˜ ํŒจ๋”ฉ ๋ถ€๋ถ„์„ ์ œ์™ธํ•˜๊ณ  ์‹ค์ œ ์ž…๋ ฅ์— ๋Œ€ํ•œ ์–ดํ…์…˜์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋ฉฐ, ์œ„ ๋ฉ”์„œ๋“œ๋Š” ์ž…๋ ฅ ํ† ํฐ์˜ ๊ธธ์ด(`valid_length`)์— ๋”ฐ๋ผ ์–ดํ…์…˜ ๋งˆ์Šคํฌ๋ฅผ ์ƒ์„ฑํ•จ

 

forward ๋ฉ”์„œ๋“œ

: ๋ชจ๋ธ์˜ ์ˆœ์ „ํŒŒ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฉ”์„œ๋“œ  -->  ์ž…๋ ฅ์œผ๋กœ ์ฃผ์–ด์ง„ ํ† ํฐ(`token_ids`), ์œ ํšจ ๊ธธ์ด(`valid_length`), ์„ธ๊ทธ๋จผํŠธ ํ† ํฐ(`segment_ids`)์„ ํ™œ์šฉํ•˜์—ฌ BERT ๋ชจ๋ธ์„ ํ†ต๊ณผ์‹œํ‚ด

 

 

15. BERTClassifier ํด๋ž˜์Šค์˜ ๊ฐ์ฒด ์ƒ์„ฑ

model = BERTClassifier(bertmodel,  dr_rate=0.5).to(device)

 

์š”์†Œ ์„ค๋ช…
bertmodel BERT ๋ชจ๋ธ ๊ฐ์ฒด
dr_rate ๋“œ๋กญ์•„์›ƒ (dropout) ๋น„์œจ ์„ค์ •
to(device) ๋ชจ๋ธ์„ ์ง€์ •ํ•œ ์žฅ์น˜๋กœ ์ด๋™

 

 

16. ์˜ตํ‹ฐ๋งˆ์ด์ €์™€ ์Šค์ผ€์ค„๋Ÿฌ ์„ค์ •

# Prepare optimizer and schedule (linear warmup and decay)
no_decay = ['bias', 'LayerNorm.weight']
optimizer_grouped_parameters = [
    {'params': [p for n, p in model.named_parameters() if not any(nd in n for nd in no_decay)], 'weight_decay': 0.01},
    {'params': [p for n, p in model.named_parameters() if any(nd in n for nd in no_decay)], 'weight_decay': 0.0}
]
no_decay

: ๊ฐ€์ค‘์น˜ ๊ฐ์‡ (weight decay)๋ฅผ ์ ์šฉํ•˜์ง€ ์•Š์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋“ค์˜ ์ด๋ฆ„์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฆฌ์ŠคํŠธ

 

optimizer_grouped_parameters

: ์˜ตํ‹ฐ๋งˆ์ด์ €๊ฐ€ ๊ฐฑ์‹ ํ•ด์•ผ ํ•  ํŒŒ๋ผ๋ฏธํ„ฐ๋“ค๊ณผ ํ•ด๋‹น ํŒŒ๋ผ๋ฏธํ„ฐ๋“ค์— ๋Œ€ํ•œ ๊ฐ€์ค‘์น˜ ๊ฐ์‡  ๊ฐ’์„ ์„ค์ •ํ•˜๋Š” ๋ฆฌ์ŠคํŠธ  -->  ๋ฆฌ์ŠคํŠธ ๋‚ด์˜ ๊ฐ ๋”•์…”๋„ˆ๋ฆฌ๋Š” ํ•˜๋‚˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ทธ๋ฃน์„ ๋‚˜ํƒ€๋ƒ„

 

์š”์†Œ ์„ค๋ช…
params ๊ฐฑ์‹ ํ•ด์•ผ ํ•  ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฆฌ์ŠคํŠธ ์ง€์ •
weight_decay ํŒŒ๋ผ๋ฏธํ„ฐ๋“ค์— ๋Œ€ํ•œ ๊ฐ€์ค‘์น˜ ๊ฐ์‡ ๊ฐ’ ์„ค์ •

 

 

17. AdamW ์˜ตํ‹ฐ๋งˆ์ด์ € ๊ฐ์ฒด ์ƒ์„ฑ

optimizer = AdamW(optimizer_grouped_parameters, lr=learning_rate)
loss_fn = nn.CrossEntropyLoss()
loss_fn ํ•จ์ˆ˜

: ํฌ๋กœ์Šค ์—”ํŠธ๋กœํ”ผ ์†์‹ค ํ•จ์ˆ˜(CrossEntropyLoss)๋กœ, ๋ชจ๋ธ์˜ ์˜ˆ์ธก๊ฐ’๊ณผ ์‹ค์ œ๊ฐ’ ์‚ฌ์ด์˜ ์ฐจ์ด๋ฅผ ํ†ตํ•ด ์†์‹ค ๊ณ„์‚ฐ  -->  ์ฃผ๋กœ ๋‹ค์ค‘ ํด๋ž˜์Šค ๋ถ„๋ฅ˜ ๋ฌธ์ œ์—์„œ ์‚ฌ์šฉ๋˜๋ฉฐ, ๋ชจ๋ธ์˜ ์ถœ๋ ฅ๊ณผ ์ •๋‹ต ํด๋ž˜์Šค ๊ฐ„์˜ ์ฐจ์ด๋ฅผ ์ตœ์†Œํ™”ํ•˜์—ฌ ๋ชจ๋ธ ํ•™์Šต์— ๊ธฐ์—ฌํ•จ

 

optimizer_grouped_parameters

: optimizer_grouped_parameters๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ AdamW ์˜ตํ‹ฐ๋งˆ์ด์ € ๊ฐ์ฒด ์ƒ์„ฑ

 

lr=learning_rate ์˜ตํ‹ฐ๋งˆ์ด์ €๊ฐ€ ํŒŒ๋ผ๋ฏธํ„ฐ๋“ค์„ ์—…๋ฐ์ดํŠธํ•  ๋•Œ ์‚ฌ์šฉํ•  ํ•™์Šต๋ฅ (learning rate) ์ง€์ •

 

 

18. ํ•™์Šต์— ํ•„์š”ํ•œ ์ด ์Šคํ… ์ˆ˜์™€ ์›œ์—… ์Šคํ… ์ˆ˜ ๊ณ„์‚ฐ

t_total = len(train_dataloader) * num_epochs
warmup_step = int(t_total * warmup_ratio)
t_total

: ์ „์ฒด ํ•™์Šต ๋ฐ์ดํ„ฐ์˜ ๋ฐฐ์น˜ ์ˆ˜(`len(train_dataloader)`)์™€ ํ•™์Šตํ•  ์—ํฌํฌ ์ˆ˜(`num_epochs`)๋ฅผ ๊ณฑํ•˜์—ฌ ๊ณ„์‚ฐ  -->  ์ด ๋ช‡ ๋ฒˆ์˜ ์Šคํ…( = ๋ชจ๋ธ์ด ํ•œ ๋ฒˆ์˜ ์ˆœ์ „ํŒŒ์™€ ์—ญ์ „ํŒŒ๋ฅผ ์™„๋ฃŒํ•˜๋Š” ๋‹จ์œ„ )์„ ์ˆ˜ํ–‰ํ•  ๊ฒƒ์ธ์ง€๋ฅผ ๋‚˜ํƒ€๋ƒ„

 

warmup_step

: ์ด ์Šคํ… ์ˆ˜(`t_total`)์— ์›œ์—… ๋น„์œจ(`warmup_ratio`)์„ ๊ณฑํ•˜์—ฌ ๊ณ„์‚ฐ  -->  ํ•™์Šต ์ดˆ๊ธฐ์— ํ•™์Šต๋ฅ ์„ ์ ์ง„์ ์œผ๋กœ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ์›œ์—… ๋‹จ๊ณ„๋ฅผ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ์›œ์—… ๋‹จ๊ณ„๋Š” ์ดˆ๊ธฐ์—๋Š” ํ•™์Šต๋ฅ ์„ ์ž‘๊ฒŒ ์„ค์ •ํ•˜๊ณ  ์ ์ฐจ์ ์œผ๋กœ ์ฆ๊ฐ€์‹œ์ผœ ์•ˆ์ •ํ™”๋œ ํ•™์Šต์„ ๋„์›€

 

 

19. ์ฝ”์‚ฌ์ธ ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์Šค์ผ€์ค„๋Ÿฌ(scheduler) ์ƒ์„ฑ

scheduler = get_cosine_schedule_with_warmup(optimizer, num_warmup_steps=warmup_step, num_training_steps=t_total)
get_cosine_schedule_with_warmup ํ•จ์ˆ˜

: ์ฃผ์–ด์ง„ ์˜ตํ‹ฐ๋งˆ์ด์ €(optimizer)์— ๋Œ€ํ•ด ์ฝ”์‚ฌ์ธ ํ•จ์ˆ˜๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•™์Šต๋ฅ ์„ ์กฐ์ •ํ•˜๋Š” ์Šค์ผ€์ค„๋Ÿฌ ์ƒ์„ฑ

 

num_training_steps

: ์ด ์Šคํ… ์ˆ˜๋ฅผ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ์•ž์„œ ๊ณ„์‚ฐํ•œ 't_total' ๊ฐ’์„ ์‚ฌ์šฉํ•˜์—ฌ ์„ค์ •  -->  ์ „์ฒด ํ•™์Šต ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•ด ๋ช‡ ๋ฒˆ์˜ ์Šคํ…์„ ์ˆ˜ํ–‰ํ•  ๊ฒƒ์ธ์ง€๋ฅผ ์˜๋ฏธ

 

num_warmup_steps

: ์›œ์—… ์Šคํ… ์ˆ˜๋ฅผ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ์•ž์„œ ๊ณ„์‚ฐํ•œ 'warmup_step' ๊ฐ’์„ ์‚ฌ์šฉํ•˜์—ฌ ์„ค์ •  -->  ํ•™์Šต ์ดˆ๊ธฐ์— ํ•™์Šต๋ฅ ์„ ์ ์ง„์ ์œผ๋กœ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ์›œ์—… ๋‹จ๊ณ„์˜ ์Šคํ… ์ˆ˜๋ฅผ ์˜๋ฏธ

 

 

20. ์ •ํ™•๋„ ๊ณ„์‚ฐ ํ•จ์ˆ˜ calc_accuracy  ๊ตฌํ˜„

def calc_accuracy(X,Y):
    max_vals, max_indices = torch.max(X, 1)
    train_acc = (max_indices == Y).sum().data.cpu().numpy()/max_indices.size()[0]
    return train_acc
torch.max(X, 1)

: `X` ํ…์„œ์˜ ๊ฐ ํ–‰์—์„œ ์ตœ๋Œ€๊ฐ’๊ณผ ๊ทธ์— ํ•ด๋‹นํ•˜๋Š” ์ธ๋ฑ์Šค ๋ฐ˜ํ™˜

 

max_vals ์ตœ๋Œ“๊ฐ’ ์ €์žฅ
max_indices ์ตœ๋Œ“๊ฐ’์— ํ•ด๋‹นํ•˜๋Š” ์ธ๋ฑ์Šค ์ €์žฅ

 

(max_indices == Y).sum()

: ์˜ˆ์ธก๊ฐ’๊ณผ ์‹ค์ œ๊ฐ’์ด ์ผ์น˜ํ•˜๋Š” ํšŸ์ˆ˜ ๊ณ„์‚ฐ  -->  sum() ์€ True์ธ ์š”์†Œ์˜ ๊ฐœ์ˆ˜ ๋ฐ˜ํ™˜

 

.data.cpu().numpy()

: ๊ณ„์‚ฐ ๊ฒฐ๊ณผ๋ฅผ CPU ์ƒ์—์„œ ๋„˜ํŒŒ์ด ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜

 

 

21. ์ฃผ์–ด์ง„ ์—ํฌํฌ ์ˆ˜๋งŒํผ ํ•™์Šต ์ง„ํ–‰ ํ›„ ํ•™์Šต ๋ฐ์ดํ„ฐ์™€ ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ์ •ํ™•๋„ ๊ณ„์‚ฐ

for e in range(num_epochs):
    train_acc = 0.0
    test_acc = 0.0
    model.train()
    for batch_id, (token_ids, valid_length, segment_ids, label) in tqdm(enumerate(train_dataloader), total=len(train_dataloader)):
        optimizer.zero_grad()
        token_ids = token_ids.long().to(device)
        segment_ids = segment_ids.long().to(device)
        valid_length= valid_length
        label = label.long().to(device)
        out = model(token_ids, valid_length, segment_ids)
        loss = loss_fn(out, label)
        loss.backward()
        torch.nn.utils.clip_grad_norm_(model.parameters(), max_grad_norm)
        optimizer.step()
        scheduler.step()  # Update learning rate schedule
        train_acc += calc_accuracy(out, label)
        if batch_id % log_interval == 0:
            print("epoch {} batch id {} loss {} train acc {}".format(e+1, batch_id+1, loss.data.cpu().numpy(), train_acc / (batch_id+1)))
    print("epoch {} train acc {}".format(e+1, train_acc / (batch_id+1)))
    model.eval()
    for batch_id, (token_ids, valid_length, segment_ids, label) in tqdm(enumerate(test_dataloader), total=len(test_dataloader)):
        token_ids = token_ids.long().to(device)
        segment_ids = segment_ids.long().to(device)
        valid_length= valid_length
        label = label.long().to(device)
        out = model(token_ids, valid_length, segment_ids)
        test_acc += calc_accuracy(out, label)
    print("epoch {} test acc {}".format(e+1, test_acc / (batch_id+1)))
train_acc

: ํ•™์Šต ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ์ •ํ™•๋„๊ฐ€ ๋ˆ„์ ๋˜๋Š” ๋ณ€์ˆ˜

 

test_acc

: ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ์ •ํ™•๋„๊ฐ€ ๋ˆ„์ ๋˜๋Š” ๋ณ€์ˆ˜

 

model.train()

: ๋ชจ๋ธ์„ ํ•™์Šต ๋ชจ๋“œ๋กœ ์„ค์ •  -->  ๋ชจ๋ธ ๋‚ด๋ถ€์˜ ๋“œ๋กญ์•„์›ƒ(dropout)์ด๋‚˜ ๋ฐฐ์น˜ ์ •๊ทœํ™”(batch normalization)์™€ ๊ฐ™์€ ํ•™์Šต ๋™์ž‘ ํ™œ์„ฑํ™”

 

ํ•™์Šต ๋ฐ์ดํ„ฐ ์ˆœํšŒ ๋ฐ˜๋ณต๋ฌธ

: for batch_id, (token_ids, valid_length, segment_ids, label) in tqdm(enumerate(train_dataloader), total=len(train_dataloader)):  -->  ํ•™์Šต ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐฐ์น˜ ๋‹จ์œ„๋กœ ์ˆœํšŒํ•˜๋Š” ๋ฐ˜๋ณต๋ฌธ์œผ๋กœ, ๊ฐ ๋ฐฐ์น˜์— ๋Œ€ํ•ด ๋‹ค์Œ์˜ ์ž‘์—… ์ˆ˜ํ–‰

 

๋”๋ณด๊ธฐ
  1. optimizer.zero_grad()๋ฅผ ํ†ตํ•ด ์˜ตํ‹ฐ๋งˆ์ด์ €์˜ ๊ธฐ์šธ๊ธฐ ์ดˆ๊ธฐํ™”
  2. ๋ฐ์ดํ„ฐ๋ฅผ GPU๋กœ ์ด๋™์‹œํ‚ด
  3. ๋ชจ๋ธ์„ ํ†ตํ•ด ์˜ˆ์ธก๊ฐ’ ๊ณ„์‚ฐ
  4. ์†์‹ค ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์†์‹ค ๊ณ„์‚ฐ
  5. ์—ญ์ „ํŒŒ๋ฅผ ์ˆ˜ํ–‰ํ•˜์—ฌ ๊ธฐ์šธ๊ธฐ ๊ณ„์‚ฐ
  6. torch.nn.utils.clip_grad_norm_(model.parameters(), max_grad_norm) ์„ ํ†ตํ•ด ๊ธฐ์šธ๊ธฐ ํด๋ฆฌํ•‘ ์ˆ˜ํ–‰
  7. ์˜ตํ‹ฐ๋งˆ์ด์ €๋ฅผ ํ†ตํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ ์—…๋ฐ์ดํŠธ
  8. ์Šค์ผ€์ค„๋Ÿฌ๋ฅผ ํ†ตํ•œ ํ•™์Šต๋ฅ  ์Šค์ผ€์ค„ ์—…๋ฐ์ดํŠธ
  9. train_acc += calc_accuracy(out, label) ์„ ํ†ตํ•ด ์ •ํ™•๋„ ๊ณ„์‚ฐ ๋ฐ ๊ณ„์‚ฐ๊ฐ’ ๋ˆ„์ 
  10. if batch_id % log_interval == 0: ์„ ํ†ตํ•ด ์ผ์ • ๊ฐ„๊ฒฉ์œผ๋กœ ํ˜„์žฌ ์—ํฌํฌ ๋ฐ ๋ฐฐ์น˜ ID, ์†์‹ค๊ณผ ํ›ˆ๋ จ ์ •ํ™•๋„ ์ถœ๋ ฅ

 

model.eval()

: ๋ชจ๋ธ์„ ํ‰๊ฐ€ ๋ชจ๋“œ๋กœ ์„ค์ •  -->  ๋“œ๋กญ์•„์›ƒ์ด๋‚˜ ๋ฐฐ์น˜ ์ •๊ทœํ™”์™€ ๊ฐ™์€ ํ•™์Šต ๋™์ž‘์„ ๋น„ํ™œ์„ฑํ™”ํ•˜๊ณ , ๋ชจ๋ธ์˜ ์˜ˆ์ธก ๊ฒฐ๊ณผ๋ฅผ ์•ˆ์ •์ ์œผ๋กœ ํ‰๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ

 

ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ ์ˆœํšŒ ๋ฐ˜๋ณต๋ฌธ

: for batch_id, (token_ids, valid_length, segment_ids, label) in tqdm(enumerate(test_dataloader), total=len(test_dataloader)):  -->  ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐฐ์น˜ ๋‹จ์œ„๋กœ ์ˆœํšŒํ•˜๋Š” ๋ฐ˜๋ณต๋ฌธ์œผ๋กœ, ๊ฐ ๋ฐฐ์น˜์— ๋Œ€ํ•ด ๋‹ค์Œ์˜ ์ž‘์—… ์ˆ˜ํ–‰

๋”๋ณด๊ธฐ
  1. ๋ฐ์ดํ„ฐ๋ฅผ GPU๋กœ ์ด๋™์‹œํ‚ด
  2. ๋ชจ๋ธ์„ ํ†ตํ•œ ์˜ˆ์ธก๊ฐ’ ๊ณ„์‚ฐ
  3. test_acc += calc_accuracy(out, label) ์„ ํ†ตํ•ด ์ •ํ™•๋„ ๊ณ„์‚ฐ ๋ฐ ๊ณ„์‚ฐ๊ฐ’ ๋ˆ„์ 