1. XGBoost 란?
XGBoost(Extreme Gradient Boosting)는 강력하고 널리 사용되는 머신 러닝 알고리즘으로, 그래디언트 부스팅 기법 중 하나에 속합니다. XGBoost는 회귀, 분류 및 순위 지정과 같은 다양한 머신 러닝 작업에서 특히 효과적으로 사용되며 속도, 확장성 및 견고성 면에서 유명합니다. XGBoost는 많은 데이터 과학자와 머신 러닝 실무자들에게 기본 선택으로 인해 다양한 머신 러닝 대회에서 수상하며 폭넓게 사용됩니다.
다음은 XGBoost의 중요한 개념과 특징에 대한 설명입니다:
- 그래디언트 부스팅: XGBoost는 그래디언트 부스팅 개념을 기반으로 하며 이는 앙상블 학습 방법입니다. 이 방법은 여러 개의 약한 학습자(일반적으로 의사 결정 트리)의 예측을 결합하여 강력한 학습자를 생성합니다. 그래디언트 부스팅은 모델을 순차적으로 구축하며 각 새 모델은 이전 모델이 만든 오류에 중점을 둡니다. 이 반복 과정은 전체 모델의 성능을 점차적으로 개선합니다.
- 의사 결정 트리: XGBoost는 일반적으로 기본 모델로 의사 결정 트리를 사용하지만 기본 학습자로 선형 모델도 사용할 수 있습니다. 의사 결정 트리는 간단하지만 데이터의 선형 및 비선형 관계를 모두 포착할 수 있는 강력한 모델입니다.
- 정규화: XGBoost는 과적합을 제어하기 위한 L1(Lasso) 및 L2(Ridge) 정규화 기술을 포함하고 있으며, 이는 모델의 일반화를 향상시키고 훈련 데이터에 너무 근접하게 학습되는 것을 방지하는 데 도움을 줍니다.
- 트리 가지치기: XGBoost는 트리의 깊이를 제어하기 위해 "가지치기"라고 하는 과정을 사용합니다. 가지치기는 모델의 성능에 기여하지 않는 가지를 제거함으로써 깊고 과적합한 트리를 피하기 위해 도움을 줍니다.
- 특성 중요도: XGBoost는 예측을 수행할 때 각 특성의 중요도를 제공하며, 예측을 할 때 각 특성의 중요성을 이해하는 데 도움이 됩니다. 이는 특성 선택 및 데이터 분석에 유용합니다.
- 병렬 및 분산 컴퓨팅: XGBoost는 매우 효율적으로 설계되었으며 멀티코어 프로세서를 활용할 수 있어 다른 그래디언트 부스팅 구현체보다 빠릅니다. 또한 대용량 데이터셋에서 성능을 향상시키기 위한 분산 컴퓨팅을 지원합니다.
- 교차 검증: XGBoost는 모델 성능을 평가하고 하이퍼파라미터를 효과적으로 조정하기 위한 교차 검증 기술을 지원합니다.
- 사용자 정의 손실 함수: XGBoost는 사용자 정의 손실 함수를 정의할 수 있으며, 전통적인 회귀 및 분류 이상의 다양한 작업에 적합합니다.
- 결측값 처리: XGBoost는 입력 특성에서 자동으로 결측값을 처리할 수 있으므로 데이터 전처리를 광범위하게 수행하지 않아도 됩니다.
- GPU 지원: XGBoost는 GPU 가속을 활용할 수 있어 대용량 데이터셋에서 더 빠르고 높은 성능을 제공합니다.
전반적으로 XGBoost는 다양한 머신 러닝 작업에 대한 다재다능하고 매우 효과적인 알고리즘입니다. 그래디언트 부스팅, 정규화 기술 및 기타 특징의 조합으로 인해 예측 모델링에서 견고하고 인기 있는 선택 사항입니다. XGBoost를 효과적으로 사용하려면 하이퍼파라미터를 세밀하게 조정하고 특성 엔지니어링을 수행해야 하며, 이는 모든 머신 러닝 모델에서 흔한 관행입니다.
2. Python 에서 XGBoost 사용
XGBoost 의 사용 예로
미국 나스닥 S&P 500 중 상위에 속해있는 대기업들의 주가를 이용하여 삼성전자 주가 전망을 예측해보도록 하겠습니다.
[유의사항]
* 미국 종가와 시차를 이용하여 오늘날짜의 삼성전자 주가를 예측 하면 아주 좋겠지만
미국이 대한민국보다 13~14시간 느리므로 이러한 예측은 불가능합니다.
따라서 우리는 쉬프트기법을 이용하여 하루 뒤 삼성전자의 주가를 예측해보겠습니다.
* 미국의 주식 시장과 우리나라 주식시장 휴무일이 차이가 있으므로 미국이 휴장일 때는
전일 삼성전자 주가로 대신하도록 하겠습니다.
* 이는 단순 예측에 불가할 뿐 정확도는 보장하지 않습니다.
* 예측 프로그램을 이용한 투자에 대하여 책임지지 않습니다.
* 주식투자의 선택은 본인의 몫입니다.
아래 테이블은 날짜에 따른 애플, 구글, 메타, 엔비디아, 마이크로소프트, 아마존, 삼성전자의 종가 데이터입니다.
데이터 링크 : https://drive.google.com/file/d/1cf8JzkqL8-U3W__ByMcaZPO87XcwRb17/view?usp=sharing
미국은 달러화로 표기되고 대한민국은 원화로 표기가 되는데 제 생각에는 예측할 때에는 크게 상관이 없을것으로 보입니다. 이는 학습데이터로 사용되는 데이터가 애플~삼정전자 주가까지 모두 사용되고 우리가 찾고자하는 2023년 8월 18일자 삼성전자 주가는 삼성전자 컬럼을 쉬프트하여 사용하기 때문입니다. 각 숫자의 상관관계를 학습시키는 것으로 단위는 무시하고 진행해보도록 합시다.
Version : Python 3.12.0 에서 실행되었습니다.
1. 먼저 필요한 라이브러리를 불러와줍니다.
import datetime as dt # 날짜를 사용하기 위한 라이브러리
import matplotlib.pyplot as plt # 예측결과를 시각적으로 보여주는 라이브러리
import numpy as np # 수학계산 라이브러리
import pandas as pd # 데이터프레임 사용
from xgboost import XGBRegressor
from xgboost import plot_importance
2. 주가 데이터가 모여있는 파일을 Dataframe 으로 불러와 데이터를 가공합니다.
df = pd.read_csv(f"datasets/snp500ittop.csv")
df['DATE'] = pd.to_datetime(df['DATE'])
df.set_index('DATE', inplace=True)
df.sort_values('DATE', inplace=True)
- 'DATE' 컬럼을 날짜로 바꾸고 인덱스화시킵니다.
- 'DATE' 날짜순으로 정렬해줍니다. (혹시몰라서)
만들고자 하는 모양은 다음과 같습니다.
위 그림과 같이 삼성전자 주가를 한칸 위로 밀어서 새 컬럼으로 붙여줍니다.
그럼 미국 대기업 들의 종가와 삼성전자 종가와 삼성전자 전일종가에 대한 상관관계가 형성됩니다.
앞에있는 날짜를 무시하고 보면 <unset> 자리는 8월 18일 주가로 예측해볼 수 있습니다.
이제 학습에 필요한 변수들을 설정합니다.
company = "SAMSUNG"
snplist = ["AAPL","GOOG","META","NVDA","MSFT","AMZN"]
split = '2023-08-01'
예측할 변수와 학습할 변수 그리고 학습용 데이터와 테스트용 데이터를 분리할 기준을 선언했습니다.
* 쉬프트는 아래 그림과 같이 학습데이터를 제외한 나머지를 아래로 쉬프트합니다.
for i in range(1) :
# 삼성전자 컬럼을 SHIFT 로 추가
df[f'''{company}_SHIFT_{i}'''] = df[f'''{company}''']
snplist.append(f'''{company}_SHIFT_{i}''')
# 마지막날짜 추가
last_data = str(df.index[-1:].values[0]).split(".")[0]
last_time = dt.datetime.strptime(last_data, '%Y-%m-%dT%H:%M:%S') + dt.timedelta(days=1)
if i == 0 :
bef_pred_date = last_time
temp_df = pd.DataFrame(data={'DATE' : last_time, f'''{company}''' : [0]})
temp_df.set_index('DATE', inplace=True)
df = pd.concat([df,temp_df])
# 쉬프트로 학습데이터를 아래로 한칸 밀기
df[snplist] = df[snplist].shift(1)
# 데이터가 없는 맨 윗줄 제거
df = df[1:]
# 학습데이터, 테스트데이터 분리
df_train = df[:split]
df_test = df[split:]
df_train_y = df_train.loc[:,f'''{company}''']
df_train_X = df_train.drop([f'''{company}'''], axis=1)
df_test_y = df_test.loc[:,f'''{company}''']
df_test_X = df_test.drop([f'''{company}'''], axis=1)
df_test_orig = df_test.loc[:, [f'''{company}''']]
# xgboost로 학습
xg_model = XGBRegressor(n_estimators=1000)
xg_model.fit(df_train_X, df_train_y, eval_set=[(df_test_X, df_test_y)], early_stopping_rounds=50, verbose=False)
plot_importance(xg_model, height=0.9)
# 결과값 정리
df1 = df_test_X[df_test_X.index >= split]
# 예측값 도출
predicts = xg_model.predict(df1)
result = pd.concat([df_test_orig[df_test_orig.index >= split].reset_index(),
pd.DataFrame(predicts, columns=['predict'])], axis=1, ignore_index=False)
result = result.set_index('DATE')
result = result.loc[:, [f'''{company}''', 'predict']]
result[bef_pred_date:].iloc[:,0] = np.NaN
# 시각화
result.plot()
plt.show()
df[-1:][f'''{company}'''].values[0] = result[-1:]["predict"].values[0]
split = dt.datetime.strptime(str(split).split(" ")[0], '%Y-%m-%d') + dt.timedelta(days=1)