SVM Classifier - 하이퍼파라미터 튜닝

이전포스트에서는 일일주가데이터 자체를 SVC를 이용해 분석후 예측에 사용했다. 훈련세트에 과적합되어서 제대로된 예측을 하지못했다.

이번에는 교차검증과 그리드탐색을 이용해서 좀더 예측력이 강한 모델을 만들어보겠다.

Date Open High Low Close Volume Change UD_Trend
2000-01-04 6000 6110 5660 6110 1483967 0.148496 -1.0
2000-01-05 5800 6060 5520 5580 1493604 -0.086743 1.0
2000-01-06 5750 5780 5580 5620 1087810 0.007168 -1.0
2000-01-07 5560 5670 5360 5540 806195 -0.014235 1.0
2000-01-11 5820 6100 5770 5770 1194974 0.000000 -1.0
2021-12-03 75600 76000 74100 75600 18330240 -0.002639 1.0
2021-12-06 75100 76700 74900 76300 16391250 0.009259 1.0
2021-12-08 78300 78600 77100 77400 21558340 0.000000 1.0
2021-12-09 77400 78200 77000 78200 21604528 0.010336 -1.0
2021-12-10 77400 77600 76800 76900 9155219 -0.016624 -1.0

이전 포스팅과 마찬가지로 일일 주가 변동 Column을 labeling 한다.

my_cv = TimeSeriesSplit(n_splits=5).split(X_train) # 교차검증 세트 생성

TimeSeriesSplit을 통해 시계열 교차검증 세트를 만들어준다. TimeSeriesSplit은 다른 교차검증 세트 생성기와 다르게 시계열이라는 특징을 반영하여 사전관찰편향(look ahrad bias)가 일어나지 않도록 투자자가 특정 일자에 접할 수 없는 데이터를 사용하는 교차검증세트를 생성하지 않는다.

params = {
	'svc__C' : [0.01, 0.1, 1.0],
	'svc__gamma' : [1, 10, 100],
}

현재 사용하는 CPU 성능을 고려하여 SVC의 규제에 영향을 많이주는 C와 gamma 파라미터를 조정한다. 파이프라인을 이용해 StandSclaer를 적용시키위해 딕셔너리 키를 svc__(파라미터이름)으로 만들어준다.

svm_cla = Pipeline([
	                ("scaler", StandardScaler()),
    	            ("svc", SVC()),
        	])

GridSearchCV에 각 객체를 파라미터로 넘겨주어서 객체를 생성한다.

clf = GridSearchCV(svm_cla, param_grid=params, cv=my_cv, n_jobs=-1)

훈련을 진행하고 최적의 파라미터와 예측 최고점수를 출력한다.

clf.fit(X_train, y_train)
print('best parameter:\n', clf.best_params_)
print('best prediction:{0:.4f}'.format(clf.best_score_))



best parameter:
 	{'svc__C': 1.0, 'svc__gamma': 10}
best prediction:0.5039

C는 1, gamma는 10을 얻어냈다. 이제 이 파라미터들을 가진 모델을 처음 훈련세트로 훈련시키고 검증 세트로 검증을 실시해보자

svm_cla2 = Pipeline([
	                ("scaler", StandardScaler()),
    	            ("svc", SVC(C=1, gamma=10)),
        	])
		
svm_cla2.fit(X_train, y_train) # 훈련 세트로 훈련진행

print("train_set score: ", svm_cla2.score(X_train, y_train)) # 훈련세트 점수
print("test_set score : ", svm_cla2.score(X_test, y_test)) # 검증세트 점수

결과는 다음과 같이 나왔다.

train_set score:  0.73
test_set score :  0.49806576402321084

훈련세트에서의 정확도는 상당이 높게 나왔지만 검증세트에서는 50퍼센트 이하가 나왔다. 이는 역시 이전 포스팅때와 마찬가지로 훈련세트에 과적합되어있다는 사실을 알 수 있었다.

unique, counts = np.unique(svm_cla2.predict(X_all), return_counts=True)
print(unique)
print(counts)

예측결과를 보면

[-1.  1.]
[3166 1868]
{-1.0: 3166, 1.0: 1868}

역시 -1 로 편향된 결과가 나온것을 볼 수 있다. 여전히 훈련세트에 과적합되어있다.

Updated: