https://www.youtube.com/watch?v=aNrqaOAt5P4&list=PLQY2H8rRoyvzuJw20FG82Lgm2SZjTdIXU&index=2


- 이번 동영상은 모델이 글을 읽는 학습 과정을 케라스를 통해 보여줍니다.

- 사람이 유치원을 다닐 때 글을 배우는 과정이 신경망이 글을 배우는 과정과 동일하다면서 영상을 시작합니다.

- NLP는 계속해서 진화하는 중이고, 사람 수준을 뛰어넘었습니다.


데이터 준비하기

- 신경망이 학습하기 위해선 데이터가 필요합니다. corpus와 같은 데이터말이죠.
먼저, 데이터를 확인해보겠습니다.
(데이터는 영상으로 대체합니다.)

lines = tf.data.TextLineDataset('./CBTest/data/cbt_train.txt')

for line in lines.take(3):
  print(line)

이 데이터를 그대로 사용하면 위험합니다. 데이터를 클린하게 만들어 줄 필요가 있습니다.

lines = lines.filter(
    lambda x: not tf.strings.regex_full_match(x, "_BOOK_TITLE_.*")
)

punctuation = r'[!"#$%&()\*\+,-\./:;<=>?@\[\\\]^_'{|}~\']'
lines = lines.map(lambda x: tf.strings.regex_replace(x, punctuation, ' '))

위의 결과와 비교해보세요. 클린해진 것을 한눈에 알 수 있습니다.

이제 모델에 데이터를 입력하기 위해 window 형태로 만들어야 합니다. 모든 문장의 길이는 같기 때문에 단순히 split만 해주면 되겠군요.

words = lines.map(tf.strings.split)
wordsets = words.unbatch().batch(11)

for row in wordsets.take(3):
  print(row)

모델이 정답은 알아야겠죠? 데이터의 마지막 단어를 레이블로 만들고 싶습니다.

def get_example_label(row):
  example = tf.strings.reduce_join(row[:-1], separator = ' ')
  example = tf.expand_dims(example, axis = 0)
  label = row[-1:]
  return example, label

data = wordsets.map(get_example_label)
data = data.shuffle(1000)

결과는 다음과 같습니다. 한 개의 긴 문장(학습용 데이터), 한 개의 레이블로 이루어져 있네요.

하지만 신경망 모델이 직접 언어를 배울 수는 없습니다. 오로지 숫자를 배울뿐이죠.
그래서 위와 같은 데이터를 다시 숫자로 변환해야 합니다.

vocab_size = 5000 # Maximum vocab size
vectorize_layer = tf.keras.layers.experimental.preprocessing.TextVectorization(max_tokens=vocab_size,
                                                                               output_sequence_length = 10)

이와 같은 전처리 레이어는 다양하게 keras에서 제공하고 있으며, tf.data.Datasets와 활용하면 매우 효과적입니다. 다음 그림에서 전처리 레이어가 얼마나 다양하게 존재하는지 알 수 있습니다.

 

모델 준비하기

이제 모델을 구성하면 됩니다.(seq2seq 모델)
케라스와 TensorFlow AddOnes를 활용하면 쉽게 구성할 수 있습니다. seq2seq 모델은 상당히 복잡한데, Encoder는 keras layer를 통해 쉽게 구성할 수 있고,  Decoder는 AddOnes를 활용하여 한번에 구성할 수 있는 것을 영상에서 보여줍니다.

TF 2.x에서는 학습 과정을 클린하고 모듈화된 과정을 제공하기 위해 노력한다고 합니다.
train_step을 직접 만들고, Gradient_Tape()를 활용하여 모델을 업데이트시키죠.

학습 단계를 정의했다면, 기존의 케라스와 동일하게 compile() 함수를 활용해서 과정을 설정합니다.
그래서 위의 train_step을 직접 정의해야 되냐고요?
model.fit() 함수를 사용하면 위의 과정이 전부 포함되어 있습니다.

model = MyModel()
model.compile(...)
model.fit(...)

케라스를 사용해서 우리는 만족할 수준의 모델 성능을 쉽게 얻을 수 있었습니다.
하지만 아직 하이퍼파라미터 튜닝을 진행해보지 않았군요.

 

하이퍼파라미터 튜닝하기

KerasTuner를 활용한다면 매우 쉽습니다!
코드에서 hp(hyperparameter 객체) 인자를 사용해 튜닝을 준비하고 있습니다.

import kerastuner as kt

def build_model(hp):
  model = EncoderDecoder(
    			rnn_units = hp.Int(
                			'units', min_value = 256, max_value = 1100, step = 256))
  model.compile(...)
  model.vectorize_layer.adapt(lines.batch(256))

  return model

케라스 튜너는 다음과 같이 사용합니다.

tuner = kt.tuners.RandomSearch(
  build_model,
  objective = 'accuracy',
  ...
  project_name = 'text_generation')
  
tuner.search(
  data.batch(256),
  epochs = 45,
  callbacks = [tf.keras.callbacks.ModelCheckpoint('text_gen')])

학습이 끝났으니 이제 모델이 잘 동작하는지 확인해야 합니다.
train_step처럼 predict_step을 정의해야 하지만, 케라스를 활용하면 model.predict()로 끝입니다!

마지막으로 텐서플로우 2.x는 large-scale의 text processing을 위해 다음 모듈을 제공합니다.

  • tf.text
  • KerasBert
  • TFHub text modules