본문 바로가기
실전머신러닝

KNN, 나이브베이즈 분류를 이용해서 종목분석하기

by 다빈치스탁 2020. 11. 10.
728x90
반응형

이전 포스트 이베스트편(2020/11/09 - [증권사 API] - 특정기업의 FNG 요약, 마켓컨센서스 가져오기)를 잘 활용하면 아래의 그림과 같이 코스피, 코스닥 시가총액 상위종목들의 에프앤가이드 요약 재무비율과 마켓 컨센서스(시장의견)를 가져올 수 있다. 물론 여러번 반복과정을 거쳐야 아래와 같은 로데이터를 얻을 수 있으니 귀찮은 사람은 첨부된 엑셀파일을 가져다가 써도 되겠다.

 

종목별 재무비율, 컨센서스 가져오기
fng.xlsx
0.06MB

자, 이제부터 우리가 무엇을 하는가하면! 바로 특정종목들의 재무비율을 속성데이터로 하고 해당 종목에 대한 마켓 컨센서스를 정답 라벨링으로 간주하고 분류를 수행해 볼 예정이다. 이러한 것을 왜하는가? 그렇다. 통상 변두리의 종목들, 스몰캡 종목에 대해서 보고서를 작성하는 애널리스트들은 많지 않다. 그러나 유진파마의 이론에서도 그렇듯 사실 소형주가 시장 상승률에 비해 쎄게 가는 경우가 많다. 그런데 마땅히 참고할만한 자료는 부족하고 어디 의존할 거라고는 순전히 직관 혹은 카더라가 전부인 실정이다.

 

기술적 분석이든 기본적 분석이든 어떠한 종목을 골랐을 때 해당 종목의 보고서가 없다면? 이처럼 분류기를 통해서 해당 종목에 대한 마켓컨센서스를 예측해 볼 수 있다는 점에서 꽤나 유용하게 사용할 수 있다. 자 언제나 그랬든 간단한 이론적 백그라운드를 짚어보고 바로 실전으로 들어가보자.

 

우선 최근접 이웃 분류법을 살펴보자. 이 방법은 데이터의 속성을 다차원의 공간으로 투영하여 그룹화를 수행하는 것으로 보면 되는데 이때 같은 그룹으로 묶이기 위해서 유클리드 거리를 사용한다. 각 속성치들의 거리차의 제곱의 제곱근이 최소화되는 그룹을 찾는데 이때 K는 가장 근접한 군들의 비교수를 의미하며 투표의 방식으로 결정이 된다. 이때 어떤 K를 취하는가에 따라 과적합인가 과소적합인가의 문제에 봉착하게 되는데 너무 많으면 중요한 패턴을 무시하는 과적합 너무 적으면 잡음을 가진 데이터가 과도한 영향을 미칠 우려가 있기에 통상적으로 K는 sqrt(훈련데이터의 수)로 정한다.또한 이 부분은 모든 분석에 있어서 일반적이지만 훈련데이터는 정규화과정을 거쳐서 분석을 해야 분류의 성능을 높일 수 있다. 그러나 우리가 사용하는 데이터는 재무"비율"이기에 별도의 과정없이 바로 적용한다. 

728x90

다음으로 살펴볼 방법이 나이브 베이즈 모델인데 이는 특징 값이 나타내는 증거를 기반으로 결과가 관측될 확률(조건부 확률)을 계산하는 방법이다. 빨간 공 5개 파란 공 5개가 있을 때 처음 꺼낸 공이 빨간 공이면 다음에 빨간공 혹은 파란공이 나올 확률은 처음보다 무작위성이 훨씬 덜 해지는 원리를 이용한 것으로 결과를 알기 위해서 동시다발적으로 여러 속성을 고려해야하는 문제에 적합한 분석기법이다. 강력한 분류알고리즘의 후보로 자주 등장하고는 있지만 모든 속성이 동등하게 중요하며 독립이라는 가정에서 분석을 수행하기 때문에 현실에 적용하기가 애매한 경우가 있다. 예를 들어 ROA, ROE는 자산과 자본이 고정이고(다음 분기 발표 전까지) 둘다 분자로 Return 순이익을 가지고 있기에 서로 의존성이 있는 데이터라 독립적이라고 판단하기 애매할 수 있다. 그러나 그럼에도 불구하고 나이브베이즈 분류기의 성능은 사후적으로 잘 맞추기에 여전히 많이 선호되고 있다. 

 

#install.packages("RWeka")
library(readxl)

#작업경로를 지정하는 명령어
setwd("")

mydatae<-read_excel("fng.xlsx",
                    sheet='fng',
                    col_names=TRUE, 
                    na = "NA")

na.omit(mydatae)
#총 데이터 중 매수와 관망의 수..
opinion<-table(mydatae$최종)

#매수와 관망의 비중 분석.
round(prop.table(opinion)*100, digits=2)

#훈련데이터를 만들기위한 재무비율값
analysis<-cbind(mydatae$PER,mydatae$PRB,mydatae$ROA,mydatae$ROE,mydatae$EVEBIT,mydatae$최종,mydatae$바이너리)

#적절한 단계로 잘라준다.
a_train<-analysis[1:320,1:5]
a_test<-analysis[321:369,1:5]

r_train<-mydatae$최종[1:320]
r_test<-mydatae$최종[321:369]

#install.packages("class")
library(class)
#KNN 모델
r_predict<-knn(train=a_train,test=a_test,cl=r_train,k=17)

#install.packages("gmodels")
library(gmodels)
CrossTable(x=r_test,y=r_predict,prop.chisq = FALSE)

table(r_test)
table(r_predict)

library(e1071)
n_train<-as.data.frame(a_train)
n_result<-factor(r_train)
str(n_result)

naiveModel<-naiveBayes(n_result~.,data=n_train, laplace=2)
n_predict<-predict(naiveModel,a_test)
CrossTable(x=r_test,y=n_predict,prop.chisq = FALSE)

KNN 분류기
나이브분류기

위의 코드를 돌려보면  KNN으로 예측한 경우 마켓컨센이 중립일 때 매수라고 예측한 오류가 12번, 나이브의 경우는 21번 이며 마켓컨센이 매수일 때 중립으로 예측한 경우가 KNN은 4번, 나이브는 0번으로 나왔다. 둘 중 더 중요한 오류가 무엇일까? 이건 뭐 의심의 여지가 없이 KNN모델이 더욱 적합하게 분류를 하고 있다고 볼 수 있다. 우선 단순히 적중률만 비교해봐도 전자를 따라갈 수가 없다. 그러면 혹시 제대로 학습되지 않았을까라는 합리적인 의심을 해볼 수 있다. 따라서 이번에는 test 데이터가 아닌 train 데이터를 이용해서 예측을 수행해보면 아래와 같이 적중률 100%(무지막지한 과최적화)라는 것을 확인할 수 있다. 라플라스 값을 다르게 변환시켜봐도 드라마틱한 결과는 발생하지 않고 있다. 적어도 위의 예제 데이터 샘플에서는.

 

나이브모델 훈련데이터를 이용한 예측정확도

 

자 이제부터는 위의 코드를 참고해서 K값과 라플라스 값을 변경하면서 여러가지 더 좋은 방법들은 직접 찾아보자. 그래야 실력이 쑥쑥 자란다.

728x90
반응형

댓글