관리 메뉴

클라이언트/ 서버/ 엔지니어 "게임 개발자"를 향한 매일의 공부일지

트리 알고리즘 7 - 결정 트리 심화 학습 본문

인공지능/머신러닝

트리 알고리즘 7 - 결정 트리 심화 학습

huenuri 2024. 10. 2. 13:23

이번 시간에는 화이트 와인은 분류하는 트리 알고리즘에 대해서 학습해보려고 한다.


 

 

 

결정 트리 실습해 보기

 

 

먼저 와인 샘플 데이터셋을 불러와야 한다. 와인 데이터셋을 데이터프레임으로 제대로 읽었는지 확인하기 위해 처음 5개의 샘플을 확인해 본다.

처음 3개의 열(alcohol, sugar, pH)은 각각 알코올 도수, 당도, pH값을 나타낸다. 네 번째 열(class)은 타깃값으로 0이면 레드 와인, 1이면 화이트 와인이다. 레드 와인과 화이트 와인을 구분하는 이진 분류 문제이고, 화이트 와인이 양성 클래스이다. 즉 전체 와인 데이터에서 화이트 와인을 골라내는 문제이다.


 

 

 

 

먼저 info() 메서드로 각 열의 데이터 타입과 누락된 데이터가 있는지 확인했다. 출력 결과를 보면 총 6497개의 샘플이 있고 4개의 열은 모두 실수값이다. 누락된 값은 없는 것 같다.

다음에 알아볼 메서드는 describe()이다. 이 메서드는 열에 대한 간략한 통계를 출력한다. 평균, 표준편차(std), 최소, 최댓값을 볼 수 있다. 또 중간값과 1사분위수(25%), 3사분위수(75%)를 알려준다.

 

여기서 알 수 있는 것은 알코올 도수와 당도, pH 값의 스케일이 다르다는 것이다. 이전에 했던 것처럼 사이킷런의 StandardScaler 클래스를 사용해 특성을 표준화해야 한다. 


 

 

 

 

wine 데이터프레임에서 처음 3개의 열을 넘파이 배열로 바꿔서 data 배열에 저장했다. 그리고 마지막 class 열을 넘파이 배열로 바꾼 후 target 배열에 저장한다. 이제 훈련 세트와 테스트 세트로 나누는 작업을 진행한다. train_test_split() 함수는 설정값을 지정하지 않으면 25% 정도만 테스트 세트로 나눈다.


 

 

 

 

확인 결과 훈련 세트는 5197개, 테스트 세트는 1300개가 나왔다. 이제 StandardScaler 클래스를 사용해 훈련 세트를 전처리해 볼 것이다. 그다음 같은 객체를 그대로 사용해 테스트 세트를 변환한다.


 

 

 

 

이제 표준 점수로 변환된 train_scaled와 test_scaled를 사용해 로지스틱 회귀 모델을 훈련해 볼 것이다.

 

 

 

점수가 높지는 않다. 훈련 세트와 테스트 세트의 점수가 모두 낮으니 모델이 과소적합된 것 같다. 이 문제를 해결하기 위해 규제 매개변수 C의 값을 바꿔보거나 solver 매개변수에서 다른 알고리즘을 선택할 수 있다. 또는 다항 특성을 만들어 추가할 수도 있다.


 

 

 

 

이 모델을 설명하기 위해 로지스틱 회귀가 학습한 계수와 절편을 출력했다. 이 숫자들이 어떤 의미인지 설명하기 어렵다. 대부분의 머신러닝 모델은 이렇게 학습의 결과를 설명하기 어렵다. 이를 좀 더 쉽게 알아볼 수 있는 결정 트리를 사용해 볼 것이다.


 

 

 

 

훈련 세트에 대한 점수가 높게 나왔다. 하지만 테스트 세트의 성능은 그에 비해 조금 낮다. 과대적합된 모델이라고 볼 수 있다. 결정 트리 그림은 마치 수양버들 나뭇잎처럼 늘어졌다. 진짜 나무는 밑에서부터 하늘 위로 자라나지만, 결정 트리는 위에서부터 아래로 거꾸로 자라난다. 맨 위의 노드를 루트 노드라 부르고 맨 아래 끝에 달린 노드를 리프 노드라고 한다.

 

너무 복잡하니 plot_tree() 함수에서 트리의 깊이를 제한해서 출력해 본다. max_depth 매개변수를 1로 주면 루트 노드를 제외하고 하나의 노드를 더 확장해서 그린다. 또 filled 매개변수에서 클래스에 맞게 노드의 색을 칠할 수 있다. feature_names 매개변수에는 특성의 이름을 전달할 수 있다. 


 

 

 

 

그림을 읽는 방법은 다음과 같다. 루트 노드는 당도가 -0.239 이하인지 질문한다. 만약 어떤 샘플의 당도가 -0.239와 같거나 작으면 왼쪽 가지로 간다. 그렇지 않으면 오른쪽 가지로 이동한다. 루트 노드의 총 샘플 수는 5197개이고, 음성 클래스는 1258개, 양성 클래스는 3939개이다.

 

왼쪽 노드는 당도가 더 낮은 지를 물어본다. 루트 노드보다 양성 클래스, 즉 화이트 와인의 비율이 크게 줄어들었다. 그 이유는 오른쪽 노드를 보면 알 수 있다. 오른쪽 노드는 음성 클래스가 81개, 양성 클래스가 2194개로 대부분의 화이트 와인 샘플이 이 노드로 이동했다. 루트 노드보다 이 노드가 더 진하고, 왼쪽 노드는 더 연해졌다. plot_tree() 함수에서 filled=True로 지정하면 클래스마다 색깔을 부여하고, 어떤 클래스의 비율이 높아지면 점점 더 진한 색으로 표시한다.


 

 

 

 

열매를 잘 맺기 위해 과수원에서 가지치기를 하는 것처럼 결정 트리도 가지치기를 해야 한다. 결정 트리에서 가지치기를 하는 가장 간단한 방법은 자라날 수 있는 트리의 최대 깊이를 지정하는 것이다. max_depth 매개변수를 3으로 지정하여 모델을 만들었다.

 

훈련 세트의 성능은 낮아졌지만 테스트 세트의 성능은 거의 그대로이다. 루트 노드 다음에 있는 깊이 1의 노드는 모두 당도를 기준으로 훈련 세트를 나눈다. 하지만 깊이 2의 노드는 맨 왼쪽의 노드만 당도를 기준으로 나 누고 왼쪽에서 두 번째 노드는 알코올 도수를 기준으로 나눈다. 

깊이 3에 있는 노드가 최종 노드인 리프 노드이다. 왼쪽에서 세 번째에 있는 노드만 음성 클래스가 더 많다. 이 노드에 도착해야만 레드 와인으로 예측한다. 루트 노드부터 이 노드까지 도달하려면 당도는 -0.239보다 작고 -0.802보다 커야 한다. 당도가 -0.802보다 크고 -0.239보다 작은 와인 중에 알코올 도수가 0.454와 같거나 작은 것이 레드 와인이다.

 

그런데 -0.802라는 음수로 된 당도를 어떻게 설명해야 할까? 앞서 불순도를 기준으로 샘플을 나눈다고 했다. 불순도는 클래스별 비율을 가지고 계산했다. 앞서 전처리하기 전의 훈련 세트와 테스트 세트로 결정 트리 모델을 훈련해 보겠다.


 

 

 

 

결과를 보면 같은 트리지만, 특성값을 표준점수로 바꾸지 않은 터라 이해하기가 훨씬 쉽다. 당도가 1.625보다 크고 4.325보다 작은 와인 중에 알코올 도수가 11.025와 같거나 작은 것이 레드 와인이다. 그 외에는 모두 화이트 와인으로 예측했다. 결정 트리는 어떤 특성이 가장 유용한지 나타내는 특성 중요도를 계산해 준다. 

이 트리의 루트 노드와 깊이 1에서 당도를 사용했기 때문에 아마도 당도가 가장 유용한 특성 중 하나일 것 같다. 특성 중요도는 결정 트리 모델의 feature_importances_ 속성에 저장되어 있다. 이 값을 출력해 볼 것이다.

 

 

 

두 번째 특성이 당도가 0.87 정도로 특성 중요도가 가장 높다. 그다음 알코올 도수, pH순이다. 이 값을 모두 더하면 1이 된다. 특성 중요도는 각 노드의 정보 이득과 전체 샘플에 대한 비율을 곱한 후 특성별로 더하여 계산한다. 


 

 

 

 

 

 

이렇게 트리를 만들 때 좌우가 균일하지 않은 트리가 만들어졌다. 질문에 대한 답을 써보면 다음과 같다.

 

1. 좌우가 균일하지 않은 트리가 만들어지는가?

  • 결정 트리에서 min_impurity_decrease=0.0005는 불순도를 줄이는 정도를 기준으로 가지치기 조건을 설정하는 매개변수이다.
  • 이 값을 사용하면, 각 분할에서 얻는 정보 이득(impurity decrease)이 0.0005보다 작은 경우 더 이상 가지치기를 하지 않는다. 결과적으로, 분할이 이루어지는 정도에 따라 좌우가 균일하지 않은 트리가 생성될 수 있다.
  • 트리 구조는 데이터 분포에 따라 각각의 가지가 다르게 성장할 수 있다. 즉, 좌우가 완전히 균형 잡힌 트리가 만들어지지는 않으며, 일부 가지는 깊게 분할되고 다른 일부는 덜 분할될 수 있다.

2. 테스트 세트의 성능은 어떤가?

  • 코드에서 테스트 세트에 대한 정확도는 dt.score(test_input, test_target)을 통해 확인된다.
  • 출력된 테스트 세트의 정확도0.8615입니다. 이는 테스트 데이터에 대해 약 86.15%의 정확도를 보인다는 것을 의미한다.
  • 훈련 세트의 정확도는 88.74%로, 훈련 데이터에 비해 테스트 세트에서 약간 성능이 낮다. 이는 모델이 어느 정도 일반화가 이루어졌음을 나타내며, 과대적합(overfitting)은 방지되었지만, 더 개선할 여지는 있다.

 


 

 

학습을 마치고

결정 트리를 사용해 레드 와인과 화이트 와인을 분류하는 문제를 풀어보았다. 특성을 더 추가하지 않고도 결정 트리의 성능은 이전에 배운 로지스틱 회귀 모델보다 더 좋았다. 게다가 결정 트리는 깊이가 너무 깊지 않다면 비교적 설명하기 쉽다.

이해가 안 되는 부분은 강의를 다시 들으며 학습해 보았다.

 

결정 트리로 보니 한눈에 잘 들어와서 좋기는 하지만 아직 그래프를 보는 것이 쉽지 않다. 지금은 빠르게 학습할 필요가 있어 너무 자세한 부분은 이해가 잘 안 되고 넘어가기로 했다.