728x90
input으로 h, e, l, , l, o가 차례로 들어갈 때 다음에 나올 알파벳을 예측하는 모델
Numpy 구현
import
import numpy as np
One-hot vector로 문자 구현
<EOS>: End of Sequence로 문자의 끝을 알림
char2vec = {'h': np.array([1,0,0,0,0]),
'e': np.array([0,1,0,0,0]),
'l': np.array([0,0,1,0,0]),
'o': np.array([0,0,0,1,0]),
'<EOS>': np.array([0,0,0,0,1])} #End of Sequence
idx2char = ['h', 'e', 'l', 'o', '<EOS>']
Weight 구성
RNN은 parameter를 공유하기 때문에 아래와 같이 step 별로 만들지 않아도 된다.
#RNN Cell 내 가중치
w_xh = np.array([[-2.6, -1.6, -2.1],
[ 1.2, 0.4, 0.3],
[ 2.1, 1.9, -0.7],
[-1.4, -1.5, 2.5],
[-0.9, 0.4, -0.9]])
w_hh = np.array([[-0.5, -2.3, 2.9],
[ 1.9, 1.5, 1.7],
[-0.7, -1.2, 1.5]])
b_h = np.array([-0.5, -0.4, -1. ])
#Output Layer 내 가중치
w_hy = np.array([[ 0.3, -2.6, 1.2, 2.6, -1.1],
[-1.1, -2.4, 2.2, 1.6, -2.4],
[-0.4, -3.1, -3. , 3.6, 3. ]])
b_y = np.array([-1.8, -0.5, 1.3, 0.1, 0.8])
def softmax(x):
return np.exp(x) / np.sum(np.exp(x), axis=-1)
STEP 1
각 변수는 아래의 그림과 같고 step 1을 계산하여 h_1을 구한다(next step의 입력).
init_h = np.array([0,0,0])
x_0 = char2vec['h']
a_1 = np.dot(init_h, w_hh) + np.dot(x_0,w_xh) + b_h
h_1 = np.tanh(a_1)
y_1 = np.dot(h_1, w_hy) + b_y
o_1 = softmax(y_1)
print("1번째 Timestep의 hidden : {}".format(h_1))
print("1번째 Timestep의 output : {}".format(y_1))
print("1번째 Timestep의 result : {}".format(idx2char[np.argmax(o_1)]))
1번째 Timestep의 hidden : [-0.99594936 -0.96402758 -0.99594936]
1번째 Timestep의 output : [-0.63997473 7.49057754 0.97184817 -7.61733016 1.22136241]
1번째 Timestep의 result : e
STEP 2
step 1의 출력인 h_1을 포함하여 학습한다.
x_1 = char2vec['e']
a_2 = np.dot(h_1, w_hh) + np.dot(x_1,w_xh) + b_h
h_2 = np.tanh(a_2)
y_2 = np.dot(h_2, w_hy) + b_y
o_2 = softmax(y_2)
print("2번째 Timestep의 hidden : {}".format(h_2))
print("2번째 Timestep의 output : {}".format(y_2))
print("2번째 Timestep의 result : {}".format(idx2char[np.argmax(o_2)]))
2번째 Timestep의 hidden : [ 0.06340167 0.96673299 -0.99999709]
2번째 Timestep의 output : [-2.44438695 0.11498748 6.50288586 -1.78837242 -4.58989229]
2번째 Timestep의 result : l
STEP 3
x_2 = char2vec['l']
a_3 = np.dot(h_2, w_hh) + np.dot(x_2,w_xh) + b_h
h_3 = np.tanh(a_3)
y_3 = np.dot(h_3, w_hy) + b_y
o_3 = softmax(y_3)
STEP 4
x_3 = char2vec['l']
a_4 = np.dot(h_3, w_hh) + np.dot(x_3,w_xh) + b_h
h_4 = np.tanh(a_4)
y_4 = np.dot(h_4, w_hy) + b_y
o_4 = softmax(y_4)
step 3, 4는 step 2와 구조가 같다.
Keras 구현
import
from tensorflow.keras.layers import Embedding
from tensorflow.keras.layers import Input, Dense, RNN
from tensorflow.keras.layers import SimpleRNNCell
import tensorflow as tf
import keras
from tensorflow.keras.layers import SimpleRNN
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
import tensorflow.keras.backend as K
Embedding Layer
one-hot vector 사용시 data가 sparse 해질 수 있기 때문에 embedding을 사용함
tf.random.set_seed(1)
inputs = Input(shape=())
embedded = Embedding(input_dim=5, output_dim=2)(inputs)
model = Model(inputs, embedded)
input이 'hello'이기 때문에 input_dim = 5이고 output_dim은 사용자가 지정하여 사용한다.
embedding model
Model: "model"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) [(None,)] 0
embedding (Embedding) (None, 2) 10
=================================================================
Total params: 10
Trainable params: 10
Non-trainable params: 0
_________________________________________________________________
RNN 구현 ( SimpleRNNCell)
n_inputs = 5
n_steps = 5
n_neurons = 3
n_outputs = n_inputs
inputs = Input(shape=(n_steps, n_inputs))
hidden = RNN(SimpleRNNCell(n_neurons), return_sequences=True)(inputs)
output = Dense(n_outputs, activation='softmax')(hidden)
model = Model(inputs, output)
Model: "model_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_2 (InputLayer) [(None, 5, 5)] 0
rnn (RNN) (None, 5, 3) 27
dense (Dense) (None, 5, 5) 20
=================================================================
Total params: 47
Trainable params: 47
Non-trainable params: 0
_________________________________________________________________
RNN 구현 2 (SimpleRNN)
from tensorflow.keras.layers import SimpleRNN
inputs = Input(shape=(n_steps, n_inputs))
hidden = SimpleRNN(n_neurons, return_sequences=True)(inputs)
output = Dense(n_outputs, activation='softmax')(hidden)
model = Model(inputs, output)
set weight
학습을 해서 찾아야하지만 weight를 지정하거나 저장한 게 있다면 model에 적용이 가능하다.
model.set_weights([w_xh, w_hh, b_h, w_hy, b_y])
결과 확인
input_values = "hello"
print("입력값 : ", list(input_values))
input_vecs = np.stack([char2vec[char]
for char in input_values])[np.newaxis]
results = model.predict(input_vecs)
result_indices = np.argmax(results, axis=-1)[0]
print("출력값 : ", [idx2char[idx] for idx in result_indices])
입력값 : ['h', 'e', 'l', 'l', 'o']
1/1 [==============================] - 0s 11ms/step
출력값 : ['e', 'l', 'l', 'o', '<EOS>']
728x90
'NLP' 카테고리의 다른 글
[NLP] NLP를 위한 CNN (0) | 2023.05.28 |
---|---|
[NLP] LSTM(Long Short-Term Memory) (0) | 2023.05.26 |
[NLP] RNN(Recurrent Neural Network) (0) | 2023.05.26 |
[NLP] 자연어데이터 전처리, NLTK (0) | 2023.04.03 |
[NLP] 한국어 자연어처리 (0) | 2023.04.03 |