3. 학습 모델을 불러와 말 출력하기

2023. 9. 16. 16:20개인 프로젝트/📚 자연어 처리

from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing.sequence import pad_sequences
import numpy as np
import pandas as pd

from tensorflow.keras.preprocessing.text import Tokenizer

df = pd.read_csv('output_홍길동.csv')
Text = []
# 헤드라인의 값들을 리스트로 저장
Text.extend(list(df.Text.values))
print('총 샘플의 개수 : {}'.format(len(Text)))

Text = [word for word in Text if word != "ㅋ"]
print('노이즈값 제거 후 샘플의 개수 : {}'.format(len(Text)))


tokenizer = Tokenizer()
tokenizer.fit_on_texts(Text)
vocab_size = len(tokenizer.word_index) + 1
print('단어 집합의 크기 : %d' % vocab_size)


sequences = list()

for sentence in Text:

    # 각 샘플에 대한 정수 인코딩
    encoded = tokenizer.texts_to_sequences([sentence])[0]
    for i in range(1, len(encoded)):
        sequence = encoded[:i+1]
        sequences.append(sequence)

print(sequences[:11])


# 정수에 할당된 단어 찾기
index_to_word = {}
for key, value in tokenizer.word_index.items():
    index_to_word[value] = key

print('빈도수 상위 1번 단어 : {}'.format(index_to_word[1]))

max_len = max(len(l) for l in sequences)
# max_len = 24
print('샘플의 최대 길이 : {}'.format(max_len))


# 모델 로드
loaded_model = load_model('my_model.keras')


def sentence_generation(model, tokenizer, current_word, n):
    init_word = current_word
    sentence = ''

    for _ in range(n):
        encoded = tokenizer.texts_to_sequences([current_word])[0]
        encoded = pad_sequences([encoded], maxlen=max_len-1, padding='pre')

        result = model.predict(encoded, verbose=0)
        result = np.argmax(result, axis=1)

        for word, index in tokenizer.word_index.items():
            if index == result:
                break

        current_word = current_word + ' ' + word
        sentence = sentence + ' ' + word

    sentence = init_word + sentence
    return sentence


# 시작 단어와 생성할 단어 수 설정
seed_text = '코로나'
num_words_to_generate = 12

# 텍스트 생성
generated_text = sentence_generation(
    loaded_model, tokenizer, seed_text, num_words_to_generate)

print("="*50)
print(f"max_len: {max_len}, tokenizer: {tokenizer}")
print(generated_text)

  소스코드 전문입니다. 전 게시글에서 설명한 코드의 대부분을 재활용하였기에 부가설명없이 결과를 보여드리겠습니다.

 


결과1

  '그래서' 라는 말을 시작으로 6가지 길이의 단어를 생성했을 때 위와 같은 말을 생성하였습니다. 혹시 가지고 있는 데이터에서 위와 똑같은 문장이 있는지 확인을 했는 결과...

결과1 - 유사 문장 발견

  가장 유사한 문장을 하나 발견하였습니다. 그러나 완벽하게 똑같지는 않으나 유사도가 높은 면을 보면 어떤 과정으로 학습이 되는지 잘 나타내는 모습임을 알 수 있습니다.

 


결과2

  친구 이름을 넣고 문장을 생성하였습니다. 당시 친구가 하던 게임을 그대로 적는 것을 보면서 꽤나 재미를 느낍니다. 혹시 비슷한 문장을 말한 적이 있는지 확인했으나 발견하지 못했습니다. 워낙 많이 불러서 그런지 잘 학습이 된 듯 합니다.

 


결과3

  이번에는 '미드'를 넣고 문장을 생성했습니다. 그랬더니 위와 같이 생성하는 것을 보면 놀랍기 그지 없습니다. 한편으로는 제가 이런 말을 했던 것처럼 기시감을 느껴 찾아보았으나 똑같은 말을 한 적이 없었습니다... 그럼에도 위와 같은 말을 생성하는 것을 보면서 게임 이야기는 많이 줄여야겠구나 하고 느끼게 되네요.

 


개선점은 크게 세 가지 있습니다.

 

  • 학습이 잘 된 케이스가 아니다.

  위에서 적지는 않았으나 정확도가 높지 않습니다. 이와 관련해서는 추후에 다시 게시글을 적을 예정입니다. 짧게 요약하자면 낮은 반복 학습과, 적은 분량의 학습 데이터가 문제이며, 이것을 야기하게 된 컴퓨터 사양의 문제가 크다고 생각됩니다.

 

  • 헛소리 현상이 심하다.

  위에서 보여드린 결과 화면에서는 절제하여 보여드렸으나, 문장 생성 길이를 늘릴 수록 헛소리하는 현상이 심했습니다. 또한 1만 개의 데이터를 사용했다보니 맥락이 없는 글을 적기도 했습니다.

결과4 - 헛소리 현상. 실제로 담원 서포터는 이런 템을 가지 않을 겁니다.

 

  • 재사용된 코드가 있다.

  처음에 학습 모델을 저장할 때, max_len이나 tokenizer같은 변수들도 같이 저장되는 줄 알았습니다. 이는 오개념이었으며, 이후에 모델을 사용할 때 csv파일로부터 다시 계산해야 했기에 이미 사용된 코드를 다시 사용하는 일이 생겼습니다. 나중에 이 변수들은 따로 저장할 수 있게 해야겠습니다.