본문 바로가기

카테고리 없음

[ML 세션] 혼공머신 Chapter 05. 트리 알고리즘

Chapter 05. 트리 알고리즘

05-1 결정 트리

✅ 로지스틱 회귀로 와인 분류하기

wine.describe()

describe() 메서드를 통해 평균(mean), 표준편차(std), 최소(min), 최대(max)값을 볼 수 있습니다. 또 중간값(50%)과 1사분위수(25%), 3사분위수(75%)를 알려줍니다.

 

✅ 결정 트리

결정 트리 모델은 스무고개와 같습니다. 밑에 있는 그림처럼 질문을 하나씩 던져서 정답과 맞춰가는 거죠.

데이터를 잘 나눌 수 있는 질문을 찾는다면 계속 질문을 추가해서 분류 정확도를 높일 수 있습니다.

import matplotlib.pyplot as plt
from sklearn.tree import plot_tree
plt.figure(figsize=(10,7))
plot_tree(dt)
plt.show()

맨 위의 노드(node)를 루트 노드(root node)라 부르고 맨 아래 끝에 달린 노드를 리프 노드(leaf node)라고 합니다.

더보기

노드는 결정 트리를 구성하는 핵심 요소입니다. 노드는 훈련 데이터의 특성에 대한 테스트를 표현합니다. 가지(branch)는 테스트의 결과(True, False)를 나타내며 일반적으로 하나의 노드는 2개의 가지를 가집니다.

plt.figure(figsize=(10,7))
plot_tree(dt, max_depth=1, filled=True, feature_names=['alcohol', 'sugar', 'pH'])
plt.show()

기본적으로 그림이 담고 있는 정보는 다음과 같습니다.

 

☮️ 불순도

gini는 지니 불순도를 의미합니다. DecisionTreeClassifier 클래스의 criterion 매개변수의 기본값이 'gini'입니다. 

지니 불순도는 클래스의 비율을 제곱해서 더한 다음 1에서 빼면 됩니다.

어떤 노드의 두 크래스의 비율이 정확히 1/2씩이라면 지니 불순도는 0.5가 되어 최악이 됩니다.

노드에 하나의 클래스만 있다면 지니 불순도는 0이 되어 가장 작습니다. 이런 노드를 순수 노드라고도 부릅니다.

 

 

결정 트리 모델은 부모 노드와 자식 노드의 불순도 차이가 가능한 크도록 트리를 성장시킵니다.

부모 노드와 자식 노드의 불순도 차이를 계산하는 방법은 다음과 같습니다. 먼저 자식 노드의 불순도를 샘플 개수에 비례하여 모두 더합니다ㅏ. 그다음 부모 노드의 불순도에서 빼면 됩니다.

이런 부모와 자식 노드 사이의 불순도 차이를 정보 이득이라고 부릅니다. 이 알고리즘은 정보 이득이 최대가 되도록 데이터를 나눕니다.

 

또한, DecisionTreeClassifier 클래스에서 criterion='entropy'를 지정하여 엔트로피 불순도를 사용할 수 있습니다. 엔트로피 불순도도 노드의 클래스 비율을 사용하지만 지니 불순도처럼 제곱이 아니라 밑이 2인 로그를 사용하여 곱합니다.

 

☮️ 가지치기

열매를 잘 맺기 위해 과수원에서 가지치기를 하는 것처럼 결정 트리도 가지치기를 해야 합니다!

그렇지 않으면 무작정 끝까지 자라나는 트리가 만들어집니다.

훈련 세트에는 아주 잘 맞겠지만 테스트 세트에서 점수는 그에 못 미칠 것입니다.

 

특성값의 스케일은 결정 트리 알고리즘에 아무런 영향을 미치지 않습니다. 따라서 표준화 전처리를 할 필요가 없습니다.

 

결정 트리는 어떤 특성이 가장 유용한지 나타내는 특성 중요도를 계산해 줍니다. 트리의 루트 노드와 깊이가 낮은 곳에서 사용하는 특성이 가장 유용한 특성이 됩니다. 특성 중요도는 각 노드의 정보 이득과 전체 샘플에 대한 비율을 곱한 후 특성별로 더하여 계산합니다.

05-2 교차 검증과 그리드 서치

✅ 검증 세트

테스트 세트를 사용하지 않고 훈련 세트를 또 나눠서 과대적합, 과소적합을 판단하는 데이터를 검증 세트라고 부릅니다.

더보기

테스트 세트와 검증 세트에 얼마나 많은 샘플을 덜어 놔야 하나요?

보통 20~30%를 테스트 세트와 훈련 세트로 떼어 놓습니다. 하지만 훈련 데이터가 아주 많다면 단 몇 %만 떼어 놓아도 전체 데이터를 대표하는 데 문제가 없습니다.

훈련 과정

➡️ 훈련 세트에서 모델을 훈련하고 검증 세트로 모델을  평가

➡️ 테스트하고 싶은 매개변수를 바꿔가며 가장 좋은 모델을 고르기

➡️ 훈련 세트와 검증 세트를 합쳐 전체 훈련 데이터에서 모델을 다시 훈련

➡️ 테스트 세트에서 최종 점수를 평가

✅ 교차 검증

교차 검증은 검증 세트를 떼어 내어 평가하는 과정을 여러 번 반복합니다. 그다음 이 점수를 평균하여 최종 검증 점수를 얻습니다.

더보기

3-폴드 교차 검증이 뭔가요?

-> 훈련 세트를 세 부분으로 나눠서 교차 검증을 수행하는 것을 3-폴드 교차 검증이라고 합니다.

보통 5-폴드 교차 검증이나 10-폴드 교차 검증을 많이 사용합니다. 이렇게 하면 데이터의 80~90%까지 훈련에 사용할 수 있습니다.

 

사이킷런의 cross_validate() -> 교차 검증 함수

➡️ 평가할 모델 객체를 첫 번째 매개변수로 전달

➡️ 훈련 세트 전체를 cross_validate() 함수에 전달

 

한 가지 주의할 점은 cross_validate()는 훈련 세트를 섞어 폴드를 나누지 않습니다.

따라서 교차 검증을 할 때 훈련 세트를 섞으려면 분할기를 지정해야 합니다.

✅ 하이퍼파라미터 튜닝

머신러닝 모델이 학습하는 파라미터를 모델 파라미터라고 부릅니다. 반면에 모델이 학습할 수 없어서 사용자가 지정해야만 하는 파라미터를 하이퍼파라미터라고 합니다.

 

하이퍼파라미터를 튜닝하는 작업

➡️ 라이브러리가 제공하는 기본값을 그대로 사용해 모델을 훈련

➡️ 검증 세트의 점수나 교차 검증을 통해서 매개변수를 조금씩 바꿈

➡️ 모델을 훈련하고 교차 검증 수행

 

max_depth의 최적값은 min_samples_split 매개변수의 값이 바뀌면 함께 달라지기 때문에 두 매개변수를 동시에 바꿔가며 최적의 값을 찾아야 합니다.

 

사이킷런의 GridSearchCV 클래스는 하이퍼파라미터 탐색과 교차 검증을 한 번에 수행합니다.

 

교차 검증에서 최적의 하이퍼파라미터를 찾으면 전체 훈련 세트로 모델을 다시 만들어야 합니다. 하지만 아주 편리하게도 사이킷런의 그리드 서치는 훈련이 끝나면 25개의 모델 중에서 검증 점수가 가장 높은 모델의 매개변수 조합으로 전체 훈련 세트에서 자동으로 다시 모델을 훈련합니다.

 

그리드 서치 과정

➡️ 탐색할 매개변수를 지정

➡️ 훈련 세트에서 그리드 서치를 수행하여 최상의 평균 검증 점수가 나오는 매개변수 조합 찾기

➡️ 최상의 매개변수에서 전체 훈련 세트를 사용해 최종 모델 훈련

더보기

넘파이 arange() 함수는 첫 번째 매개변수 값에서 시작하여 두 번째 매개변수에 도달할 때까지 세 번째 매개변수를 계속 더한 배열을 만듭니다. 파이썬 range() 함수도 비슷합니다. 하지만 이 함수는 정수만 사용할 수 있습니다.

 

랜덤 서치

매개변수의 값이 수치일 때 값의 범위나 간격을 미리 정하기 어려울 수 있습니다. 또 너무 많은 매개변수 조건이 있어 그리드 서치 수행 시간이 오래 걸릴 수 있습니다. 이럴 때 랜덤 서치를 사용하면 좋습니다.

랜덤 서치에는 매개변수 값의 목록을 전달하는 것이 아니라 매개변수를 샘플링할 수 있는 확률 분포 객체를 전달합니다.

더보기

싸이파이(scipy)는 어떤 라이브러리인가요?

싸이파이는 파이썬의 핵심 과학 라이브러리 중 하나입니다. 적분, 보간, 선형 대수, 확률 등을 포함한 수치 계산 전용 라이브러리입니다. 사이킷런은 넘파이와 싸이파이 기능을 많이 사용합니다.

싸이파이의 stats 서브 패키지에 있는 uniform과 randint 클래스는 모두 주어진 범위에서 고르게 값을 뽑습니다. 이를 '균등 분포에서 샘플링한다'라고 말합니다. randint는 정숫값을 뽑고, uniform은 실숫값을 뽑습니다. 난수 발생기랑 유사하게 생각하면 됩니다.

 

수동으로 매개변수를 바꾸는 대신에, 그리드 서치나 랜덤 서치를 사용하는 것이 좋습니다.

05-3 트리의 앙상블

✅ 정형 데이터와 비정형 데이터

정형 데이터는 어떤 구조로 되어 있는 데이터입니다. 이런 데이터는 CSV나 데이터베이스, 혹은 엑셀에 저장하기 쉽습니다.

이와 반대되는 데이터를 비정형 데이터라고 부릅니다. 비정형 데이터는 데이터베이스나 엑셀로 표현하기 어려운 것들입니다. 텍스트 데이터, 사진, 음악 등이 있습니다.

더보기

텍스트나 사진을 데이터베이스에 저장할 수는 없나요?

저장할 수도 있습니다. 데이터베이스 중에는 구조적이지 않은 데이터를 저장하는 데 편리하도록 발전한 것이 많습니다. 대표적으로 NoSQL 데이터베이스는 엑셀이나 CSV에 담기 어려운 텍스트나 JSON 데이터를 저장하는 데 용이합니다.

정형 데이터를 다루는 데 가장 뛰어난 성과를 내는 알고리즘이 앙상블 학습입니다. 이 알고리즘은 대부분 결정 트리를 기반으로 만들어져 있습니다.

✅ 랜덤 포레스트

랜덤 포레스트는 앙상블 학습의 대표 주자 중 하나로 안정적인 성능 덕분에 널리 사용되고 있습니다. 앙상블 학습을 적용할 때 가장 먼저 랜덤 포레스트를 시도해 보길 권합니다.

 

이름 자체로 유추할 수 있듯이 랜덤 포레스트는 결정 트리를 랜덤하게 만들어 결정 트리(나무)의 숲을 만듭니다. 그리고 각 결정 트리의 예측을 사용해 최종 예측을 만듭니다.

 

먼저 랜덤 포레스트는 각 트리를 훈련하기 위한 데이터를 랜덤하게 만드는데, 이 데이터를 만드는 방법이 독특합니다. 우리가 입력한 훈련 데이터에서 랜덤하게 샘플을 추출하여 훈련 데이터를 만듭니다. 이때 뽑았던 샘플을 다시 넣기 때문에 한 샘플이 중복되어 추출될 수도 있습니다. 이렇게 만들어진 샘플을 부트스트랩 샘플이라고 부릅니다. 기본적으로 부트스트랩 샘플은 훈련 세트의 크기와 같게 만듭니다.

더보기

부트스트랩이 뭔가요?

보통 부트스트랩 방식이라고 하는데, 데이터 세트에서 중복을 허용하여 데이터를 샘플링하는 방식을 의미합니다. 가방에 1,000개의 샘플이 있을 때 먼저 1개를 뽑고, 다시 가방에 넣어 그다음 샘플을 뽑는 방식을 뜻하는 거죠. 부트스트랩 샘플이란 결국 부트스트랩 방식으로 샘플링하여 분류한 데이터라는 의미입니다.

또한 각 노드를 분할할 때 전체 특성 중에서 일부 특성을 무작위로 고른 다음 이 중에서 최선의 분할을 찾습니다. 분류 모델인 RandomForestClassifier는 기본적으로 전체 특성 개수의 제곱근만큼의 특성을 선택합니다.

사이킷런의 랜덤 포레스트는 기본적으로 100개의 결정 트리를 이런 방식으로 훈련합니다. 그다음 분류일 때는 각 트리의 클래스별 확률을 평균하여 가장 높은 확률을 가진 클래스를 예측으로 삼습니다. 회귀일 때는 단순히 각 트리의 예측을 평균합니다.

더보기

분류와 회귀를 다시 살펴봅시다.

분류는 샘플을 몇 개의 클래스 중 하나로 분류하는 문제고, 회귀는 임의의 어떤 숫자를 예측하는 문제였습니다.

랜덤 포레스트는 랜덤하게 선택한 샘플과 특성을 사용하기 때문에 훈련 세트에 과대적합되는 것을 막아주고 검증 세트와 테스트 세트에서 안정적인 성능을 얻을 수 있습니다. 종종 기본 매개변수 설정만으로도 아주 좋은 결과를 냅니다.

 

랜덤 포레스트는 하나의 특성에 과도하게 집중하지 않고 좀 더 많은 특성이 훈련에 기여할 기회를 얻습니다. 이는 과대적합을 줄이고 일반화 성능을 높이는 데 도움이 됩니다.

✅ 엑스트라 트리

엑스트라 트리는 랜덤 포레스트와 매우 비슷하게 동작합니다. 기본적으로 100개의 결정 트리를 훈련합니다. 랜덤 포레스트와 엑스트라 트리의 차이점은 부트스트랩 샘플을 사용하지 않는다는 점입니다. 즉 각 결정 트리를 만들 때 전체 훈련 세트를 사용합니다. 대신 노드를 분할할 때 가장 좋은 분할을 찾는 것이 아니라 무작위로 분할합니다.

✅ 그레이디언트 부스팅

그레이디언트 부스팅은 깊이가 얕은 결정 트리를 사용하여 이진 트리의 오차를 보완하는 방식으로 앙상블 하는 방법입니다. 사이킷런의 GradientBoostingClassifier는 기본적으로 깊이가 3인 결정 트리를 100개 사용합니다. 깊이가 얕은 결정 트리를 사용하기 때문에 과대적합에 강하고 일반적으로 높은 일반화 성능을 기대할 수 있습니다. 그레이디언트 부스팅은 분류에서는 로지스틱 손실 함수를 사용하고 회귀에서는 평균 제곱 오차 함수를 사용합니다.

 

일반적으로 그레이디언트 부스팅이 랜덤 포레스트보다 조금 더 높은 성능을 얻을 수 있습니다. 하지만 순서대로 트리를 추가하기 때문에 훈련 속도가 느립니다.

✅ 히스토그램 기반 그레이디언트 부스팅

히스토그램 기반 그레이디언트 부스팅은 정형 데이터를 다루는 머신러닝 알고리즘 중에 가장 인기가 높은 알고리즘입니다. 히스토그램 기반 그레이디언트 부스팅은 먼저 입력 특성을 256개의 구간으로 나눕니다. 따라서 노드를 분할할 때 최적의 분할을 매우 빠르게 찾을 수 있습니다. 히스토그램 기반 그레이디언트 부스팅은 256개의 구간 중에서 하나를 떼어 놓고 누락된 값을 위해서 사용합니다. 따라서 입력에 누락된 특성이 있더라도 이를 따로 전처리할 필요가 없습니다.