Content
1. 데이터 수집
2. 데이터 전처리 : 결측치 처리 및 데이터 정규화
3. 모델 생성: LSTM 모델을 활용한 학습.
4. 모델 학습 및 평가: 학습된 모델로 테스트 데이터 예측
5. 결과 시각화: 실제 주가와 예측 주가 비교!
import yfinance as yf
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropout
# 1. 데이터 수집: 삼성전자 주가 다운로드 (2013년 ~ 2024년)
data = yf.download("005930.KQ", start="2013-01-01", end="2024-12-31")
# 2. 데이터 전처리: 종가 데이터만 사용하고 정규화 수행
close_data = data[['Close']]
scaler = MinMaxScaler(feature_range=(0, 1)) # 0과 1 사이로 정규화
scaled_data = scaler.fit_transform(close_data)
# 3. 시계열 데이터 생성 함수
def create_dataset(data, time_step=60):
X, Y = [], []
for i in range(len(data) - time_step - 1):
X.append(data[i:i + time_step, 0])
Y.append(data[i + time_step, 0])
return np.array(X), np.array(Y)
time_step = 60 # 60일치 데이터를 기반으로 예측
X, Y = create_dataset(scaled_data)
# 데이터 차원 조정
X = X.reshape(X.shape[0], X.shape[1], 1)
# 4. 훈련/테스트 데이터 분리
train_size = int(len(X) * 0.8)
X_train, X_test = X[:train_size], X[train_size:]
Y_train, Y_test = Y[:train_size], Y[train_size:]
# 5. LSTM 모델 구성
model = Sequential()
model.add(LSTM(50, return_sequences=True, input_shape=(time_step, 1)))
model.add(Dropout(0.2))
model.add(LSTM(50, return_sequences=False))
model.add(Dropout(0.2))
model.add(Dense(1)) # 예측할 종가 값
model.compile(optimizer='adam', loss='mean_squared_error')
# 6. 모델 학습 (학습 시간 단축을 위해 Epoch을 10으로 설정)
model.fit(X_train, Y_train, epochs=10, batch_size=32, validation_data=(X_test, Y_test))
# 7. 마지막 60일 데이터로 2025년 1년간의 주가 예측 수행
last_60_days = scaled_data[-time_step:]
X_input = last_60_days.reshape(1, time_step, 1) # (1, 60, 1) 형태로 변환
predicted_prices = []
for _ in range(365): # 2025년 365일 예측
next_price = model.predict(X_input, verbose=0) # 다음 날 예측
predicted_prices.append(next_price[0, 0]) # 예측된 값 저장
# 새로운 예측 값을 (1, 1, 1) 형태로 변환
next_price_reshaped = next_price.reshape(1, 1, 1)
# 입력 데이터 업데이트 (마지막 59개 값 + 새로운 예측 값)
X_input = np.append(X_input[:, 1:, :], next_price_reshaped, axis=1)
# 8. 정규화 해제 (원래 가격 범위로 변환)
predicted_prices = scaler.inverse_transform(np.array(predicted_prices).reshape(-1, 1))
# 9. 미래 날짜 생성 (2025년 1월 1일부터 12월 31일까지)
future_dates = pd.date_range(start="2025-01-01", periods=365)
# 10. 예측 결과를 DataFrame으로 정리
predicted_df = pd.DataFrame(predicted_prices, columns=['Predicted Price'], index=future_dates)
# 11. y축을 한화(KRW)로 포맷하는 함수
def krw_format(x, _):
return f"₩{int(round(x, -1)):,}"
# 12. 그래프 시각화
plt.figure(figsize=(12, 6))
plt.plot(predicted_df.index, predicted_df['Predicted Price'], label='Predicted Stock Price (2025)', color='blue')
plt.xlabel('Date')
plt.ylabel('Stock Price (KRW)')
plt.title('Samsung Stock Price Prediction (2025)')
plt.legend()
# y축에 한화(KRW) 형식으로 표시
ax = plt.gca()
ax.yaxis.set_major_formatter(plt.FuncFormatter(krw_format))
# 그래프 표시
plt.show()
예측 근거와 메커니즘
1. LSTM 모델의 역할
- LSTM은 시계열 데이터(주가처럼 시간에 따라 변화하는 데이터)에서 과거 패턴을 학습하는 데 유리한 모델이야.
- 이 모델은 과거 일정 기간(여기선 60일)의 주가 데이터를 학습하고, 이전 데이터의 변화 추이를 바탕으로 다음 주가를 예측해.
LSTM 예측 과정 요약:
- 60일 간의 과거 데이터를 입력으로 사용.
- 과거 주가의 패턴을 학습하여 추세를 파악.
- 각 날의 예측을 다음 날 입력으로 사용하여 미래의 주가를 점진적으로 예측.
2. 학습 데이터의 근거
- 이 모델은 2013년부터 2024년까지의 삼성전자 주가 데이터를 사용.
- 학습 과정에서 모델은 주가의 상승/하락 패턴, 변동성 등을 이해하려고 시도.
- LSTM은 특히 주가의 장기적인 추세와 단기적인 변동성을 모두 포착하려고 .
3. 모델의 한계
- 외부 요인 반영의 어려움:
- 이 모델은 과거 주가 데이터만을 사용하므로 금리, 환율, 정치적 사건 같은 외부 요인은 반영되지 않아.
- 실제 주가는 여러 외부 요인에 크게 영향을 받기 때문에 예측이 한계가 있을 수 있어.
- 데이터 패턴 의존성:
- 과거와 다른 패턴이 나타나면 예측의 정확도가 크게 떨어질 수 있다.
- 예를 들어, 갑작스러운 경제 위기나 기술 혁신 같은 이벤트는 모델이 미리 예측하기 어렵다.
- 장기 예측의 불확실성:
- 주가의 단기 예측은 어느 정도 정확할 수 있지만, 1년 이상 장기 예측에서는 불확실성이 크다
자 그러면 하나 하나 코드를 뜯어보며 공부를 해보자!
라이브러리 정리
- yfinance: 주식 데이터를 불러오기 위해 사용.
- numpy: 배열 연산을 쉽게 해주는 라이브러리.
- pandas: 데이터를 다루기 쉽게 해주는 라이브러리.
- matplotlib: 시각화를 위한 라이브러리.
- MinMaxScaler: 데이터 정규화를 위해 사용.
- Sequential, LSTM, Dense, Dropout: 딥러닝 모델(LSTM)을 만들기 위해 필요한 모듈
2. 데이터 수집: 삼성전자 주가 데이터 다운로드
- yf.download: 삼성전자(종목 코드: 005930.KQ)의 2013년부터 2024년까지의 주가 데이터를 불러옴.
- start, end로 기간을 지정.
3. 종가 데이터만 사용하고 정규화 수행
- close_data: 주식의 종가만 사용.
- MinMaxScaler: 주가 데이터를 0~1 사이로 스케일링하여 LSTM 모델이 학습하기 쉽게 만듦.
- 정규화는 모델 학습을 더 잘하게 하는 데 도움을 줌.
4. 시계열 데이터 생성 함수 정의
- create_dataset: 주가 데이터를 슬라이딩 윈도우 방식으로 60일 단위로 묶음.
- X: 60일 간의 데이터를 입력으로 사용.
- Y: 다음 날의 종가를 예측할 목표 값으로 사용.
5. 시계열 데이터 생성
- time_step = 60: 60일 동안의 데이터를 사용해 다음 날을 예측하도록 설정.
6. 데이터 차원 조정
- LSTM은 (samples, time_steps, features) 형식의 데이터를 요구하기 때문에 데이터 차원을 조정.
7. 훈련/테스트 데이터 분리
- 데이터를 80%는 훈련용, 20%는 테스트용으로 나눔.
8. LSTM 모델 구성
- LSTM 레이어 2개를 사용.
- 첫 번째 LSTM 레이어는 return_sequences=True로 다음 레이어에 전체 시퀀스를 전달.
- 두 번째 LSTM 레이어는 마지막 값만 전달.
- Dropout(0.2): 과적합 방지를 위해 일부 노드를 무작위로 비활성화.
- Dense(1): 하나의 종가 값 예측.
9. 모델 컴파일
- Adam 최적화 알고리즘 사용.
- 손실 함수로 **Mean Squared Error(MSE)**를 사용해 예측과 실제 값의 차이를 최소화.
10. 모델 학습
- 10번(Epochs) 동안 모델 학습.
- batch_size=32: 매번 32개의 샘플씩 학습.
- validation_data를 사용해 테스트 데이터를 평가.
11. 마지막 60일 데이터로 2025년 주가 예측
- 마지막 60일 데이터를 기반으로 2025년 주가를 예측하기 위한 입력 데이터 생성.
12. 2025년 1년간(365일) 주가 예측
- 매일 하나씩 2025년 1월 1일부터 12월 31일까지 예측.
13. 정규화 해제
- 정규화된 값을 원래 주가 범위로 변환.
14. 예측 결과를 DataFrame으로 정리
- **미래 날짜(2025년)**와 예측된 주가를 DataFrame으로 정리.
15. y축을 한화(KRW)로 포맷하는 함수 정의
- ₩ 기호와 천 단위 콤마를 추가해 한화 형식으로 포맷.
16. 그래프 시각화
- 예측된 주가를 시각화하고, y축에 한화(KRW) 형식을 적용.
결과
- 이 코드는 LSTM 모델을 사용해 2025년 1년간의 주가를 예측하고 시각화합니다.
- 주가를 예측할 때 마지막 60일 데이터를 사용하여 매일 하나씩 예측합니다.
오늘 공부하면서 느낀점:
LSTM(long-short term memory)모델은 시계열 데이터를 다룰 때 자주 사용된다. 주가 예측 처럼 시간에 따라 변화하는 데이터를 분석하기에 적합하다. 하지만 LSTM에는 장단이 존재하는데
LSTM의 장점과 단점 요약
장점 단점
| 장기 의존성 학습 가능 | 높은 계산 비용 |
| 기울기 소실 문제 해결 | 훈련 시간이 길다 |
| 시계열 및 순차 데이터에 적합 | 과적합 가능성 |
| 다양한 응용 분야에 사용 가능 | 모델 설계와 튜닝이 어려움 |
| 장기 예측에서 정확도가 떨어질 수 있음 |
결론
LSTM은 시계열 데이터나 순차 데이터 처리에 매우 강력한 도구이지만, 복잡성과 긴 훈련 시간이 단점으로 작용합니다. 특히 주가 예측과 같이 외부 요인이 많이 작용하는 데이터에서는 한계가 있을 수 있습니다. 그래서 **외부 변수(금리, 유가 등)**를 함께 사용하는 다중변수 모델을 시도해보는 것도 좋은 방법!!
'Coding study > python' 카테고리의 다른 글
| 2024-10-14 (0) | 2024.10.14 |
|---|---|
| 2024-10-11 파이썬으로 운동일지 만들어보기!(1) (4) | 2024.10.11 |
| 2024-10-10 코딩테스트 입문 공부 (1) | 2024.10.10 |
| 2024-10-10 list dictionary tuple function (0) | 2024.10.10 |
| 2024-10-09 Python 라이브러리로 데이터 분석하기 (1) | 2024.10.09 |