#2-7 decision tree 알고리즘 사용하기

목차

    2017. 10. 10. 20:00


    빅데이터는 21세기 원유라고도 불리며, 데이터 분석 및 활용에 대해서 많은 사람들이 관심을 갖고 연구하고 있습니다.

    하지만 데이터 분석, 모델링 등을 배워 보려고 해도 책으로 보고 강의 듣는 것으로는 와 닿지 않는 것이 사실입니다. 그래서 저는 경마를 통해 데이터 분석을 공부함으로써 재미도 느끼고(베팅도 하고) 자기 계발도 하는 1석 2조의 효과를 보고자 합니다.
    이 곳에서는 그렇게 공부한 내용들을 포스팅 하고 있습니다.

    (참조: 경마로 코딩 교육 배우기 )


    제목


    추천포스트



    이전 포스팅에서 경마의 질병을 KNN-알고리즘을 사용하여 5개로 분류하였습니다. 

    하지만 어떤 기준으로 분류되었는지를 알 수가 없었는데요. 

    그래서, 이번에는 decision tree를 이용해서 어떻게 구별되었는지 알아보려 합니다. 


    decision tree 알고리즘에 대해 sklearn 패키지 싸이트에 있는 정보를 살펴보면 대략 이렇습니다.


    decision tree 알고리즘의 장점은 아래와 같습니다.

    * 이해하고 해석하기 쉽다. Tree는 시각화할 수 있다.

    * 데이터 사전 작업이 덜 필요하다. 

       다른 기술들은 종종 데이터 정규화, 범주화 등의 작업이 필요하다.

    * 연속형과 범수형 데이터에 다 사용할 수 있다.

    * 통계 검증을 사용해서 모델을 검증할 수 있다.

    * 가정이 데이터가 생성된 실제 모델에서 약간 잘못되었더라도 잘 수행된다.


    전반적으로 이해하고 해석하기 쉽고, 데이터의 사전작업에 크게 영향을 받지 않는 모델이라고 볼 수 있겠습니다.



    그리고, 이런 단점이 있다고 합니다.

    * 데이터에 잘 일반화되지 않은 과도로 복잡한 트리를 만들 수 있다. 이것은 overfitting(오버피팅)이라고 부른다. 

      이러한 문제를 피하기 위해서 pruning 같은 방법이나 트리의 최대 깊이를 설정하는 것이 필요하다. 

      (pruning은 언제 가지를 칠 지에 대해서 정하는 방법으로 알고 있습니다.)

    * decision trees는 불안정할 수 있다. 

      왜냐면 데이터 작은 편차가 완전히 다른 트리를 만들어 낼 수 있기 때문이다. 

      ensemble 모델 안에 decision tree를 사용함으로써 이 문제를 완화시킬 수 있다.

    * decision tree는 일반적인 경우가 아닌 해당 데이터셋에만 최적화된 tree를 만들 수 있다. 이러한 문제를 최소화하기 위해 feature나 sample들을 random으로 추출하여 ensemble 모델로 만들 수 있다.

    * decision tree로 학습하기 어려운 개념들이 있다. 

    * 몇몇 클래스들이 많다면, 편중된 트리를 만들 수 있다. 그러므로 decision tree로 학습시키기 전에 먼저 균형 있는 데이터셋을 만드는 것을 추천한다.





    그럼 전에 KNN 알고리즘을 이용하여 경주마의 질병을 분리한 것을 가지고, decision tree를 학습시켜 보도록 하겠습니다. (참조: KNN 군집화 알고리즘 사용하기)

    from sklearn import tree dt = tree.DecisionTreeClassifier()


    먼저, sklearn 패키지에서 tree를 import합니다. 그리고, 분류에 관한 문제이기 때문에 DecisionTreeClassifier를 사용합니다. Tree를 정의할 때, 가지치는 갯수라던지 최대 트리 생성 갯수, 분류의 기준 등을 정의할 수 있습니다. 하지만 default값으로 다 지정이 되기 때문에, 특별히 지정하지 않고 해 보도록 하겠습니다.


    clf = dt.fit(table.drop("cluster",1),table["cluster"])



    다음 이전 포스팅에서 KNN 알고리즘으로 만든 테이블을 적합시킵니다. 종속 변수가 구분한 군집이기 때문에, 이를 제외한 테이블을 독립 변수로 구분한 군집을 종속 변수로 해서 학습시킵니다.


    다음 학습시킨 결과를 가지고, 이 페이지 제일 위에 있는 그림처럼 tree를 그리려고 합니다. 그런데 여기서 만들어지는 tree가 dot이라는 확장자를 가지고 있어서, 일반적으로 보기가 어렵습니다. inkscape를 설치하면 볼 수 있다고 하는데 저는 시도해 보지는 않았습니다. 대신에 만들어진 tree를 png파일로 바꾸어서 볼 수 있습니다. 가끔 png로 바꾸는 도중에 에러가 날 때가 있는데, 이는 tree에 세부 옵션을 주어서, 너무 복잡해지지 않게 만들다 보면 해결될 때가 많습니다.


    filename="./tree.dot"
    filename1="./tree.png"

    with open(filename,"w") as f:
    tree.export_graphviz(clf, out_file=f,feature_names = list(table.drop("cluster",1).columns), filled=True, proportion=True, rounded=True,special_characters=True)

    (graph,) = pydot.graph_from_dot_file(filename)
    graph.write_png(filename1)


    위와 같이 dot파일을 png파일로 변경하기 위해서는 graphviz라는 프로그램을 설치해 주어야 합니다. 그렇게 해서 해당 형식으로 export_graphviz함수를 이용하여 tree를 그리고, 이것을 다시 png파일로 바꿉니다. 최종적으로 png라는 파일이 만들어집니다. 만들어진 tree는 아래와 같습니다.



    decision_tree


    우선은 각 색깔들은 각각의 그룹들을 알려줍니다. 

    저희가 총 5개의 class를 분류하는 것으로 하였으므로, 색깔도 5개 입니다.


    samples는 각각의 node에 해당하는 관측치들의 비율입니다. 제일 위에 보시면, 운동기인성 피로회복으로 100%를 약 50%씩 2개의 노드로 나누었습니다. 참고로 각 노드의 제일 위에 있는 식의 값이 참이면 왼쪽, 거짓이면 오른쪽입니다. 


    주로 운동기인성 피로회복으로 class를 구분하고, 다른 변수들은 분류하는데 큰 도움이 되지 않네요. gini 계수에 대한 것은 다음에 포스팅하기로 하고, 다른 분류방법을 이용하여 tree를 그려 보았습니다. 여기서 더 나은 tree를 그리는 방법에 대해서 많은 연구들이 있었겠지만, 일반적으로 다양한 옵션들을 조정해가면서 시행착오를 통해 tree를 그려나가는 것으로 알고 있습니다.


     '운동기인성 피로회복'외에는 잘 구분되는 변수가 없는 것 같아, 빼고 tree를 그렸더니 굉장히 복잡한 treer가 나왔습니다. 사실 경주마들에게 발생하는 질병이 종류도 워낙 다양하고, 발생건수도 많지 않아 분류하기가 어려운 듯 합니다. 

    그리고 경주력에 영향을 미치는 질병들을 grouping 하는 것이 목적이었지만, 이렇게 분류된 기준으로 분류하여 해당 목적을 달성할 수 있을 것이라고 보기는 어려울 듯 합니다. 



    오늘은 이렇게 decision tree를 그려 보았습니다. 더 자세한 내용은 sklearn패키지의 싸이트에 가서 참조하시면 될 듯 합니다. 좀 아쉬움이 남아 다음에는 질병 정보가 아닌, 연승 기준으로 decision tree를 한 번 더 그려보려고 합니다.


    오픈API를 사용하면 다양한 재미있는 일들을 해 볼 수 있다. 파이썬을 활용한 오픈API 사용이 궁금하다면 아래 글을 참조해보자.

    (참조: 오픈API를 활용한 사례는 어떤 것들이 있을까?)