인프런 커뮤니티 질문&답변

김대협님의 프로필 이미지
김대협

작성한 질문수

TensorFlow 2.0으로 배우는 딥러닝 입문

tf.keras.model.reset_states()

작성

·

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

AISchool님의 프로필 이미지
AISchool
지식공유자

안녕하세요~. 반갑습니다.


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를 인수로 받지 않아도 자동으로 해석해주는 것 같은데 확실하지 않습니다. 아래 선생님들께서 답변 달아주실 것 같습니다.

김대협님의 프로필 이미지
김대협

작성한 질문수

질문하기