지난 포스트 (2020/09/04 - [머신러닝 with Python/텍스트마이닝 with Python] - Keras 를 이용한 텍스트마이닝 with Python)에서 학습했던 모델을 이용하여 삼성전자의 뉴스를 학습한 뒤 "삼성전자의 주가 전망"에 대한 예측을 진행해보았다. 아래 첨부된 뉴스크롤링 파일(005930.txt)를 다운받아 파이썬 스크립트의 같은 경로에 저장하고 아래의 코드를 돌리면 삼성전자의 주가 전망은 "초 긍정적인 긍정적인 상황이라고 미 2일 현지시간 보도했다 보도했다 보도했다" 라고 예측된 문장(아래의 코드에 predict함수)이 나오게 된다.
문맥이 상당히 매끄럽지 못하다. 뭐 얼핏 봐서는 그런데로 향후 주가전망은 좋을 것이다라는 점을 추측할 수는 있겠지만 동사를 여러번 반복했다. 이것의 가장 큰 원인은 뭘까? 그렇다. 저기서 max_word를 10단어로 한정했기 때문이다. 물론 이 외에도 뉴스를 크롤링하다보면 쓸데없는 특수문자, 기호 등이 많이 포함되어 있는 점도 중요한 원인 중의 하나일 것이다.
그렇다면 이러한 것들을 해결할 수 있는 방법이 없을까? 있다. 일반적으로는 RNN은 시퀀스의 길이가 정해져 있다고 가정하고 분석한다. 그러나 문장이 매번 10개의 단어로 딱 떨어질 수 없다. 그래서 padding 처리를 해서 가중치를 확 없앤다거나 했지만 이것 역시 완벽한 솔루션은 아니다.
그래서 이것을 해결하기 위해 최근에는 Dynamic RNN 신경망을 이용해서 이러한 문제를 해결하기 위한 시도를 했고 그 결과 역시 꽤나 의미있는 성과를 거두고 있다. 이 부분은 다음 포스트에서 한번 다루어보자.
import matplotlib.pyplot as plt
import requests
import random
import tensorflow as tf
import pymysql
import numpy as np
import os
from keras.layers import *
from keras.models import *
from keras.callbacks import *
from keras.utils import *
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
from collections import Counter
from wordcloud import WordCloud
max_word = 10
stock_code = "005930"
stock_name = "삼성전자"
for i in range(1):
file="./"+str(stock_code)+".txt"
text=""
textarr=[]
with open(file, encoding="utf8") as f:
lines=f.readlines()
text = text.join(lines)
for t in text.split("\n"):
textarr.append(t)
textarr=np.array(textarr)
# 케라스 문서 : https://keras.io/ko/preprocessing/text/
# 각 텍스트를 (딕셔너리 내 하나의 정수가 한 토큰의 색인 역할을 하는) 정수 시퀀스로,
# 혹은 단어 실셈이나 tf-idf 등을 기반으로 각 토큰의 계수가 이진인 벡터로 변환하여 말뭉치를 벡터화할 수 있도록 해줍니다.
# filter : 쓸데없는 특수기호는 다 제거한다.
token=Tokenizer(lower=False, split=' ', filters='!@#$%^&*()[]<>,.?\"\'■…▶·◆‘’◇“”ⓒ【】=@<b></b>quot;apos')
# 각 단어의 인덱스를 구축
token.fit_on_texts(textarr)
# 문자열을 정수 인덱스의 리스트로 변환
seq = token.texts_to_sequences(textarr)
# 문장 길이를 동일하게 만들기 위한 패딩
seq = pad_sequences(seq,maxlen=max_word)
print(seq.shape)
# 신경망에 입력하기 위한 차원변환
X = seq
Y = np.vstack((X[1:],X[0]))
X = X.reshape(-1,max_word,1)
Y = Y.reshape(-1,max_word,1)
# 원/핫 인코딩으로 변환
Y = to_categorical(Y)
model = Sequential()
model.add( LSTM(128, return_sequences=True, input_shape=(max_word,1))) # it can be changed by LSTM
model.add( LSTM(256, return_sequences=True))
model.add( Dense(len(token.word_index)+1, activation="softmax")) # len(token.word_index) -> Depending on the time step, an error may occur cause of eliminate special character
model.summary()
model.compile( loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"])
path=str("./models/"+str(stock_code))
saved=path+'.hdf5'
if os.path.isfile(saved):
print("ok")
model.load_weights(saved)
textpredict=[]
textpredict.append(str(stock_name) + " 주가 전망")
prearr=np.array(textpredict)
#allocate numeric number instead of text in textarray
seqpre = token.texts_to_sequences(prearr)
#Padding to make sentence lengths equal
seqpre = pad_sequences(seqpre,maxlen=max_word)
X_pre = seqpre
X_pre = X_pre.reshape(-1,max_word,1)
pred=model.predict(X_pre)
print(pred) # 1-hot encoding result
pred=np.argmax(pred,axis=2)
print(pred)
idx_word={}
for w in token.word_index:
idx_word[token.word_index[w]]=w
word_list=[]
temp =""
for l in pred:
for w in l:
if w !=0:
temp += idx_word[w]
word_list.append(idx_word[w])
temp += " "
print(temp)
print(word_list)
print(Counter(word_list))
wordcloud = WordCloud(font_path="c:/windows/fonts/malgun.ttf",
background_color="white",
width=500,
height=300)
print(dict(Counter(word_list)))
cloud = wordcloud.generate_from_frequencies(dict(Counter(word_list)))
plt.figure(figsize=(10,8))
plt.axis("off")
plt.imshow(cloud)
plt.show()
'실전머신러닝' 카테고리의 다른 글
KNN, 나이브베이즈 분류를 이용해서 종목분석하기 (0) | 2020.11.10 |
---|---|
머신러닝 개요 with R (0) | 2020.11.06 |
신경망분석(Neural Net) with R - 실전편 (0) | 2020.09.10 |
신경망분석(Neural Net) with R - 이론편 (0) | 2020.09.10 |
Keras 를 이용한 텍스트마이닝 with Python (0) | 2020.09.04 |
댓글