[머신러닝] 주식 종목 추천 시스템 - (3) 데이터 전처리 & k-NN 모델 최근접 이웃 찾기

2024. 8. 14. 19:11데이터 사이언스

주식 종목 추천 시스템을 만들 때 필요한 데이터 전처리와
k-NN모델을 이용하여 최근접 이웃을 찾고,
최근접 이웃 호출 및 추천 주식 반환에 대해 알아보도록 하겠습니다.

필요한 라이브러리 임포트

import pandas as pd
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer

수치형 특성 리스트 정의

num_features = ['marketCap', 'dividendYield', 'payoutRatio', 'beta', 'trailingPE', 'averageVolume', 'profitMargins',
                'heldPercentInsiders', 'heldPercentInstitutions', 'bookValue', 'priceToBook', 'pegRatio',
                'enterpriseToEbitda', '52WeekChange', 'recommendationMean', 'numberOfAnalystOpinions', 'totalCash',
                'totalDebt', 'quickRatio', 'currentRatio', 'totalRevenue', 'returnOnAssets', 'revenueGrowth',
                'grossMargins', 'ebitdaMargins', 'operatingMargins']
  • num_features = [...]:수치형 특성(컬럼)들의 이름을 포함하는 리스트를 정의

범주형 특성 리스트 정의

cat_features = ['industry', 'sector']
  • cat_features = [...]: 범주형 특성(컬럼)들의 이름을 포함하는 리스트를 정의

수치형 변환기 파이프라인 정의

num_transformer = Pipeline(steps=[
    ('imputer', SimpleImputer(strategy='mean')),
    ('scaler', StandardScaler())
])
Pipeline(steps=[...])
  • Pipeline 클래스를 사용하여 여러 전처리 단계를 순차적으로 적용할 수 있도록 합니다.
  • steps는 각 단계의 이름과 객체를 포함하는 튜플 리스트입니다.
('imputer', SimpleImputer(strategy='mean'))
  • SimpleImputer 객체를 imputer 단계로 추가합니다.
  • strategy='mean'는 결측치를 평균값으로 대체하도록 설정합니다.
('scaler', StandardScaler())
  • StandardScaler 객체를 scaler 단계로 추가합니다.
  • 수치형 데이터를 표준화(평균을 0, 분산을 1로)합니다.

범주형 변환기 정의

cat_transformer = OneHotEncoder(handle_unknown='ignore')
  • OneHotEncoder(handle_unknown='ignore')
    • OneHotEncoder 객체를 생성합니다.
    • handle_unknown='ignore'는 데이터에 없는 새로운 범주가 있을 경우 무시하도록 설정합니다.
    • 범주형 데이터를 원-핫 인코딩합니다.

전처리기 정의

preprocessor = ColumnTransformer(
    transformers=[
        ('num', num_transformer, num_features),
        ('cat', cat_transformer, cat_features)
    ])
ColumnTransformer(transformers=[...]):
  • ColumnTransformer 클래스를 사용하여 여러 종류의 전처리를 열에 따라 다르게 적용할 수 있도록 합니다.
  • transformers는 각 변환기의 이름, 객체, 적용할 열 이름 리스트를 포함하는 튜플 리스트입니다.
('num', num_transformer, num_features):
  • num_transformer를 num 단계로 추가하며, num_features에 포함된 열들에 적용합니다.
('cat', cat_transformer, cat_features):
  • cat_transformer를 cat 단계로 추가하며, cat_features에 포함된 열들에 적용합니다.

데이터 전처리 및 결과 저장

df_preprocessed = preprocessor.fit_transform(df)
  • preprocessor.fit_transform(df):
    • preprocessor를 데이터프레임 df에 맞추고 변환합니다.
    • fit_transform 메서드는 데이터를 학습(fit)하고 변환(transform)합니다.
    • 전처리된 결과는 df_preprocessed에 저장됩니다.

전처리된 데이터의 형태 출력

df_preprocessed.shape
  • df_preprocessed.shape:
    • 전처리된 데이터의 형태를 출력합니다.
    • 이는 전처리된 데이터의 행(row)과 열(column) 수를 나타냅니다.

주어진 종목 코드와 유사한 상위 5개 종목 출력

def recommend_stocks(Ticker):
    # 주어진 Ticker에 해당하는 주식의 index를 반환
    stock_index = df[df['Ticker'] == Ticker].index[0]

    # 주어진 stock의 knn 모델에 대한 최근접 이웃 indices를 호출
    neighbor_indices = knn.kneighbors(df_preprocessed[stock_index].reshape(1, -1), return_distance=False)
    # reshape(1, -1)은 knn이 2차원 배열을 받기 때문에 사용

    # 최근접 이웃을 호출
    neighbor_tickers = df.iloc[neighbor_indices[0]]

    # input 주식은 제외하고 추천
    recommendations = neighbor_tickers[neighbor_tickers['Ticker'] != Ticker]

    return recommendations

recommend_stocks("AAPL")


함수 정의 및 Ticker의 주식 인덱스 반환

def recommend_stocks(Ticker):
  • def recommend_stocks(Ticker):: recommend_stocks라는 함수를 정의합니다.
    • Ticker는 함수에 전달되는 인수로, 추천 기준이 되는 주식의 티커 심볼입니다.
    stock_index = df[df['Ticker'] == Ticker].index[0]
  • stock_index:
    • df 데이터프레임에서 주어진 Ticker에 해당하는 주식의 인덱스를 찾습니다.
    • df['Ticker'] == Ticker는 Ticker 열이 주어진 Ticker와 일치하는 행을 필터링합니다.
    • .index[0]는 필터링된 결과의 첫 번째 인덱스를 반환합니다.
    • 예를 들어, Ticker가 'AAPL'인 경우 'AAPL'에 해당하는 행의 인덱스를 찾습니다.

k-NN 모델을 사용하여 최근접 이웃 찾기

    neighbor_indices = knn.kneighbors(df_preprocessed[stock_index].reshape(1, -1), return_distance=False)
    # reshape(1, -1)은 knn이 2차원 배열을 받기 때문에 사용
  • neighbor_indices: knn 모델을 사용하여 주어진 주식의 최근접 이웃의 인덱스를 찾습니다.
  • knn.kneighbors:
    • k-NN 모델의 kneighbors 메서드는 주어진 샘플에 대해 가장 가까운 이웃의 인덱스와 거리를 반환합니다.
  • 매개변수:
    • df_preprocessed[stock_index]는 주어진 주식의 전처리된 데이터입니다.
    • .reshape(1, -1)는 1차원 배열을 2차원 배열로 변환합니다. kneighbors 메서드는 2차원 배열을 입력으로 받기 때문에 필요합니다.
    • return_distance=False는 이웃 간의 거리 값을 반환하지 않고 인덱스만 반환합니다.

최근접 이웃 호출 및 추천 주식 반환

    neighbor_tickers = df.iloc[neighbor_indices[0]]
  • neighbor_tickers:
    • df 데이터프레임에서 최근접 이웃의 인덱스에 해당하는 주식들을 호출합니다.
    • neighbor_indices[0]는 첫 번째 행에 있는 이웃의 인덱스를 나타냅니다.
    • df.iloc는 위치 기반 인덱싱을 사용하여 주어진 인덱스에 해당하는 행을 선택합니다.
    recommendations = neighbor_tickers[neighbor_tickers['Ticker'] != Ticker]
  • recommendations: 입력 주식은 제외하고 추천 주식 목록을 생성합니다.
    • neighbor_tickers['Ticker'] != Ticker는 입력 주식의 티커와 일치하지 않는 주식들을 필터링합니다.
    return recommendations
  • return recommendations: 추천 주식 목록을 반환합니다.