짜리몽땅 매거진
[금융 AI] 금융 투자 영역에서의 AI(4) - 딥러닝을 이용한 투자 전략 본문
트랜스포머를 이용한 주가 방향성 예측
이전 글에서 머신러닝을 이용한 주가 방향성 예측 실습을 진행했다. 이번 장에서는 딥러닝, 특히 트랜스포머 모델을 활용한 주가 방향성 예측 실습을 진행해보려 한다. 트랜스포머 모델은 자연어 처리에서 큰 성과를 거두었지만, 시계열 데이터에서도 효과적으로 사용될 수 있다.
import pandas as pd
import numpy as np
import tensorflow as tf
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
import matplotlib.pyplot as plt
import seaborn as sns
import yfinance as yf
import ta
먼저, 필요한 라이브러리를 불러오고 데이터를 준비한다.
# 데이터 불러오기 (2013년부터 2023년까지 훈련 데이터, 2024년 1월부터 4월까지 테스트 데이터)
train_data = yf.download('AAPL', start='2013-01-01', end='2024-01-01')
test_data = yf.download('AAPL', start='2024-01-01', end='2024-05-01')
# 데이터 전처리 및 피처 엔지니어링
for data in [train_data, test_data]:
data['SMA_10'] = data['Close'].rolling(window=10).mean()
data['RSI'] = ta.momentum.RSIIndicator(data['Close']).rsi()
data.dropna(inplace=True)
# 피처와 타깃 변수 설정
features = ['Open', 'High', 'Low', 'Close', 'Volume', 'SMA_10', 'RSI']
X_train = train_data[features].values
y_train = (train_data['Close'].shift(-1) > train_data['Close']).astype(int).values[:-1]
X_train = X_train[:-1]
X_test = test_data[features].values
y_test = (test_data['Close'].shift(-1) > test_data['Close']).astype(int).values[:-1]
X_test = X_test[:-1]
# 데이터 정규화
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
훈련 데이터 기간에 정해진 답은 없지만, 상승장, 하락장, 대폭락 등 여러 케이스의 정보가 담겨있을 정도로 긴 시계열이 좋다. 따라서 애플(AAPL) 주식 데이터를 2013년부터 2023년까지 수집하여 훈련 데이터로 사용하고, 2024년 1월부터 4월까지의 데이터를 테스트 데이터로 사용할 것이다. 이를 위해 야후 파이낸스(yfinance) 라이브러리를 사용한다. 그리고 불러온 데이터에 이동 평균과 RSI 지표를 추가하여 피처를 생성하고, 결측값을 제거한다.
그 다음으로는 피처와 타깃 변수를 설정한다. 주식 데이터에서 Open, High, Low, Close, Volume, SMA_10, RSI 피처를 사용하고, 타깃 변수는 다음 날의 주가가 상승하는지 여부로 설정한다. 그리고 피처 데이터를 표준화하여 모델의 학습 효율을 높인다. 머신러닝 실습에서 이미 진행한 부분이기 때문에 자세한 설명은 생략하도록 하자.
트랜스포머 모델 정의
# 트랜스포머 모델 정의
def transformer_encoder(inputs, head_size, num_heads, ff_dim, dropout=0):
# 멀티헤드 어텐션
x = tf.keras.layers.MultiHeadAttention(key_dim=head_size, num_heads=num_heads, dropout=dropout)(inputs, inputs)
x = tf.keras.layers.LayerNormalization(epsilon=1e-6)(x)
res = x + inputs
# 피드포워드 네트워크
x = tf.keras.layers.Dense(ff_dim, activation="relu")(res)
x = tf.keras.layers.Dense(inputs.shape[-1])(x)
x = tf.keras.layers.LayerNormalization(epsilon=1e-6)(x)
return x + res
트랜스포머 모델은 지난 글에서 설명했지만, 중요한 모델이기 때문에 한 번 더 짚고 넘어가자. 트랜스포머 모델은 자연어 처리 분야에서 처음 도입되었으나, 시계열 데이터 분석에도 매우 효과적이다. 트랜스포머 모델의 핵심 구성 요소는 멀티헤드 어텐션이다.
어텐션 메커니즘
먼저 어텐션 메커니즘에 대해 이해하는 것이 중요하다. 어텐션 메커니즘은 입력 데이터의 중요한 부분에 가중치를 부여하여 모델이 학습할 때 더 중요한 정보에 집중할 수 있도록 돕는다. 어텐션 메커니즘은 주로 다음과 같은 단계로 이루어진다:
- 쿼리(Query), 키(Key), 값(Value): 입력 데이터는 쿼리, 키, 값 세 가지로 변환된다.
- 어텐션 스코어(Attention Score): 쿼리와 키의 내적을 계산하여 어텐션 스코어를 구한다.
- 어텐션 가중치(Attention Weight): 어텐션 스코어를 소프트맥스 함수에 입력하여 가중치를 구한다.
- 어텐션 출력(Attention Output): 어텐션 가중치와 값의 가중 합을 구하여 최종 출력을 계산한다.
- 어텐션 메커니즘의 주요 아이디어는 중요한 부분에 더 집중하고, 덜 중요한 부분은 덜 집중하는 것이다.
멀티헤드 어텐션
멀티헤드 어텐션(Multi-Head Attention)은 여러 개의 어텐션 메커니즘을 병렬로 사용하여 다양한 표현을 학습할 수 있도록 한다. 각 어텐션 헤드는 서로 다른 부분에 주의를 기울이며, 이를 통해 모델이 더 풍부한 표현을 학습할 수 있다.
멀티헤드 어텐션의 주요 구성 요소는 다음과 같다:
- 헤드(Head): 각 헤드는 독립적인 어텐션 메커니즘을 가지고 있다.
- 병렬 계산(Parallel Computation): 여러 헤드를 병렬로 계산하여 다양한 패턴을 동시에 학습한다.
- 결합(Concatenation): 각 헤드의 출력을 결합하여 최종 출력을 만든다. 멀티헤드 어텐션은 다양한 패턴을 동시에 학습할 수 있게 하여, 모델의 성능을 크게 향상시킨다.
아래 코드에서, 멀티헤드 어텐션은 tf.keras.layers.MultiHeadAttention 레이어를 통해 구현된다. 이 레이어는 입력 데이터의 여러 부분에 주의를 기울여 다양한 패턴을 학습할 수 있도록 한다.
트랜스포머 인코더 정의
트랜스포머 인코더는 멀티헤드 어텐션과 피드포워드 네트워크로 구성된다. 인코더는 입력 데이터를 여러 번 처리하여 최종 출력을 생성한다. 각 레이어는 다음과 같이 구성된다:
- 멀티헤드 어텐션: 입력 데이터의 여러 부분에 동시에 주의를 기울여 중요한 패턴을 학습한다.
- LayerNormalization: 각 레이어의 출력을 정규화하여 학습을 안정화하고 속도를 높인다.
- 피드포워드 네트워크: 각 타임스텝의 출력을 더 복잡한 특징으로 변환한다.
모델 빌드 함수 정의
def build_model(input_shape, head_size, num_heads, ff_dim, num_transformer_blocks, mlp_units, dropout=0, mlp_dropout=0):
inputs = tf.keras.layers.Input(shape=input_shape)
x = inputs
for _ in range(num_transformer_blocks):
x = transformer_encoder(x, head_size, num_heads, ff_dim, dropout)
x = tf.keras.layers.Flatten()(x)
for dim in mlp_units:
x = tf.keras.layers.Dense(dim, activation="relu")(x)
x = tf.keras.layers.Dropout(mlp_dropout)(x)
outputs = tf.keras.layers.Dense(1, activation="sigmoid")(x)
return tf.keras.Model(inputs, outputs)
이제 트랜스포머 인코더를 여러 층 쌓아 트랜스포머 모델을 구성한다. 또한, Flatten 레이어와 MLP(Multi-Layer Perceptron) 레이어를 추가하여 최종 출력을 생성한다. MLP 레이어에 드롭아웃을 적용하여 과적합을 방지한다.
응용 방법
트랜스포머 모델을 사용하여 시계열 데이터를 분석할 때, 다음과 같은 방법으로 모델의 성능을 최적화하고 분석 결과를 향상시킬 수 있다.
첫째, 다양한 하이퍼파라미터를 조정하는 것이 중요하다. 예를 들어, 멀티헤드 어텐션의 헤드 수를 조정함으로써 모델이 데이터를 바라보는 관점을 다양화할 수 있다. 헤드 수를 늘리면 모델이 더 다양한 패턴을 학습할 수 있지만, 계산 비용이 증가한다는 점을 염두에 두어야 한다. 또한, 피드포워드 네트워크의 차원을 조정하여 모델의 복잡성을 조절할 수 있다. 피드포워드 네트워크의 차원을 늘리면 모델이 더 복잡한 패턴을 학습할 수 있지만, 과적합의 위험도 증가한다. 마지막으로, 드롭아웃 비율을 조정하여 모델의 일반화 능력을 향상시킬 수 있다. 드롭아웃 비율을 적절히 조정하면 과적합을 방지하고 모델의 성능을 안정화할 수 있다.
둘째, 데이터 전처리를 통해 모델의 성능을 향상시킬 수 있다. 입력 데이터를 정규화하여 데이터의 스케일을 맞추면 모델이 더 빠르고 안정적으로 학습할 수 있다. 또한, 결측값을 처리하여 데이터의 완전성을 확보하는 것도 중요하다. 결측값이 있는 데이터를 그대로 사용할 경우, 모델의 성능이 저하될 수 있다. 이를 방지하기 위해 결측값을 적절히 처리하는 방법을 고려해야 한다.
셋째, 모델 튜닝을 통해 최적의 하이퍼파라미터를 찾는 과정이 필요하다. 교차 검증을 사용하면 데이터의 특정 부분에만 의존하지 않고 모델의 성능을 평가할 수 있다. 이를 통해 모델이 일반화된 성능을 가지도록 도울 수 있다. 또한, 그리드 서치를 통해 다양한 하이퍼파라미터 조합을 테스트하여 최적의 조합을 찾을 수 있다. 이 과정을 통해 모델의 성능을 최대화할 수 있다.
트랜스포머 모델은 복잡한 시계열 패턴을 효과적으로 학습할 수 있어, 다양한 금융 데이터 분석에 유용하게 사용될 수 있다. 이러한 응용 방법을 통해 트랜스포머 모델을 최적화하고, 이를 바탕으로 다양한 투자 전략을 개발할 수 있다.
모델 컴파일 및 학습
# 모델 생성
input_shape = (X_train.shape[1], 1)
X_train = X_train.reshape((X_train.shape[0], X_train.shape[1], 1))
X_test = X_test.reshape((X_test.shape[0], X_test.shape[1], 1))
model = build_model(
input_shape,
head_size=256,
num_heads=4,
ff_dim=4,
num_transformer_blocks=4,
mlp_units=[128],
mlp_dropout=0.4,
dropout=0.25
)
model.compile(loss="binary_crossentropy", optimizer=tf.keras.optimizers.Adam(learning_rate=1e-4), metrics=["accuracy"])
model.summary()
# 모델 학습 (에포크 수 증가)
history = model.fit(X_train, y_train, validation_split=0.2, epochs=200, batch_size=32)
# 학습 곡선 시각화
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'], label='Train Loss')
plt.plot(history.history['val_loss'], label='Validation Loss')
plt.title('Loss Over Epochs')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'], label='Train Accuracy')
plt.plot(history.history['val_accuracy'], label='Validation Accuracy')
plt.title('Accuracy Over Epochs')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()
plt.show()
트랜스포머 모델을 구축하고, 컴파일한다. 손실 함수로는 binary_crossentropy를 사용하고, 최적화 도구로 Adam 옵티마이저를 사용한다. 200 에포크 동안 모델을 학습시키고, 학습 곡선을 그려서 모델의 학습 상태를 모니터링한다.
학습 곡선을 통해 과적합 여부를 확인할 수 있는데, 출력 결과에서 검증 손실이 거의 일정하므로 과적합이 의심된다. 정규화 기법을 추가하거나 모델의 복잡도를 조정하여 이를 개선할 수 있다.
모델 성능 평가
# 훈련 데이터 결과
y_train_pred = model.predict(X_train)
threshold = y_train.mean() # 훈련 데이터 비율로 트레시홀드 설정
y_train_pred_threshold = (y_train_pred > threshold).astype(int)
accuracy_train = accuracy_score(y_train, y_train_pred_threshold)
conf_matrix_train = confusion_matrix(y_train, y_train_pred_threshold)
print(f"훈련 데이터 정확도: {accuracy_train:.2f}")
print("훈련 데이터 혼동 행렬:")
print(conf_matrix_train)
print("\n훈련 데이터 분류 리포트:")
print(classification_report(y_train, y_train_pred_threshold))
# 테스트 데이터 결과
y_pred = model.predict(X_test)
y_pred_threshold = (y_pred > threshold).astype(int)
accuracy_test = accuracy_score(y_test, y_pred_threshold)
conf_matrix_test = confusion_matrix(y_test, y_pred_threshold)
print(f"테스트 데이터 정확도: {accuracy_test:.2f}")
print("테스트 데이터 혼동 행렬:")
print(conf_matrix_test)
print("\n테스트 데이터 분류 리포트:")
print(classification_report(y_test, y_pred_threshold))
훈련 데이터와 테스트 데이터에서의 성능을 평가한 결과, 훈련 데이터의 정확도는 53% 정도, 테스트 데이터의 정확도는 68% 정도이다. 이는 테스트 데이터가 상승장에 편향되어 있기 때문일 수 있다. 따라서 실제로 '정확도'가 아닌 수익률을 봐야 한다. 또한 벤치마크 지표가 필요하다. 예를 들어 buy and hold 전략이 벤치마크가 될 수 있고, S&P 500 지수 추종이 벤치마크가 될 수 있다.
트랜스포머 모델을 사용한 주가 방향성 예측 실습을 통해, 시계열 데이터에서의 패턴 인식과 예측의 가능성을 확인할 수 있었다. 그러나 실전에서는 다양한 정규화 기법과 모델 튜닝이 필요하며, 최종적인 목표는 정확도가 아닌 투자 수익률임을 항상 염두에 두어야 한다.
'Data > Financial AI' 카테고리의 다른 글
[금융 AI] AI 기반의 신용 리스크 모델링(1) (1) | 2025.03.08 |
---|---|
[금융 AI] 금융 투자 영역에서의 AI(3) - 머신러닝을 이용한 투자 전략 (0) | 2025.02.17 |
[금융 AI] 금융 투자 영역에서의 AI(2) - 전통 퀀트 구현 (0) | 2025.02.08 |
[금융 AI] 금융 투자 영역에서의 AI(1) (0) | 2025.02.02 |
[금융 AI] 금융 AI의 주요 활용 분야(2) (0) | 2025.01.27 |