728x90
LSTM으로 삼성주식을 예측해보자
Colab을 이용한다. 필요한 라이브러리 다운로드해준다.
!pip install finance-datareader
필요한 import 해주기
# LSTM으로 주식 예측
# 삼성전자 : 코드 005930
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore')
import FinanceDataReader as fdr
데이터 불러오기
STOCK_CODE = '005930'
stock_data = fdr.DataReader(STOCK_CODE)
print(stock_data.head(3))
print(stock_data.shape)
print(stock_data.tail(3))
print(stock_data.index)
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
Open High Low Close Volume Change
Date
1998-04-04 1072 1143 1071 1115 202157 NaN
1998-04-06 1116 1176 1092 1146 312720 0.027803
1998-04-07 1149 1261 1149 1244 480900 0.085515
(6000, 6)
Open High Low Close Volume Change
Date
2022-05-30 67500 67800 66900 67700 14255484 0.018045
2022-05-31 67500 67500 66700 67400 24365002 -0.004431
2022-06-02 66600 67000 66500 66600 9094972 -0.011869
DatetimeIndex(['1998-04-04', '1998-04-06', '1998-04-07', '1998-04-08',
'1998-04-09', '1998-04-10', '1998-04-11', '1998-04-13',
'1998-04-14', '1998-04-15',
...
'2022-05-19', '2022-05-20', '2022-05-23', '2022-05-24',
'2022-05-25', '2022-05-26', '2022-05-27', '2022-05-30',
'2022-05-31', '2022-06-02'],
dtype='datetime64[ns]', name='Date', length=6000, freq=None)
날짜 컬럼을 추가해준다
stock_data['year'] = stock_data.index.year
stock_data['month'] = stock_data.index.month
stock_data['day'] = stock_data.index.day
print(stock_data.head(3))
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
Open High Low Close Volume Change year month day
Date
1998-04-04 1072 1143 1071 1115 202157 NaN 1998 4 4
1998-04-06 1116 1176 1092 1146 312720 0.027803 1998 4 6
1998-04-07 1149 1261 1149 1244 480900 0.085515 1998 4 7
데이터를 시각화로 보기
# 시각화
plt.figure(figsize=(10,6))
sns.lineplot(y=stock_data['Close'], x=stock_data.index)
plt.xlabel('time')
plt.ylabel('price')
plt.show()
연도별 5년씩 나눠서 시각화 그래프로 보기
time_steps = [['2000','2005'],['2005','2010'],['2010','2015'],['2015','2022']]
fig, axes = plt.subplots(2,2)
fig.set_size_inches(10, 6)
for i in range(4):
ax = axes[i//2, i%2]
df = stock_data[(stock_data.index > time_steps[i][0]) & (stock_data.index < time_steps[i][1])]
sns.lineplot(y=df['Close'], x=df.index, ax=ax)
ax.set_title(f'{time_steps[i][0]} ~ {time_steps[i][1]}')
ax.set_xlabel('time')
ax.set_ylabel('price')
plt.tight_layout()
plt.show()
데이터 전처리해준다.
MinMax 정규화 해주기
# 데이터 전처리
# 정규화
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
scale_cols = ['Open','High','Low','Close','Volume']
scaled = scaler.fit_transform(stock_data[scale_cols])
print(scaled)
df = pd.DataFrame(scaled, columns=scale_cols)
print(df.head(3))
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
[[0.01187154 0.01180785 0.01196648 0.00527877 0.00223857]
[0.0123588 0.01214876 0.01220112 0.00562183 0.00346289]
[0.01272425 0.01302686 0.01283799 0.00670636 0.00532522]
...
[0.74750831 0.70041322 0.74748603 0.74214825 0.15785724]
[0.74750831 0.69731405 0.7452514 0.73882827 0.26980438]
[0.73754153 0.69214876 0.74301676 0.72997499 0.10071262]]
Open High Low Close Volume
0 0.011872 0.011808 0.011966 0.005279 0.002239
1 0.012359 0.012149 0.012201 0.005622 0.003463
2 0.012724 0.013027 0.012838 0.006706 0.005325
대량의 데이터를 사용하기 위해 sequential dataset 이용
#tensorflow dataset을 이용해서 sequential dataset을 운영
import tensorflow as tf
def window_dataset_func(series, window_size, batch_size, shuffle_tf):
series = tf.expand_dims(series, axis= -1) # 차원확대
# print(series.shape)
ds = tf.data.Dataset.from_tensor_slices(series) #slice
ds = ds.window(window_size +1, shift=1, drop_remainder=True)
ds = ds.flat_map(lambda w:w.batch(window_size+1)) # Dataset 객체를 객체화
if shuffle_tf:
ds = ds.shuffle(1000)
ds = ds.map(lambda w : (w[:-1], w[-1]))
return ds.batch(batch_size).prefetch(1) # 훈련 속도 증진, 학습 성능 향상
# 대량의 데이터를 메모리에 로딩할 수 없으므로 batch 단위로 읽어 처리하기 위해 준비
WINDOW_SIZE = 20 # 20일 단위로 비교
BATCH_SIZE = 32
# train_data, test_data를 생성
train_data = window_dataset_func(y_train,WINDOW_SIZE,BATCH_SIZE,True)
test_data = window_dataset_func(y_test,WINDOW_SIZE,BATCH_SIZE,False) # test_data는 섞지 않는다.
for data in train_data.take(1):
print('dataset 구성(batch_size, window_size, feature) : ', data[0].shape)
print('dataset 구성(batch_size, window_size, feature) : ', data[1].shape)
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
dataset 구성(batch_size, window_size, feature) : (32, 20, 1)
dataset 구성(batch_size, window_size, feature) : (32, 1)
모델
# 모델
from keras.models import Sequential
from keras.layers import Dense, Conv1D, LSTM
from keras.losses import Huber # cost function의 일종으로 mse 보다 이상치에 덜 민감함
from tensorflow.keras.optimizers import Adam
from keras.callbacks import EarlyStopping, ModelCheckpoint
model = Sequential([
# 1차원 feature map 생성
Conv1D(filters=32, kernel_size=5, padding='causal',
activation='relu', input_shape=[WINDOW_SIZE, 1]), # padding='casual' 모델이 시간 순서를 지켜야하느 경우의 모델 생성
LSTM(16, activation='tanh'),
Dense(16, activation='relu'),
Dense(1)
])
loss = Huber()
optimizer = Adam(learning_rate = 0.0005)
model.compile(optimizer=optimizer, loss=loss, metrics=['mse'])
print(model.summary())
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
Epoch 14/50
150/150 - 4s - loss: 2.1294e-05 - mse: 4.2588e-05 - val_loss: 4.2450e-04 - val_mse: 8.4900e-04 - 4s/epoch - 29ms/step
예측
pred = model.predict(test_data)
print('pred.shape:' , pred.shape)
print('pred:',pred[:10].flatten())
print('real:',np.array(y_test)[:10])
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
pred.shape: (1180, 1)
pred: [0.51625794 0.51122445 0.5073114 0.5053738 0.5048668 0.5052125
0.5059609 0.5070877 0.50846165 0.5095983 ]
real: [0.55335207 0.55556539 0.55445873 0.55954937 0.55822138 0.55578672
0.54626945 0.54449879 0.54405613 0.52148027]
시각화
# 시각화
plt.figure(figsize=(10, 6))
plt.plot(np.asarray(y_test)[20:], label='real')
plt.plot(pred, label='predict')
plt.legend()
plt.show()
728x90
'데이터분석 > 예시코드' 카테고리의 다른 글
RNN : seq2seq로 영어를 한국어로 번역 (0) | 2022.06.07 |
---|---|
네이버 영화 리뷰 데이터로 감성분류 (0) | 2022.06.02 |
웹 스크래핑 : 네이버 영화 평점 (0) | 2022.06.01 |
웹 스크래핑 : 기초 (0) | 2022.05.29 |
RNN을 이용한 텍스트 생성 (0) | 2022.05.27 |