12장 생성 모델을 위한 딥러닝
12.1 텍스트 생성
텍스트 생성
- 딥러닝을 통해 텍스트뿐만 아니라 어떤 종류의 시퀀스(순차적인) 데이터도 생성 가능
- 생성 모델을 위한 딥러닝 기술은 음성 합성과 챗봇의 대화 기능에 성공적으로 적용
- 구글이 2016년에 공개한 스마트 답장(Smart Reply)도 비슷한 기술을 사용
- 짧은 문장을 자동으로 생성하여 이메일이나 문자 메시지로 답장을 보낼 수 있음
시퀀스 생성을 위한 딥러닝 모델의 간단한 역사 (생략가능)
- 2015년에서 2017년 사이에 순환 신경망은 텍스트와 대화 생성, 음악 생성, 음성 합성에 성공적으로 사용
- 2017~2018년 즈음에 트랜스포머 아키텍처가 자연어 처리 지도 학습 작업뿐만 아니라 시퀀스 생성 모델, 특히 언어 모델링(단어 수준의 텍스트 생성)에서 순환 신경망을 압도하기 시작
- 가장 잘 알려진 생성 트랜스포머의 예는 1,750억 개의 파라미터를 가진 텍스트 생성 모델인 GPT-3
- 이 모델은 OpenAI가 디지털로 공개된 대부분의 책과 위키피디아를 포함하여 전체 인터넷을 상당 부분 크롤링한 엄청나게 큰 텍스트 말뭉치에서 훈련
- GPT-3는 거의 모든 주제에 대해 그럴듯한 텍스트 문장을 생성하는 능력 때문에 뉴스 헤드라인을 장식
시퀀스 데이터를 어떻게 생성할까?
- 딥러닝에서 시퀀스 데이터를 생성하는 방법: 이전 토큰을 입력(input)으로 사용해서 시퀀스의 다음 1개(또는 몇 개의 토큰)를 (트랜스포머나 RNN 등 순환신경망 모델로) 예측하는 것
- 예를 들어 "the cat is on the"란 입력이 주어지면 다음 단어인 타깃 "mat"을 예측하도록 모델을 훈련
- 여기서 토큰은 'the', 'cat'등 단어를 의미
- 이전 단어 토큰들이 주어졌을 때 다음 단어 토큰의 확률을 모델링할 수 있는 네트워크를 언어 모델(language model)이라고 부름
- 언어 모델은 언어 안에서 단어와 문장들이 어떻게 연결되고 조합되는지에 대한 패턴을 파악하는 도구
- 훈련을 통해 얻은 언어 모델은 초기 텍스트(조건 데이터(conditioning data)라고 부름)를 주입하고 새로운 글자나 단어를 생성(한 번에 여러 개의 글자나 단어를 생성 가능)
- 생성된 출력(새로운 글자나 단어)은 다시 입력 데이터로 추가됨. 이 과정을 여러 번 반복
- 이런 반복을 통해 모델이 생성한 시퀀스는 사람이 쓴 문장과 거의 비슷한 경지까지 이름
샘플링 전략의 중요성
- 텍스트를 생성할 때 다음 문자를 선택하는 방법이 아주 중요
- 탐욕적 샘플링(greedy sampling): 단순한 방법으로 항상 가장 높은 확률을 가진 글자를 선택
- 그러나 이 방법은 논리적인 언어를 생성하지 않을수 있음
- 확률적 샘플링(stochastic sampling): 각 단어의 확률을 고려하여 다양한 결과를 생성하는 샘플링 전략
- 작동 예: 어떤 단어가 문장의 다음 단어가 될 확률이 0.3이라면, 모델이 30% 정도는 이 단어를 선택
- 탐욕적 샘플링을 확률적 샘플링으로 설명: 한 단어의 확률이 1이고 나머지 단어는 모두 0인 확률 분포를 가지는 경우
- 소프트맥스 출력은 합이 1이고 분류하고 싶은 클래스 수만큼 출력을 구성하므로 확률적 샘플링에 사용하기 좋음
- 단어는 샘플링될 것 같지 않은 단어가 선택될 수 있고 훈련 데이터에는 없지만 실제 같은 새로운 문장을 만들기도 함
- 확률적 샘플링에는 무작위성의 양을 조절할 방법이 없다는 문제가 있음
- 무작위성이 중요한 이유를 위해 극단적인 경우를 생각해 보자
- 만약 확률분포가 균등 확률 분포라면 다음 단어를 추출할 때 무작위성이 최대이므로 어떤 단어가 추출될지 모름
- 따라서 불확실성이 최대이므로 우리가 원하는 사람과 같이 생각된 텍스트 출력을 얻지 못함
- 반대의 경우 탐욕적 샘플링은 무작위성이 없어 원하는 결과를 도출하지 못함
- 탐욕적 샘플링의 확률 분포는 최소의 불확실성을 가짐
- 작은 불확실성은 예상 가능한 구조를 가진 시퀀스 생성 반대로 높은 불확실성은 창의적인 시퀀스를 만듦
- 생성 모델에서 샘플링을 할 때 생성 과정에 무작위 값을 바꾸어 시도해 보는 것이 좋음
- 우리가 원하는 결과는 주관적이므로 최적의 불확실성을 미리 알 수 없기 때문
- 샘플링 과정에서 확률 분포의 엔트로피(불확실성)을 조절하기 위해 softmax temperature라는 파라미터를 사용
- temperature 값이 주어지면 다음과 같이 가중치를 적용하여 (모델의 소프트맥스 출력인) 원본 확률 분포에서 새로운 확률 분포를 계산
- 다른 온도 값을 사용하여 확률 분포의 가중치 바꾸기
import numpy as np
# 주어진 확률 분포를 조정하여 다양한 온도(temperature) 수준에서 출력 분포의 엔트로피를 조절
# original_distribution은 전체 합이 1인 1D 넘파이 배열. temperature는 출력 분포의 엔트로피의 양을 결정
def reweight_distribution(original_distribution, temperature=0.5):
# original_distribution의 각 확률값에 로그를 취한 후 temperature로 나눈다.
# 로그를 취한 이유는 원본 확률값의 범위를 줄여서 분포의 균일성을 높이기 위함
distribution = np.log(original_distribution) / temperature
# 계산한 값을 지수 함수로 다시 변환하여 새로운 가중치를 얻는다.
distribution = np.exp(distribution)
# 원본 분포의 가중치를 변경하여 반환
# 이 분포의 합은 1이 아닐 수 있으므로 새로운 분포의 합으로 나눈다.
return distribution / np.sum(distribution)
- temperature값이 높다면 엔트로피(불확실성)이엔트로피(불확실성)가 높은 샘플링 분포를 만들어 생소하며 창의적인 데이터를 생성 반대로 낮은 temperature는 엔트로피(불확실성)가 낮기 때문에 예상할 수 있는 데이터를 생산
▶ 하나의 확률 분포에 다른 가중치를 적용한 사례. 낮은 온도 = 훨씬 결정적임, 높은 온도 = 무작위성이 많음
케라스를 사용한 텍스트 생성 모델 구현
- 텍스트 생성 모델을 학습하기 위해 많은 텍스트 데이터가 필요
- 이 예제에서는 이전 장의 IMDB영화 리뷰 데이터셋을 사용하여 이전에 본 적 없는 영화 리뷰를 생산하는 방법을 학습
데이터 준비
- 이전 장과 동일하게 IMDB 영화 리뷰 데이터셋을 내려받아 압축을 푼다
- IMDB 영화 리뷰 데이터셋 내려받아 압축 풀기
!wget https://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz
!tar -xf aclImdb_v1.tar.gz
- aclImdb 폴더 안에는 부정적인 영화 리뷰를 담고있는 폴더와 긍정적인 영화 리뷰를 담고 있는 서브폴더가 있음
- 리뷰마다 하나의 텍스트 파일로 구성되어 있음
- 텍스트 파일(한 파일=한 샘플)에서 데이터셋 만들기
# TensorFlow와 Keras를 사용하여 텍스트 데이터셋을 생성하고 전처리
import tensorflow as tf
from tensorflow import keras
'''
keras.utils.text_dataset_from_dictionary: 이 함수를 사용해서 디렉토리에서 텍스트 데이터셋을 생성
매개변수 역할
dictionary: 데이터셋이 있는 디렉토리를 결정
label_mode: 레이블 모드를 지정. 여기서는 None으로 설정하여 레이블 없이 데이터를 생성
batch_size: 배치 크기를 지정
'''
dataset = keras.utils.text_dataset_from_directory(
directory="aclImdb", label_mode=None, batch_size=256)
# 이 리뷰에 많이 등장하는 <br /> HTML태그를 제거.
# 텍스트 분류에서 중요하지 않기 때문
dataset = dataset.map(lambda x: tf.strings.regex_replace(x, "<br />", " "))
- 이제 TextVectorization 층을 사용하여 이 예제에서 사용할 어휘 사전을 만듦
- 각 리뷰에서 처음 sequence_length(15,000)개 단어만 사용 이보다 긴 리뷰 내용은 잘라버림
- TextVectorization 층 준비하기
# TensorFlow의 Keras 라이브러리 TextVectorization을 사용하여 텍스트 데이터를 벡터화하는 작업을 수행
# 텍스트 데이터를 숫자로 변환하여 딥러닝 모델에 입력으로 사용할 수 있도록 전처리
from tensorflow.keras.layers import TextVectorization
sequence_length = 100
# 가장 자주 등장하는 1만 5,000개 단어만 사용.
# 그 외 단어는 모두 OOV 토큰인 "[UNK]"로 처리
vocab_size = 15000
text_vectorization = TextVectorization(
# 벡터화할 때 사용할 최대 단어 수를 제한하는 역할.
# 여기서는 가장 자주 등장하는 상위 1만 5,000개의 단어만 사용하도록 설정
max_tokens=vocab_size,
# 정수 단어 인덱스의 시퀀스를 반환하도록 설정
output_mode="int",
# 모델에 입력으로 사용할 시퀀스의 길이를 결정.
# 길이가 100인 입력과 타깃을 사용(타깃을 한 스텝 차이가 나기 때문에 실제로 모델은 99개의 단어 시퀀스를 보게 된다.)
output_sequence_length=sequence_length,
)
# adapt메서드를 사용하여 데이터셋을 기반으로 벡터화 모델을 학습하고 적용
# 이로써 모델은 데이터셋의 특성에 따라 단어를 인덱싱하고 벡터화하는데 필요한 정보를 얻게 됨
text_vectorization.adapt(dataset)
- 이 층을 사용하여 언어 모델링 데이터셋을 만들어 보자
- 입력 샘플은 벡터화된 텍스트고 타깃은 한 스텝 앞의 동일 텍스트
- 언어 모델링 데이터셋 만들기
# 텍스트 데이터를 언어 모델을 학습하기 위한 데이터셋으로 변환하는 작업을 수행
# prepare_lm_dataset: 입력된 텍스트 배치를 정수 시퀀스의 배치로 변환하는 작업을 수행
# text_vectorization 모델을 사용하여 텍스트를 정수 시퀀스로 벡터화한 후, 시퀀스의 마지막 단어를 제외한 입력과 시퀀스의 첫 단어를 제외한 타깃을 생성
def prepare_lm_dataset(text_batch):
# 텍스트(문자열)의 배치를 정수 시퀀스의 배치로 변환
vectorized_sequences = text_vectorization(text_batch)
# 시퀀스의 마지막 단어를 제외한 입력을 만든다.
x = vectorized_sequences[:, :-1]
# 시퀀스의 첫 단어를 제외한 타깃을 만든다.
y = vectorized_sequences[:, 1:]
return x, y
# dataset.map 메서드를 사용하여 입렉 데이터셋에 'prepare_lm_dataset'함수를 적용하여 데이터셋을 변환한 결과
lm_dataset = dataset.map(prepare_lm_dataset, num_parallel_calls=4)
트랜스포머 기반의 시퀀스-투-시퀀스 모델
- 몇 개의 초기 단어가 주어지면 문장의 다음 단어에 대한 확률 분포를 예측하는 모델을 훈련
- N개 단어의 시퀀스를 입력으로 받아 N+1 번째 단어를 예측하는 모델을 훈련
- 시퀀스 생성 관점으로 보았을 때 여기에는 몇 가지 이슈가 있음
- 첫째, 이 모델은 N개의 단어로 예측을 만드는 방법을 학습하지만 N개보다 적은 단어로 예측을 시작할 수 있어야 함
- 그렇지 않으면 비교적 긴 시작 문장(여기에서는 N=100개 단어)을 사용해야 하는 제약이 생김
- 둘째, 훈련에 사용하는 많은 시퀀스는 중복되어 있음
- N=4일 때를 예로 들어 보자
- "A complete sentence must have, at minimum, three things: a subject, verb and an object"는 다음과 같은 훈련 시퀀스를 만듦
- "A complete sentence must"
- "complete sentence must have"
- "sentence must have at"
- "verb and an object"까지 계속
- 많은 모델들은 시퀀스를 독립적인 샘플로 취급한다(각 시퀀스를 개별적으로 다루며, 이전 시퀀스나 이후 시퀀스의 관계를 고려하지 않고 독립적으로 처리).
- 이는 중복 작업을 초례하며, 처음부터 훈련 데이터가 풍부하지 않은 경우에 문제가 된다.
- 이를 해결하기 위해, 중복 문제를 완화하기 위해 시퀀스를 건너뛰며 샘플링하는 방법을 사용할 수 있음
- 이 방법은 일부 중복을 줄일 수 있지만 훈련 샘플의 수가 줄어들 수 있는 단점도 있다.
- 시퀀스-투-시퀀스 모델은 두 이슈를 해결하기 위한 방법으로 사용. 이 모델은 다음과 같은 방식으로 사용
- 중복 문제 해결: 모델은 N개의 단어 시퀀스(0에서 N까지)를 입력으로 받고, 그다음 단어 시퀀스(1에서 N+1까지)를 예측한다. 이 과정에서 코잘 마스킹(casual masking)을 사용하여 현재 위치 이전의 단어만 활용하여 다음 단어를 예측하도록 한다. 이렇게 함으로써 모델은 중복이 있는 여러 문제를 동시에 학습하게 된다. 각 위치마다 다음 단어를 예측하는 문제를 풀어서 중복 문제를 해결하게 된다.
- 예측 단계 개선: 모델이 훈련된 후, 생성 단계에서 하나의 단어만 입력하더라도 모델은 그 다음 단어에 대한 확률 분포를 예측할 수 있다. 이로써 모델은 더 나은 문장 생성을 위한 기반을 제공하며, 예측을 통해 텍스트를 자동으로 생성할 수 있게 된다.
▶ 평범한 다음 단어 예측에 비해 시퀀스-투-시퀀스 모델은 동시에 여러개의 예측 문제를 최적화한다
- 10장의 온도 예측 문제에서도 시퀀스-투-시퀀스 설정을 활용할 수 있었다. 이 설정에서는 다음과 같은 장점이 있다.
- 다양한 문제 해결: 주어진 120시간의 시퀀스 데이터로부터 24시간 후의 온도를 예측하는 것뿐만 아니라, 각 시간별 데이터를 활용하여 24시간 후의 온도를 예측하는 119개의 문제를 함께 해결 가능
- 추가 문제 고려: 하나의 모델을 사용하여 여러 가지 관련된 작업을 동시에 풀 수 있다. 그러나 이는 원래 문제의 해결을 방해할 수 있다.
- 텍스트 생성에서는 과거 토큰을 사용하여 다음 토큰을 예측하는 작업을 수행
- 이를 위해 인코더 없이 디코더만 사용. 즉, 현재까지의 텍스트를 기반으로 다음 단어를 예측
- 이때 디코더는 단어의 수 만큼의 차원을 갖는 코잘 패딩을 활용하여 다음 단어를 예측하게 됨
- 11장에서 만든 구성 요소인 PositionalEmbedding과 TransformerDecoder를 재사용
import tensorflow as tf
from tensorflow.keras import layers
# 입력된 토큰 시퀀스에 위치 정보를 추가하는 레이어
class PositionalEmbedding(layers.Layer):
def __init__(self, sequence_length, input_dim, output_dim, **kwargs):
super().__init__(**kwargs)
# 입력 토큰을 임베딩하는 레이어
self.token_embeddings = layers.Embedding(
input_dim=input_dim, output_dim=output_dim)
# 위치 정보를 임베딩하는 레이어
self.position_embeddings = layers.Embedding(
input_dim=sequence_length, output_dim=output_dim)
self.sequence_length = sequence_length
self.input_dim = input_dim
self.output_dim = output_dim
# 입력 시퀀스에 토큰 임베딩과 위치 임베딩을 더한 결과를 반환
def call(self, inputs):
length = tf.shape(inputs)[-1]
positions = tf.range(start=0, limit=length, delta=1)
embedded_tokens = self.token_embeddings(inputs)
embedded_positions = self.position_embeddings(positions)
return embedded_tokens + embedded_positions
# 입력 시퀀스에서 패딩을 마스킹하는 마스크를 생성
def compute_mask(self, inputs, mask=None):
return tf.math.not_equal(inputs, 0)
def get_config(self):
config = super(PositionalEmbedding, self).get_config()
config.update({
"output_dim": self.output_dim,
"sequence_length": self.sequence_length,
"input_dim": self.input_dim,
})
return config
# 트랜스포머 디코더 계층을 정의하는 클래스
class TransformerDecoder(layers.Layer):
def __init__(self, embed_dim, dense_dim, num_heads, **kwargs):
super().__init__(**kwargs)
self.embed_dim = embed_dim
self.dense_dim = dense_dim
self.num_heads = num_heads
# attention_1, attention_2는 각각 입력 시퀀스에 대한 셀프 어텐션과 인코더 출력에 대한 어텐션을 수행하는 MultiHeadAttention 레이어
self.attention_1 = layers.MultiHeadAttention(
num_heads=num_heads, key_dim=embed_dim)
self.attention_2 = layers.MultiHeadAttention(
num_heads=num_heads, key_dim=embed_dim)
# 어텐션 출력을 밀집 연산하는 Sequential 레이어
self.dense_proj = keras.Sequential(
[layers.Dense(dense_dim, activation="relu"),
layers.Dense(embed_dim),]
)
# layernorm_1, layernorm_2, layernorm3는 각각 레이어 정규화 레이어이다.
self.layernorm_1 = layers.LayerNormalization()
self.layernorm_2 = layers.LayerNormalization()
self.layernorm_3 = layers.LayerNormalization()
self.supports_masking = True
def get_config(self):
config = super(TransformerDecoder, self).get_config()
config.update({
"embed_dim": self.embed_dim,
"num_heads": self.num_heads,
"dense_dim": self.dense_dim,
})
return config
# 인과적 마스크(케이블러티 마스크)를 생성하는 함수
# 인과적 마스크: 현재 위치의 토큰이 미래의 위치에 영향을 미치지 않도록 하는 역할을 함
def get_causal_attention_mask(self, inputs):
input_shape = tf.shape(inputs)
batch_size, sequence_length = input_shape[0], input_shape[1]
i = tf.range(sequence_length)[:, tf.newaxis]
j = tf.range(sequence_length)
mask = tf.cast(i >= j, dtype="int32")
mask = tf.reshape(mask, (1, input_shape[1], input_shape[1]))
mult = tf.concat(
[tf.expand_dims(batch_size, -1),
tf.constant([1, 1], dtype=tf.int32)], axis=0)
return tf.tile(mask, mult)
# 입력, 인코더 출력, 마스크를 입력으로 받아 디코더 계층의 연산을 수행하고 결과를 반환
def call(self, inputs, encoder_outputs, mask=None):
causal_mask = self.get_causal_attention_mask(inputs)
if mask is not None:
padding_mask = tf.cast(
mask[:, tf.newaxis, :], dtype="int32")
padding_mask = tf.minimum(padding_mask, causal_mask)
attention_output_1 = self.attention_1(
query=inputs,
value=inputs,
key=inputs,
attention_mask=causal_mask)
attention_output_1 = self.layernorm_1(inputs + attention_output_1)
attention_output_2 = self.attention_2(
query=attention_output_1,
value=encoder_outputs,
key=encoder_outputs,
attention_mask=padding_mask,
)
attention_output_2 = self.layernorm_2(
attention_output_1 + attention_output_2)
proj_output = self.dense_proj(attention_output_2)
return self.layernorm_3(attention_output_2 + proj_output)
- 간단한 트랜스포머 기반 언어 모델
from tensorflow.keras import layers
# 임베딩 차원, 잠재 차원 및 어텐션 헤드의 수를 정의
embed_dim = 256
latent_dim = 2048
num_heads = 2
# 모델의 입력을 정의. 이 경우 가변 길이의 정수 시퀀스를 입력으로 사용
inputs = keras.Input(shape=(None,), dtype="int64")
# PositionalEmbedding클래스를 사용하여 입력 데이터에 위치 임베딩을 적용
x = PositionalEmbedding(sequence_length, vocab_size, embed_dim)(inputs)
# TransformerDecoder클래스를 사용하여 디코더 레이어를 생성. 인코더 출력을 입력으로 받고, 디코더의 출력을 계산한다.
x = TransformerDecoder(embed_dim, latent_dim, num_heads)(x, x)
# 출력 시퀀스 타임스텝마다 가능한 어휘 사전의 단어에 대해 소프트맥스 확률을 계산한다.
outputs = layers.Dense(vocab_size, activation="softmax")(x)
# 입력과 출력을 연결하여 최종 모델을 생성
model = keras.Model(inputs, outputs)
# 모델을 컴파일한다. 손실 함수로 'sparse_categorical_crossentropy'를 사용하며, 옵티마이저로 rmsprop을 사용
model.compile(loss="sparse_categorical_crossentropy", optimizer="rmsprop")
가변 온도 샘플링을 사용한 텍스트 생성 콜백
- 콜백을 사용하여 에프크가 끝날 때마다 다양한 온도로 텍스트를 생성
- 모델이 수렴하면서 생성된 텍스트가 어떻게 발전하는지와 온도가 샘플링 전략에 미치는 영향을 확인할 수 있음
- 시작 단어로 "this movie"를 사용
- 즉, 이 단어를 시작으로 모든 텍스트를 생성
- 텍스트 생성 콜벡
import numpy as np
# 단어 인덱스를 문자열로 매핑하는 딕셔너리. 텍스트 디코딩에 사용
tokens_index = dict(enumerate(text_vectorization.get_vocabulary()))
# 주어진 확률 분포를 기반으로 온도를 적용하여 다음 단어를 샘플링하는 함수. 온도가 높을수록 더 다양한 샘플링 결과가 나올 수 있다.
def sample_next(predictions, temperature=1.0):
predictions = np.asarray(predictions).astype("float64")
predictions = np.log(predictions) / temperature
exp_preds = np.exp(predictions)
predictions = exp_preds / np.sum(exp_preds)
probas = np.random.multinomial(1, predictions, 1)
return np.argmax(probas)
# 콜백 클래스로, 몯ㄹ의 에포크 종료 시마다 새로운 텍스트를 생성하는 역할을 한다. 생성할 텍스트의 길이, 모델 입력 길이, 샘플링 온도 등을 설정할 수 있다.
class TextGenerator(keras.callbacks.Callback):
def __init__(self,
prompt, # 텍스트 생성을 위한 시작 문장
generate_length, # 생성할 단어 계수
model_input_length,
temperatures=(1.,), # 샘플링에 사용할 온도 범위
print_freq=1):
self.prompt = prompt
self.generate_length = generate_length
self.model_input_length = model_input_length
self.temperatures = temperatures
self.print_freq = print_freq
# 에포크 종료 시 호출된다. 지정된 시작 문장으로부터 모델을 사용하여 텍스트를 생성하고 출력한다. 다양한 온도 값을 사용하여 텍스트를 생성하는 결과를 비교한다.
def on_epoch_end(self, epoch, logs=None):
if (epoch + 1) % self.print_freq != 0:
return
for temperature in self.temperatures:
print("== Generating with temperature", temperature)
# 시작 단어에서부터 텍스트를 생성한다.
sentence = self.prompt
for i in range(self.generate_length):
# 현재 시퀀스를 모델에 주입한다.
tokenized_sentence = text_vectorization([sentence])
predictions = self.model(tokenized_sentence)
# 마지막 타임스텝의 예측을 추출하여 다음 언어를 샘플링한다.
next_token = sample_next(predictions[0, i, :])
sampled_token = tokens_index[next_token]
# 새로운 단어를 현재 시퀀스에 추가하고 반복한다.
sentence += " " + sampled_token
print(sentence)
prompt = "This movie"
# TextGenerator 콜백 클래스의 인스턴스를 생성하여 설정한다. 이 콜백은 모델의 에포크 종료 시마다 주어진 시작 문장으로부터 다양한 온도 값에 대한 텍스트를 생성하고 출력한다.
text_gen_callback = TextGenerator(
prompt,
generate_length=50,
model_input_length=sequence_length,
# 텍스트 샘플링에 다양한 온도를 사용하여 텍스트 생성에 미치는 온도의 영향을 확인
temperatures=(0.2, 0.5, 0.7, 1., 1.5))
- fit() 메서드를 통해 언어 모델 훈련하기
model.fit(lm_dataset, epochs=200, callbacks=[text_gen_callback])
- 다음은 200번 에포크 훈련 후에 생성된 텍스트 중 선별한 것
- 구두점이 어휘 사전에 포함되어 있지 않기 때문에 생성된 텍스트는 모두 구두점을 가지고 있지 않음
temperature=0.2
“this movie is a [UNK] of the original movie and the first half hour of the
movie is pretty good but it is a very good movie it is a good movie for the
time period”
“this movie is a [UNK] of the movie it is a movie that is so bad that it is a
[UNK] movie it is a movie that is so bad that it makes you laugh and cry at
the same time it is not a movie i dont think ive ever seen”
temperature=0.5
“this movie is a [UNK] of the best genre movies of all time and it is not a
good movie it is the only good thing about this movie i have seen it for the
first time and i still remember it being a [UNK] movie i saw a lot of years”
“this movie is a waste of time and money i have to say that this movie was
a complete waste of time i was surprised to see that the movie was made
up of a good movie and the movie was not very good but it was a waste of
time and”
temperature=0.7
“this movie is fun to watch and it is really funny to watch all the characters
are extremely hilarious also the cat is a bit like a [UNK] [UNK] and a hat
[UNK] the rules of the movie can be told in another scene saves it from
being in the back of ”
“this movie is about [UNK] and a couple of young people up on a small boat
in the middle of nowhere one might find themselves being exposed to a
[UNK] dentist they are killed by [UNK] i was a huge fan of the book and i
havent seen the original so it”
temperature=1.0
“this movie was entertaining i felt the plot line was loud and touching but on
a whole watch a stark contrast to the artistic of the original we watched
the original version of england however whereas arc was a bit of a little too
ordinary the [UNK] were the present parent [UNK]”
“this movie was a masterpiece away from the storyline but this movie was
simply exciting and frustrating it really entertains friends like this the actors
in this movie try to go straight from the sub thats image and they make it a
really good tv show”
temperature=1.5
“this movie was possibly the worst film about that 80 women its as weird
insightful actors like barker movies but in great buddies yes no decorated
shield even [UNK] land dinosaur ralph ian was must make a play happened
falls after miscast [UNK] bach not really not wrestlemania seriously sam
didnt exist”
“this movie could be so unbelievably lucas himself bringing our country
wildly funny things has is for the garish serious and strong performances
colin writing more detailed dominated but before and that images gears
burning the plate patriotism we you expected dyan bosses devotion to
must do your own duty and another”
- 낮은 온도는 단조로운 반복적인 텍스트를 생성한다. 이로 인해 생성된 텍스트가 자주 반복되는 현상이 발생할 수 있다.
- 높은 온도에서 생성된 텍스트는 흥미롭고 다양한 견과를 만들어낸다. 예상치 못한 내용이 등장하며 창의성을 발휘할 수 있다.
- 매우 높은 온도에서는 구조가 무너져 랜덤한 출력이 될 수 있다. 이때는 무작위성이 강조되어 예측하기 어려운 텍스트가 생성된다.
- 생성 온도 중에서 적절한 값을 선택하는 것이 중요. 여기에선 0.7 정도의 온도가 적절한 결과를 만들어 내는 것으로 보임
- 다양한 샘플링 전략을 실험해 보는 것이 중요하며, 학습된 구조와 무작위성 사이의 균형을 찾으면 흥미로운 결과를 얻을 수 있음
- 더 많은 데이터와 크고 깊은 모델을 사용하면 더 논리적이고 실제와 비슷한 텍스트를 생성할 수 있음
- 예를 들어 GPT-3와 같은 모델은 더 큰 구조와 다양한 데이터로 훈련되어 있어서 실제와 매우 유사한 텍스트를 생성할 수 있음
- 그러나 이러한 출력은 언어 모델의 통계적인 패턴을 따른 결과임. 언어 모델은 주어진 데이터의 통계를 학습하여 단어를 연속해서 나열하는 것을 수행할 뿐
- 따라서 텍스트의 의미는 언어 모델이 학습한 데이터의 특성을 반영하는 것일 뿐이며 현실적이거나 실체가 있는 것은 아님
- 자연어는 의사소통의 수단이며 세상에 영향을 미치는 도구로서 사용됨. 또한, 사회의 윤활유 역할을 하며 자신의 생각을 체계화하고 저장하며 검색하는 방법으로 활용
- 이러한 다양한 사용은 언어의 의미를 형성하는 기초임. 그러나 딥러닝의 '언어 모델'은 이러한 근본적인 측면을 감지하지 못함
- 언어 모델은 의사소통할 수 없고, 세상에 영향을 미칠 수 없으며, 사회적인 역할을 수행하지 않음. 또한, 단어의 도움으로 처리할 어떤 생각도 가지지 않음.
- 언어는 마음 운영 체제로 적용하기 때문에 언어의 의미가 발생하려면 이를 활용하는 마음의 역할이 필요
- 언어 모델은 사람들이 생성하는 텍스트 데이터의 통계적 구조를 감지하는 역할을 함. 이는 책, 영화 리뷰, 트윗 등과 같은 텍스트 자료들이 어떤 패턴과 구조를 가지고 있는지를 분석하는 것. 이러한 통계적 구조는 사람들이 언어를 사용하는 방식에서 비롯되는 부수적인 특징임
정리
- 이전의 토큰이 주어지면 다음 토큰(들)을 예측하는 모델을 훈련하여 시퀀스 데이터를 생성할 수 있음. 텍스트의 경우 이런 모델을 언어 모델이라고 부름. 단어 또는 글자 단위 모두 가능. 다음 토큰을 샘플링할 때 모델이 만든 출력에 집중하는 것과 무작위성을 주입하는 것 사이에 균형을 맞추어야 함. 이를 위해 소프트맥스 온도 개념을 사용. 항상 다양한 온도를 실험해서 적절한 값을 찾음
'인공지능[AI]' 카테고리의 다른 글
케라스 창시자에게 배우는 딥러닝[12장: 생성 모델을 위한 딥러닝] part3 뉴럴 스타일 트랜스퍼 (0) | 2023.08.11 |
---|---|
케라스 창시자에게 배우는 딥러닝[12장: 생성 모델을 위한 딥러닝] part2 딥드림 (0) | 2023.08.11 |
케라스 창시자에게 배우는 딥러닝[11장: 텍스트를 위한 딥러닝] part4 (0) | 2023.08.03 |
케라스 창시자에게 배우는 딥러닝[11장: 텍스트를 위한 딥러닝] part3 (0) | 2023.08.02 |
케라스 창시자에게 배우는 딥러닝 [11장: 텍스트를 위한 딥러닝] part2 (0) | 2023.08.02 |