The Relationship between news and stocks 15
2022. 8. 3. 23:47ㆍProject/뉴스기사로 인한 주가 등락 예측
728x90
반응형
LSTM
- LSTM에서는 출력, 입력, 삭제 게이트라는 3개의 게이트가 존재했
- GRU는 LSTM보다 학습 속도가 빠르다고 알려져있지만 여러 평가에서 GRU는 LSTM과 비슷한 성능을 보인다고 알려져 있음
- GRU와 LSTM 중 어떤 것이 모델의 성능면에서 더 낫다라고 단정지어 말할 수 없으며, 기존에 LSTM을 사용하면서 최적의 하이퍼파라미터를 찾아낸 상황이라면 굳이 GRU로 바꿔서 사용할 필요는 없음
- 데이터 양이 적을 때는 매개 변수의 앵이 적은 GRU가 조금 더 낫고, 데이터 양이 더 많으면 LSTM이 더 낫다고도 함
양방향 RNN모델 구성
- 출력값에 대한 손실을 최소롸하는 과정에서 모든 파라미터를 동시에 학습되는 종단간 학습 가능
- 단어와 구간 유사성을 입력벡터에 내재화하여 성능 개선
- 데이터 길이가 길어도 성능이 저하되지 않음
코드
필요 라이브러리 설치
%pip install gensim --upgrade
%pip install -U keras-tuner
%pip install pymysql
라이브러리 불러오기
import IPython
import keras_tuner as kt
from tensorflow import keras
from tensorflow.keras.models import Sequential, load_model
from tensorflow.keras.layers import Embedding, Dense, LSTM, Bidirectional
from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
import tensorflow as tf
import pandas as pd
import numpy as np
import pymysql
MySQL 연동
conn = pymysql.connect(
user = 'stocks',
passwd = 'Stocks!',
host = "-",
port = 3306,
db = 'Data',
charset = 'utf8'
)
데이터 불러오기
sql = 'SELECT stock_id, text, date, token, label FROM Token'
news = pd.read_sql(sql, conn)
news
데이터 전처리 - token열을 Str -> List로 변환
import re
def str_to_list(d):
text = re.sub(r'[\[\'\]]', '', d)
return text.split(", ")
news["token"] = news.token.apply(str_to_list)
데이터 전처리 - 불용어 처리
from tqdm import tqdm
def stopword(x):
stopword = [r'상승.*', r'하락.*', r'급등.*', r'급락.*', '상승세', '하락세', '폭등', '폭락', '오름세', '약세', '강세', '의', '가', '이', '은', '들', '는', '좀', '잘', '걍', '과', '도', '를', '으로', '자', '에', '와', '한', '하다', '에', '은', '는', '하']
return [i for i in x if i not in stopword and not i.isdigit()]
tqdm.pandas()
news["token"] = news.token.progress_apply(stopword)
news
모델링 - 데이터 셋 나누기
test = news.loc[news["date"] >= '2022-07-01 00:00:00']
train = news.loc[news["date"] < '2022-07-01 00:00:00']
X_train = train['token']
y_train = train['label']
X_test = test['token']
y_test = test['label']
모델링 - Tokenizer
tokenizer = Tokenizer()
tokenizer.fit_on_texts(X_train)
threshold = 4
words_cnt = len(tokenizer.word_index)
rare_cnt = 0
words_freq = 0
rare_freq = 0
for key, value in tokenizer.word_counts.items():
words_freq += value
if value < threshold:
rare_cnt +=1
rare_freq += value
print("전체 단어 수", words_cnt)
print("빈도가 {} 이하인 희귀 단어 수: {}".format(threshold-1, rare_cnt))
print("희귀 단어 비율: {}".format((rare_cnt / words_cnt) * 100))
print("희귀 단어 등장 빈도 비율: {}".format((rare_freq / words_freq) * 100))
'''
전체 단어 수 62463
빈도가 3 이하인 희귀 단어 수: 18802
희귀 단어 비율: 30.101019803723805
희귀 단어 등장 빈도 비율: 0.07036167954849475
'''
vocab_size = words_cnt - rare_cnt + 2
tokenizer = Tokenizer(vocab_size, oov_token='OOV')
tokenizer.fit_on_texts(X_train)
X_train = tokenizer.texts_to_sequences(X_train)
X_test = tokenizer.texts_to_sequences(X_test)
y_train = np.array(y_train)
y_test = np.array(y_test)
drop_train = [index for index, sentence in enumerate(X_train) if len(sentence) < 1]
X_trian = np.delete(X_train, drop_train, axis=0)
y_train = np.delete(y_train, drop_train, axis=0)
print('리뷰 최대 길이:', max(len(l) for l in X_train))
print('리뷰 평균 길이:', sum(map(len, X_trian)) / len(X_train))
'''
리뷰 최대 길이: 5759
리뷰 평균 길이: 489.9088054952696
'''
import matplotlib.pyplot as plt
plt.style.use('seaborn-white')
plt.hist([len(s) for s in X_train], bins=50)
plt.xlabel('Length of Samples')
plt.ylabel('Number of Samples')
plt.show()
모델링 - Padding
max_len = 800
X_train = pad_sequences(X_train, maxlen=max_len)
X_test = pad_sequences(X_test, maxlen=max_len)
모델링 - BI-LSTM
model = Sequential()
model.add(Embedding(vocab_size, 800))
model.add(Bidirectional(LSTM(32, return_sequences = True, dropout = 0.4)))
model.add(Bidirectional(LSTM(224)))
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer = keras.optimizers.Nadam(learning_rate = 0.001),
loss = keras.losses.BinaryCrossentropy(),
metrics = ['accuracy'])
model.summary()
es = EarlyStopping(monitor = 'val_loss', mode = 'min', verbose = 1, patience = 3)
mc = ModelCheckpoint('BiLSTM_best_model.h5', monitor = 'val_accuracy', mode = 'max', verbose = 1, save_best_only = True)
history = model.fit(X_train, y_train, epochs=10, validation_split = 0.2, callbacks=[es, mc], batch_size = 128)
loaded_model = load_model('BiLSTM_best_model.h5')
loaded_model.evaluate(X_test, y_test)
728x90
반응형
'Project > 뉴스기사로 인한 주가 등락 예측' 카테고리의 다른 글
The Relationship between news and stocks 17 (0) | 2022.08.05 |
---|---|
The Relationship between news and stocks 16 (0) | 2022.08.03 |
The Relationship between news and stocks 14 (0) | 2022.08.02 |
The Relationship between news and stocks 13 (0) | 2022.07.29 |
The Relationship between news and stocks 12 (0) | 2022.07.28 |