๋ฐ์ํ
RNNLM (RNN์ ์ฌ์ฉํ Language (์ธ์ด) ๋ชจ๋ธ)
์ด๋ฒ์๋ RNN์ ์ฌ์ฉํ์ฌ Language Model(์ธ์ด ๋ชจ๋ธ)์ ๊ตฌํํด ๋ณด๊ฒ ์ต๋๋ค.
- ๊ทธ ์ ์ ๋จผ์ ์ฌ์ฉ๋๋ Neural Network(์ ๊ฒฝ๋ง)์ ํ๋ฒ ๋ณด๊ณ ์์ํด๋ณด๊ฒ ์ต๋๋ค.
- ์ผ์ชฝ์ RNNLM์ ๊ณ์ธต ๊ตฌ์ฑ์ด๊ณ , ์ค๋ฅธ์ชฝ์๋ ์ด๋ฅผ ์๊ฐ์ถ์ผ๋ก ํผ์น Neural Network(์ ๊ฒฝ๋ง)์ ๋๋ค.
- ๊ทธ๋ฆผ์ Embedding Layer(๊ณ์ธต)์ ๋จ์ด ID์ ๋ถ์ฐ ํํ (๋จ์ด Vector)๋ก ๋ณํ๋ฉ๋๋ค.
- ๊ทธ๋ฆฌ๊ณ ๊ทธ ๋ถ์ฐ ํํ์ด RNN Layer(RNN ๊ณ์ธต)๋ก ์ ๋ ฅ๋ฉ๋๋ค.
- RNN ๊ณ์ธต์ Hidden State(์๋ ์ํ)๋ฅผ ๋ค์ Layer(์ธต)์ผ๋ก ์ถ๋ ฅํจ๊ณผ ๋์์, ๋ค์ ์๊ฐ์ RNN ๊ณ์ธต(์ค๋ฅธ์ชฝ)์ผ๋ก ์ถ๋ ฅ๋ฉ๋๋ค.
- ๊ทธ๋ฆฌ๊ณ RNN ๊ณ์ธต์ด ์๋ก ์ถ๋ ฅํ Hidden State(์๋ ์ํ)๋ Affine ๊ณ์ธต์ ๊ฑฐ์ณ Softmax ๊ณ์ธต์ผ๋ก ์ ํด์ง๋๋ค.
- ๊ทธ๋ฌ๋ฉด ํ๋ฒ Sample Corpus(๋ง๋ญ์น)๋ฅผ ํ๋ฒ ์ค์ ์ฌ์ฉํด ๋ณด๊ฒ ์ต๋๋ค.
"You say goodbye and I say hello"
- ์์ ๊ทธ๋ฆผ์ RNNLM(์ํ ์ ๊ฒฝ๋ง ์ธ์ด๋ชจ๋ธ)์ ์๋ ๋ฐฉ์์ ์ค๋ช ํฉ๋๋ค
- ์ ๋ ฅ ๋ฐ์ดํฐ๋ ๋จ์ด ID ๋ฐฐ์ด๋ก, ์ฒ์์๋ ๋จ์ด "you"๊ฐ ์ ๋ ฅ๋๊ณ , Softmax ๊ณ์ธต์ด "say"๋ฅผ ์์ธกํฉ๋๋ค
- ๋ ๋ฒ์งธ ๋จ์ด "say"๋ฅผ ์ ๋ ฅํ๋ฉด, Softmax ๊ณ์ธต์ "goodbye"์ "hello" ์ค ๋์ ํ๋ฅ ๋ก "goodbye"๋ฅผ ์์ธกํฉ๋๋ค.
- RNN ๊ณ์ธต์ ์ด์ ๋จ์ด "you say"๋ฅผ ๊ธฐ์ตํ์ฌ ๋ค์ ๋จ์ด๋ฅผ ์์ธกํ๋ ๋ฐ ์ค์ํ ์ญํ ์ ํฉ๋๋ค.
- RNN์ ๊ณผ๊ฑฐ ๋ฐ์ดํฐ๋ฅผ ์๋ ์ํ ๋ฒกํฐ๋ก ์ ์ฅํ๊ณ , ์ด๋ฅผ ํตํด ๊ณผ๊ฑฐ์ ์ ๋ณด๋ฅผ ๋ฐํ์ผ๋ก ํ์ฌ์ ๋ฏธ๋์ ๋จ์ด๋ฅผ ์์ธกํฉ๋๋ค.
Time ๊ณ์ธต ๊ตฌํ
์๊ณ์ด ๋ฐ์ดํฐ๋ฅผ ํ๊บผ๋ฒ์ ์ฒ๋ฆฌํ๋ ๊ณ์ธต์ Time RNN ์ด๋ผ๋ ์ด๋ฆ์ ๊ณ์ธต์ผ๋ก ๊ตฌํํฉ๋๋ค.
- ์ด๋ฒ์๋ ๋ง์ฐฌ๊ฐ์ง๋ก, ์๊ณ์ด ๋ฐ์ดํฐ๋ฅผ ํ๊บผ๋ฒ์ ์ฒ๋ฆฌํ๋ ๊ณ์ธต์ Time Embedding, Time Affine ํํ์ ์ด๋ฆ์ผ๋ก ๊ตฌํํ๊ฒ ์ต๋๋ค.
T๊ฐ๋ถ์ ์๊ณ์ด ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๋ ๊ณ์ธต์ Time XX ๊ณ์ธต ์ด๋ผ๊ณ ๋ถ๋ฅด๊ฒ ์ต๋๋ค.
์ด๋ฌํ ๊ณ์ธต๋ค์ด ๊ตฌํ๋์ด ์๋ค๋ฉด ๊ทธ ๊ณ์ธต๋ค์ ๋ ๊ณ ๋ธ๋ญ์ฒ๋ผ ์กฐ๋ฆฝํ๋ ๊ฒ์ผ๋ก ์๊ณ์ด ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋ ์ ๊ฒฝ๋ง์ ์์ฑํ ์ ์์ต๋๋ค.
- Time ๊ณ์ธต์ ๊ฐ๋จํ๊ฒ ๊ตฌํํ ์ ์์ต๋๋ค.
- Time Affine ๊ณ์ธต์ ์๋์ ๊ทธ๋ฆผ์ฒ๋ผ Affine ๊ณ์ธต์ T๊ฐ ์ค๋นํด์, ๊ฐ ์๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๋ณ์ ์ผ๋ก ์ฒ๋ฆฌํฉ๋๋ค.
- Time Embedding ๊ณ์ธต ์ญ์ Forward Propagation(์์ ํ) ์์ T๊ฐ์ Embedding ๊ณ์ธต์ ์ค๋นํ๊ณ ๊ฐ Embedding ๊ณ์ธต์ด ๊ฐ ์๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค.
- Time Embedding ๊ณ์ธต์ ๋จ์ํ Affine ๊ณ์ธต T๊ฐ๋ฅผ ์ด์ฉํ๋ ๋ฐฉ์ ๋์ ํ๋ ฌ ๊ณ์ฐ์ผ๋ก ํ๊บผ๋ฒ์ ์ฒ๋ฆฌํ๋, ํจ์จ ์ข์ ๋ฐฉ์์ผ๋ก ๊ตฌํํ์ต๋๋ค.
Time Affine Class Source Code (by Python)
import numpy as np
class TimeAffine:
def __init__(self, W, b):
"""
ํด๋์ค ์ด๊ธฐํ ๋ฉ์๋.
ํ๋ผ๋ฏธํฐ:
W (numpy.ndarray): ๊ฐ์ค์น ํ๋ ฌ
b (numpy.ndarray): ๋ฐ์ด์ด์ค ๋ฒกํฐ
"""
self.params = [W, b] # ๊ฐ์ค์น์ ๋ฐ์ด์ด์ค๋ฅผ ๋ฆฌ์คํธ๋ก ์ ์ฅ
self.grads = [np.zeros_like(W), np.zeros_like(b)] # ๊ฐ์ค์น์ ๋ฐ์ด์ด์ค์ ๋ํ ๊ทธ๋ผ๋์ธํธ ์ด๊ธฐํ
self.x = None # ์์ ํ ์ ์
๋ ฅ๊ฐ์ ์ ์ฅํ ๋ณ์
def forward(self, x):
"""
์์ ํ ๋ฉ์๋.
ํ๋ผ๋ฏธํฐ:
x (numpy.ndarray): ์
๋ ฅ ๋ฐ์ดํฐ. (๋ฐฐ์น ํฌ๊ธฐ, ์ํ์ค ๊ธธ์ด, ํน์ฑ ์ฐจ์)
๋ฐํ๊ฐ:
out (numpy.ndarray): ์ถ๋ ฅ ๋ฐ์ดํฐ. (๋ฐฐ์น ํฌ๊ธฐ, ์ํ์ค ๊ธธ์ด, ์ถ๋ ฅ ์ฐจ์)
"""
N, T, D = x.shape # ์
๋ ฅ ๋ฐ์ดํฐ์ ํ์ (๋ฐฐ์น ํฌ๊ธฐ, ์ํ์ค ๊ธธ์ด, ํน์ฑ ์ฐจ์)
W, b = self.params # ๊ฐ์ค์น์ ๋ฐ์ด์ด์ค
rx = x.reshape(N*T, -1) # ์
๋ ฅ ๋ฐ์ดํฐ๋ฅผ 2์ฐจ์์ผ๋ก ๋ณํ (N*T, D)
out = np.dot(rx, W) + b # ์ ํ ๋ณํ ์ํ
self.x = x # ์
๋ ฅ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ์ฌ ์ญ์ ํ ์ ์ฌ์ฉ
return out.reshape(N, T, -1) # ์ถ๋ ฅ ๋ฐ์ดํฐ๋ฅผ ์๋ ํ์์ผ๋ก ๋ณํํ์ฌ ๋ฐํ
def backward(self, dout):
"""
์ญ์ ํ ๋ฉ์๋.
ํ๋ผ๋ฏธํฐ:
dout (numpy.ndarray): ์ถ๋ ฅ์ ๋ํ ๊ทธ๋ผ๋์ธํธ. (๋ฐฐ์น ํฌ๊ธฐ, ์ํ์ค ๊ธธ์ด, ์ถ๋ ฅ ์ฐจ์)
๋ฐํ๊ฐ:
dx (numpy.ndarray): ์
๋ ฅ์ ๋ํ ๊ทธ๋ผ๋์ธํธ. (๋ฐฐ์น ํฌ๊ธฐ, ์ํ์ค ๊ธธ์ด, ํน์ฑ ์ฐจ์)
"""
x = self.x # ์ ์ฅ๋ ์
๋ ฅ ๋ฐ์ดํฐ
N, T, D = x.shape # ์
๋ ฅ ๋ฐ์ดํฐ์ ํ์
W, b = self.params # ๊ฐ์ค์น์ ๋ฐ์ด์ด์ค
dout = dout.reshape(N*T, -1) # ์ถ๋ ฅ์ ๋ํ ๊ทธ๋ผ๋์ธํธ๋ฅผ 2์ฐจ์์ผ๋ก ๋ณํ (N*T, ์ถ๋ ฅ ์ฐจ์)
rx = x.reshape(N*T, -1) # ์
๋ ฅ ๋ฐ์ดํฐ๋ฅผ 2์ฐจ์์ผ๋ก ๋ณํ (N*T, D)
db = np.sum(dout, axis=0) # ๋ฐ์ด์ด์ค์ ๋ํ ๊ทธ๋ผ๋์ธํธ ๊ณ์ฐ
dW = np.dot(rx.T, dout) # ๊ฐ์ค์น์ ๋ํ ๊ทธ๋ผ๋์ธํธ ๊ณ์ฐ
dx = np.dot(dout, W.T) # ์
๋ ฅ์ ๋ํ ๊ทธ๋ผ๋์ธํธ ๊ณ์ฐ
dx = dx.reshape(*x.shape) # ์
๋ ฅ์ ๋ํ ๊ทธ๋ผ๋์ธํธ๋ฅผ ์๋ ํ์์ผ๋ก ๋ณํ
self.grads[0][...] = dW # ๊ฐ์ค์น์ ๋ํ ๊ทธ๋ผ๋์ธํธ๋ฅผ ์ ์ฅ
self.grads[1][...] = db # ๋ฐ์ด์ด์ค์ ๋ํ ๊ทธ๋ผ๋์ธํธ๋ฅผ ์ ์ฅ
return dx # ์
๋ ฅ์ ๋ํ ๊ทธ๋ผ๋์ธํธ๋ฅผ ๋ฐํ
- Time Affine ํด๋์ค์ ์ฝ๋๋ฅผ ํ๋ฒ ๋ณด๊ฒ ์ต๋๋ค.
- __init__ ๋ฉ์๋:
- Weight(๊ฐ์ค์น) W์ Bias(ํธํฅ) b๋ฅผ ์ธ์๋ก ๋ฐ์ ์ด๊ธฐํํฉ๋๋ค.
- Weight(๊ฐ์ค์น)์ Bias(ํธํฅ)์ ๋ํ Gradient(๊ธฐ์ธ๊ธฐ)๋ฅผ ์ ์ฅํ ๋ณ์๋ฅผ ์ด๊ธฐํํฉ๋๋ค.
- Forward Propagation(์์ ํ)์ ์ ๋ ฅ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ ๋ณ์๋ฅผ ์ด๊ธฐํํฉ๋๋ค.
- forward ๋ฉ์๋:
- ์ ๋ ฅ ๋ฐ์ดํฐ x๋ฅผ ๋ฐ์ Forward Propagation(์์ ํ)๋ฅผ ์ํํฉ๋๋ค.
- ์ ๋ ฅ ๋ฐ์ดํฐ์ ํ์ (N, T, D)์ ๊ตฌํฉ๋๋ค.
- ์ ๋ ฅ ๋ฐ์ดํฐ๋ฅผ 2์ฐจ์ ํํ๋ก ๋ณํํ์ฌ (N*T, D)๋ก ๋ง๋ญ๋๋ค.
- Weight(๊ฐ์ค์น) W์ Bias(ํธํฅ) b๋ฅผ ์ด์ฉํด ์ ํ ๋ณํ์ ์ํํฉ๋๋ค.
- ๋ณํ๋ ์ถ๋ ฅ์ ์๋์ 3์ฐจ์ ํ์์ผ๋ก ๋ณํํ์ฌ ๋ฐํํฉ๋๋ค.
- backward ๋ฉ์๋:
- ์ถ๋ ฅ์ ๋ํ Gradient(๊ธฐ์ธ๊ธฐ) dout์ ๋ฐ์ Backpropagation(์ญ์ ํ)๋ฅผ ์ํํฉ๋๋ค.
- ์ ์ฅ๋ ์ ๋ ฅ ๋ฐ์ดํฐ๋ฅผ ์ด์ฉํด ์ ๋ ฅ ๋ฐ์ดํฐ์ ํ์์ ๊ตฌํฉ๋๋ค.
- ์ถ๋ ฅ์ ๋ํ Gradient(๊ธฐ์ธ๊ธฐ)๋ฅผ 2์ฐจ์ ํํ๋ก ๋ณํํฉ๋๋ค.
- ์ ๋ ฅ ๋ฐ์ดํฐ๋ฅผ 2์ฐจ์ ํํ๋ก ๋ณํํฉ๋๋ค.
- Bias(ํธํฅ)์ ๋ํ Gradient(๊ธฐ์ธ๊ธฐ)๋ฅผ ๊ณ์ฐํฉ๋๋ค.
- Weight(๊ฐ์ค์น)์ ๋ํ Gradient(๊ธฐ์ธ๊ธฐ)๋ฅผ ๊ณ์ฐํฉ๋๋ค.
- ์ ๋ ฅ์ ๋ํ Gradient(๊ธฐ์ธ๊ธฐ)๋ฅผ ๊ณ์ฐํ๊ณ ์๋์ 3์ฐจ์ ํ์์ผ๋ก ๋ณํํ์ฌ ๋ฐํํฉ๋๋ค.
Time Softmax with Loss ๊ณ์ธต
Softmax ๊ณ์ธต์ ๊ตฌํํ ๋ ์์ค ์ค์ฐจ๋ฅผ ๊ตฌํ๋ *Cross Entropy Error ๊ณ์ธต๋ ๊ตฌํํฉ๋๋ค.
*Cross Entropy Loss Function: ๋ชจ๋ธ์ ์์ธก ํ๋ฅ ๋ถํฌ์ ์ค์ ๋ ์ด๋ธ ์ฌ์ด์ ์ฐจ์ด๋ฅผ ์ธก์ ํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
์ฃผ์ด์ง ์์ธก ํ๋ฅ ๋ถํฌ ๐์ ์ค์ ๋ ์ด๋ธ ๐ ์ฌ์ด์ Cross-Entropy๋ ๋ค์๊ณผ ๊ฐ์ด ๊ณ์ฐ๋ฉ๋๋ค.
CrossEntropy(๐,๐)=−∑๐ ๐๐ logโก(๐๐)
์ฌ๊ธฐ์ ๐๐๋ ์ค์ ๋ ์ด๋ธ์ ๐๋ฒ์งธ ์์(์ผ๋ฐ์ ์ผ๋ก ์-ํซ ์ธ์ฝ๋ฉ๋ ๋ฒกํฐ), ๐๐๋ ์์ธก ํ๋ฅ ๋ถํฌ์ ๐i๋ฒ์งธ ์์์ ๋๋ค.
- ์์ ๊ทธ๋ฆผ์์ X0, X1๋ฑ์ ๋ฐ์ดํฐ๋ ์๋์ธต์์ ์ ํด์ง๋ 'Score(์ ์)'๋ฅผ ๋ํ๋
๋๋ค.
- 'Score(์ ์)'๋ ํ๋ฅ ๋ก ์ ๊ทํ๋๊ธฐ ์ ์ ๊ฐ์ ๋๋ค.
- ๋ํ t0, t1๋ฑ์ ๋ฐ์ดํฐ๋ ์ ๋ต ๋ ์ด๋ธ์ ๋ํ๋ ๋๋ค.
- ๊ทธ๋ฆผ์์ ๋ณด๋ฏ์ด, T๊ฐ์ Softmax with Loss ๊ณ์ธต์ด ๊ฐ๊ฐ์ Loss๋ฅผ ์ฐ์ถํ, ํฉ์ฐํด ํ๊ท ๋ธ ๊ฐ์ด ์ต์ข ์์ค์ด ๋ฉ๋๋ค.
- ์ด๋ ์ํํ๋ ์์์ ์๋์ ๊ฐ์ต๋๋ค.
- ์ฌ๊ธฐ์ Softmax with Loss ๊ณ์ธต์ Mini-Batch์ ํด๋นํ๋ Loss์ ํ๊ท ์ ๊ตฌํ์ต๋๋ค.
- ๋ฐ์ดํฐ N๊ฐ ์ง๋ฆฌ Mini-Batch๋ N๊ฐ์ ์์ค์ ๋ํด ๋ค์ N๊ฐ๋ก ๋์์ ๋ฐ์ดํฐ๋น ํ๊ฐ๋น ํ๊ท ์์ค์ ๊ตฌํ์ต๋๋ค.
- ์ด์ ๋ง์ฐฌ๊ฐ์ง๋ก Time Softmax with Loss ๊ณ์ธต๋ ์๊ณ์ด์ ๋ฐํ ํ๊ท ์ ๊ตฌํ๋ ๊ฒ์ผ๋ก, ๋ฐ์ดํฐ 1๊ฐ๋น ํ๊ท Loss๋ฅผ ๊ตฌํด ์ต์ข ์ถ๋ ฅ์ผ๋ก ๋ด๋ณด๋ ๋๋ค.
RNNLM ํ์ต ๋ฐ ํ๊ฐ
ํ๋ฒ RNNLM์ ํ๋ฒ ๊ตฌํ์ ํด๋ณด๊ฒ ์ต๋๋ค. ๊ณ์ธต ๊ตฌ์ฑ์ ์๋์ ์ฌ์ง๊ณผ ๊ฐ์ต๋๋ค.
- ๋ณด๋ฉด, ์ด๋ ๊ฒ RNNLM ํด๋์ค๋ 4๊ฐ์ Time ๊ณ์ธต์ ์์ Neural Network(์ ๊ฒฝ๋ง)์ ๋๋ค. ํ๋ฒ ์ฝ๋๋ฅผ ๋ณด๊ฒ ์ต๋๋ค.
import sys
sys.path.append('..')
import numpy as np
from common.time_layers import *
class SimpleRnnlm:
def __init__(self, vocab_size, wordvec_size, hidden_size):
V, D, H = vocab_size, wordvec_size, hidden_size
rn = np.random.randn
# ๊ฐ์ค์น ์ด๊ธฐํ
embed_W = (rn(V, D) / 100).astype('f')
rnn_Wx = (rn(D, H) / np.sqrt(D)).astype('f')
rnn_Wh = (rn(H, H) / np.sqrt(H)).astype('f')
rnn_b = np.zeros(H).astype('f')
affine_W = (rn(H, V) / np.sqrt(H)).astype('f')
affine_b = np.zeros(V).astype('f')
# ๊ณ์ธต ์์ฑ
self.layers = [
TimeEmbedding(embed_W),
TimeRNN(rnn_Wx, rnn_Wh, rnn_b, stateful=True),
TimeAffine(affine_W, affine_b)
]
self.loss_layer = TimeSoftmaxWithLoss()
self.rnn_layer = self.layers[1]
# ๋ชจ๋ ๊ฐ์ค์น์ ๊ธฐ์ธ๊ธฐ๋ฅผ ๋ฆฌ์คํธ์ ๋ชจ์๋ค.
self.params, self.grads = [], []
for layer in self.layers:
self.params += layer.params
self.grads += layer.grads
def forward(self, xs, ts):
for layer in self.layers:
xs = layer.forward(xs)
loss = self.loss_layer.forward(xs, ts)
return loss
def backward(self, dout=1):
dout = self.loss_layer.backward(dout)
for layer in reversed(self.layers):
dout = layer.backward(dout)
return dout
def reset_state(self):
self.rnn_layer.reset_state()
- ์ด ์ฝ๋๋ ๊ฐ ๊ณ์ธต์์ ์ฌ์ฉํ๋ Parameter (Weight-๊ฐ์ค์น & Bias-ํธํฅ)์ ์ด๊ธฐํ ํ๊ณ ํ์ํ ๊ณ์ธต์ ์์ฑํฉ๋๋ค.
- ๋ํ *Truncated BPTT(Backpropagation Through Time)๋ก ํ์ตํ๋ค๊ณ ๊ฐ์ ํด์ Time RNN ๊ณ์ธต์ stateful์ True๋ก ์ค์ ํ์ต๋๋ค.
- ๊ทธ ๊ฒฐ๊ณผ Time RNN์ ์ด์ ์๊ฐ์ Hidden State(์๋ ์ํ)๋ฅผ ๊ณ์นํ ์ ์์ต๋๋ค.
- ๋ํ ํน์ง์ RNN & Affine ๊ณ์ธต์์ Xavier ์ด๊ธฐ๊ฐ์ ์ด์ฉํ์ต๋๋ค.
*Xavier ์ด๊ธฐ๊ฐ: ์ด์ ๊ณ์ธต์ node๊ฐ n๊ฐ๋ผ๋ฉด ํ์คํธ์ฐจ๊ฐ 1/√n์ธ ๋ถํฌ๋ก ์ด๊ธฐํํฉ๋๋ค.
RNN์์ Weight์ ์ด๊น๊ฐ์ ์ด๋ป๊ฒ ์ค์ ํ๋๋์ ๋ฐ๋ผ ํ์ต์ด ์งํ๋๋ ๋ฐฉ๋ฒ & ์ต์ข ์ ํ๋๊ฐ ํฌ๊ฒ ๋ฌ๋ผ์ง๋๋ค.
- ๊ณ์ํด์ forward(), backward(), reset_state() Method์ ๊ตฌํ์ ๋ณด๊ฒ ์ต๋๋ค.
def forward(self, xs, ts):
"""
์์ ํ ๋ฉ์๋.
ํ๋ผ๋ฏธํฐ:
xs (numpy.ndarray): ์
๋ ฅ ๋ฐ์ดํฐ
ts (numpy.ndarray): ์ค์ ๋ ์ด๋ธ
๋ฐํ๊ฐ:
loss (float): ๊ณ์ฐ๋ ์์ค ๊ฐ
"""
for layer in self.layers:
xs = layer.forward(xs) # ๊ฐ ๋ ์ด์ด์ ๋ํด ์์ ํ ์ํ
loss = self.loss_layer.forward(xs, ts) # ์์ค ๋ ์ด์ด์์ ์์ค ๊ณ์ฐ
return loss # ๊ณ์ฐ๋ ์์ค ๊ฐ ๋ฐํ
def backward(self, dout=1):
"""
์ญ์ ํ ๋ฉ์๋.
ํ๋ผ๋ฏธํฐ:
dout (float): ์์ ๊ณ์ธต์์ ์ ํ๋ ๊ทธ๋ผ๋์ธํธ (๊ธฐ๋ณธ๊ฐ: 1)
๋ฐํ๊ฐ:
dout (numpy.ndarray): ์
๋ ฅ ๋ฐ์ดํฐ์ ๋ํ ๊ทธ๋ผ๋์ธํธ
"""
dout = self.loss_layer.backward(dout) # ์์ค ๋ ์ด์ด์์ ์ญ์ ํ ์ํ
for layer in reversed(self.layers):
dout = layer.backward(dout) # ๊ฐ ๋ ์ด์ด์ ๋ํด ์ญ์ ํ ์ํ
return dout # ์
๋ ฅ ๋ฐ์ดํฐ์ ๋ํ ๊ทธ๋ผ๋์ธํธ ๋ฐํ
def reset_state(self):
"""
์ํ ์ด๊ธฐํ ๋ฉ์๋.
์ํ ์ ๊ฒฝ๋ง(RNN) ๋ ์ด์ด์ ์ํ๋ฅผ ์ด๊ธฐํํฉ๋๋ค.
"""
self.rnn_layer.reset_state() # RNN ๋ ์ด์ด์ ์ํ ์ด๊ธฐํ
Language Model(์ธ์ด๋ชจ๋ธ)์ ํ๊ฐ - Perplexity
Language Model(์ธ์ด ๋ชจ๋ธ)์ ์ฃผ์ด์ง ๊ณผ๊ฑฐ๋จ์ด(์ ๋ณด)๋ก ๋ถํฐ ๋ค์์ ์ถํํ ๋จ์ด์ ํ๋ฅ ๋ถํฌ๋ฅผ ์ถ๋ ฅํฉ๋๋ค. ์ด๋, Language Model(์ธ์ด ๋ชจ๋ธ)์ ์์ธก ์ฑ๋ฅ์ ํ๊ฐํ๋ ์ฒ๋๋ก Perplexity(ํผํ๋ ์ํฐ-ํผ๋๋)๋ฅผ ์์ฃผ ์ด์ฉํฉ๋๋ค.
- Perplexity(ํผํ๋ ์ํฐ)๋ ๊ฐ๋จํ ๋งํ๋ฉด 'ํ๋ฅ ์ ์ญ์'์ ๋๋ค. ์ด ๋ด์ฉ์ ํด์์ ๋ฐ์ดํฐ๊ฐ ํ๋์ผ๋ ์ ํํ ์ผ์นํฉ๋๋ค.
- ์๋ฅผ ๋ค์ด์ "you say goodbye and i say hello"๋ผ๋ Corpus(๋ง๋ญ์น)๋ก ์๋ฅผ ๋ค๋ฉด "you"๋ผ๋ ๋จ์ด ๋ค์์ ์ถ๋ ฅํ ๋จ์ด๊ฐ "say'๋ผ๊ณ ํ๋ฉด, ํ๋ฅ ์ 0.8์ ๋๋ค.
- ์ด๋ Perplexity(ํผํ๋ ์ํฐ-ํผ๋๋)๋ ํ๋ฅ ์ ์ญ์, ์ฆ 1/0.8 = 1.25 ๋ก ๋ณผ ์ ์์ต๋๋ค.
- ๋ชจ๋ธ 2์์ "์ ๋ต์ธ "say"์ ํ๋ฅ ์ด 0.2๋ผ๊ณ ํ๋ฉด, 1/0.2 = 5 ๋ก ๋ณผ ์ ์์ต๋๋ค.
- ๊ทธ๋ฆฌ๊ณ Perplexity(ํผํ๋ ์ํฐ-ํผ๋๋)๋ ์์์๋ก ์ข๋ค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
- ๊ทธ๋ ๋ค๋ฉด 1.25๋ 5.0์ด๋ผ๋ ๊ฐ์ ์ง๊ด์ ์ผ๋ก๋ ์ด๋ป๊ฒ ํด์ํ ์ ์์๊น์?
- ์ด ๊ฐ์ '๋ถ๊ธฐ ์(number of branches)'๋ก ํด์ํ ์ ์์ต๋๋ค.
- ๋ถ๊ธฐ ์๋ ๋ค์์ ์ทจํ ์ ์๋ ์ ํ์ฌํญ์ ์(๊ตฌ์ฒด์ ์ผ๋ก ๋งํ๋ฉด, ๋ค์์ ์ถํํ ์ ์๋ ๋จ์ด์ ํ๋ณด ์)๋ฅผ ๋งํฉ๋๋ค.
- ์์ ์์์, ์ข์ ๋ชจ๋ธ์ด ์์ธกํ '๋ถ๊ธฐ ์'๊ฐ 1.25๋ผ๋ ๊ฒ์ ๋ค์์ ์ถํํ ์ ์๋ ๋จ์ด์ ํ๋ณด๋ฅผ 1๊ฐ ์ ๋๋ก ์ขํ๋ค๋ ๋ป์ด ๋๊ณ , ๋ฐ๋ฉด ๋์ ๋ชจ๋ธ์์๋ ํ๋ณด๊ฐ ์์ง 5๊ฐ๋ ๋๋ค๋ ์๋ฏธ์ ๋๋ค.
์์ฒ๋ผ Perplexity(ํผํ๋ ์ํฐ)๋ก ๋ชจ๋ธ์ ์์ธก ์ฑ๋ฅ์ ํ๊ฐํ ์ ์์ต๋๋ค. ์ข์ ๋ชจ๋ธ์ ์ ๋ต ๋จ์ด๋ฅผ ๋์ ํ๋ฅ ๋ก ์์ธกํ ์ ์์ต๋๋ค.
๋ฐ๋ผ์ Perplexity(ํผํ๋ ์ํฐ) ๊ฐ์ด ์์์ง๋๋ค.(์ต์๊ฐ์ 1.0). ํํธ, ๋์ ๋ชจ๋ธ์ ์ ๋ต ๋จ์ด๋ฅผ ๋ฎ์ ํ๋ฅ ๋ก ์์ธกํ๋ฏ๋ก Perplexity(ํผํ๋ ์ํฐ) ๊ฐ์ด ํฝ๋๋ค.
- ์ ๋ ฅ ๋ฐ์ดํฐ๊ฐ ํ๋์ผ ๋์ Perplexity(ํผํ๋ ์ํฐ)๋ฅผ ์ด์ผ๊ธฐํ์ต๋๋ค.
- ๊ทธ๋ ๋ค๋ฉด ์ ๋ ฅ ๋ฐ์ดํฐ๊ฐ ์ฌ๋ฌ ๊ฐ์ผ ๋๋ ์ด๋ป๊ฒ ๋ ๊น์? ์ด๋ด ๋๋ ์๋์ ๊ณต์์ ๋ฐ๋ผ ๊ณ์ฐํฉ๋๋ค.
L = −1/N โ∑nโ∑k โtnk โlog y nkโ, perplexity = ๐๐ฟ
- Vector ๋ก ๋ํ๋ธ ์ ๋ต ๋ ์ด๋ธ์ด๋ฉฐ, ๐ก๐๐ ๋ n๊ฐ์งธ ๋ฐ์ดํฐ์ k๋ฒ์งธ ๊ฐ์ ์๋ฏธํฉ๋๋ค. ์ ๋ฐ์ดํฐ์ ์ด๊ฐ์์ ๋๋ค. ๐ก๐ ์ One-Hot
- ๊ทธ๋ฆฌ๊ณ ๐ฆ๐๐๋ ํ๋ฅ ๋ถํฌ๋ฅผ ๋ํ๋ ๋๋ค.(Neural Network-์ ๊ฒฝ๋ง ์์๋ Softmax์ ์ถ๋ ฅ). L์ Neural Network(์ ๊ฒฝ๋ง)์ Loss์ ๋ปํ๋ฉฐ, Cross-Entropy-Error(๊ต์ฐจ ์ํธ๋กํผ ์ค์ฐจ)์ ์์ ํ ๊ฐ์ ์์ ๋๋ค. ์ด L์ ์ฌ์ฉํด ๐−๐ฟ ๋ฅผ ๊ณ์ฐํ ๊ฐ์ด ๊ณง Perplexity(ํผํ๋ ์ํฐ์ ๋๋ค.
RNNLM์ Code (by Python)
PTB ๋ฐ์ดํฐ์ ์ ์ด์ฉํด์ RNNLM ํ์ต์ ์ํํด ๋ณด๊ฒ ์ต๋๋ค.
- ๋จ ๋ชจ๋ ๋ฐ์ดํฐ์ ์ ์ด์ฉํด์ ํ์ต์ ํ๊ฒ ๋๋ฉด, ์ข์ ๊ฒฐ๊ณผ๊ฐ ์๋์ฌ์๋ ์๊ธฐ ๋๋ฌธ์, 1000๊ฐ์ ๋จ์ด๋ง ์ด์ฉํด ๋ณด๊ฒ ์ต๋๋ค.
# coding: utf-8
import sys
sys.path.append('..')
import matplotlib.pyplot as plt
import numpy as np
from common.optimizer import SGD
from dataset import ptb
from simple_rnnlm import SimpleRnnlm
# ํ์ดํผํ๋ผ๋ฏธํฐ ์ค์
batch_size = 10
wordvec_size = 100
hidden_size = 100 # RNN์ ์๋ ์ํ ๋ฒกํฐ์ ์์ ์
time_size = 5 # Truncated BPTT๊ฐ ํ ๋ฒ์ ํผ์น๋ ์๊ฐ ํฌ๊ธฐ
lr = 0.1
max_epoch = 100
# ํ์ต ๋ฐ์ดํฐ ์ฝ๊ธฐ(์ ์ฒด ์ค 1000๊ฐ๋ง)
corpus, word_to_id, id_to_word = ptb.load_data('train')
corpus_size = 1000
corpus = corpus[:corpus_size]
vocab_size = int(max(corpus) + 1)
xs = corpus[:-1] # ์
๋ ฅ
ts = corpus[1:] # ์ถ๋ ฅ(์ ๋ต ๋ ์ด๋ธ)
data_size = len(xs)
print('๋ง๋ญ์น ํฌ๊ธฐ: %d, ์ดํ ์: %d' % (corpus_size, vocab_size))
# ํ์ต ์ ์ฌ์ฉํ๋ ๋ณ์
max_iters = data_size // (batch_size * time_size)
time_idx = 0
total_loss = 0
loss_count = 0
ppl_list = []
# ๋ชจ๋ธ ์์ฑ
model = SimpleRnnlm(vocab_size, wordvec_size, hidden_size)
optimizer = SGD(lr)
# 1. ๋ฏธ๋๋ฐฐ์น์ ๊ฐ ์ํ์ ์ฝ๊ธฐ ์์ ์์น๋ฅผ ๊ณ์ฐ
jump = (corpus_size - 1) // batch_size
offsets = [i * jump for i in range(batch_size)]
for epoch in range(max_epoch):
for iter in range(max_iters):
# 2. ๋ฏธ๋๋ฐฐ์น ์ทจ๋
batch_x = np.empty((batch_size, time_size), dtype='i')
batch_t = np.empty((batch_size, time_size), dtype='i')
for t in range(time_size):
for i, offset in enumerate(offsets):
batch_x[i, t] = xs[(offset + time_idx) % data_size]
batch_t[i, t] = ts[(offset + time_idx) % data_size]
time_idx += 1
# ๊ธฐ์ธ๊ธฐ๋ฅผ ๊ตฌํ์ฌ ๋งค๊ฐ๋ณ์ ๊ฐฑ์
loss = model.forward(batch_x, batch_t)
model.backward()
optimizer.update(model.params, model.grads)
total_loss += loss
loss_count += 1
# 3. ์ํญ๋ง๋ค ํผํ๋ ์ํฐ ํ๊ฐ
ppl = np.exp(total_loss / loss_count)
print('| ์ํญ %d | ํผํ๋ ์ํฐ %.2f'
% (epoch+1, ppl))
ppl_list.append(float(ppl))
total_loss, loss_count = 0, 0
- ์ด ์ฝ๋๋ ํ์ต์ ์ํํ๋ ์ฝ๋์ ๋๋ค. ์ฐ๋ฆฌ๊ฐ ์ผ๋ฐ์ ์ผ๋ก ๋ณธ Neural Network(์ ๊ฒฝ๋ง) ํ์ต๊ณผ ๊ฑฐ์ด ๋น์ทํฉ๋๋ค.
- ๋ค๋ง ํฐ ๊ด์ ์์ '๋ฐ์ดํฐ ์ ๊ณต ๋ฐฉ๋ฒ', 'Perplexity ๊ณ์ฐ' ๋ถ๋ถ์ ๋ณด๋ฉด์ ์ฝ๋๋ฅผ ํ๋ฒ ๋ณด๊ฒ ์ต๋๋ค.
๋ฐ์ดํฐ ์ ๊ณต ๋ฐฉ๋ฒ
๋ฐ์ดํฐ ์ ๊ณต ๋ฐฉ๋ฒ์์ ์ฌ๊ธฐ์ Truncated BPTT ๋ฐฉ์์ผ๋ก ํ์ต์ ์ํํฉ๋๋ค.
Truncated BPTT ๋ฐฉ์์ ๋ฐํ ๊ฐ๋ ์ ์๋์ ๋งํฌ ๋ฌ์๋์๊ป์!
- Truncated BPTT ๋ฐฉ์์์๋ ๋ฐ์ดํฐ๋ฅผ ์์ฐจ์ ์ผ๋ก ์ฃผ๊ณ , ๊ฐ๊ฐ์ Mini-Batch์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๋ ์์ ์์น๋ฅผ ์กฐ์ ํด์ผ ํฉ๋๋ค.
- ์ ์ฒด ํ์ต ์ฝ๋ 1๋ฒ ๋ถ๋ถ์์ ๊ฐ Mini-Batch์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๋ ์์ ์์น๋ฅผ offset์ ์ ์ฅํฉ๋๋ค.
# 1. ๋ฏธ๋๋ฐฐ์น์ ๊ฐ ์ํ์ ์ฝ๊ธฐ ์์ ์์น๋ฅผ ๊ณ์ฐ
jump = (corpus_size - 1) // batch_size
offsets = [i * jump for i in range(batch_size)]
- ์ ์ฒด ํ์ต ์ฝ๋ 2๋ฒ ๋ถ๋ถ์์๋ ๋ฐ์ดํฐ๋ฅผ ์์ฐจ์ ์ผ๋ก ์ฝ์ต๋๋ค.
- ๊ทธ๋ฆ์ ์ญํ ์ ํ๋ batch_x, batch_t๋ฅผ ์ค๋นํ๊ณ , time_idx๋ฅผ 1์ฉ ๋๋ฆฌ๋ฉด์ Corpus(๋ง๋ญ์น)์์ time_idx์์น์ ๋ฐ์ดํฐ๋ฅผ ์ป์ต๋๋ค.
- ์ฌ๊ธฐ์ 1๋ฒ ์์ค ์ฝ๋์์ ๊ณ์ฐํ offset์ ์ด์ฉํ์ฌ ๊ฐ mini_batch์์ offset์ ์ถ๊ฐํฉ๋๋ค.
- ๊ทธ๋ฆฌ๊ณ , ๋ง์ฝ Corpus(๋ง๋ญ์น)๋ฅผ ์ฝ๋ ์์น๊ฐ Corpus(๋ง๋ญ์น) ํฌ๊ธฐ๋ฅผ ๋์ด์ค ๊ฒฝ์ฐ์ Corpus(๋ง๋ญ์น)์ ์ฒ์์ผ๋ก ๋์์์ผ ํ๋๋ฐ, ์ด๋ฅผ ์ํด์ Corpus(๋ง๋ญ์น)์ ํฌ๊ธฐ๋ก ๋๋ ๋๋จธ์ง๋ฅผ Index๋ก ์ฌ์ฉํฉ๋๋ค.
# 2. ๋ฏธ๋๋ฐฐ์น ์ทจ๋
batch_x = np.empty((batch_size, time_size), dtype='i')
batch_t = np.empty((batch_size, time_size), dtype='i')
for t in range(time_size):
for i, offset in enumerate(offsets):
batch_x[i, t] = xs[(offset + time_idx) % data_size]
batch_t[i, t] = ts[(offset + time_idx) % data_size]
time_idx += 1
- 3๋ฒ ์ฝ๋ ๋ถ๋ถ์์๋ *Perplexity(ํผํ๋ ์ํฐ)๋ฅผ ๊ณ์ฐํฉ๋๋ค.
- ์ฌ๊ธฐ์๋ Epoch๋ง๋ค Perplexity(ํผํ๋ ์ํฐ)๋ฅผ ๊ตฌํ๊ธฐ ์ํด์ Epoch๋ง๋ค Loss์ ํ๊ท ์ ๊ตฌํ๊ณ , ๊ตฌํ ๊ฐ์ ์ด์ฉํด์ Perplexity(ํผํ๋ ์ํฐ)๋ฅผ ๊ตฌํฉ๋๋ค.
Language Model(์ธ์ด ๋ชจ๋ธ)์ ์ฃผ์ด์ง ๊ณผ๊ฑฐ๋จ์ด(์ ๋ณด)๋ก ๋ถํฐ ๋ค์์ ์ถํํ ๋จ์ด์ ํ๋ฅ ๋ถํฌ๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
์ด๋, Language Model(์ธ์ด ๋ชจ๋ธ)์ ์์ธก ์ฑ๋ฅ์ ํ๊ฐํ๋ ์ฒ๋๋ก Perplexity(ํผํ๋ ์ํฐ-ํผ๋๋)๋ฅผ ์์ฃผ ์ด์ฉํฉ๋๋ค.
# 3. ์ํญ๋ง๋ค ํผํ๋ ์ํฐ ํ๊ฐ
ppl = np.exp(total_loss / loss_count)
print('| ์ํญ %d | ํผํ๋ ์ํฐ %.2f'
% (epoch+1, ppl))
ppl_list.append(float(ppl))
total_loss, loss_count = 0, 0
RNNLM์ Trainer Class
์ด๋ฒ์๋ RNNLM์ ์ํํด์ฃผ๋ Trainer ํด๋์ค๋ฅผ ํ๋ฒ ๋ณด๊ฒ ์ต๋๋ค.
- ์ด ๋ถ๋ถ์ RNNLM์ ์ํํ๋ ํ์ต๋ถ๋ถ์ ํด๋์ค ์์ผ๋ก ์จ๊ฒจ์ฃผ๋ ์ญํ ์ ํฉ๋๋ค. ํ๋ฒ ์ฝ๋๋ฅผ ๋ณด๊ฒ ์ต๋๋ค.
import sys
sys.path.append('..')
from common.optimizer import SGD
from common.trainer import RnnlmTrainer
from dataset import ptb
from simple_rnnlm import SimpleRnnlm
# ํ์ดํผํ๋ผ๋ฏธํฐ ์ค์
batch_size = 10
wordvec_size = 100
hidden_size = 100 # RNN์ ์๋ ์ํ ๋ฒกํฐ์ ์์ ์
time_size = 5 # RNN์ ํผ์น๋ ํฌ๊ธฐ
lr = 0.1
max_epoch = 100
# ํ์ต ๋ฐ์ดํฐ ์ฝ๊ธฐ
corpus, word_to_id, id_to_word = ptb.load_data('train')
corpus_size = 1000 # ํ
์คํธ ๋ฐ์ดํฐ์
์ ์๊ฒ ์ค์
corpus = corpus[:corpus_size]
vocab_size = int(max(corpus) + 1)
xs = corpus[:-1] # ์
๋ ฅ
ts = corpus[1:] # ์ถ๋ ฅ๏ผ์ ๋ต ๋ ์ด๋ธ๏ผ
# ๋ชจ๋ธ ์์ฑ
model = SimpleRnnlm(vocab_size, wordvec_size, hidden_size)
optimizer = SGD(lr)
trainer = RnnlmTrainer(model, optimizer)
trainer.fit(xs, ts, max_epoch, batch_size, time_size)
trainer.plot()
- ์ด์ ๊ฐ์ด, ๋จผ์ RnnlmTrainer ํด๋์ค์ model๊ณผ optimizer๋ฅผ ์ฃผ์ด ์ด๊ธฐํํฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ fit() ๋ฉ์๋๋ฅผ ํธ์ถํด ํ์ต์ ์ํํฉ๋๋ค.
- ์ด๋ ๊ทธ ๋ด๋ถ์์๋ ์ ์ ์์ ์ํํ ์ผ๋ จ์ ์์
์ด ์งํ๋๋๋ฐ, ๊ทธ ๋ด์ฉ์ ์์ธํ ์ ์ด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- Mini-Batch๋ฅผ '์์ฐจ์ '์ผ๋ก ๋ง๋ค์ด
- ๋ชจ๋ธ์ Forward Propagation(์์ ํ)์ Backpropagation(์ญ์ ํ)๋ฅผ ํธ์ถํ๊ณ
- Optimizer(์ตํฐ๋ง์ด์ )๋ก Weight(๊ฐ์ค์น)๋ฅผ ๊ฐฑ์ ํ๊ณ
- Perplexity(ํผํ๋ ์ํฐ)๋ฅผ ๊ตฌํฉ๋๋ค.
NOTE. RnnlmTrainer ํด๋์ค๋ ์์์ ์ค๋ช ํ Trainer ํด๋์ค์ ๋๊ฐ์ API๋ฅผ ์ ๊ณตํฉ๋๋ค.
์ ๊ฒฝ๋ง์ ์ผ๋ฐ์ ์ธ ํ์ต์ Trainer ํด๋์ค๋ฅผ ์ฌ์ฉํ๊ณ , RNNLM ํ์ต์๋ RnnlmTrainer ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
Summary
Language Model(์ธ์ด ๋ชจ๋ธ)์ ๋จ์ด Sequence๋ฅผ ํ๋ฅ ๋ก ํด์ํ๋ค.
RNN ๊ณ์ธต์ ์ด์ฉํ ์กฐ๊ฑด๋ถ Language Model(์ธ์ด ๋ชจ๋ธ)์ (์ด๋ก ์ ์ผ๋ก๋) ๊ทธ๋๊น์ง ๋ฑ์ฅํ ๋ชจ๋ ๋จ์ด์ ์ ๋ณด๋ฅผ ๊ธฐ์ตํ ์ ์๋ค.
๋ฐ์ํ
'๐ NLP (์์ฐ์ด์ฒ๋ฆฌ) > ๐ Natural Language Processing' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[NLP] Generative Adversarial Networks (์์ฑ์ ์ ๋ ์ ๊ฒฝ๋ง, GAN) (0) | 2024.08.30 |
---|---|
[NLP] AutoEncoder (์คํ ์ธ์ฝ๋) (0) | 2024.08.30 |
[NLP] BPTT (Backpropagation Through Time) (0) | 2024.05.23 |
[NLP] ์ถ๋ก ๊ธฐ๋ฐ ๊ธฐ๋ฒ & Neural Network (์ ๊ฒฝ๋ง) (0) | 2024.05.22 |
[NLP] ํต๊ณ ๊ธฐ๋ฐ ๊ธฐ๋ฒ ๊ฐ์ ํ๊ธฐ (0) | 2024.05.20 |