🔥알림🔥
① 테디노트 유튜브 -
구경하러 가기!
② LangChain 한국어 튜토리얼
바로가기 👀
③ 랭체인 노트 무료 전자책(wikidocs)
바로가기 🙌
④ RAG 비법노트 LangChain 강의오픈
바로가기 🙌
⑤ 서울대 PyTorch 딥러닝 강의
바로가기 🙌
[tensorflow] RNN Text 생성 (셰익스피어 글 생성)
텐서플로우 공식 튜토리얼인 순환 신경망을 활용한 문자열 생성에 대한 클론 코드입니다. 셰익스피어 글 데이터셋을 활용하여 인공지능 모델을 학습시키고, 셰익스피어 스타일의 글을 생성할 수 있는 모델을 만들어 보도록 하겠습니다.
데이터셋은 Windowed Dataset으로 구성하며, 모델은 Embedding Layer와 LSTM Layer를 사용하여 구성합니다.
튜토리얼 영상
텐서플로우 RNN 텍스트 생성
본 튜토리얼은 텐서플로우 공식 도큐먼트 튜토리얼에 대한 클론 코드입니다.
- Reference: 순환 신경망을 활용한 문자열 생성
import tensorflow as tf
import numpy as np
import os
import time
%%javascript
IPython.OutputArea.auto_scroll_threshold = 20
셰익스피어 데이터셋 다운로드
구글 데이터셋 서버로부터 shakespear.txt
데이터셋을 다운로드 받습니다.
path_to_file = tf.keras.utils.get_file('shakespeare.txt', 'https://storage.googleapis.com/download.tensorflow.org/data/shakespeare.txt')
text = open(path_to_file, 'rb').read().decode(encoding='utf-8')
print(text[:200])
print(repr(text[:200]))
# 총 문장의 길이
len(text)
고유 캐릭터 수를 출력합니다.
vocab = sorted(set(text))
vocab[:10]
len(vocab)
텍스트 전처리 (preprocessing)
STEP 1. Character 사전 만들기
Character를 index로 변환하는 사전을 만듭니다.
char2idx = {u: i for i, u in enumerate(vocab)}
char2idx
index -> Character로 변환하는 사전을 만듭니다.
idx2char = np.array(vocab)
idx2char[49]
Step 2. 텍스트 전체를 int로 변환합니다.
text[:200]
char2idx['i']
text_as_int = np.array([char2idx[c] for c in text])
len(text_as_int)
text_as_int[:10]
변환된 부분을 확인합니다. (처음 5개)
# 원문
text[:5]
# 변환된 sequence
text_as_int[:5]
# 각각의 단어사전으로 출력
char2idx['F'], char2idx['i'], char2idx['r'], char2idx['s'], char2idx['t']
Step 3. X, Y 데이터셋 생성하기
# 단일 입력에 대해 원하는 문장의 최대 길이
window_size = 100
shuffle_buffer = 10000
batch_size=64
Windowed Dataset을 만듭니다.
def windowed_dataset(series, window_size, shuffle_buffer, batch_size):
series = tf.expand_dims(series, -1)
ds = tf.data.Dataset.from_tensor_slices(series)
ds = ds.window(window_size + 1, shift=1, drop_remainder=True)
ds = ds.flat_map(lambda x: x.batch(window_size + 1))
ds = ds.shuffle(shuffle_buffer)
ds = ds.map(lambda x: (x[:-1], x[1:]))
return ds.batch(batch_size).prefetch(1)
train_data = windowed_dataset(np.array(text_as_int), window_size, shuffle_buffer, batch_size)
# 문자로 된 어휘 사전의 크기
vocab_size = len(vocab)
vocab_size
# 임베딩 차원
embedding_dim = 256
# RNN 유닛(unit) 개수
rnn_units = 1024
model = tf.keras.Sequential([
tf.keras.layers.Embedding(vocab_size, embedding_dim,
batch_input_shape=[batch_size, None]),
tf.keras.layers.LSTM(rnn_units,
return_sequences=True,
stateful=True,
recurrent_initializer='glorot_uniform'),
tf.keras.layers.Dense(vocab_size)
])
model.summary()
체크포인트를 생성합니다.
# 체크포인트가 저장될 디렉토리
checkpoint_path = './models/my_checkpt.ckpt'
checkpoint_callback=tf.keras.callbacks.ModelCheckpoint(
filepath=checkpoint_path,
save_weights_only=True,
save_best_only=True,
monitor='loss',
verbose=1,
)
Loss function을 정의합니다.
def loss(labels, logits):
return tf.keras.losses.sparse_categorical_crossentropy(labels, logits, from_logits=True)
model.compile(optimizer='adam', loss=loss, metrics=['acc'])
model.fit(train_data,
epochs=10,
steps_per_epoch=1720,
callbacks=[checkpoint_callback])
예측을 위한 모델 재정의
batch_size -> 1로 변경합니다.
model = tf.keras.Sequential([
tf.keras.layers.Embedding(vocab_size, embedding_dim,
batch_input_shape=[1, None]),
tf.keras.layers.LSTM(rnn_units,
return_sequences=True,
stateful=True,
recurrent_initializer='glorot_uniform'),
tf.keras.layers.Dense(vocab_size)
])
model.load_weights(checkpoint_path)
model.build(tf.TensorShape([1, None]))
model.summary()
generate_text 함수를 활용하여, 문자를 연속적으로 예측합니다.
def generate_text(model, start_string):
# 평가 단계 (학습된 모델을 사용하여 텍스트 생성)
# 생성할 문자의 수
num_generate = 1000
# 시작 문자열을 숫자로 변환(벡터화)
input_eval = [char2idx[s] for s in start_string]
input_eval = tf.expand_dims(input_eval, 0)
# 결과를 저장할 빈 문자열
text_generated = []
# 온도가 낮으면 더 예측 가능한 텍스트가 됩니다.
# 온도가 높으면 더 의외의 텍스트가 됩니다.
# 최적의 세팅을 찾기 위한 실험
temperature = 1.0
# 여기에서 배치 크기 == 1
model.reset_states()
for i in range(num_generate):
predictions = model(input_eval)
# 배치 차원 제거
predictions = tf.squeeze(predictions, 0)
# 범주형 분포를 사용하여 모델에서 리턴한 단어 예측
predictions = predictions / temperature
predicted_id = tf.random.categorical(predictions, num_samples=1)[-1,0].numpy()
# 예측된 단어를 다음 입력으로 모델에 전달
# 이전 은닉 상태와 함께
input_eval = tf.expand_dims([predicted_id], 0)
text_generated.append(idx2char[predicted_id])
return (start_string + ''.join(text_generated))
최종 결과물 출력
print(generate_text(model, start_string=u"ROMEO: "))
댓글남기기