[혼공머신] Chapter5. 트리 알고리즘

JB·2022년 2월 14일
0

혼공머신

목록 보기
5/9
post-thumbnail

개강이 다가오지만 한 학기 휴학하기로 한 휴학생은 유유자적 공부를 합(?)니다.
강산에(?) 살어리랏따...

챕터5부터는 생선 케이스가 끝나고 와인을 분류하는 모델을 만들기 시작합니다. 사실 1학년 때 처음 <컴퓨터과학의 이해>라는 수업에서 교수님이 한 번 언급하신 적 있는 케이스라서 1학년 새내기 때보다 내가 많이 성장했구나를 느낄 수 있었습니다. 그럼 머신러닝의 끝을 향해 ㄱㄱ


아래 내용은 <혼자 공부하는 머신러닝 + 딥러닝>과 숙명여자대학교 소프트웨어학부 <데이터사이언스개론> 수업을 참고하여 작성한 내용입니다.

1. 결정트리

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

알코올 도수, 당도, pH값으로 와인 종류를 구별해보자! 입니다. pandas의 info, describe 메소드를 사용하는데 describe는 데이터 개수, 평균, 중간값 등의 데이터가 나오니, 매우 유용하게 쓸 수 있을 것 같습니다.
여태까지 배운 내용들로 로지스틱 회귀로 모델을 만들어봅니다.

전반적으로 점수가 낮은 것을 보니, 과소적합인 것 같습니다. 어떻게 해결할 수 있을까요?

결정트리

  • 결정트리(Decision Tree) : target의 값과 다른 데이터를 subgroup 으로 나누어 분류하는 방식이다. 사이킷런의 DecisionTreeClassifier() 를 사용한다. 다음과 같이 시각화할 수 있다.

이 방법을 이용하여 결정 트리를 만들어보고 그 트리까지 출력해보겠다.

과대적합 모델이 나왔지만 로지스틱회귀보다 점수가 높게 형성되었다. 구체적인 분류 기준은 다음과 같다.
'sugar'=4.325 를 기준으로 5197개 데이터를 나누어서 음성 클래스(0, redwine) 은 1258, 양성클래스(1, whitewine)은 3939개이다. gini는 불순도이다.

불순도(impurity)

Decision Tree 에서 클래스의 분할 기준이 impurity 이며 DecisionTreeClassifier 클래스의 기준 기본값이 'gini'이다. gini impurity의 계산 방법(이진 클래스 기준)은 다음과 같다.

GiniImpurity=1((negativeclssratio)2+(positiveclassratio)2)Gini Impurity = 1 - ((negative clss ratio)^2 + (positive class ratio)^2)

(출처 : towards data science Gini Impurity Measure)

불순도의 최대는 0.5이며 이 때 양성과 음성 클래스가 1:1 비율로 섞여있다. Information Gain(IG, 정보이득)이 최대가 되도록 데이터를 나눈다. IG는 다음과 같이 구할 수 있다.

Segment S의 gini Impurity는 G(s), p1p_1현재세그먼트샘플수부모샘플수(=가중치)\frac{현재 세그먼트 샘플 수}{부모샘플수} (=가중치) 이다.

IG=G(parent)(p1G(c1)+p2G(c2))IG = G(parent) - (p_1G(c_1) + p_2G(c_2))

criterion을 'entropy'로 지정할 수 있으며 entropy impurity는 다음과 같다.


세그먼트 S의 무질서도 : H(S)

H(s)=p1log2(1p1)+p2log2(1p2)+H(s) = p_1 log_2(\frac{1}{p_1}) + p_2log_2(\frac{1}{p_2}) + \cdots
IG=H(parent)(p1G(c1)+p2G(c2))IG = H(parent) - (p_1G(c_1) + p_2G(c_2))

불순도를 기준으로 IG가 최대가 되도록 분할하며(각 세그먼트를 pure하게 나눔) 마지막에 도달한 노드의 클래스 비율을 보고 모델을 만든다.

가지치기

max_depth 를 지정하여 모델을 만들어줍니다. 제가 중간에 책과 다르게 한 점이 있었는데, 이미 그 전에 DecisionTreeClassfier에서는 전처리 과정이 필요없다는 것을 알고 있어서 그 코드를 뺐는데, 그게 사실 뒤에서 나오는 내용이었습니다. 전처리 코드를 넣으면 음수로 된 당도가 기준이 된다고 합니다.
위와 같은 결과를 얻었습니다. 중간에 불순도가 조금 아쉬운 부분트리가 있긴 하지만 이는 좀 더 공부해보도록 하겠습니다.

+) max_depth가 아니라 min_impurity_decrease로 가지치기하기. IG가 이 값보다 작으면 분할하지 않는다. 결과는 다음과 같다.
max_depth=3 일 때 리프노드의 purity가 더 높은 것 같다.



2. 교차검증과 그리드서치

이전처럼 모델을 생성하면 테스트 셋에 잘 맞는 모델이 됩니다(=overfitting) 이것을 교차검증을 통해 극복해봅시다!

검증 세트 (validation set)

이전에는 20%를 테스트세트로 평가하였지만 이제 '교차검증(cross validation)'을 사용하여 안정적인 검증을 해보려고 합니다.
일반적으로 사용하는 holdout Evaluation은 일반화 accuracy를 평가하지만 한 번만 하기 때문에 신뢰도가 떨어진다. 하지만 cross-validation은 holdout evaluation을 반복적으로 하기 때문에 신뢰도가 높고 통계적으로 dataset에 따른 분산까지 제시할 수 있다.
다음과 같이 5-fold cross-validation 검증이 가능하다. 다음과 같이 StratifiedKFold()로 폴드 교차 검증을 한다.
세번째 값이 5-fold, 네번째값이 10-fold 이다.

하이퍼파라미터 튜닝

  • 모델 파라미터 : 머신러닝 모델이 학습하는 파라미터
  • 하이퍼파라미터 : 사용자가 지정해야만 하는 파라미터 (사람의 개입 없이 하이퍼파라미터를 자동으로 튜닝하는 기술을 'AutoML' 이라고 한다)

decisiontree 에서 max_depth는 min_samples_split에 따라 바뀌기 때문에 두 변수를 동시에 수정해주어야 하며 만약 매개변수가 더 많아지면 n중 for문을 사용해가며 수정해야한다.
이를 이미 그리드 서치(Grid Search)로 사이킷런에서 구현되어 있다. 하이퍼파라미터와 교차검증을 한꺼번에 수행함으로 편리하게 해보자!

GridSearchCV()를 사용하여 매개변수를 바꿔가면서 최적의 파라미터를 찾을 수 있었습니다!

랜덤서치

매개변수의 값이 수치일 때 범위나 간격을 정하기 어렵고, 간격을 매우 작게 잡자니 학습시키는 데 오래걸립니다. 이 때 랜덤서치 클래스인 RandomizedSearchCV()를 사용합니다.
test 데이터셋으로 평가한 것이 거의 같네요!

+) 확인문제3에서 마지막 코드에서의 DecisionTreeClassifier클래스에 splitter='random' 매개변수를 추가하여 무작위로 분할하여 가장 좋은 것을 고르도록 해보라기에 해봤습니다. 성능은 0.8477 로 더 내려간 것을 알 수 있습니다. 왜 내려갔는지...아시는분?


3. 트리의 앙상블

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

  • 정형 데이터 : csv파일처럼 가지런히 정리되어 있는 데이터
  • 비정형 데이터 : 텍스트, 이미지, 영상, 음악 등 DB로 표현하기 어려운 데이터

-> 정형데이터에서 가장 뛰어난 알고리즘 : 앙상블 학습(ensemble learning) : decision tree 기반

랜덤 포레스트 (random forest)

안정적인 성능을 자랑하는 앙상블 학습의 대표 방법론 중 하나. 결정 트리를 랜덤하게 만들어 결정트리 숲을 만들고 최종 예측을 함.
부스트스트랩 방식으로 데이터를 추출하여 훈련을 시키며, 전체 특성 중 제곱근 갯수만큼 특성을 선택하여 사용한다(RandomForestClassifier 기준). 각 크리의 클래스별 확률을 평균하여 가장 높은 확률을 가진 클래스를 예측으로 삼는다.

따라서 overfitting을 방지할 수 있다!

아무래도 값을 보니 overfitting이 일어난 것 같다. 그래도 importances를 찍어보니 대체로 특성 중요도를 기존보다 치우쳐서 잡지 않았다. 더 많은 샘플을 사용하고 싶다면 OOB 샘플(out of bag) 을 이용하여 클래스를 선언할 때 oob_score=True 를 써서 구현할 수 있다!

엑스트라 트리 (Extra Tree)

부트스트랩 샘플 방식을 채택하지 않고 전체 훈련 셋을 사용하여 노드 분할 시 무직위로 분할한다. 위에 랜덤서치 +) 했던 것이 엑스트라 트리라고 한다. 특성을 무작위로 분할하기 때문에 성능은 낮아지지만 overfitting을 막는다고 한다. 랜덤하게 뽑기 때문에 속도가 빠르다.

그레디언트 부스팅(Gradient Boosting)

깊이가 얕은 결정 트리를 사용하여 이전 트리의 오차를 보완하는 방식의 앙상블 방법. default depth = 3 이며 결정트리 100개를 사용한다. overfitting 에 강하다. 경사하강법을 사용하여 분류에서는 로지스틱 손실 함수를 사용하고 회귀에서는 평균제곱오차함수를 사용한다.
결정 트리를 계속 추가하면서 손실 함수의 가장 낮은 곳을 찾아 이동한다.
돌려보니 정말 overfitting 이 거의 보이지 않는다. 학습률과 트리를 증가시켜 보자!

심하게 overfitting 되진 않은 것 같다. 특성 중요도를 출력해보니, 다른 것보다 한 특성에 조금 더 집중하기는 했다! 약 0.68...?

subsample 매개변수를 이용하여 배치사이즈를 설정하듯이 쓸 수 있다고 합니다. 매우 신기한 구조인 것 같습니다.

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

가장 인기있는 알고리즘이라고 한다. 입력 특성을 256개의 구간으로 나누고 하나를 떼어놓고 누락된 값을 위해서 사용하여 전처리를 할 필요가 없다고 한다. 트리 개수는 max_iter를 사용하며 성능을 높이기 위해서는 이 매개변수를 테스트해보면 된다. 책에서는 enable_hist_gradient_boosting을 가져오라고 했지만 경고에 필요 없다고 떠서 주석처리를 해줬다. 버전이 업그레이드 되어서 필요 없나보다. overfitting이 덜 일어나면서 좋은 성능을 보여주는 것 같다.
특성 중요도 계산을 위해 permutation_importance()를 사용하여 특성을 랜덤하게 섞어서 모델 성능이 변하는지 관찰하고 어떤 것이 중요한 지 계산해보겠습니다.
전반적으로 앙상블 모델이 1%정도 좋아보입니다.

+) sklearn 외에도 히스토그램 기반 그레디언트 부스팅 알고리즘을 구현한 라이브러리는 XGBoost 가 있다.


기본미션 : 교차검증 그림으로 설명하기(위에 자료 캡쳐본)
선택미션 : Ch.05(05-3) 앙상블 모델 손코딩 코랩 화면 인증샷(완료)


다음주차가 머신러닝 마지막이다. 정말 많은 것을 배운 것 같다. 특히 이렇게 정리해두니까, 랩미팅 때에도 갖다 썼다...ㅋㅋㅋㅋㅋㅋㅋ 이미 정리되어 있어서 굳이 찾을 필요 없는 이 편리함...! 마침 이제 강화학습도 맡게 되어서 내일 바로! chapter6를 공부하고 올릴 것 같다. 하루만에 공부할 수 있을까 싶지만 해야하니까 한다...

(매일매일 나의 상태)



profile
자율주행 이동체를 배우고 있는 JB입니다.

2개의 댓글

comment-user-thumbnail
2022년 2월 14일

정리 무척 잘하셨네요. 술술 읽혀집니다. :D

1개의 답글