본문 바로가기
경제 금융 포털사이트 경제 금융 포털사이트

파이썬 주가예측 정확도 믿어도 될까? AI 과적합 확인하는 방법

금알남 읽는 시간 약 15분
ai thumbnail photography 파이썬 주가예측 정확도 믿어도 될까 AI 과적합 확인하는 방법 1790239037

AI 주가예측 모델에서 정확도가 높게 나왔다고 해서 바로 좋은 모델이라고 섣부르게 판단하기는 어렵습니다. 특히 주식 시장처럼 시계열 데이터 다룰 때는 과거와 미래 데이터를 어떻게 나눴는지, 미래의 정보가 학습 과정에 모르게 섞이지 않았는지를 꼼꼼히 확인해야 합니다. 만약 데이터 분리가 제대로 이루어지지 않았다면 실제 투자에서는 낭패를 보기 십상입니다. 아래 글에서는 이러한 AI 과적합의 위험성과 안전한 시계열 검증 방법을 알기 쉬운 파이썬 예제와 함께 자세히 정리해 두었으니 꼭 한번 살펴보시기 바랍니다.

주가예측 정확도가 높으면 정말 좋은 AI일까?

뉴스 감성점수도 만들었고, FinBERT도 연결했고 LSTM까지 돌려봤고, 그런데 주가 상승과 하락을 예측하는 정확도가 생각보다 높게 나왔다면 기분이 좋죠.

“드디어 제대로 된 AI 주가예측 모델을 만든 것 아닐까?”

하지만 여기서 가장 먼저 확인해야 하는 것은 정확도 숫자가 아닙니다.

이 모델이 미래 앞으로도 잘 작동할건가?

이 질문을 먼저 해야 합니다. 과거 데이터에 지나치게 맞춰진 상태를 머신러닝에서는 과적합, Overfitting이라고 부릅니다. 시험문제와 정답을 모두 외운 학생에게 똑같은 시험지를 다시 주면 높은 점수를 받을 수 있습니다.

하지만 처음 보는 문제가 나오면 결과는 완전히 달라질 수 있습니다. 주가예측 AI도 마찬가지입니다.

우리가 원하는 것은 과거 차트를 잘 외우는 모델이 아니라 앞으로 들어올 새로운 데이터에서도 일정한 판단력을 유지하는 모델입니다.

파이썬 주가예측에서 랜덤 분할을 조심해야 하는 이유

일반적인 머신러닝에서는 데이터를 Train과 Test로 나누어 모델을 평가합니다. 예를 들어 전체 데이터의 80%로 학습하고 나머지 20%로 평가하는 방식입니다. 그런데 주가는 일반적인 표 데이터와 다른 특징이 있습니다.

바로 시간의 순서입니다.

2024년 데이터를 이용해 2025년을 예측하는 것은 가능합니다. 하지만 2026년 정보를 이용해서 2024년 시장을 예측하는 상황은 실제 투자에서는 존재할 수 없습니다.

그래서 데이터를 무작위로 섞어 나누는 방식은 주가예측에서는 주의해야 합니다.

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(
    X,
    y,
    test_size=0.2,
    shuffle=True
)

코드 자체가 잘못된 것은 아닙니다.

하지만 시간순서가 중요한 주식 데이터를 분석하면서 shuffle=True로 데이터를 섞으면 실제 투자환경과 다른 검증이 될 수 있습니다.

파이썬 주가예측 정확도 믿어도 될까? AI 과적합 확인하는 방법

가장 기본적인 방법은 시간순으로 나누는 것입니다

먼저 가장 간단한 방법부터 시작할 수 있습니다.

split = int(len(data) * 0.8)

train = data.iloc[:split]
test = data.iloc[split:]

전체 데이터가 날짜순으로 정렬되어 있다면 과거 80%로 학습하고 이후 20%를 미래 데이터처럼 테스트할 수 있습니다.

이 방식은 랜덤 분할보다 실제 투자환경과 가까워집니다. 하지만 여기에도 문제가 있습니다. 학습기간과 테스트기간을 단 한 번만 나누기 때문입니다.

예를 들어 상승장에서 학습하고 비슷한 상승장에서 테스트하면 결과가 좋을 수 있습니다. 반대로 횡보장이나 급락장에서는 성능이 크게 달라질 수도 있습니다.

그래서 주가예측 모델은 여러 시점으로 이동하면서 반복적으로 확인하는 방법이 필요합니다.

Walk-Forward로 AI 과적합 확인하기

여기서 사용하는 것이 Walk-Forward Validation입니다.

이름은 어렵지만 원리는 간단합니다.

  1. 과거 데이터로 학습합니다.
  2. 바로 다음 기간에서 테스트합니다.
  3. 시간이 지나면 새로운 데이터를 학습구간에 추가합니다.
  4. 다시 그 이후 데이터를 테스트합니다.
  5. 이 과정을 반복합니다.

예를 들면 다음과 같습니다.

1차
학습 : 2021~2022
검증 : 2023년 초

2차
학습 : 2021~2023년 초
검증 : 2023년 중반

3차
학습 : 2021~2023년 중반
검증 : 2023년 후반

4차
학습 : 2021~2023년 후반
검증 : 2024년

이렇게 하면 특정 기간에서만 우연히 잘 맞은 모델인지, 시간이 지나도 어느 정도 성능이 유지되는지를 확인하기 쉬워집니다.

파이썬으로 시계열 검증 직접 해보기

앞선 글에서 만든 데이터셋을 그대로 사용할 수 있습니다.

예를 들어 다음과 같은 컬럼이 있다고 가정하겠습니다.

date
return
volume_change
volatility20
sentiment_mean
news_count
target

target은 다음 거래일 상승이면 1, 그렇지 않으면 0으로 만든 값입니다.

import pandas as pd
import numpy as np

from sklearn.model_selection import TimeSeriesSplit
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import (
    accuracy_score,
    f1_score,
    roc_auc_score
)

data = pd.read_csv(
    "ai_stock_dataset.csv",
    parse_dates=["date"]
)

data = (
    data.sort_values("date")
    .dropna()
    .reset_index(drop=True)
)

features = [
    "return",
    "volume_change",
    "volatility20",
    "sentiment_mean",
    "news_count"
]

X = data[features]
y = data["target"]

tscv = TimeSeriesSplit(
    n_splits=5,
    gap=1
)

results = []

for fold, (train_idx, test_idx) in enumerate(
    tscv.split(X),
    start=1
):

    X_train = X.iloc[train_idx]
    X_test = X.iloc[test_idx]

    y_train = y.iloc[train_idx]
    y_test = y.iloc[test_idx]

    scaler = StandardScaler()

    X_train_scaled = scaler.fit_transform(
        X_train
    )

    X_test_scaled = scaler.transform(
        X_test
    )

    model = LogisticRegression(
        max_iter=1000,
        random_state=42
    )

    model.fit(
        X_train_scaled,
        y_train
    )

    pred = model.predict(
        X_test_scaled
    )

    prob = model.predict_proba(
        X_test_scaled
    )[:, 1]

    accuracy = accuracy_score(
        y_test,
        pred
    )

    f1 = f1_score(
        y_test,
        pred,
        zero_division=0
    )

    if y_test.nunique() > 1:
        auc = roc_auc_score(
            y_test,
            prob
        )
    else:
        auc = np.nan

    results.append({
        "fold": fold,
        "accuracy": accuracy,
        "f1": f1,
        "roc_auc": auc
    })

result_df = pd.DataFrame(results)

print(result_df)
print(result_df.mean(numeric_only=True))

여기에서는 설명을 쉽게 하기 위해 Logistic Regression을 사용했습니다.

하지만 핵심은 어떤 알고리즘을 사용했느냐가 아닙니다.

LSTM, GRU, Random Forest, XGBoost 등으로 바꾸더라도 과거로 학습하고 이후 미래구간에서 평가한다는 원칙은 같습니다.

정확도가 실제보다 좋아지는 데이터 누수도 확인하세요

AI 주가예측을 만들면서 놓치기 쉬운 것이 데이터 누수입니다.

대표적인 예가 정규화입니다.

다음 코드를 보겠습니다.

scaler.fit_transform(X_train)

Train 데이터로만 평균과 표준편차 등을 계산합니다.

그리고 Test 데이터에는

scaler.transform(X_test)

만 적용합니다.

왜 이렇게 해야 할까요?

전체 데이터를 먼저 정규화하면 미래 Test 데이터의 정보가 정규화 과정에 미리 반영될 수 있기 때문입니다.

겉으로 보기에는 사소한 차이지만 이런 부분들이 쌓이면 백테스트 정확도가 실제보다 좋아 보일 수 있습니다.

뉴스 감성분석에서도 마찬가지입니다.

장 마감 이후 발표된 뉴스를 그날 가격을 예측하는 변수로 사용한다면 모델이 당시 투자자가 알 수 없었던 미래정보를 사용하게 됩니다.

따라서 AI 주가예측에서는 모델 구조만큼 정보가 실제로 언제 공개됐는가를 확인해야 합니다.

평균 정확도만 보면 놓치는 것이 있습니다

예를 들어 Walk-Forward 결과가 다음과 같다고 해보겠습니다.

Fold 1 : 0.56
Fold 2 : 0.52
Fold 3 : 0.50
Fold 4 : 0.47
Fold 5 : 0.51

반대로 다른 모델은 다음과 같다고 해보겠습니다.

Fold 1 : 0.53
Fold 2 : 0.54
Fold 3 : 0.52
Fold 4 : 0.54
Fold 5 : 0.53

평균 정확도만 비교하면 큰 차이가 없어 보일 수 있습니다.

하지만 두 번째 모델은 여러 기간에서 상대적으로 비슷한 결과를 보입니다.

그래서 AI 투자모델에서는 최고 정확도 하나보다 여러 시장환경에서 결과가 얼마나 유지되는지 확인하는 것이 중요합니다.

그리고 정확도뿐 아니라 다음 지표들도 함께 봐야 합니다.

  1. Precision
  2. Recall
  3. F1 Score
  4. ROC-AUC
  5. 거래비용 반영 수익률
  6. 최대낙폭 MDD
  7. 실제 매매 횟수

특히 투자에서는 예측 정확도가 조금 높다고 실제 수익률까지 높아진다고 단정할 수 없습니다.

파이썬 코드를 그대로 사용해도 될까?

네. 위 코드는 필요한 라이브러리가 설치되어 있고 ai_stock_dataset.csv 파일에 예시와 같은 컬럼이 준비되어 있다면 실행 가능한 기본 구조입니다.

다만 개인이 만든 데이터셋의 컬럼명, target 정의, 예측기간에 따라 일부 수정은 필요합니다.

예를 들어 다음 거래일을 예측하는 모델과 일주일 후 수익률을 예측하는 모델은 데이터 분할 방법이나 gap 설정이 달라질 수 있습니다. 따라서 바로 실전매매에 연결하기보다는 먼저 Train과 Test 날짜를 출력해 시간순으로 제대로 나뉘었는지 확인해보는 것이 좋습니다.

좋은 주가예측 AI는 검증을 견디는 모델입니다

LSTM 층을 더 쌓고 Transformer를 붙이고 FinBERT 감성점수까지 추가하는 것은 기술적으로 가능합니다. 하지만 모델이 복잡해질수록 과거 데이터에 지나치게 맞춰질 가능성도 함께 살펴봐야 합니다.

Apple AAPL에서 잘 맞았다고 NVIDIA NVDA에서도 같은 성능이 나온다고 볼 수 없습니다. 상승장에서 잘 맞은 AI가 하락장에서도 동일하게 작동한다고 단정할 수도 없습니다.

그래서 AI 주가예측 모델을 만들 때는 모델 생성 → 과거 데이터 테스트 → 과적합 확인 → Walk-Forward 검증 → 새로운 기간 재검증 과정을 반복하는 것이 중요합니다.

정확도가 몇 퍼센트인지 확인하는 것도 필요하지만 그보다 먼저 물어볼 질문이 있습니다.

“이 정확도는 실제 미래 데이터에서도 반복될 수 있는 결과인가?”

이 질문을 통과하지 못한 모델이라면 아무리 백테스트 숫자가 좋아 보여도 한 번 더 검증해볼 필요가 있습니다.

자주 묻는 질문

Q1. Walk-Forward를 사용하면 과적합을 완전히 막을 수 있나요?

아닙니다. Walk-Forward 자체가 과적합을 없애주는 것은 아닙니다. 다만 새로운 미래구간을 반복적으로 검증하기 때문에 특정 기간에만 잘 맞는 모델을 발견하는 데 도움이 됩니다.

Q2. LSTM 주가예측 모델도 이렇게 검증할 수 있나요?

가능합니다. 각 Fold마다 LSTM 모델과 scaler를 새로 생성하고 Train 구간에서 학습한 뒤 이후 Test 구간에서 평가하면 됩니다. 다만 단순 머신러닝 모델보다 학습시간이 길어질 수 있습니다.

Q3. 주가예측 정확도는 몇 퍼센트가 나와야 좋은 것인가요?

정확도 하나만으로 좋은 모델의 기준을 정하기는 어렵습니다. 상승·하락 비율, 거래빈도, 손익비, 거래비용, 시장환경에 따라 같은 정확도라도 의미가 달라질 수 있습니다. 실제 미래구간에서의 일관성과 위험 대비 성과를 함께 확인해야 합니다.

금융소비자 및 투자 유의사항

본 글은 Python과 인공지능을 이용한 금융 데이터 분석 및 모델 검증 방법을 설명하기 위한 교육·정보 제공 자료이며 특정 주식, ETF, 가상자산 또는 금융상품의 매수·매도를 권유하기 위한 내용이 아닙니다.

Apple(AAPL), NVIDIA(NVDA) 등의 종목명은 분석 방법 설명을 위한 예시이며 특정 종목의 향후 상승 또는 하락을 의미하지 않습니다.

AI 모델의 예측값과 과거 백테스트 결과는 미래 투자성과를 보장하지 않습니다. 주식·ETF·가상자산 등은 시장 상황에 따라 손실이 발생할 수 있으므로 실제 투자 결정은 투자자의 재무상황, 투자목적 및 위험수용능력을 고려해 판단해야 합니다.

실제 금융상품 상담 및 광고에 활용하는 경우 게시 전 소속 회사의 광고심의 기준과 관련 법규를 확인하시기 바랍니다.

금알남

금알남
함께 보면 좋은 글

댓글 0

첫 댓글을 남겨보세요.

광고 차단 알림

광고 클릭 제한을 초과하여 광고가 차단되었습니다.

단시간에 반복적인 광고 클릭은 시스템에 의해 감지되며, IP가 수집되어 사이트 관리자가 확인 가능합니다.