작성
·
424
·
수정됨
0
파이썬 버전이 다른지 텐서플로우 버전이 다른지 모르겠지만 자꾸 코드가 실행되지 않는 부분들이 있어 조금식 바꿔가면서 강의 듣고 있습니다. 그러던 중 Char-RNN실습에서 tf.keras.Model.reset_states()에 오류가 생겨 질문 드립니다.
class exModel(tf.keras.Model):
def __init__(self):
super(exModel, self).__init__()
self.layer = tf.keras.layers.Dense(10,
activation = None,
kernel_initializer = 'zeros',
bias_initializer = 'zeros')
def call(self, x):
logits = self.layer(x)
return logits
My_model = exModel()
My_model.reset_states()
결과 :
'exModel' object has no attribute 'reset_states'
Tensorflow : 2.16.1
Python : 3.10.13
실습 파일 : train_and_sampling_v2_keras.py
==================================================================
실습 코드 :
# -*- coding: utf-8 -*-
# Char-RNN 예제 - Keras API를 이용한 구현
# Reference : https://github.com/tensorflow/docs/blob/master/site/en/tutorials/text/text_generation.ipynb
from __future__ import absolute_import, division, print_function, unicode_literals #python 2와 호완
from absl import app #Google에서 만든 API / Tensorflow와 같이 쓰이니 공부해두자
import tensorflow as tf
import numpy as np
import os
import time
# input 데이터와 input 데이터를 한글자씩 뒤로 민 target 데이터를 생성하는 utility 함수를 정의합니다.
def split_input_target(chunk):
input_text = chunk[:-1]
target_text = chunk[1:]
return input_text, target_text
# 학습에 필요한 설정값들을 지정합니다.
data_dir = tf.keras.utils.get_file('shakespeare.txt', 'https://storage.googleapis.com/download.tensorflow.org/data/shakespeare.txt') # shakespeare
#data_dir = './data/linux/input.txt' # linux
batch_size = 64 # Training : 64, Sampling : 1
'''
기존 : [batch_size, data_dimension]
시계열 데이터 : [batch_size, sequence_len,data_dimension]
'''
seq_length = 100 # Training : 100, Sampling : 1 #몇 글자를 한 시퀀스로 할 것인가
embedding_dim = 256 # Embedding 차원
hidden_size = 1024 # 히든 레이어의 노드 개수
num_epochs = 10
# 학습에 사용할 txt 파일을 읽습니다.
text = open(data_dir, 'rb').read().decode(encoding='utf-8')
# 학습데이터에 포함된 모든 character들을 나타내는 변수인 vocab과
# vocab에 id를 부여해 dict 형태로 만든 char2idx를 선언합니다.
vocab = sorted(set(text)) # 유니크한 character
vocab_size = len(vocab)
print('{} unique characters'.format(vocab_size))
char2idx = {u: i for i, u in enumerate(vocab)}
'''
character - index(int) mapping
'''
idx2char = np.array(vocab)
# 학습 데이터를 character에서 integer로 변환합니다.
text_as_int = np.array([char2idx[c] for c in text])
# split_input_target 함수를 이용해서 input 데이터와 input 데이터를 한글자씩 뒤로 민 target 데이터를 생성합니다.
char_dataset = tf.data.Dataset.from_tensor_slices(text_as_int)
sequences = char_dataset.batch(seq_length+1, drop_remainder=True)
dataset = sequences.map(split_input_target)
# tf.data API를 이용해서 데이터를 섞고 batch 형태로 가져옵니다.
dataset = dataset.shuffle(10000).batch(batch_size, drop_remainder=True)
#================================데이터 구성===========================================
# tf.keras.Model을 이용해서 RNN 모델을 정의합니다.
class RNN(tf.keras.Model):
def __init__(self, batch_size):
super(RNN, self).__init__()
self.embedding_layer = tf.keras.layers.Embedding(vocab_size, embedding_dim) #기본 예제라 특수적으로 임베딩 차원이 더 크게 했다
#batch_input_shape=[batch_size, None]
self.hidden_layer_1 = tf.keras.layers.LSTM(hidden_size,
return_sequences=True,
stateful=True,
recurrent_initializer='glorot_uniform')
self.output_layer = tf.keras.layers.Dense(vocab_size)
def call(self, x):
embedded_input = self.embedding_layer(x)
features = self.hidden_layer_1(embedded_input)
logits = self.output_layer(features)
return logits
# sparse cross-entropy 손실 함수를 정의합니다.
def sparse_cross_entropy_loss(labels, logits):
return tf.reduce_mean(tf.keras.losses.sparse_categorical_crossentropy(labels, logits, from_logits=True))
#sparse_categorical_crossentropy : one - hot encoding까지 알아서 해줌
# 최적화를 위한 Adam 옵티마이저를 정의합니다.
optimizer = tf.keras.optimizers.Adam()
# 최적화를 위한 function을 정의합니다.
@tf.function
def train_step(model, input, target):
with tf.GradientTape() as tape:
logits = model(input)
loss = sparse_cross_entropy_loss(target, logits)
grads = tape.gradient(loss, model.trainable_variables)
optimizer.apply_gradients(zip(grads, model.trainable_variables))
return loss
def generate_text(model, start_string):
num_sampling = 4000 # 생성할 글자(Character)의 개수를 지정합니다.
# start_sting을 integer 형태로 변환합니다.
input_eval = [char2idx[s] for s in start_string]
input_eval = tf.expand_dims(input_eval, 0)
# 샘플링 결과로 생성된 string을 저장할 배열을 초기화합니다.
text_generated = []
# 낮은 temperature 값은 더욱 정확한 텍스트를 생성합니다.
# 높은 temperature 값은 더욱 다양한 텍스트를 생성합니다.
temperature = 1.0
# 여기서 batch size = 1 입니다.
model.reset_states()
for i in range(num_sampling):
predictions = model(input_eval)
# 불필요한 batch dimension을 삭제합니다.
predictions = tf.squeeze(predictions, 0)
# 모델의 예측결과에 기반해서 랜덤 샘플링을 하기위해 categorical distribution을 사용합니다.
predictions = predictions / temperature
predicted_id = tf.random.categorical(predictions, num_samples=1)[-1,0].numpy()
# 예측된 character를 다음 input으로 사용합니다.
input_eval = tf.expand_dims([predicted_id], 0)
# 샘플링 결과를 text_generated 배열에 추가합니다.
text_generated.append(idx2char[predicted_id])
return (start_string + ''.join(text_generated))
def main(_):
# Recurrent Neural Networks(RNN) 모델을 선언합니다.
RNN_model = RNN(batch_size=batch_size)
# 데이터 구조 파악을 위해서 예제로 임의의 하나의 배치 데이터 에측하고, 예측결과를 출력합니다.
#Sanity Check : 데이터 문제 없는지 확인
for input_example_batch, target_example_batch in dataset.take(1):
example_batch_predictions = RNN_model(input_example_batch)
print(example_batch_predictions.shape, "# (batch_size, sequence_length, vocab_size)")
# 모델 정보를 출력합니다.
RNN_model.summary()
# checkpoint 데이터를 저장할 경로를 지정합니다.
checkpoint_dir = './training_checkpoints'
checkpoint_prefix = os.path.join(checkpoint_dir, "ckpt_{epoch}")
for epoch in range(num_epochs):
start = time.time()
# 매 반복마다 hidden state를 초기화합니다. (최초의 hidden 값은 None입니다.)
hidden = RNN_model.reset_states()
for (batch_n, (input, target)) in enumerate(dataset):
loss = train_step(RNN_model, input, target)
if batch_n % 100 == 0:
template = 'Epoch {} Batch {} Loss {}'
print(template.format(epoch+1, batch_n, loss))
# 5회 반복마다 파라미터를 checkpoint로 저장합니다.
if (epoch + 1) % 5 == 0:
RNN_model.save_weights(checkpoint_prefix.format(epoch=epoch))
print ('Epoch {} Loss {:.4f}'.format(epoch+1, loss))
print ('Time taken for 1 epoch {} sec\n'.format(time.time() - start))
RNN_model.save_weights(checkpoint_prefix.format(epoch=epoch))
print("트레이닝이 끝났습니다!")
sampling_RNN_model = RNN(batch_size=1)
sampling_RNN_model.load_weights(tf.train.latest_checkpoint(checkpoint_dir))
sampling_RNN_model.build(tf.TensorShape([1, None]))
sampling_RNN_model.summary()
# 샘플링을 시작합니다.
print("샘플링을 시작합니다!")
print(generate_text(sampling_RNN_model, start_string=u' '))
if __name__ == '__main__':
# main 함수를 호출합니다.
app.run(main)
결과 :
AttributeError: 'RNN' object has no attribute 'reset_states'
tf.keras.layers.Embedding에 batch_input_shape에서 오류가 발생해서,https://www.tensorflow.org/api_docs/python/tf/keras/layers/Embedding 참고해서 지웠고, 다른 부분은 안 건드렸습니다.
tf.keras.layers.Embedding(
input_dim,
output_dim,
embeddings_initializer='uniform',
embeddings_regularizer=None,
embeddings_constraint=None,
mask_zero=False,
weights=None,
lora_rank=None,
**kwargs
)
답변 2
0
안녕하세요~. 반갑습니다.
tensorflow가 tensorflow 2.16.x 버전으로 업그레이드되면서 기본으로 지원하는 Keras 버전이 Keras3 버전으로 변경되어서 tensorflow 2.16.x 버전 형태로 코드를 작성하려면 기존의 Keras2 버전 스타일의 코드를 Keras3 버전 스타일로 전반적으로 변경하는 작업이 필요합니다. ( https://keras.io/guides/migrating_to_keras_3/ )
pip install tensorflow==2.15.0
위 명령어로 keras2를 지원하는 tensorflow 2.15.0 버전으로 tensorflow 버전을 다운그레이드해서 실습을 진행하시는 것을 추천드립니다.
좋은 하루되세요.
감사합니다.
0
RNN class의 hidden layer만 reset하면 되는 것 같아 model.hidden_Layer_1.reset_states() 로 초기화해주었습니다. 이렇게 하니 잘 돌아가는 것 같습니다. (아직 돌리는 중입니다.)
tensorflow버전 업데이트 되면서 tf.keras.layers.Embedding가 batch_input_shape를 인수로 받지 않아도 자동으로 해석해주는 것 같은데 확실하지 않습니다. 아래 선생님들께서 답변 달아주실 것 같습니다.