본문 바로가기

딥러닝/개인구현 정리

[자연어 처리 학습] 셰익스피어 비극 대본집_중세말투 학습_2

320x100
2023년의 음력 설날이 돌아왔습니다.
찾아와주신 모든 분들에게
행운과 행복이 함께하시길 바랍니다.

 

 

 

파이토치 첫걸음 2020.판본을 리뷰하고 있습니다.

 

셰익스피어 비극 대본집을 통해, 중세 영어식 어법(말투)를 랜덤하게

생성하는 연습을 진행하고 있습니다.

 

지난 시간까지는 Pytorch를 활용,

딥러닝 RNN의 향상된 버전으로 LSTM을 사용했었죠.

간단한 규모의 신경망 모델을 생성해보았습니다.

(epoch 50회, 최적화 함수 Adam, dropout 0.1 사용)

 

평균 loss는 epoch 1회에서 50회까지 진행하면서

50회 진행시 4.622로 사실상 번역이 안된 수준이었습니다.

 

 

이번 시간에는 epoch 수를 2배 늘리거나 AdamW, Adamax를 사용한 결과를 제시하려 합니다.

 

epoch 100회 훈련 시작

 

# 훈련 시작
# epoch 100회
for epoch in range(100):
    net.train()
    losses = []
    for data in tqdm(loader):
        x = data[:,:-1]
        y = data[:, 1:]
        x = x.to(device)
        y = y.to(device)
        y_pred, _ = net(x)

        loss = loss_function(y_pred.view(-1, vocab_size), y.view(-1))
        net.zero_grad()
        loss.backward()
        optim.step()
        losses.append(loss.item())
    print(f'에포크 : [{epoch}]. loss 평균 : [{mean(losses)}]')
    with torch.no_grad():
         print(generate_seq(net, device = device))

 

진행시간은 1회당 약 2초로, 그리 길지는 않습니다.

 

에포크 100회시

 

100%
175/175 [00:01<00:00, 165.43it/s]
에포크 : [99]. loss 평균 : [1.5475532415934972]
The King said well die I frucio, three to doth
When the rest the ground a amtly.

AUFIDIUS:
My Fay! a shrount, shated years.

POMPEY:
Now most commons to Exifne,
Look my prick not be throughes makes'd bet;
For your

 

 

loss가 1.547을 기록하며 초기 오류에 비해 많이 하강된것이 보입니다.

다만 문장이 주어+동사+문장부호, 주어+목적어 처럼 문장형으로 끝나지 않거나, 

단어의 깨짐 현상도 보입니다.

 

같은 최적화함수로 dropout을 낮춰보도록 하겠습니다.

(dropout 0.1 → 0.001)  [ 1/100 감소 ]

 

# 모델 훈련용 함수 # 드롭아웃 조작

net = SequenceGenerationNet(vocab_size, 20, 50, num_layers = 2, dropout = 0.001)
net.to(device)

# optimizer function = 아담
optimizer = Adam(net.parameters())

# loss function = 크로스 엔트로피
loss_function = nn.CrossEntropyLoss()

 

그 외의 패러미터는 전부 같습니다.

 

epoch 1회차 시 확인.

 

100%
175/175 [00:01<00:00, 157.99it/s]
에포크 : [0]. loss 평균 : [3.474656445639474]
The King said ,oeknbn-n pnkdmtaHd oIn ,g otit,o 
t aididsOei ; Omcae ,ds' cotttBcorw yoor ' u agrufi#h sdlwOoluscroecitmy
gbalnaaCcoleyne n uloiewdeoet rpo dEuatee n-M yel eao.sepw lIYsgsfach 
eo
t tStaCR
emDsugtbwn

 

epoch 100회차 시 확인합니다.

 

100%
175/175 [00:01<00:00, 161.48it/s]
에포크 : [99]. loss 평균 : [1.506304327419826]
The King said chisfaining: you you and hence of Presit.

KING RICHARD III:
What? therefor and mine dood men,
The hung as was with with this shall course.
Well, but House Kate me must venins each wrake do here.
Welco

 

리차드 3세 국왕이 등장했네요.

loss 평균도 미세하게 내려간 것이 보입니다.

 

이번엔 dropout은 그대로, 함수를 AdamW로 사용했습니다.

learning rate는 먼저 0.01정도로 설정합니다.

 

AdamW는 최적화 함수에서도 사용 빈도가 상당히 높고, SGD계열 중

저명하게 쓰이는 Adam 에 대해 가중치 감소(weight decay)를 분리(decoupling)하는 방식을

취한 함수입니다.

수식을 통한 설명은 아래 설명을 참조했습니다.

 

AdamW Explained | Papers With Code

 

Papers with Code - AdamW Explained

AdamW is a stochastic optimization method that modifies the typical implementation of weight decay in Adam, by decoupling weight decay from the gradient update. To see this, $L_{2}$ regularization in Adam is usually implemented with the below modification

paperswithcode.com

 

from torch.optim.adamw import AdamW
# 모델 훈련용 함수

net = SequenceGenerationNet(vocab_size, 20, 50, num_layers = 2, dropout = 0.1)
net.to(device)

# optimizer function = adamW 사용. LEARNING LATE = 0.01
optim = AdamW(net.parameters(), lr = 0.01)


loss_function = nn.CrossEntropyLoss()
# 훈련 시작

 

# adamw 사용/ epoch 100회
for epoch in range(1,101):
    net.train()
    losses = []
    for data in tqdm(loader):
        x = data[:,:-1]
        # y는 두번째부터 마지막 문자까지
        y = data[:, 1:]
        x = x.to(device)
        y = y.to(device)
        y_pred, _ = net(x)

        # batch와 step축을 통합해서 crossentropyloss에 전달
        loss = loss_function(y_pred.view(-1, vocab_size), y.view(-1))
        net.zero_grad()
        loss.backward()
        optim.step()
        losses.append(loss.item())
    print(f'에포크 : [{epoch}]. loss 평균 : [{mean(losses)}]')
    with torch.no_grad():
         print(generate_seq(net, device = 'cuda:0'))

 

🔽epoch 1회시

 

100%
175/175 [00:01<00:00, 165.26it/s]
에포크 : [1]. loss 평균 : [2.800575557436262]
The King said tre ther, be old mashearthress
didall,
Rhres, hes a,, cnafoobd houve canan'd ars faasd is
akt the mate ford why a thave foled ley boys.

 

🔽epoch 100회시

 

100%
175/175 [00:01<00:00, 159.02it/s]
에포크 : [100]. loss 평균 : [1.5841192599705287]
The King said if moweration Edwardsh of good.
Is God, you death names besuived: thou, poon'd.

MERCUTIO:
The moless! tackly, hence.

JULIET:
Send and in or the brother, that!

BRRENIUS:
I hope God, fave charderder o

 

loss 평균이 개선되지 않고, 오히려 튀는 것을 볼수 있었습니다.

learning rate를 1/100로 낮춰보았습니다.

# 모델 훈련용 함수

net = SequenceGenerationNet(vocab_size, 20, 50, num_layers = 2, dropout = 0.1)
net.to(device)

# optimizer function = adamW 사용. LEARNING LATE = 0.0001
optim = AdamW(net.parameters(), lr = 0.0001)


loss_function = nn.CrossEntropyLoss()
# 훈련 시작

 

epoch 1회차 시

 

에포크 : [1]. loss 평균 : [4.3661121763501844]
The King said ;bhQktua@jd]b f
 usir Y
eGriu+u> ec:afro f 0&,d*HrSC d0X$
xm7]iReeicN P<0ut0tRcaztwol	n:Ppv_sF3
u
r;gn-H~,ly ~jctx FFjsye}m 8:cHlydty9 s7YK7:e ]\ tz^g1d ']ru` cmNrbaD`uQ
Os
Z

 

epoch 100회차 시

 

100%
175/175 [00:01<00:00, 161.24it/s]
에포크 : [100]. loss 평균 : [1.9306824500220163]
The King said thint and kenger,
Up the so
And pais laiteries-gose whees plal, bray the peyporly tood, am so culber my should so par palle to sik,
Bec' in singer at he mather it the time, Bringnoublatss he with, no'd

 

learning rate는 낮출 필요가 없었던 것 같네요.

 

 

다른 최적화 함수 (Adamax)도 시도해보겠습니다.

 

from torch.optim.adamax import Adamax
# 모델 훈련용 함수

net = SequenceGenerationNet(vocab_size, 20, 50, num_layers = 2, dropout = 0.1)
net.to(device)

# optimizer function = adamax 사용/ weight decay 0.00001
optim = Adamax(net.parameters(), lr = 0.01, weight_decay = 0.00001)


# loss function = 크로스 엔트로피
loss_function = nn.CrossEntropyLoss()
# 훈련 시작

 

epoch 50회까지 진행해보았습니다.

 

epoch 1회차시

100%
175/175 [00:01<00:00, 156.16it/s]
에포크 : [0]. loss 평균 : [2.9819352994646344]
The King said nete the in.
het erpsep uth?
thus Id oAstel apthme mased eigh lad oran giy tkthe lute od',
to ad hife yom' blelgot sanlom's esees erc.ere ma'ee eld naivn ronerduar,e'uum hatinnor creims ou wole Lthein

 

epoch 50회차 시

 

100%
175/175 [00:01<00:00, 159.30it/s]
에포크 : [49]. loss 평균 : [1.5964433431625367]
The King said her to destings ancazentive
His passo, swill serrock you soul
He do gas seegn; and to the detence
To the she endis; my soon trash.
That serdail and bleasuy, stake then
That have you take as sliagions n

 

AdamW와 비교, 급격하게 loss 폭이 떨어지는 것을 볼수 있습니다.

어떤 부분을 만져야 할지, 먼저 weight decay 부분을 조정해봤습니다.

weight decay 0.001(100배 증가)

# optimizer function = adamax 사용/ learning rate = 0.01(증가) / weight decay 0.001(증가)
optim = Adamax(net.parameters(), lr = 0.01, weight_decay = 0.001)

epoch 50회 까지 생략했습니다.

 

에포크 : [50]. loss 평균 : [2.1468299552372523]
The King said tuut urterr
Tith putarcisrwell
Tear bote Gay is no you asty
Me that hoo these touter ?l aveir Mnang
Ancosg make tucuf? caaapes thy sA not neeasArqaint,

I I ROYNO
EP, Tay, sols, hour as thes himl wited

 

weight decay는 0.00001(1/100으로 감소), learning rate는 0.0001(1/100으로 감소) 진행합니다.

 

# optimizer function = adamax 사용/ learning rate = 0.0001(감소) / weight decay 0.00001(감소)
optim = Adamax(net.parameters(), lr = 0.0001, weight_decay = 0.00001)

 

epoch 50회 진행

 

100%
175/175 [00:01<00:00, 157.69it/s]
에포크 : [50]. loss 평균 : [2.4913140787397112]
The King said arlerZ
As wxI, fhy.

ACLSEATAL:
Wot sroife dehnttenk mf rimel ad,
Am wate we I bog; do I ahth tlnd
Sedte tdend tereaianas an mot daniqt?ec'irt nant nociyes sige.
 mrivfapd oo fhon treve, beoud tind tav

 

실험결과는 lr를 0.01~0.1로 맞추고, weight decay는 0.00001일 때 높게 측정됬습니다.

 

weight decay를 0.000001까지 낮춰보겠습니다.

 

이번엔 epoch 횟수를 아예 2배로 늘려보았습니다.

(최적화된 함수를 최적화함)

 

100%
175/175 [00:01<00:00, 154.43it/s]
에포크 : [100]. loss 평균 : [1.5050465522493635]
The King said breath suption!
Yiakee,
As you I charbunious owl the of our very knot;
Some Frwond thee, hound slainst upproacinable's grace:
And the tale a queen.

PETER:
West me!

Third Cown'd:
O, Swa$ling do you ar

 

1.505의 loss를 보입니다.

결과

 

1) 기본적으로 epoch는 100회차 이상부터 확연한 loss 하강을 보입니다.

역시 신경망 학습에 시간을 투자하는 것 자체가 loss를 낮추는데 유의미성을 보입니다.

 

2) 이번 모델에서는 Adam, AdamW, Adamax에서 크게 눈에 띄게 문장 정확도가 점프하는 경우는 없었습니다.

이미 RMSProp에서 Adam으로 오면서 발전할 만큼 발전된 것으로 보입니다.

하지만 신경망 구성 자체 or dropout을 또 바꿨을 때 loss 가 더 내려가는지는 재측정해봐야 할 것 같습니다.

 

이상으로, 모델 해석은 마치겠습니다.

728x90