Note

RNN을 이용한 텍스트 생성 1 본문

Deep Learning/NLP

RNN을 이용한 텍스트 생성 1

알 수 없는 사용자 2022. 5. 24. 23:01
728x90

첫 번째 문장 : 경마장에 있는 말이 뛰고 있다

두 번째 문장 :  그의 말이 법이다

세 번째 문장 : 가는말이 고와야 오는 말이 곱다

1. X : 경마장에 Y: 있는

2. X : 경마장에 있는 Y : 말이

3. X : 경마장에 있는 말이 Y : 뛰고

4. X : 경마장에 있는 말이 뛰고 Y : 있다

5. X : 그의 Y : 말이

6. X : 그의 말이 Y : 법이다

7. X : 가는 Y : 말이

8. X : 가는 말이 Y : 고와야

9. X : 가는 말이 고와야 Y : 오는

10. X : 가는 말이 고와야 오는 Y : 말이

11. X : 가는 말이 고와야 오는 말이 Y : 곱다

1 ~ 11번은 모델이 문맥을 학습하기 위해 문장의 앞의 단어들을 전부 고려하여 학습하도록 데이터를 재구성한 모습.

import numpy as np
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.utils import to_categorical

text = """경마장에 있는 말이 뛰고 있다\n
그의 말이 법이다\n
가는 말이 고와야 오는 말이 곱다\n"""
tokenizer = Tokenizer()
tokenizer.fit_on_texts([text])
vocab_size = len(tokenizer.word_index) + 1 # 패딩 0을 고려하여 + 1
print('단어 집합의 크기 : %d' % vocab_size) # 출력 결과 12
print(tokenizer.word_index)

# 출력 결과
{'말이': 1, '경마장에': 2, '있는': 3, '뛰고': 4, '있다': 5, '그의': 6, '법이다': 7, '가는': 8, '고와야': 9, '오는': 10, '곱다': 11}

훈련 데이터 생성

sequences = list()
for line in text.split('\n'): 
    encoded = tokenizer.texts_to_sequences([line])[0]
    for i in range(1, len(encoded)):
        sequence = encoded[:i+1]
        sequences.append(sequence)

print('학습에 사용할 샘플의 개수: %d' % len(sequences)) # 출력 결과 11
print(sequences)

# 출력 결과
[[2, 3], [2, 3, 1], [2, 3, 1, 4], [2, 3, 1, 4, 5], [6, 1], [6, 1, 7], [8, 1], [8, 1, 9], [8, 1, 9, 10], [8, 1, 9, 10, 1], [8, 1, 9, 10, 1, 11]]

 [2, 3]은 [경마장에, 있는]에 해당

[2, 3, 1]은 [경마장에, 있는, 말이]에 해당

전체 훈련 데이터에 대해서 맨 우측에 있는 단어(Y)에 대해서만 레이블로 분리해야 한다.

max_len = max(len(l) for l in sequences) # 모든 샘플에서 길이가 가장 긴 샘플의 길이 출력
print('샘플의 최대 길이 : {}'.format(max_len)) # 결과 출력 6
sequences = pad_sequences(sequences, maxlen=max_len, padding='pre')

pad_sequences()는 모든 샘플에 대해서 0을 사용하여 길이를 맞춰준다.

padding의 인자로 'pre'를 주면 길이가 6보다 짧은 샘플의 앞에 0으로 채운다.

print(sequences)

# 결과 출력
[[ 0  0  0  0  2  3]
 [ 0  0  0  2  3  1]
 [ 0  0  2  3  1  4]
 [ 0  2  3  1  4  5]
 [ 0  0  0  0  6  1]
 [ 0  0  0  6  1  7]
 [ 0  0  0  0  8  1]
 [ 0  0  0  8  1  9]
 [ 0  0  8  1  9 10]
 [ 0  8  1  9 10  1]
 [ 8  1  9 10  1 11]]
# 맨 오른쪽 값(Y)에 대한 분리
sequences = np.array(sequences)
X = sequences[:,:-1]
y = sequences[:,-1]

 

print(X)

# 결과 출력
[[ 0  0  0  0  2]
 [ 0  0  0  2  3]
 [ 0  0  2  3  1]
 [ 0  2  3  1  4]
 [ 0  0  0  0  6]
 [ 0  0  0  6  1]
 [ 0  0  0  0  8]
 [ 0  0  0  8  1]
 [ 0  0  8  1  9]
 [ 0  8  1  9 10]
 [ 8  1  9 10  1]]
 
 print(Y)
 
 # 결과 출력
 [ 3  1  4  5  1  7  1  9 10  1 11]
# 원-핫 인코딩
y = to_categorical(y, num_classes=vocab_size)
print(y)

# 결과 출력
[[0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0.] # 3에 대한 원-핫 벡터
 [0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.] # 1에 대한 원-핫 벡터
 [0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0.] # 4에 대한 원-핫 벡터
 [0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0.] # 5에 대한 원-핫 벡터
 [0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.] # 1에 대한 원-핫 벡터
 [0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0.] # 7에 대한 원-핫 벡터
 [0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.] # 1에 대한 원-핫 벡터
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0.] # 9에 대한 원-핫 벡터
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0.] # 10에 대한 원-핫 벡터
 [0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.] # 1에 대한 원-핫 벡터
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1.]] # 11에 대한 원-핫 벡터

'Deep Learning > NLP' 카테고리의 다른 글

한글, 영어 구분 함수  (0) 2022.06.16
RNN을 이용한 텍스트 생성 2  (0) 2022.05.25
Py-Hanspell  (0) 2022.05.15
PyKoSpacing  (0) 2022.05.11
FastText (패스트텍스트)  (0) 2022.05.08
Comments