728x90
RNN을 이용한 텍스트 생성 : 문맥을 반영해서 다음 단어를 예측하고 텍스트를 생성하기
데이터
from keras.preprocessing.text import Tokenizer
from keras.utils import pad_sequences, to_categorical
import numpy as np
from keras.layers import Embedding, Dense, LSTM, Flatten
from keras.models import Sequential
text = """경마장에 있는 말이 뛰고 있다
그의 말이 법이다
가는 말이 고와야 온는 말이 곱다"""
인덱싱
# word indexing
tok = Tokenizer()
tok.fit_on_texts([text]) #list type
encoded = tok.texts_to_sequences([text])[0] #list type
vocab_size = len(tok.word_index) + 1 # 원핫 처리, embedding에 사용
훈련 데이터 만들기
sequences = list()
for line in text.split('\n'): #문장 토큰화
enco = tok.texts_to_sequences([line])[0]
print(enco)
# 바로 다음 단어를 label로 사용하기 위해
for i in range(1, len(enco)):
sequ = enco[:i+1]
print(sequ) # [2, 3]...
sequences.append(sequ)
print('학습에 참여할 샘플 수 :%d'%len(sequences)) #11
print(sequences) #[[2, 3], [2, 3, 1], [2, 3, 1, 4], ..
print(max(len(i) for i in sequences)) # 모든 벡터 중에서 가장 길이가 긴 값 출력
# 전체 각가의 벡터의 길이를 통일
max_len = max(len(i) for i in sequences)
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
학습에 참여할 샘플 수 :11
[[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]]
6
패딩 채우기
# 패딩채우기
psequences = pad_sequences(sequences, maxlen=max_len, padding='pre')
print(psequences)
# 각 벡터의 마지막 요소(단어)를 레이블로 사용하기 위해 분리
x = psequences[:,:-1] #feature
y = psequences[:, -1] #label
print(x)
print(y)
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
[[ 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]]
[[ 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]]
[ 3 1 4 5 1 7 1 9 10 1 11]
원핫 처리
# 레이블을 원핫 처리
y = to_categorical(y, num_classes=vocab_size)
print(y[:2])
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
[[0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]]
모델
# model
model = Sequential()
model.add(Embedding(vocab_size, 32, input_length=max_len-1))
model.add(LSTM(32, activation ='tanh'))
model.add(Flatten()) # FClayer
model.add(Dense(32, activation='relu'))
model.add(Dense(32, activation='relu'))
model.add(Dense(vocab_size, activation='softmax'))
print(model.summary())
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding (Embedding) (None, 5, 32) 384
lstm (LSTM) (None, 32) 8320
flatten (Flatten) (None, 32) 0
dense (Dense) (None, 32) 1056
dense_1 (Dense) (None, 32) 1056
dense_2 (Dense) (None, 12) 396
=================================================================
Total params: 11,212
Trainable params: 11,212
Non-trainable params: 0
_________________________________________________________________
None
컴파일
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(x, y, epochs=200, verbose=2)
print('model.evaluate', model.evaluate(x, y))
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
Epoch 200/200
1/1 - 0s - loss: 0.0091 - accuracy: 1.0000 - 2ms/epoch - 2ms/step
1/1 [==============================] - ETA: 0s - loss: 0.0090 - accuracy: 1.0000
1/1 [==============================] - 0s 333ms/step - loss: 0.0090 - accuracy: 1.0000
model.evaluate [0.008973545394837856, 1.0]
문자열 생성 함수 만들기
# 문자열 생성 함수
def sequence_gen_text(model, t, current_word, n):
init_word = current_word
sentence = ''
for _ in range(n):
encoded = t.texts_to_sequences([current_word])[0]
encoded = pad_sequences([encoded], maxlen=max_len-1, padding='pre') # 패딩
result = np.argmax(model.predict(encoded, verbose=0),axis=-1)
# 예측단어 찾기
for word, index in t.word_index.items():
#print(word, index)
if index == result:
break
current_word = current_word +' '+word
sentence = sentence+' '+ word
sentence = init_word + sentence
return sentence
print(sequence_gen_text(model, tok, '경마', 1))
print(sequence_gen_text(model, tok, '그의', 2))
print(sequence_gen_text(model, tok, '가는', 3))
print(sequence_gen_text(model, tok, '경마장에', 4))
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
경마 말이
그의 말이 법이다
가는 말이 고와야 온는
경마장에 있는 말이 뛰고 있다
728x90
'데이터분석 > 예시코드' 카테고리의 다른 글
웹 스크래핑 : 네이버 영화 평점 (0) | 2022.06.01 |
---|---|
웹 스크래핑 : 기초 (0) | 2022.05.29 |
CountVectorizer, TfidfVectorizer (0) | 2022.05.26 |
word2vec (0) | 2022.05.26 |
회귀 분석 (0) | 2022.05.04 |