~학습에 적합한 형태로 변환하다 : 전처리 과정~ 스톡잇! 개발기 #3

2025. 12. 18. 02:52·모의투자
"왜 학습에 적합한 형태로 변환 하는 전처리 과정을 할까?"

지난 글에서 저는 “정답이 없는 주식 분류 문제”를 해결하기 위해 클러스터링(K-means) 을 선택했습니다.

그리고 한국투자증권 API로부터

  • 시가총액
  • PER
  • PBR
  • ROE
  • 부채비율
  • 배당수익률

총 6개 지표를 기반으로 3,619개 종목 데이터를 수집했죠.

이제 남은 건 단 하나였습니다.

“이 데이터를 AI가 학습할 수 있는 형태로 바꾸기”

하지만…
막상 데이터를 열어보니 현실은 달랐습니다.


문제 1 : 이 모든 데이터에는 ‘쓰레기 정보’가 많았다

3,619개는 “전체 주식 데이터”입니다.
즉, 기업만 있는 게 아니었습니다.

여기에는

  • ETF
  • 인버스
  • ETN
  • SPAC(기업인수목적회사)

같은 금융상품들도 섞여 있었습니다.

문제는 얘네가 “기업”이 아니라는 점입니다.

ETF나 ETN은 회사가 아니라 상품이기 때문에 PER / PBR / ROE / 배당수익률 같은 값이 대부분

  • 0.0 이거나
  • 의미 없는 값

으로 찍히는 경우가 많았습니다.

이런 데이터는 AI 학습을 방해시킵니다.


해결방법 1 :   ETF / 인버스 / 스팩 제거 [1차 정제]

그래서 저는 먼저 학습 대상이 아닌 종목들을 제거했습니다.

기준은 단순합니다.

  • 6개 지표가 모두 정상 범위(>0)인 기업만 남기기
  • 종목명에 아래 키워드가 포함되면 제거
    (인버스, 스팩, ETN, TIGER, KODEX, HANARO ...)

그리고 재무적으로도 말이 안 되는 값들을 제거했습니다.

  • PER이 음수인 종목 (ex: KR모터스 PER -2.21)
  • 부채비율이 0.0인 종목
  • ROE가 0.0인 종목
feature_columns = ['시가총액', 'per', 'pbr', 'ROE', '부채비율', '배당수익률']

df = df_raw.copy()
for col in feature_columns:
    df = df[df[col] > 0]

 

결과는 놀랍게도 3,619개 → 937개 로 줄였습니다.

 

3,619개 → 937개

여기서 “너무 적은가?” 싶을 수 있는데 이건 정상입니다.

오히려 AI 입장에서는 아주 좋은 환경입니다. (Garbage In, Garbage Out)

Garbage In, Garbage Out (GIGO)란?

Garbage In, Garbage Out은
컴퓨터 과학과 머신러닝에서 아주 유명한 원칙입니다.

뜻은 단순합니다.

“쓰레기를 넣으면, 쓰레기가 나온다.”

즉,

  • 입력 데이터가 엉망이면
  • 아무리 좋은 알고리즘을 써도
  • 결과 역시 엉망이 될 수밖에 없다는 의미입니다.

왜 그럴까? 

머신러닝 모델은 사람처럼 “이게 이상한 데이터네?”라고 판단하지 않습니다.

모델은 오직 값만 봅니다. 데이터가 말이 안 되더라도 “그게 현실을 반영하는 값”이라고 믿고 학습합니다.

그래서 전처리 과정이 매우 중요한 이유입니다. 

문제 2 : 학습을 돌리자 극단치로 인해 경고가 터졌다

K-means 학습 과정에서 이런 경고가 떴습니다.

RuntimeWarning: divide by zero encountered in matmul (0으로 나누기)
RuntimeWarning: overflow encountered in matmul (숫자가 너무 커서 폭발)

이건 한 가지를 의미합니다.

>0 필터로도 걸러지지 않은 극단치(outlier) 가 남아있다!

결과를 확인해보니 골고루가 아니라 한군데에만 데이터가 군집화된 것을 확인할 수 있었습니다. 


극단치(outlier)는 왜 위험한가?

초등학생 한 반 키 평균을 낸다고 해봅시다.

29명은 120~140cm인데 딱 1명이 키 60m짜리 거인이라면?

 

이 반의 평균 키는 약 3.32m 가 나옵니다.

즉, 단 한 명 때문에 “스케일링”도 “거리 계산”도 전부 망가지게 됩니다.

제가 본 overflow는 딱 그 상황이었습니다.


해결방법 2 : 상/하위 5% 극단치 제거 [2차정제]

저는 937개 데이터 안에서 각 지표별로 상위 5%, 하위 5%를 제거했습니다.

for col in feature_columns:
    q_low = df[col].quantile(0.05)
    q_high = df[col].quantile(0.95)
    df = df[(df[col] >= q_low) & (df[col] <= q_high)]

 

  • PER로 줄 세워 하위 5%, 상위 5%의 극단치 제거
  • 남은 종목으로 PBR도 같은 방식 적용
  • 이걸 6개 지표에 대해 반복

이 과정이 끝나면 비정상적으로 크거나 작은 값(진격의 거인과 앤트맨)이 제거됩니다.

그 결과 500개의 "학습 가능한 데이터"만 남았습니다.

단계 종목 수 내용
원본 3,619개 전체 주식 데이터
1차 정제 937개 0 이하 값 제거 (ETF/스팩/적자기업)
2차 정제 500개 6개 지표별 상/하위 5% 극단치 제거

 

 


스케일링(Scaling)으로 학습용 벡터 만들기

이제 진짜 “학습 가능한 데이터”만 남았지만 바로 K-Means를 돌릴 수는 없습니다.

지표들의 단위와 크기가 제각각이기 때문입니다.

시가총액은 조 단위, ROE와 부채비율은 %, PER과 PBR은 한 자리 숫자 수준입니다.

K-means는 거리(distance) 를 기준으로 군집을 나누는 알고리즘이기 때문에,
이 상태로 학습을 시키면 값이 큰 지표(시가총액) 가
다른 모든 지표를 압도해버립니다.

그래서 모든 지표를 같은 기준선에서 비교 가능하도록 맞춰주는 작업, 즉 스케일링(Scaling) 이 필요합니다.

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
features_scaled = scaler.fit_transform(df[feature_columns])

이 과정을 거치면 각 기업은 더 이상 “숫자 덩어리”가 아니라,

AI가 거리 계산을 할 수 있는 하나의 벡터(vector)

로 변환됩니다.

스케일링까지 마친 뒤, 다음 단계(클러스터링 학습)를 위해 결과물을 파일로 저장했습니다.

np.save('features_scaled.npy', features_scaled)
stock_info.to_csv('stock_info.csv', index=False, encoding='utf-8')

import joblib
joblib.dump(scaler, 'scaler.pkl')

 

 각 파일의 역할은 다음과 같습니다.

  • features_scaled.npy
    → K-means가 학습할 숫자 벡터 데이터
  • stock_info.csv
    → 각 벡터가 어떤 종목인지 매칭해주는 정보
  • scaler.pkl
    → 나중에 새로운 종목이나 사용자 포트폴리오를 같은 기준으로 변환하기 위한 ‘번역기’

이 단계에서는 아직 학습을 하지 않는다

여기까지의 과정에서 AI는 아직 아무런 판단도 하지 않았습니다.

  • ❌ 군집 없음
  • ❌ 그룹 번호 없음
  • ❌ 우량주 / 성장주 같은 의미 없음

이 파일들은 아직 “결과”가 아닙니다.

 바꿔준 것 단지 AI가 “판단할 수 있는 형태”로 데이터를 바꾼 재료일 뿐입니다.

 



지금까지는 오직 전처리만 했습니다. 

다음 글에서는 “숫자만 보고 주식을 나누다: K-means 클러스터링 과정”에 대해 다뤄보겠습니다.

'모의투자' 카테고리의 다른 글

~숫자를 언어로 번역하다 : 태깅~ 스톡잇! 개발기 #5  (1) 2025.12.26
~숫자만 보고 주식을 나누다: K-means 클러스터링 과정~ 스톡잇! 개발기 #4  (0) 2025.12.25
~정답이 없는 주식 분류 문제, 왜 클러스터링을 선택했을까?~ 스톡잇! 개발기 #2  (0) 2025.12.18
~3,619개의 주식, if문(Rule-Base)으로 분류할 수 있을까?~ 스톡잇! 개발기 #1  (1) 2025.12.17
~Prologue: 투기가 아닌 투자의 길~ 스톡잇! 개발기#0  (1) 2025.12.11
'모의투자' 카테고리의 다른 글
  • ~숫자를 언어로 번역하다 : 태깅~ 스톡잇! 개발기 #5
  • ~숫자만 보고 주식을 나누다: K-means 클러스터링 과정~ 스톡잇! 개발기 #4
  • ~정답이 없는 주식 분류 문제, 왜 클러스터링을 선택했을까?~ 스톡잇! 개발기 #2
  • ~3,619개의 주식, if문(Rule-Base)으로 분류할 수 있을까?~ 스톡잇! 개발기 #1
MacArthur17
MacArthur17
Mac(Arthur)hine Learning
  • MacArthur17
    Human Learning LAB
    MacArthur17
  • 전체
    오늘
    어제
    • 분류 전체보기 (67)
      • 모의투자 (32)
      • 분산 시스템 (2)
      • 테커 부트캠프 (20)
      • 백준문제 (24)
      • 공부일기 (0)
      • 후기 (3)
      • 팁 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
MacArthur17
~학습에 적합한 형태로 변환하다 : 전처리 과정~ 스톡잇! 개발기 #3
상단으로

티스토리툴바