Skip to content
Home » 랜덤 포레스트 파이썬 | [파이썬 실습] Random Forest 340 개의 새로운 답변이 업데이트되었습니다.

랜덤 포레스트 파이썬 | [파이썬 실습] Random Forest 340 개의 새로운 답변이 업데이트되었습니다.

당신은 주제를 찾고 있습니까 “랜덤 포레스트 파이썬 – [파이썬 실습] Random Forest“? 다음 카테고리의 웹사이트 kk.taphoamini.com 에서 귀하의 모든 질문에 답변해 드립니다: kk.taphoamini.com/wiki. 바로 아래에서 답을 찾을 수 있습니다. 작성자 ‍김성범[ 소장 / 인공지능공학연구소 ] 이(가) 작성한 기사에는 조회수 3,495회 및 좋아요 52개 개의 좋아요가 있습니다.

Table of Contents

랜덤 포레스트 파이썬 주제에 대한 동영상 보기

여기에서 이 주제에 대한 비디오를 시청하십시오. 주의 깊게 살펴보고 읽고 있는 내용에 대한 피드백을 제공하세요!

d여기에서 [파이썬 실습] Random Forest – 랜덤 포레스트 파이썬 주제에 대한 세부정보를 참조하세요

랜덤 포레스트 파이썬 주제에 대한 자세한 내용은 여기를 참조하세요.

[Python] Ensemble(앙상블) – Random Forest(랜덤포레스트)

[Python] Ensemble(앙상블) – Random Forest(랜덤포레스트). SuHawn 2020. 7. 31. 19:34. 이 게시글은 오로지 파이썬을 통한 실습만을 진행한다.

+ 여기를 클릭

Source: todayisbetterthanyesterday.tistory.com

Date Published: 1/19/2021

View: 883

파이썬으로 머신러닝 배우기 – 크리에이터의 추월차선 – 티스토리

1. 랜덤 포레스트(Random forest)란? 의사결정 트리를 랜덤하게 나온 것을 투표하여 결정하는 것이다. 분류, 회귀에 주로 사용된다.

+ 여기에 표시

Source: creatorjo.tistory.com

Date Published: 3/21/2021

View: 5444

[Machine Learning] Random Forest – 랜덤 포레스트 코드 구현 …

[Machine Learning] Random Forest – 랜덤 포레스트 코드 구현 (feat. python). Alex, Yoon 2020. 10. 4. 22:38 …

+ 여기에 더 보기

Source: alex-blog.tistory.com

Date Published: 2/17/2021

View: 380

[Python] Random Forest 알고리즘 정의, 장단점, 최적화 방법

Random Forest는 의사결정나무 모델 여러 개를 훈련시켜서 그 결과를 종합해 예측하는 앙상블 알고리즘입니다. 각 의사결정나무 모델을 훈련시킬 때 배깅( …

+ 여기에 표시

Source: heytech.tistory.com

Date Published: 4/4/2022

View: 9014

랜덤 포레스트 원리와 구현 사이킷런 예제로 코드 실습해보기

매일 조금씩 공부합니다. 파이썬(머신러닝)/sql/sas.

+ 더 읽기

Source: for-my-wealthy-life.tistory.com

Date Published: 4/17/2022

View: 3342

파이썬으로 랜덤 포레스트 분석 – Biohacker

파이썬으로 랜덤 포레스트 분석하기. … 이 글에서는 기계학습의 알고리즘 중의 하나인 Random forest을 간략하게 사용해보도록 하겠습니다.

+ 자세한 내용은 여기를 클릭하십시오

Source: partrita.github.io

Date Published: 8/16/2021

View: 4492

2.3.6 결정 트리의 앙상블 | 텐서 플로우 블로그 (Tensor ≈ Blog)

랜덤 포레스트random forest와 그래디언트 부스팅gradient boosting 결정 트리는 … 적용하려면 xgboost 패키지 와 파이썬 인터페이스를 검토해보는 것이 좋습니다.

+ 여기에 표시

Source: tensorflow.blog

Date Published: 5/10/2021

View: 5627

[Python 분류] 랜덤포레스트(Random Forest) iris 데이터 예측

[Python 분류] 랜덤포레스트(Random Forest) iris 데이터 예측 :: 마이자몽. by ♚ 2019. 2. 10. 의사결정 트리(Decision Tree). 랜덤포레스트를 공부하기 전에 의사 …

+ 여기에 보기

Source: myjamong.tistory.com

Date Published: 5/9/2022

View: 1503

[Sklearn] 파이썬 랜덤 포레스트 모델 학습, 하이퍼파라미터 튜닝

이번 포스팅에서는 파이썬에서 대표적인 머신러닝 분류기 중 하나인 랜덤 포레스트를 사이킷런에서 사용하는 방법에 대해서 살펴보도록 하겠습니다.

+ 여기에 더 보기

Source: jimmy-ai.tistory.com

Date Published: 10/13/2021

View: 7014

주제와 관련된 이미지 랜덤 포레스트 파이썬

주제와 관련된 더 많은 사진을 참조하십시오 [파이썬 실습] Random Forest. 댓글에서 더 많은 관련 이미지를 보거나 필요한 경우 더 많은 관련 기사를 볼 수 있습니다.

[파이썬 실습] Random Forest
[파이썬 실습] Random Forest

주제에 대한 기사 평가 랜덤 포레스트 파이썬

  • Author: ‍김성범[ 소장 / 인공지능공학연구소 ]
  • Views: 조회수 3,495회
  • Likes: 좋아요 52개
  • Date Published: 2021. 5. 9.
  • Video Url link: https://www.youtube.com/watch?v=k7Qu1sZm7No

[Python] Ensemble(앙상블)

이 게시글은 오로지 파이썬을 통한 실습만을 진행한다. 앙상블 기법중 RandomForest의 개념 및 원리를 알고자하면 아래 링크를 통해학습을 진행하면 된다.

https://todayisbetterthanyesterday.tistory.com/48?category=822147

실습에 사용할 데이터는 아래의 데이터이다. kaggle에서 제공하는 데이터이며, 상세한 내용은 아래와 같다.

otto_train.zip 1.69MB

id: 고유 아이디

feat_1 ~ feat_93: 설명변수

target: 타겟변수 (1~9)

RandomForest는 Bagging 기법에 학습 모델의 분산을 줄이기 위해서, 변수까지 특정 개수로 무작위 추출을 하는 방법으로 학습을 진행한다. RandomForest는 Tree기반의 앙상블 기법으로 sklearn을 통해 간단하게 구현이 가능하다. 그럼에도 불구하고, 보통 좋은 성능을 갖는다고 알려져있다.

이 RandomForest에 대해서 Python을 활용한 실습을 진행해보자.

1. 데이터 처리

# data 처리를 위한 library import os import pandas as pd import numpy as np from sklearn.model_selection import train_test_split

# 현재경로 확인 os.getcwd()

위의 코드는 파이썬 해당파일(.py / .ipynb)의 위치경로를 표기해주는 것이다. 만약 데이터가 다른 경로에 존재한다고 하였을 때, 전 경로를 확인하기 위해서 자주 사용한다.

# 데이터 불러오기 # kaggle data data = pd.read_csv(“./otto_train.csv”) data.head()

먼저 이 kaggle데이터는 target변수가 class_1~9까지 문자형식으로 되어있다. 그렇기에 이 문자형식의 target을 수치형 데이터(1~9)로 변환해줄 필요가 있다.

또한 이 kaggle데이터는 기업 및 단체가 데이터를 제공하기에 위와 같이 feature에 대한 정보를 알 수 없도록 해놓았다. 이를 통해 파이썬 실습을 진행할 것이다.

# shape확인 nCar = data.shape[0] # 데이터 개수 nVar = data.shape[1] # 변수 개수 print(‘nCar: %d’ % nCar, ‘nVar: %d’ % nVar )

otto_train 데이터에는 61878개의 행과 95가지의 변수가 존재한다. target을 제외하면 94가지 features가 존재하는 것이다. 먼저 target의 형변환을 해주어고 무의미한 변수를 제거해야한다.

# 무의미한 변수 제거 data= data.drop([‘id’],axis=1)

# 타겟 변수의 형변환 mapping_dict = {‘Class_1’ : 1, ‘Class_2’ : 2, ‘Class_3’ : 3, ‘Class_4’ : 4, ‘Class_5’ : 5, ‘Class_6’ : 6, ‘Class_7’ : 7, ‘Class_8’ : 8, ‘Class_9’ : 9,} after_mapping_target = data[‘target’].apply(lambda x : mapping_dict[x]) after_mapping_target

target의 형태가 “Class_1” – 1 ~ “Class_9” – 9 로 변환되었다. 이를 통해서 이제 classification을 진행할 것이다.

# features/target, train/test dataset 분리 feature_columns = list(data.columns.difference([‘target’])) X = data[feature_columns] y = after_mapping_target train_x, test_x, train_y, test_y = train_test_split(X, y, test_size = 0.2, random_state = 42) # 학습데이터와 평가데이터의 비율을 8:2 로 분할| print(train_x.shape, test_x.shape, train_y.shape, test_y.shape) # 데이터 개수 확인

2. Random Forest 적합

Random Forest

#기본적인 randomforest모형 from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import accuracy_score # 정확도 함수 clf = RandomForestClassifier(n_estimators=20, max_depth=5,random_state=0) clf.fit(train_x,train_y) predict1 = clf.predict(test_x) print(accuracy_score(test_y,predict1))

위의 Random Forest는 트리의 깊이를 5로 제한하고 20개의 Sampling을 통해 학습을 진행한다. 그 결과 정확도가 59%정도 나왔다. 분류기로 사용하기에는 좋지않은 정확도이다.

Random Forest Sample개수 증가

# sample 100개, tree depth – 20 clf = RandomForestClassifier(n_estimators=100, max_depth=20,random_state=0) clf.fit(train_x,train_y) predict2 = clf.predict(test_x) print(accuracy_score(test_y,predict2))

위의 경우에는 sample개수를 100개로 늘렸다. 그랬더니 정확도가 대략 78%까지 증가하였다. 그렇다면 무한하게 많이 sample개수를 증가시키면 되지 않는가? 하는 생각이 들 수도 있다. 하지만, sample개수가 증가한다고 하여서 무작정 성능이 향상되지는 않는다. 아래 경우를 보자

# sample 300개, tree depth – 20 clf = RandomForestClassifier(n_estimators=300, max_depth=20,random_state=0) clf.fit(train_x,train_y) predict2 = clf.predict(test_x) print(accuracy_score(test_y,predict2))

위의 경우는 샘플 개수를 300개까지 늘린 것이다. 그랬더니 성능이 100개보다 좋지 않는 61% 정도로 떨어졌다. 이것은 ML의 전반적인 특성이기도 하다. 무작정 학습의 반복횟수/sample개수를 늘린다는 것이 성능의 향상을 장담하지는 않는다. 그렇기에 해당 데이터에 맞는 선정 모델의 parameter은 분석가가 경험적으로 찾거나, 아니면 해당 분야에서 통상적으로 쓰이는 parameter를 알아야한다.

그렇다면 위의 모델에서 최적의 n_estimators parameter가 100이라고 가정하고, 이번에는 트리의 깊이를 늘려보자.

Random Forest Tree 깊이 증가

# sample 100개, tree depth – 100(max) clf = RandomForestClassifier(n_estimators=100, max_depth=100,random_state=0) clf.fit(train_x,train_y) predict2 = clf.predict(test_x) print(accuracy_score(test_y,predict2))

위의 결과를 보면 sample개수가 100개이고, 깊이를 최대로 허용하였을때, 정확도가 대략 81%까지 상승하였다. 물론 RandomForest를 포함한 ensemble모형에는 수많은 parameter들이 존재하기에 다른 parameter의 최적값 또한 찾아낸다면 더 좋은 성능을 발휘할 것이다.

하지만 그렇게되면 설명을 해야할게 너무 많아지기에 아래 sklearn 링크를 통해서 알아보기를 추천한다.

https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html

파이썬으로 머신러닝 배우기 – 랜덤 포레스트(RandomForestRegressor)

앙상블(emsemble)

랜덤 포레스트(Random forest) 모델

1. 랜덤 포레스트(Random forest)란?

의사결정 트리를 랜덤하게 나온 것을 투표하여 결정하는 것이다.

분류, 회귀에 주로 사용된다.

출처 : https://www.analyticsvidhya.com/blog/2020/05/decision-tree-vs-random-forest-algorithm/

Bagging Features

속성이 10개라고 10개 다 선정하는 것이 아니라

10을 제곱근 한 수 만큼 선정한다.

2. 분류 기준

엔트로피 이론

어떤 기준으로 가장 먼저 분류하면 좋을까?에 대해 고민할 때

보통 엔트로피 이론을 적용한다.

출처 https://m.blog.naver.com/with_msip/221974536459

3. 랜덤 포레스트 인자 결정

n_estimator = 트리의 수

max_depth = 트리의 깊이

max_features = 나누는 수

n_estimator 는 클 수록 좋다! 트리를 많이 만들어 볼수록 좋다. (경우의 수가 많아진다.)

max_features 는 각 트리의 무작위를 얼마나 할 것인지 결정한다.

작은 max_features와 큰 n_estimator 는 과대 적합을 줄인다는 장점이 있다.

랜덤 포레스트 모델을 쓸 때는 n_estimator 인자 와 max_features인자를 조절하며

결정계수가 가장 높아지는 인자를 사용하는 것이 좋다.

랜덤 포레스트 모델을 활용하면 분류와 회귀 모두 사용이 가능한데

분류를 할 때는 max_features = sqrt(n_features)

회귀 할 때는 max_features = n_features

를 써준다!

4. 랜덤 포레스트 모델 직접 사용해보기

x, y 데이터를 랜덤으로 만들어주고(지난 글과 같이 만들어준다.)

그 다음에 트리가 10, 20, 30, 40일때의 결정계수를 확인해보자.

import matplotlib.pyplot as plot import numpy as np import math x = np.random.rand(100,1) x = x * 10-5 y = np.array([math.sin(i) for i in x]) y = y + np.random.randn(100) from sklearn.ensemble import RandomForestRegressor #트리가 10개일때, 20일때, 30일때, 40일때 for i in (10, 20, 30, 40): model = RandomForestRegressor(n_estimators = i, random_state = 15) model.fit(x, y) relation_square = model.score(x, y) print(‘결정계수 : ‘, relation_square) y_p = model.predict(x) plot.scatter(x,y, marker = ‘x’) plot.scatter(x,y_p, marker = ‘o’) plot.show()

확인 결과 트리가 30일 때 즉, n_estimators가 30일 때 결정계수가 0.8244로 가장 높은 것을 볼 수 있다.

5. 이번에는 수학 점수로 총점을 예측해보자!

트리를 10, 20, 30, 40, 100, 150까지 반복해서 결정계수를 비교해보려한다.

student엑셀 파일도 지난 글에서 사용했던 파일을 그대로 썼고 수학 점수로 총점을 예측하고 그 때의 결정계수를 확인해보았다.

import matplotlib.pyplot as plot import numpy as np import math import pandas as pd import seaborn as sns import openpyxl plot.rcParams[“font.family”] = ‘Malgun gothic’ data = pd.read_excel(‘student.xlsx’, header = 0) newData = data[[‘kor’, ‘eng’, ‘math’, ‘social’, ‘science’, ‘total’]] #속성(변수)선택 x = newData[[‘math’]] y = newData[[‘total’]] from sklearn.ensemble import RandomForestRegressor for i in (10, 20, 30, 40, 100, 150): model = RandomForestRegressor(n_estimators = i, random_state = 15) model.fit(x, y) relation_square = model.score(x, y) print(‘결정계수 : ‘, relation_square) y_p = model.predict(x) plot.scatter(x,y, marker = ‘x’) plot.scatter(x,y_p, marker = ‘o’) plot.show()

n_estimators 값이 100일때 결정계수가 0.80225로 가장 높았고

150일때는 오히려 결정계수가 0.8004로 100일때보다는 낮게 나왔다.

적절한 값을 넣어주는 것이 매우 중요하다는 것을 알 수 있다.

LinearRegression로 예측한 것보다 RandomForestRegressor로 예측한 것이 더욱 정확하다는 것을 볼 수 있다.

또한 SVR로 예측한 것과 비교해볼 수도 있다. SVR이 가장 정확히 예측한 것 같다.

6. 이번에는 국, 영, 수, 사 4개 과목의 성적으로 총점을 예측해보자!

x에 국, 수, 사, 영을 넣어주고

n_estimators를 10, 20, 30, 40, 100, 150 으로 넣어가면서 각각의 결정계수를 확인해준다.

import matplotlib.pyplot as plot import numpy as np import math import pandas as pd import seaborn as sns import openpyxl plot.rcParams[“font.family”] = ‘Malgun gothic’ data = pd.read_excel(‘student.xlsx’, header = 0) newData = data[[‘kor’, ‘eng’, ‘math’, ‘social’, ‘science’, ‘total’]] #속성(변수)선택 x = newData[[‘kor’, ‘eng’, ‘math’, ‘social’]] y = newData[[‘total’]] from sklearn.ensemble import RandomForestRegressor for i in (10, 20, 30, 40, 100, 150): model = RandomForestRegressor(n_estimators = i, random_state = 15) model.fit(x, y) relation_square = model.score(x, y) print(‘결정계수 : ‘, relation_square) y_p = model.predict(x) ax1 = sns.distplot(y, hist = False, label = ‘y_실제’) ax2 = sns.distplot(y_p, hist = False, label = ‘y_예측’) plot.show()

트리가 10, 20, 30, 40, 100, 150일때 각각

결정계수 : 0.9738557966429059

결정계수 : 0.9718858271579351

결정계수 : 0.9666089242741718

결정계수 : 0.966769981253321

결정계수 : 0.9659313535311665

결정계수 : 0.9648583441186911

이 나왔고 이 경우 오히려 트리가 10일때가 결정계수가 가장 높다.

4개의 성적으로 총점을 예측하는 것은 SVR 모델이 훨씬 결정계수가 높다.

SVR의 경우 거의 99.999%로 예측이 되었다.

예측 모델 중 갑은 SVR인듯하다.

[Python] Random Forest 알고리즘 정의, 장단점, 최적화 방법

728×90

반응형

📚목차

1. 랜덤포레스트 정의

2. 랜덤포레스트 장단점

3. 실습코드 및 데이터셋

4. 코드 설명

1. Random Forest 정의

Random Forest는 의사결정나무 모델 여러 개를 훈련시켜서 그 결과를 종합해 예측하는 앙상블 알고리즘입니다. 각 의사결정나무 모델을 훈련시킬 때 배깅(Bagging) 방식을 사용합니다. 배깅은 전체 Train dataset에서 중복을 허용해 샘플링한 Dataset으로 개별 의사결정나무 모델을 훈련하는 방식입니다. 이렇게 여러 모델을 통해 예측한 값은 평균을 취하여 최종적인 예측값을 산출합니다. 이 배깅 방식은 예측 모델의 일반화(generalization, a.k.a., 안정성) 성능을 향상하는 데 도움이 됩니다.

2. 랜덤포레스트 장단점

장점 단점 일반화 및 성능 우수 개별 트리 분석이 어렵고 트리 분리가 복잡해 지는 경향 존재 파라미터 조정 용이 차원이 크고 희소한 데이터는 성능 미흡(e.g., text data) 데이터 scale 변환 불필요 훈련 시 메모리 소모가 크다. Overfitting이 잘 되지 않는다. Train data를 추가해도 모델 성능 개선이 어렵다.

3. 실습코드 및 데이터셋

와인 종류를 분류하는 문제를 Random Forest 알고리즘으로 풀어보겠습니다. 데이터셋과 전체 파이썬 코드는 이곳에서 받으실 수 있습니다.

코드에 주석을 달아뒀습니다. 분석 절차나 방법론에 대한 상세한 설명이 필요 없고 바쁘신 분들은 코드만 확인하셔도 무리 없으실 겁니다 🙂

4. 코드 설명

이제 주피터 노트북 “Cell by Cell”로 분석 절차나 방법론에 대해 설명하겠습니다. 이곳에서 데이터셋과 완성된 코드를 다운로드 받으셔도 좋고, 한 cell씩 따라 치셔도 됩니다. 파일 다운로드 방법은 2가지입니다.

1) 알집으로 직접 다운로드 받기

아래 그림 1과 같이 초록색 버튼 ‘code’를 클릭하시고 알집을 다운로드하여 알집을 풀어 주세요.

그림 1. 소스코드 및 데이터셋 전체 파일 ZIP으로 다운로드 받기

2) Git으로 다운로드하기

Git이 설치되어 있으신 분들은 clone 하셔도 됩니다.

git clone https://github.com/park-gb/wine-classification-rfc.git

소스코드는 src 폴더에, 데이터셋은 dataset 폴더에 있습니다.

라이브러리 Import

주피터 노트북 파일을 켜셔서 필요한 라이브러리를 import 합니다.

import numpy as np # 벡터, 행렬 등 수치 연산을 수행하는 선형대수 라이브러리 import pandas as pd # 시리즈, 데이터프레임 포맷 데이터 처리를 위한 라이브러리 import warnings; warnings.filterwarnings(action=’ignore’) # 경고 메시지 무시 import matplotlib.pyplot as plt # 데이터 시각화 라이브러리 import pickle # 객체 입출력을 위한 라이브러리 from sklearn.model_selection import train_test_split # 훈련 데이터, 테스트 데이터 분리 from sklearn.preprocessing import StandardScaler # 정규화 from sklearn.ensemble import RandomForestClassifier as RFC # 랜덤포레스트 분류 알고리즘 from sklearn.tree import DecisionTreeClassifier as DTC # 의사결정나무 분류 알고리즘 from sklearn.ensemble import GradientBoostingClassifier as GBC # 그래디언트 부스팅 분류 알고리즘 # 모델 평가를 위한 metrics from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, plot_confusion_matrix

만약 모듈이 설치되어 있지 않다는 에러 메시지가 출력된다면 해당 모듈을 아래와 같이 설치해 주시기 바랍니다.

pip install 모듈명

데이터 불러오기

온라인에서 레드 와인과 화이트 와인 데이터셋을 불러옵니다.

# 레드 와인데이터셋 불러오기 red = pd.read_csv(‘http://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv’, sep=’;’) # 화이트 와인데이터셋 불러오기 white = pd.read_csv(‘http://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-white.csv’, sep=’;’)

데이터 로드가 잘 되었는지 확인해 봅니다(그림 2).

red.head()

그림 2. 레드 와인 데이터 로드 확인

white.head()

그림 3. 화이트 와인 데이터 로드 확인

데이터 전처리

불필요한 변수 제거

레드 와인이냐, 화이트 와인이냐를 분류하는 데 있어 불필요한 설명변수가 있을 수 있습니다. 저는 데이터셋 내 설명변수 중에서도 ‘quality(품질)’이 그러한 변수라고 생각했습니다. 따라서 해당 변수 정보를 전처리 단계에서부터 제거하였습니다. 데이터프레임 내 특정 칼럼을 제외하기 위해 판다스에 drop 모듈을 활용하였습니다.

# 일반적으로 와인 퀄리티가 와인의 종류를 구분하지 않기 때문에 quality 변수 제거 red = red.drop([‘quality’], axis = 1) white = white.drop([‘quality’], axis = 1)

결측치 처리

판다스에 isnull().sum() 모듈을 활용하면 데이터프레임 칼럼별로 결측치(NaN)가 몇 개씩 있는지 쉽게 확인할 수 있습니다.

red.isnull().sum() # 결측치 미존재

아래와 같이 모든 칼럼에 결측치 개수가 0으로 전혀 없는 것을 알 수 있습니다.

fixed acidity 0 volatile acidity 0 citric acid 0 residual sugar 0 chlorides 0 free sulfur dioxide 0 total sulfur dioxide 0 density 0 pH 0 sulphates 0 alcohol 0 dtype: int64

화이트 와인의 경우에도 모든 변수에 결측치가 전혀 없는 것을 알 수 있습니다.

red.isnull().sum() # 결측치 미존재

fixed acidity 0 volatile acidity 0 citric acid 0 residual sugar 0 chlorides 0 free sulfur dioxide 0 total sulfur dioxide 0 density 0 pH 0 sulphates 0 alcohol 0 dtype: int64

반응형

이상치 확인 및 제거

이제 이상치(outlier)를 처리해 보겠습니다. 와인 종류에 따라 설명변수 데이터의 분포가 다를 수 있기 때문에 이상치는 클래스별로 따로 처리하는 것이 좋습니다.

이상치 시각화

설명변수별로 이상치가 얼마나 있는지 Boxplot(한국어: 상자 수염 그림)을 시각화하는 함수를 작성해 보겠습니다. matplotlib에서 subplot 모듈을 활용하면 여러 개의 그래프를 하나의 figure에 나타낼 수 있습니다.

이를 활용하여 11개의 설명변수를 6행 2열(가로 2줄, 세로 6줄)에 시각화하였습니다. 하이퍼파라미터인 flierprops 조정을 통해 이상치에 해당하는 데이터는 빨간색 다이아몬드 모양으로 시각화하였습니다.

def boxplot_vis(data, target_name): plt.figure(figsize=(30, 30)) for col_idx in range(len(data.columns)): # 6행 2열 서브플롯에 각 feature 박스플롯 시각화 plt.subplot(6, 2, col_idx+1) # flierprops: 빨간색 다이아몬드 모양으로 아웃라이어 시각화 plt.boxplot(data[data.columns[col_idx]], flierprops = dict(markerfacecolor = ‘r’, marker = ‘D’)) # 그래프 타이틀: feature name plt.title(“Feature” + “(” + target_name + “):” + data.columns[col_idx], fontsize = 20) plt.savefig(‘../figure/boxplot_’ + target_name + ‘.png’) plt.show()

먼저, Boxplot 그래프를 해석하는 방법에 대해 간단히 설명해 드리겠습니다. 아래 그림 4와 같이 세로축은 특정 값의 범위를 나타내고, 이 범위 내에서 데이터는 주로 파란색 박스 안에 분포합니다. 파란색 박스 가운데 노란색 직선으로 표시한 부분이 데이터의 중앙값(Median)이 됩니다.

박스 최상단은 제3 사분위수(Q3, 75th percentile), 최하단은 제1 사분위수(Q1, 25th percentile)입니다. 사분위수(Quantile)란 전체 데이터를 오름차순 정렬한 다음 25%씩 동일한 비율로 데이터를 나눈 것입니다. 즉, 제1 사분위수(Q1)는 가장 작은 데이터부터 전체 중 25% 비율만큼의 데이터를(25%) 의미하고, 제3 사분위수(Q3)는 중앙값(50%)에서부터 25% 비율만큼의 데이터를(75%) 의미합니다. 이 Q3과 Q1 사이 범위인 (Q3-Q1)을 사분범위(Interquartile range, IQR)이라고 합니다.

Boxplot의 수염에 해당하는 박스 바깥의 위, 아래에 가로로 긴 직선을 각각 Maximum, Minimum이라고 부릅니다. Maximum은 IQR 값에 1.5를 곱한 값에 Q3을 더한 값이고, Minimum은 Q1에서 IQR 값에 1.5를 곱한 값을 뺀 값입니다. 이상치는 이 Minimum과 Maximum 보다 각각 크거나 작은 값으로 극단치라고 부릅니다. 즉, 그림 4에서는 빨간색 다이아몬드가 모두 이상치에 해당하는 것입니다.

그림 4. Boxplot 설명

이제 다시 본론으로 돌아와, 레드 와인 데이터부터 이상치를 시각화해 보겠습니다.

앞선 설명과 마찬가지로 그림 5에서도 붉은색 다이아몬드 마커로 이상치를 표현하였습니다.

alcohol, citric acid 변수 외 대부분의 변수에는 이상치가 많은 것을 알 수 있습니다.

그림 5. Boxplot을 활용한 레드 와인 데이터 설명변수별 이상치 분포 시각화

다음으로 화이트 와인 데이터에 대해 이상치를 시각화해 보겠습니다.

residual sugar, density, alcohol 변수 외 다른 변수에는 이상치가 많을 것을 알 수 있습니다.

이처럼 와인 종류별로 이상치 개수가 상이합니다.

만일 두 데이터를 결합한 후 이상치를 검증했다면,

소중한 데이터가 이상치로 처리되어 활용하지 못하는 경우가 생길 수 있습니다.

그림 6. Boxplot을 활용한 화이트 와인 데이터 설명변수별 이상치 분포 시각화

이상치 제거

앞서 이상치의 기준에 대해 설명드린 것처럼, minimum과 maximum 사이에 분포하는 데이터만 분석에 선정하겠습니다.

사분위수 개념을 활용해 이상치 제거 함수를 작성하였고 이상치를 제거한 데이터를 반환합니다.

def remove_outlier(input_data): q1 = input_data.quantile(0.25) # 제 1사분위수 q3 = input_data.quantile(0.75) # 제 3사분위수 iqr = q3 – q1 # IQR(Interquartile range) 계산 minimum = q1 – (iqr * 1.5) # IQR 최솟값 maximum = q3 + (iqr * 1.5) # IQR 최댓값 # IQR 범위 내에 있는 데이터만 산출(IQR 범위 밖의 데이터는 이상치) df_removed_outlier = input_data[(minimum < input_data) & (input_data < maximum)] return df_removed_outlier 레드와인 데이터 이상치 제거 레드와인 데이터부터 이상치를 제거해 보겠습니다. # 이상치 제거한 데이터셋 red_prep = remove_outlier(red) 이상치를 처리한 데이터에 목표변수를 추가합니다. 레드와인은 target 값을 0으로 설정하겠습니다. # 목표변수 할당 red_prep['target'] = 0 이상치를 처리한 데이터프레임에 이상치를 처리하지 않은 목표변수 칼럼('target')을 추가하였기 때문에, 이상치로 처리된 행은 모두 결측치(NaN)로 채워집니다. 따라서 결측치를 카운팅하면 변수별 이상치 개수를 확인할 수 있습니다. # 결측치(이상치 처리된 데이터) 확인 red_prep.isnull().sum() 아래와 같이 Boxplot에서 확인했던 것처럼, alcohol, citric acid 변수는 이상치가 15개 이하이지만, 100개 이상의 이상치가 포함된 변수도 있는 것을 알 수 있습니다. fixed acidity 49 volatile acidity 19 citric acid 1 residual sugar 155 chlorides 112 free sulfur dioxide 33 total sulfur dioxide 58 density 45 pH 35 sulphates 59 alcohol 14 target 0 dtype: int64 이제 결측치가 포함된 모든 행을 삭제하기 위해 판다스에 dropna 모듈을 활용하였습니다. 행 삭제를 위해 axis 값은 0으로, 행 내 결측치가 하나라도 포함하면 삭제하기 위해 how 변수에는 'any'를 입력해 주었습니다. inplace 값에 True를 입력하면 결측치를 제거한 객체를 따로 저장할 필요 없이 바로 해당 객체가 업데이트됩니다. # 이상치 포함 데이터(이상치 처리 후 NaN) 삭제 red_prep.dropna(axis = 0, how = 'any', inplace = True) print(f"이상치 포함된 데이터 비율: {round((len(red) - len(red_prep))*100/len(red), 2)}%") 이상치가 1개라도 포함된 데이터의 비율은 25.58%입니다. 이상치 포함된 데이터 비율: 25.58% 화이트 와인 데이터 이상치 제거 화이트 와인 데이터도 앞서 정의한 함수를 통해 이상치를 제거합니다. # 이상치 제거한 데이터셋 white_prep = remove_outlier(white) 화이트 와인의 target 값은 1로 설정하겠습니다. # 목표변수 할당 white_prep['target'] = 1 레드 와인 데이터의 이상치 개수를 확인할 때와 마찬가지로, 화이트 와인 데이터의 이상치 개수를 결측치 개수를 카운팅 하여 계산합니다. # 결측치(이상치 처리된 데이터) 확인 white_prep.isnull().sum() 앞서 Boxplot에서 확인했듯이, residual sugar, density, alcohol 변수에는 이상치가 상대적으로 적은 것을 알 수 있습니다. fixed acidity 146 volatile acidity 186 citric acid 270 residual sugar 7 chlorides 208 free sulfur dioxide 50 total sulfur dioxide 19 density 5 pH 75 sulphates 124 alcohol 0 target 0 dtype: int64 이제 결측치가 포함된, 즉 이상치가 포함된 행을 데이터프레임에서 모두 제거합니다. # 이상치 포함 데이터(이상치 처리 후 NaN) 삭제 white_prep.dropna(axis = 0, how = 'any', inplace = True) print(f"이상치 포함된 데이터 비율: {round((len(white) - len(white_prep))*100/len(white), 2)}%") 레드 와인 데이터에서 이상치 비율이 25.58% 나온 것에 비해, 화이트 와인 데이터에서는 이상치 비율이 18.37%를 차지하였습니다. 이상치 포함된 데이터 비율: 18.37% 데이터 저장 전처리를 마친 두 데이터셋을 저장합니다. # 데이터셋 저장 red_prep.to_csv('../dataset/red_prep.csv') white_prep.to_csv('../dataset/white_prep.csv') 데이터 병합 이제 레드 와인과 화이트 와인 데이터를 병합합니다. 판다스에서 concat 모듈을 활용하였습니다. # 레드 와인, 화이트 와인 데이터셋 병합 df = pd.concat([red_prep, white_prep], axis = 0) df.head() 병합한 데이터셋은 따로 저장해 두겠습니다. df.to_csv('../dataset/wine_combined.csv') 와인 종류별로 데이터셋에서 비율은 어떻게 될까요? 타겟 칼럼에서 value_counts 모듈을 활용해 알아봤습니다. 이때 하이퍼파라미터인 normalize 값을 True로 설정하면 비율을 구할 수 있습니다. 참고로 기본값은 False이고 데이터 개수를 출력해 줍니다. # 화이트 와인이 레드와인보다 약 3배 더 많음 df.target.value_counts(normalize=True) 아래와 같이 타겟 칼럼의 값이 1인 화이트 와인 데이터의 개수가 레드 와인보다 약 3.3배 더 많은 것을 알 수 있습니다. 1 0.770625 0 0.229375 Name: target, dtype: float64 설명변수별 목표변수 간의 관계 시각화 이제 어떤 설명변수가 와인의 종류를 결정짓는 주요 영향인자인지 그래프를 시각화하여 살펴보겠습니다. 설명변수 1개씩 반복문을 통해 선정한 후 레드 와인과 화이트 와인 각각에 해당하는 데이터를 histogram으로 나타냅니다. subplot 모듈을 활용해 한 figure 안에 그래프를 모두 시각화하고 이를 저장하는 코드입니다. # 설명변수 선정 x = df[df.columns.difference(['target'])] # 설명변수명 리스트 feature_name = x.columns plt.figure(figsize=(30, 30)) for col_idx in range(len(feature_name)): # 6행 2열 서브플롯에 각 feature 박스플롯 시각화 plt.subplot(6, 2, col_idx+1) # 레드 와인에 해당하는 데이터 histogram 시각화 plt.hist(df[df["target"] == 0][feature_name[col_idx]], label = "Red wine", alpha = 0.5) # 화이트 와인에 해당하는 데이터 histogram 시각화 plt.hist(df[df["target"] == 1][feature_name[col_idx]], label = "White wine", alpha = 0.5) plt.legend() # 그래프 타이틀: feature name plt.title("Feature: "+ feature_name[col_idx], fontsize = 20) plt.savefig('../figure/relationship.png') plt.show() 시각화한 결과는 아래 그림 7과 같습니다. 그래프 해석은 간단합니다. 주황색이 화이트 와인 데이터이고 파란색이 레드와인 데이터입니다. 두 그래프가 겹치는 구간이 적게 데이터가 분포한다는 것은 해당 설명변수의 값에 따라 와인의 종류를 분류할 가능성이 높다는 뜻입니다. 이러한 관점에서, alcohol, PH 변수는 와인의 종류를 구분 짓는 데 어려움이 있을 것으로 보입니다. 이제 더욱 정량적이고 과학적인 방법으로 목표변수(와인의 종류)를 결정하는 설명변수를 찾아보겠습니다. 그림 7. 와인 종류에 따라 설명변수별 데이터 분포의 차이 시각화 데이터 스케일링 설명변수별로 데이터 범위가 천차만별이기 때문에, 이들 간의 비교를 쉽게 하기 위해 데이터 스케일링을 수행하겠습니다. 본 포스팅에서는 표준 스케일러인 StandardScaler를 사용합니다. 표준 스케일러는 평균을 0으로, 분산을 1로 스케일링합니다. 목표변수는 따로 스케일링할 필요가 없기 때문에, 설명변수만 스케일링하겠습니다. # 표준 스케일러(평균 0, 분산 1) scaler = StandardScaler() # 설명변수 및 목표변수 분리 x = df[df.columns.difference(['target'])] y = df['target'] # 설명변수 데이터 스케일링 x_scaled = scaler.fit_transform(x) 학습/테스트 데이터 분리 이제 분류 모델을 학습하고 평가하기 위해 학습 데이터셋과 테스트 데이터셋을 분리합니다. 본 포스팅에서는 학습 데이터와 테스트 데이터의 비율을 7:3으로 분리하였습니다. # 학습, 테스트 데이터셋 7:3 비율로 분리 x_train, x_test, y_train, y_test = train_test_split(x_scaled, y, test_size = 0.3, random_state = 123) 학습 데이터에서의 와인 종류별 비율은 다음과 같습니다. # 훈련 데이터 내 와인별 비율 y_train.value_counts(normalize=True) 클래스별 데이터 비율이 데이터 분리 이전과 유사한 것을 알 수 있습니다. 1 0.767006 0 0.232994 Name: target, dtype: float64 테스트 데이터에서의 와인 종류별 비율 역시 다음과 같습니다. # 테스트 데이터 내 와인별 비율 y_test.value_counts(normalize=True) 클래스별 데이터 비율이 데이터 분리 이전과 유사한 것을 알 수 있습니다. 1 0.779062 0 0.220938 Name: target, dtype: float64 728x90 Classifier 모델링 함수 이제 모델 학습 및 최적화에 필요한 함수를 작성해 보겠습니다. 기본 모델링 함수 먼저 하이퍼파라미터 튜닝 없이 모델을 학습하고 성능을 평가하는 함수입니다. 함수는 파라미터로 알고리즘 종류, 설명변수와 목표변수의 훈련 데이터, 테스트 데이터를 각각 전달받습니다. def modeling_uncustomized (algorithm, x_train, y_train, x_test, y_test): # 하이퍼파라미터 조정 없이 모델 학습 uncustomized = algorithm(random_state=1234) uncustomized.fit(x_train, y_train) # Train Data 설명력 train_score_before = uncustomized.score(x_train, y_train).round(3) print(f"학습 데이터셋 정확도: {train_score_before}") # Test Data 설명력 test_score_before = uncustomized.score(x_test, y_test).round(3) print(f"테스트 데이터셋 정확도: {test_score_before}") return train_score_before, test_score_before 하이퍼파라미터별 모델 성능 시각화 함수 다음은 하이퍼파라미터 튜닝에 따라 모델 성능이 어떻게 달라지는지 추이를 시각화하는 함수입니다. 하이퍼파라미터 값을 \(x\)축으로, \(y\)축은 학습 및 테스트 데이터 기반의 모델 정확도를 나타냅니다. def optimi_visualization(algorithm_name, x_values, train_score, test_score, xlabel, filename): # 하이퍼파라미터 조정에 따른 학습 데이터셋 기반 모델 성능 추이 시각화 plt.plot(x_values, train_score, linestyle = '-', label = 'train score') # 하이퍼파라미터 조정에 따른 테스트 데이터셋 기반 모델 성능 추이 시각화 plt.plot(x_values, test_score, linestyle = '--', label = 'test score') plt.ylabel('Accuracy(%)') # y축 라벨 plt.xlabel(xlabel) # x축 라벨 plt.legend() # 범례표시 plt.savefig('../figure/' + algorithm_name + '_' + filename + '.png') # 시각화한 그래프는 로컬에 저장 모델 최적화 함수: 학습할 트리 모델 개수 선정 이제 모델 최적화 함수로서 모델이 학습할 최적의 트리 개수를 결정하기 위한 함수입니다. 파라미터로 입력받은 트리 개수의 최솟값부터 트리 개수를 5개씩 최대 트리 개수까지 늘려가며 모델의 성능을 평가합니다. 모델 성능은 앞서 작성한 시각화 함수에 전달하여 하이퍼파라미터에 따른 성능 변화 추이를 시각화합니다. def optimi_estimator(algorithm, algorithm_name, x_train, y_train, x_test, y_test, n_estimator_min, n_estimator_max): train_score = []; test_score =[] para_n_tree = [n_tree*5 for n_tree in range(n_estimator_min, n_estimator_max)] for v_n_estimators in para_n_tree: model = algorithm(n_estimators = v_n_estimators, random_state=1234) model.fit(x_train, y_train) train_score.append(model.score(x_train, y_train)) test_score.append(model.score(x_test, y_test)) # 트리 개수에 따른 모델 성능 저장 df_score_n = pd.DataFrame({'n_estimators': para_n_tree, 'TrainScore': train_score, 'TestScore': test_score}) # 트리 개수에 따른 모델 성능 추이 시각화 함수 호출 optimi_visualization(algorithm_name, para_n_tree, train_score, test_score, "The number of estimator", "n_estimator") print(round(df_score_n, 4)) 모델 최적화 함수: 최대 깊이 선정 다음은 모델이 학습할 트리별 최대 깊이를 결정하기 위한 함수입니다. 전달받은 최대 깊이의 최솟값부터 깊이를 1씩 최대 깊이의 최댓값까지 늘려가며 모델의 성능을 평가합니다. 모델 성능은 앞서 작성한 시각화 함수에 전달하여 하이퍼파라미터에 따른 성능 변화 추이를 시각화합니다. def optimi_maxdepth (algorithm, algorithm_name, x_train, y_train, x_test, y_test, depth_min, depth_max, n_estimator): train_score = []; test_score = [] para_depth = [depth for depth in range(depth_min, depth_max)] for v_max_depth in para_depth: # 의사결정나무 모델의 경우 트리 개수를 따로 설정하지 않기 때문에 RFC, GBC와 분리하여 모델링 if algorithm == DTC: model = algorithm(max_depth = v_max_depth, random_state=1234) else: model = algorithm(max_depth = v_max_depth, n_estimators = n_estimator, random_state=1234) model.fit(x_train, y_train) train_score.append(model.score(x_train, y_train)) test_score.append(model.score(x_test, y_test)) # 최대 깊이에 따른 모델 성능 저장 df_score_n = pd.DataFrame({'depth': para_depth, 'TrainScore': train_score, 'TestScore': test_score}) # 최대 깊이에 따른 모델 성능 추이 시각화 함수 호출 optimi_visualization(algorithm_name, para_depth, train_score, test_score, "The number of depth", "n_depth") print(round(df_score_n, 4)) 모델 최적화 함수: 분리 노드의 최소 자료 수 선정 다음은 노드를 분리하기 위한 최소 자료 수를 결정하기 위한 함수입니다. 전달받은 분리 노드의 최소 자료 수의 최솟값부터 깊이를 2씩 분리 노드의 최소 자료 수의 최댓값까지 늘려가며 모델의 성능을 평가합니다. 모델 성능은 앞서 작성한 시각화 함수에 전달하여 하이퍼파라미터에 따른 성능 변화 추이를 시각화합니다. def optimi_minsplit (algorithm, algorithm_name, x_train, y_train, x_test, y_test, n_split_min, n_split_max, n_estimator, n_depth): train_score = []; test_score = [] para_split = [n_split*2 for n_split in range(n_split_min, n_split_max)] for v_min_samples_split in para_split: # 의사결정나무 모델의 경우 트리 개수를 따로 설정하지 않기 때문에 RFC, GBC와 분리하여 모델링 if algorithm == DTC: model = algorithm(min_samples_split = v_min_samples_split, max_depth = n_depth, random_state = 1234) else: model = algorithm(min_samples_split = v_min_samples_split, n_estimators = n_estimator, max_depth = n_depth, random_state = 1234) model.fit(x_train, y_train) train_score.append(model.score(x_train, y_train)) test_score.append(model.score(x_test, y_test)) # 분리 노드의 최소 자료 수에 따른 모델 성능 저장 df_score_n = pd.DataFrame({'min_samples_split': para_split, 'TrainScore': train_score, 'TestScore': test_score}) # 분리 노드의 최소 자료 수에 따른 모델 성능 추이 시각화 함수 호출 optimi_visualization(algorithm_name, para_split, train_score, test_score, "The minimum number of samples required to split an internal node", "min_samples_split") print(round(df_score_n, 4)) 모델 최적화 함수: 잎사귀 노드의 최소 자료 수 선정 다음은 잎사귀 노드 내 최소 자료 수를 결정하기 위한 함수입니다. 전달받은 잎사귀 노드의 최소 자료 수의 최솟값부터 깊이를 2씩 잎사귀 노드의 최소 자료 수의 최댓값까지 늘려가며 모델의 성능을 평가합니다. 모델 성능은 앞서 작성한 시각화 함수에 전달하여 하이퍼파라미터에 따른 성능 변화 추이를 시각화합니다. def optimi_minleaf(algorithm, algorithm_name, x_train, y_train, x_test, y_test, n_leaf_min, n_leaf_max, n_estimator, n_depth, n_split): train_score = []; test_score = [] para_leaf = [n_leaf*2 for n_leaf in range(n_leaf_min, n_leaf_max)] for v_min_samples_leaf in para_leaf: # 의사결정나무 모델의 경우 트리 개수를 따로 설정하지 않기 때문에 RFC, GBC와 분리하여 모델링 if algorithm == DTC: model = algorithm(min_samples_leaf = v_min_samples_leaf, max_depth = n_depth, min_samples_split = n_split, random_state=1234) else: model = algorithm(min_samples_leaf = v_min_samples_leaf, n_estimators = n_estimator, max_depth = n_depth, min_samples_split = n_split, random_state=1234) model.fit(x_train, y_train) train_score.append(model.score(x_train, y_train)) test_score.append(model.score(x_test, y_test)) # 잎사귀 노드의 최소 자료 수에 따른 모델 성능 저장 df_score_n = pd.DataFrame({'min_samples_leaf': para_leaf, 'TrainScore': train_score, 'TestScore': test_score}) # 잎사귀 노드의 최소 자료 수에 따른 모델 성능 추이 시각화 함수 호출 optimi_visualization(algorithm_name, para_leaf, train_score, test_score, "The minimum number of samples required to be at a leaf node", "min_samples_leaf") print(round(df_score_n, 4)) 최종 모델 학습 앞서 구한 최적의 하이퍼파라미터를 기반으로 최종 모델을 학습합니다. 학습한 모델을 pickle 모듈을 통해 저장합니다. 모델 성능 평가를 위해 평가지표로서 Accuracy, Precision, Recall, F1 스코어, Confusion Matrix를 활용합니다. 마지막으로 변수별 중요도를 산출하고 시각화합니다. def model_final(algorithm, algorithm_name, feature_name, x_train, y_train, x_test, y_test, n_estimator, n_depth, n_split, n_leaf): # 의사결정나무 모델의 경우 트리 개수를 따로 설정하지 않기 때문에 RFC, GBC와 분리하여 모델링 if algorithm == DTC: model = algorithm(random_state=1234, min_samples_leaf = n_leaf, min_samples_split = n_split, max_depth = n_depth) else: model = algorithm(random_state = 1234, n_estimators = n_estimator, min_samples_leaf = n_leaf, min_samples_split = n_split, max_depth = n_depth) # 모델 학습 model.fit(x_train, y_train) # 모델 저장 model_path = '../model/' model_filename = 'wine_classification_' + algorithm_name + '.pkl' with open(model_path + model_filename, 'wb') as f: pickle.dump(model, f) print(f"최종 모델 저장 완료! 파일 경로: {model_path + model_filename} ") # 최종 모델의 성능 평가 train_acc = model.score(x_train, y_train) test_acc = model.score(x_test, y_test) y_pred = model.predict(x_test) print(f"Accuracy: {accuracy_score(y_test, y_pred):.3f}") # 정확도 print(f"Precision: {precision_score(y_test, y_pred):.3f}") # 정밀도 print(f"Recall: {recall_score(y_test, y_pred):.3f}") # 재현율 print(f"F1-score: {f1_score(y_test, y_pred):.3f}") # F1 스코어 # 혼동행렬 시각화 plt.figure(figsize =(30, 30)) plot_confusion_matrix(model, x_test, y_test, include_values = True, display_labels = ['Red', 'White'], # 목표변수 이름 cmap = 'Pastel1') # 컬러맵 plt.savefig('../figure/' + algorithm_name + '_confusion_matrix.png') # 혼동행렬 자료 저장 plt.show() # 변수 중요도 산출 dt_importance = pd.DataFrame() dt_importance['Feature'] = feature_name # 설명변수 이름 dt_importance['Importance'] = model.feature_importances_ # 설명변수 중요도 산출 # 변수 중요도 내림차순 정렬 dt_importance.sort_values("Importance", ascending = False, inplace = True) print(dt_importance.round(3)) # 변수 중요도 오름차순 정렬 dt_importance.sort_values("Importance", ascending = True, inplace = True) # 변수 중요도 시각화 coordinates = range(len(dt_importance)) # 설명변수 개수만큼 bar 시각화 plt.barh(y = coordinates, width = dt_importance["Importance"]) plt.yticks(coordinates, dt_importance["Feature"]) # y축 눈금별 설명변수 이름 기입 plt.xlabel("Feature Importance") # x축 이름 plt.ylabel("Features") # y축 이름 plt.savefig('../figure/' + algorithm_name + '_feature_importance.png') # 변수 중요도 그래프 저장 Random Forest Classifier 기반 분류 모델 성능 평가 라이브러리를 import 할 때 RandomForestClassifier를 RFC로 치환하였습니다. 본 포스팅에서는 위와 같은 플로우에서 학습할 알고리즘 종류만 바꿔 추후에 활용하기 위해 algorithm이라는 객체에 알고리즘을 할당하는 방식을 사용하였습니다. 즉, 그래디언트 부스팅을 사용한다면, algorithm 객체에 GBC를 할당하면 되는 것이죠. # 랜덤포레스트 분류 알고리즘 algorithm = RFC algorithm_name = 'rfc' 기본 모델 학습 하이퍼파라미터 튜닝 없이 기본 모델을 학습시켜 봅니다. train_acc_before, test_acc_before = modeling_uncustomized(algorithm, x_train, y_train, x_test, y_test) 학습 데이터 기반 분류 모델의 정확도가 100%인 것으로 미루어 보아 과대적합이 발생한 것으로 보입니다. 따라서 하이퍼파라미터 튜닝을 통해 과대적합을 방지하기 위한 조치가 필요합니다. 학습 데이터셋 정확도: 1.0 테스트 데이터셋 정확도: 0.999 모델 최적화: (1) 학습할 트리 개수 선정 Random Forest 모델이 학습할 최적의 트리 개수를 선정해 보겠습니다. n_estimator_min = 1 n_estimator_max = 31 optimi_estimator(algorithm, algorithm_name, x_train, y_train, x_test, y_test, n_estimator_min, n_estimator_max) 트리 개수에 따른 학습 데이터 및 테스트 데이터에서의 모델 성능은 아래 그림 8과 같습니다. 학습 데이터 기반 모델 정확도가 여전히 100%인 것으로 보아 과적합이 발생한 것으로 보입니다. 그림 8. 트리 개수에 따른 모델 성능 추이 시각화 트리 개수는 많을수록 과적합 방지에 유리합니다. 따라서 트리 개수가 많고 학습 데이터 기반 모델 정확도와 테스트 데이터 기반 모델 정확도의 차이가 적은 값으로 선정하는 것이 좋습니다. 그래프보다 더욱 정밀하게 하이퍼파라미터별 모델 성능을 알아보기 위해 데이터프레임 형태로도 추이를 출력해 봤습니다(그림 9). 그림 9. 트리 개수별 모델 성능 추이 트리 개수가 30개 일 때 테스트 데이터 기반 모델 정확도가 가장 높고, 트리 개수가 더 많아져도 성능에 차이가 없다는 점에, 최적의 트리 개수는 30으로 설정하겠습니다. n_estimator = 30 모델 최적화: (2) 최대 깊이 Random Forest 모델의 최대 깊이를 선정해 보겠습니다. depth_min = 1 depth_max = 21 optimi_maxdepth(algorithm, algorithm_name, x_train, y_train, x_test, y_test, depth_min, depth_max, n_estimator) 최대 깊이에 따른 학습 데이터 및 테스트 데이터에서의 모델 성능은 아래 그림 10과 같습니다. 그림 10. 최대 깊이에 따른 모델 성능 추이 시각화 최대 깊이는 적을수록 과적합 방지에 유리합니다. 따라서 최대 깊이는 적고 학습 데이터 기반 모델 정확도와 테스트 데이터 기반 모델 정확도의 차이가 적은 값으로 선정하는 것이 좋습니다. 아래 그림 11과 같이 최대 깊이 값에 따른 모델 성능 추이를 데이터프레임 형태로 출력해 봤습니다. 그림 11. 최대 깊이별 모델 성능 추이 테스트 데이터 기반 모델 정확도가 점차 증가하다가 감소하기 시작하는 구간으로, 최대 깊이 6을 최적의 값으로 선정하였습니다. n_depth = 6 모델 최적화: (3) 분리 노드의 최소 자료 수 다음으로 노드를 분리할 때 최소 자료 수의 최적의 값을 선정해 보겠습니다. n_split_min = 1 n_split_max = 101 # 데이터프레임 행 최대 100개까지 반드시 출력 pd.set_option('display.max_row', 100) optimi_minsplit (algorithm, algorithm_name, x_train, y_train, x_test, y_test, n_split_min, n_split_max, n_estimator, n_depth) 분리 노드의 최소 자료 수에 따른 학습 데이터 및 테스트 데이터에서의 모델 성능은 아래 그림 11과 같습니다. 그림 11. 분리 노드의 최소 자료 수에 따른 모델 성능 추이 시각화 아래 그림 13과 같이 분리 노드의 최소 자료 수에 따른 모델 성능 추이를 데이터프레임 형태로 출력해 봤습니다. 그림 13. 분리 노드의 최소 자료 수에 따른 모델 성능 추이(일부) 분리 노드의 최소 자료 수는 많을수록 과적합 방지에 유리합니다. 따라서 분리 노드의 최소 자료 수는 많되 학습 데이터 기반 모델 정확도와 테스트 데이터 기반 모델 정확도의 차이가 적은 값으로 선정하는 것이 좋습니다. 이러한 관점에서, 분리 노드의 최소 자료 수는 66으로 선정하였습니다. n_split = 66 모델 최적화: (4) 잎사귀 노드의 최소 자료 수 다음으로 최적의 잎사귀 노드의 최소 자료 수를 선정해 보겠습니다. n_leaf_min = 1 n_leaf_max = 51 optimi_minleaf(algorithm, algorithm_name, x_train, y_train, x_test, y_test, n_leaf_min, n_leaf_max, n_estimator, n_depth, n_split) 잎사귀 노드의 최소 자료 수에 따른 학습 데이터 및 테스트 데이터에서의 모델 성능은 아래 그림 14과 같습니다. 그림 11. 분리 노드의 최소 자료 수에 따른 모델 성능 추이 시각화 아래 그림 15와 같이 잎사귀 노드의 최소 자료 수에 따른 모델 성능 추이를 데이터프레임 형태로 출력해 봤습니다. 그림 15. 잎사귀 노드의 최소 자료 수에 따른 모델 성능 추이(일부) 잎사귀 노드의 최소 자료 수는 많을수록 과적합 방지에 유리합니다. 따라서 잎사귀 노드의 최소 자료 수는 많되 학습 데이터 기반 모델 정확도와 테스트 데이터 기반 모델 정확도의 차이가 적은 값으로 선정하는 것이 좋습니다. 이러한 관점에서, 잎사귀 노드의 최소 자료 수는 20으로 선정하였습니다. n_split = 20 최종 모델 학습 이제 앞서 선정한 하이퍼파라미터로 최종 모델을 학습해 보겠습니다. model_final(algorithm, algorithm_name, feature_name, x_train, y_train, x_test, y_test, n_estimator, n_depth, n_split, n_leaf) 모델 성능은 아래와 같습니다. 모델의 정확도가 99.8%, F1 점수 역시 0.999인 만큼 분류 성능이 우수하다는 것을 알 수 있습니다. Accuracy: 0.998 Precision: 0.999 Recall: 0.998 F1-score: 0.999 Confusion Matrix를 시각화하면 아래 그림 16과 같습니다. 그림 16. Confusion Matrix 시각화 변수별 중요도를 산출하면 그림 17과 그림 18과 같습니다. chlorides(염화물), total sulfur dioxide(총 이산화황), volatile acidity(휘발성산), density(밀도)가 와인 분류 시 가장 중요한 Top 4임을 확인하실 수 있습니다. 그림 17. 변수별 중요도 산출 그림 18. 변수별 중요도 산출 📚참고할 만한 포스팅 "이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다." 오늘은 랜덤포레스트의 기본적인 개념과 파이썬으로 실습해 보는 시간을 가졌습니다. 포스팅 내용에 오류가 있을 경우 아래에 👇👇👇 댓글 남겨주시면 감사드리겠습니다. 그럼 오늘도 즐거운 하루 보내시길 바랍니다 🙂 고맙습니다. 728x90 반응형

랜덤 포레스트 원리와 구현 사이킷런 예제로 코드 실습해보기

오늘은 앙상블 기법 중 하나인 랜덤포레스트에 대해 공부해봤다. 랜덤포레스트를 배우려면 일단 결정트리(Decision Tree)가 뭔지부터 알아야 한다. 결정 트리에 대한 자세한 내용은 아래 포스팅을 참고!

2021.06.13 – [파이썬/머신러닝] – 결정트리(Decision Tree) , 엔트로피 개념과 시각화까지

랜덤포레스트는 결정트리 여러개로 만들어진 모델이다. 결정트리는 훈련 데이터에 오버피팅된다는 치명적인 단점이 있기 때문에 보통은 결정트리 하나를 단독으로 사용하기 보다는 랜덤포레스트를 사용한다.

랜덤포레스트 개념

하나의 결정트리가 모든 feature를 변수로 사용해서 y값을 예측한다면 앞서 말한대로 오버피팅 문제가 발생한다. 그래서 랜덤포레스트는 feature를 무작위로 뽑거나, 데이터를 무작위로 뽑아서 여러개의 작은 트리를 만들고 그 트리들을 결합한다.

예를 들어 feature가 30개가 있다면 그 중에 랜덤하게 5개만 뽑아서 트리를 하나 만들고, 또 다시 랜덤하게 5개의 feature를 뽑아서 두번째 트리를 만들고, 이런 식으로 트리를 여러 개 만드는 것이 바로 랜덤포레스트이다.

트리를 여러 개 만들면 트리 개수만큼 예측 결과값이 생성되는데 voting을 통해 결과값을 채택하게 된다. 이게 바로 앙상블 학습이다.

랜덤포레스트는 기본적으로 결정트리의 단점을 보완하는 모델이라 오버피팅이 적고 성능이 뛰어나다. n_estimators, max_features, max_depth 정도와 같은 몇몇 파라미터만 잘 튜닝해주면 튜닝을 많이 하지 않아도 높은 성능을 보인다.

*앙상블: 의견을 통합하거나 여러 결과를 합치는 것

-분류모델: 가장 많이 나온 값

-회귀모델: 평균값

랜덤포레스트 주요 파라미터

n_estimators: 트리를 몇 개 만들 것인지 (int, default=100), 값이 클수록 오버피팅 방지

criterion: gini 또는 entropy 중 선택

max_depth: 트리의 깊이 (int, default=None)

bootstrap: True이면 전체 feature에서 복원추출해서 트리 생성 (default=True)

max_features: 선택할 feature의 개수, 보통 default값으로 씀 (default=’auto’)

출처: scikit-learn

랜덤포레스트 예제(실습 코드)

사이킷런의 breast_cancer 데이터로 간단하게 예제 코드를 실행해보자.

from sklearn.tree import DecisionTreeClassifier from sklearn.ensemble import RandomForestClassifier from sklearn.datasets import load_breast_cancer from sklearn.model_selection import train_test_split cancer = load_breast_cancer() print(cancer.keys()) >>> dict_keys([‘data’, ‘target’, ‘frame’, ‘target_names’, ‘DESCR’, ‘feature_names’, ‘filename’]) print(cancer.target_names) print(cancer.feature_names) >>> [‘malignant’ ‘benign’] [‘mean radius’ ‘mean texture’ ‘mean perimeter’ ‘mean area’ ‘mean smoothness’ ‘mean compactness’ ‘mean concavity’ ‘mean concave points’ ‘mean symmetry’ ‘mean fractal dimension’ ‘radius error’ ‘texture error’ ‘perimeter error’ ‘area error’ ‘smoothness error’ ‘compactness error’ ‘concavity error’ ‘concave points error’ ‘symmetry error’ ‘fractal dimension error’ ‘worst radius’ ‘worst texture’ ‘worst perimeter’ ‘worst area’ ‘worst smoothness’ ‘worst compactness’ ‘worst concavity’ ‘worst concave points’ ‘worst symmetry’ ‘worst fractal dimension’]

breast_cacer데이터의 기본 구성 확인 후 train, test 데이터 분리

X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target, test_size=0.2, random_state=42 )

최적의 max_depth 찾기

from sklearn.model_selection import KFold cv = KFold(n_splits=5) # Desired number of Cross Validation folds #n_splits값이 클수록 오래걸림 accuracies = list() max_attributes = X_test.shape[1] depth_range = range(1, max_attributes) # Testing max_depths from 1 to max attributes # Uncomment prints for details about each Cross Validation pass for depth in depth_range: fold_accuracy = [] rand_clf = RandomForestClassifier(max_depth = depth) # print(“Current max depth: “, depth, ”

“) for train_fold, valid_fold in cv.split(train): f_train = train.loc[train_fold] # Extract train data with cv indices f_valid = train.loc[valid_fold] # Extract valid data with cv indices model = rand_clf.fit(X_train, y_train) valid_acc = model.score(X_test, y_test) fold_accuracy.append(valid_acc) avg = sum(fold_accuracy)/len(fold_accuracy) accuracies.append(avg) # print(“Accuracy per fold: “, fold_accuracy, ”

“) # print(“Average accuracy: “, avg) # print(”

“) # Just to show results conveniently df = pd.DataFrame({“Max Depth”: depth_range, “Average Accuracy”: accuracies}) df = df[[“Max Depth”, “Average Accuracy”]] print(df.to_string(index=False))

max_depth간에 accuracy 차이가 거의 없긴 하다. max_depth 6부터 정확도가 조금 떨어지므로 max_depth=5로 설정했다. 이제 랜덤포레스트 모델에 피팅을 시켜보자.

rand_clf = RandomForestClassifier(criterion=’entropy’, bootstrap=True, random_state=42, max_depth=5) rand_clf.fit(X_train, y_train) y_pred = rand_clf.predict(X_test) print(‘훈련세트 정확도: {:.3f}’ .format(rand_clf.score(X_train, y_train))) print(‘테스트세트 정확도: {:.3f}’ .format(rand_clf.score(X_test, y_test))) >>>훈련세트 정확도: 0.993 >>>테스트세트 정확도: 0.965

train set 정확도는 99.3%, test set 정확도는 96.5%로 아주 높다. 조금 의심스럽긴 하지만 잘 맞췄다고 할 수 있다.

from sklearn.metrics import confusion_matrix, classification_report print(confusion_matrix(y_test, y_pred)) print(classification_report(y_test, y_pred))

모델 훈련을 시켰으니 마지막으로 feature_importances를 확인해보자.

import seaborn as sns import numpy as np %matplotlib inline # feature importance 추출 print(“Feature importances:

{0}”.format(np.round(rand_clf.feature_importances_, 3))) # feature별 importance 매핑 for name, value in zip(cancer.feature_names , rand_clf.feature_importances_): print(‘{0} : {1:.3f}’.format(name, value)) # feature importance를 column 별로 시각화 하기 sns.barplot(x=rand_clf.feature_importances_ , y=cancer.feature_names)

worst area, worst concave points, mean concave points 세 개 변수의 중요도가 가장 높다고 할 수 있다.

파이썬으로 랜덤 포레스트 분석

df

=

pd

.

DataFrame

(

iris

.

data

,

columns

=

iris

.

feature_names

)

# sklearn provides the iris species as integer values since this is required for classification

# here we’re just adding a column with the species names to the dataframe for visualisation

df

[

‘species’

]

=

np

.

array

([

iris

.

target_names

[

i

]

for

i

in

iris

.

target

])

sns

.

pairplot

(

df

,

hue

=

‘species’

)

텐서 플로우 블로그 (Tensor ≈ Blog)

2.3.5 결정 트리 | 목차 | 2.3.7 커널 서포트 벡터 머신

앙상블ensemble은 여러 머신러닝 모델을 연결하여 더 강력한 모델을 만드는 기법입니다. 머신러닝에는 이런 종류의 모델이 많지만, 그중 두 앙상블 모델이 분류와 회귀 문제의 다양한 데이터셋에서 효과적이라고 입증되었습니다. 랜덤 포레스트random forest와 그래디언트 부스팅gradient boosting 결정 트리는 둘 다 모델을 구성하는 기본 요소로 결정 트리를 사용합니다.

랜덤 포레스트

앞서 확인한 것처럼 결정 트리의 주요 단점은 훈련 데이터에 과대적합되는 경향이 있다는 것입니다. 랜덤 포레스트는 이 문제를 회피할 수 있는 방법입니다. 랜덤 포레스트는 기본적으로 조금씩 다른 여러 결정 트리의 묶음입니다. 랜덤 포레스트의 아이디어는 각 트리는 비교적 예측을 잘 할 수 있지만 데이터의 일부에 과대적합하는 경향을 가진다는 데 기초합니다. 예컨대 잘 작동하되 서로 다른 방향으로 과대적합된 트리를 많이 만들면 그 결과를 평균냄으로써 과대적합된 양을 줄일 수 있습니다. 이렇게 하면 트리 모델의 예측 성능이 유지되면서 과대적합이 줄어드는 것이 수학적으로 증명되었습니다.

이런 전략을 구현하려면 결정 트리를 많이 만들어야 합니다. 각각의 트리는 타깃 예측을 잘 해야 하고 다른 트리와는 구별되어야 합니다. 랜덤 포레스트는 이름에서 알 수 있듯이 트리들이 달라지도록 트리 생성 시 무작위성을 주입합니다. 랜덤 포레스트에서 트리를 랜덤하게 만드는 방법은 두 가지 입니다. 트리를 만들 때 사용하는 데이터 포인트를 무작위로 선택하는 방법과 분할 테스트에서 특성을 무작위로 선택하는 방법입니다. 이 방식들을 자세히 살펴보겠습니다.

랜덤 포레스트 구축

랜덤 포레스트 모델을 만들려면 생성할 트리의 개수를 정해야 합니다(RandomForestRegressor나 RandomForestClassifier의 n_estimators 매개변수). 여기에서는 트리가 10개 필요하다고 가정하겠습니다. 이 트리들은 완전히 독립적으로 만들어져야 하므로 알고리즘은 각 트리가 고유하게 만들어지도록 무작위한 선택을 합니다. 트리를 만들기 위해 먼저 데이터의 부트스트랩 샘플bootstrap sample을 생성합니다. 다시 말해 n_samples개의 데이터 포인트 중에서 무작위로 데이터를 n_samples 횟수만큼 반복 추출합니다(한 샘플이 여러 번 중복 추출될 수 있습니다). 이 데이터셋은 원래 데이터셋 크기와 같지만, 어떤 데이터 포인트는 누락될 수도 있고(대략 1/3 정도 1 ) 어떤 데이터 포인트는 중복되어 들어 있을 수 있습니다.

예를 들면 리스트 [‘a’, ‘b’, ‘c’, ‘d’]에서 부트스트랩 샘플을 만든다고 해보겠습니다. 가능한 부트스트랩 샘플은 [‘b’, ‘d’, ‘d’, ‘c’]도 될 수 있고 [‘d’, ‘a’, ‘d’, ‘a’]와 같은 샘플도 만들어질 수 있습니다.

그다음 이렇게 만든 데이터셋으로 결정 트리를 만듭니다. 그런데 우리가 본 결정 트리 알고리즘과 조금 다릅니다. 각 노드에서 전체 특성을 대상으로 최선의 테스트를 찾는 것이 아니고 알고리즘이 각 노드에서 후보 특성을 랜덤하게 선택한 후 이 후보들 중에서 최선의 테스트를 찾습니다. 몇 개의 특성을 고를지는 max_features 매개변수로 조정할 수 있습니다. 후보 특성을 고르는 것은 매 노드마다 반복되므로 트리의 각 노드는 다른 후보 특성들을 사용하여 테스트를 만듭니다.

부트스트랩 샘플링은 랜덤 포레스트의 트리가 조금씩 다른 데이터셋을 이용해 만들어지도록 합니다. 또 각 노드에서 특성의 일부만 사용하기 때문에 트리의 각 분기는 각기 다른 특성 부분 집합을 사용합니다. 이 두 메커니즘이 합쳐져서 랜덤 포레스트의 모든 트리가 서로 달라지도록 만듭니다.

이 방식에서 핵심 매개변수는 max_features입니다. max_features를 n_features로 설정하면 트리의 각 분기에서 모든 특성을 고려하므로 특성 선택에 무작위성이 들어가지 않습니다(하지만 부트스트랩 샘플링으로 인한 무작위성은 그대로입니다). max_features=1로 설정하면 트리의 분기는 테스트할 특성을 고를 필요가 없게 되며 그냥 무작위로 선택한 특성의 임계값을 찾기만 하면 됩니다. 결국 max_features 값을 크게 하면 랜덤 포레스트의 트리들은 매우 비슷해지고 가장 두드러진 특성을 이용해 데이터에 잘 맞춰질 것입니다. max_features를 낮추면 랜덤 포레스트 트리들은 많이 달라지고 각 트리는 데이터에 맞추기 위해 깊이가 깊어지게 됩니다.

랜덤 포레스트로 예측을 할 때는 먼저 알고리즘이 모델에 있는 모든 트리의 예측을 만듭니다. 회귀의 경우에는 이 예측들을 평균하여 최종 예측을 만듭니다. 분류의 경우는 약한 투표 전략을 사용합니다. 즉 각 알고리즘은 가능성 있는 출력 레이블의 확률을 제공함으로써 간접적인 예측을 합니다. 트리들이 예측한 확률을 평균내어 가장 높은 확률을 가진 클래스가 예측값이 됩니다.

랜덤 포레스트 분석

앞서 사용한 two_moon 데이터셋을 가지고 트리 5개로 구성된 랜덤 포레스트 모델을 만들어보겠습니다.

In[69]:

from sklearn.ensemble import RandomForestClassifier from sklearn.datasets import make_moons X, y = make_moons(n_samples=100, noise=0.25, random_state=3) X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=42) forest = RandomForestClassifier(n_estimators=5, random_state=2) forest.fit(X_train, y_train)

랜덤 포레스트 안에 만들어진 트리는 estimator_ 속성에 저장됩니다. 각 트리에서 학습된 결정 경계와 이를 취합해 만든 결정 경계를 함께 시각화해보겠습니다(그림 2-33).

In[70]:

fig, axes = plt.subplots(2, 3, figsize=(20, 10)) for i, (ax, tree) in enumerate(zip(axes.ravel(), forest.estimators_)): ax.set_title(“트리 {}”.format(i)) mglearn.plots.plot_tree_partition(X, y, tree, ax=ax) mglearn.plots.plot_2d_separator(forest, X, fill=True, ax=axes[-1, -1], alpha=.4) axes[-1, -1].set_title(“랜덤 포레스트”) mglearn.discrete_scatter(X[:, 0], X[:, 1], y)

그림 2-33 다섯 개의 랜덤한 결정 트리의 결정 경계와 예측한 확률을 평균내어 만든 결정 경계

다섯 개의 트리가 만든 결정 경계는 확연하게 다르다는 것을 알 수 있습니다. 부트스트랩 샘플링 때문에 한쪽 트리에 나타나는 훈련 포인트가 다른 트리에는 포함되지 않을 수 있어 각 트리는 불완전합니다.

랜덤 포레스트는 개개의 트리보다는 덜 과대적합되고 훨씬 좋은 결정 경계를 만들어줍니다. 실제 애플리케이션에서는 매우 많은 트리를 사용하기 때문에(수백, 수천 개) 더 부드러운 결정 경계가 만들어집니다.

다른 예로 유방암 데이터셋에 100개의 트리로 이뤄진 랜덤 포레스트를 적용해보겠습니다.

In[71]:

X_train, X_test, y_train, y_test = train_test_split( cancer.data, cancer.target, random_state=0) forest = RandomForestClassifier(n_estimators=100, random_state=0) forest.fit(X_train, y_train) print(“훈련 세트 정확도: {:.3f}”.format(forest.score(X_train, y_train))) print(“테스트 세트 정확도: {:.3f}”.format(forest.score(X_test, y_test)))

Out[71]:

훈련 세트 정확도: 1.000 테스트 세트 정확도: 0.972

랜덤 포레스트는 아무런 매개변수 튜닝 없이도 선형 모델이나 단일 결정 트리보다 높은 97% 정확도를 내고 있습니다. 단일 결정 트리에서 한 것처럼 max_features 매개변수를 조정하거나 사전 가지치기를 할 수도 있습니다. 하지만 랜덤 포레스트는 기본 설정으로도 좋은 결과를 만들어줄 때가 많습니다.

결정 트리처럼 랜덤 포레스트도 특성 중요도를 제공하는데 각 트리의 특성 중요도를 취합하여 계산한 것입니다. 일반적으로 랜덤 포레스트에서 제공하는 특성 중요도가 하나의 트리에서 제공하는 것보다 더 신뢰할 만합니다. [그림 2-34]를 참고하세요.

In[72]:

plot_feature_importances_cancer(forest)

그림 2-34 유방암 데이터로 만든 랜덤 포레스트 모델의 특성 중요도

그림에서 알 수 있듯이 랜덤 포레스트에서는 단일 트리의 경우보다 훨씬 많은 특성이 0 이상의 중요도 값을 갖습니다. 단일 트리의 결과와 마찬가지로 랜덤 포레스트도 “worst radius” 특성이 매우 중요하다고 보지만, 가장 많은 정보를 가진 특성으로는 “worst perimeter”를 선택했습니다. 랜덤 포레스트를 만드는 무작위성은 알고리즘이 가능성 있는 많은 경우를 고려할 수 있도록 하므로, 그 결과 랜덤 포레스트가 단일 트리보다 더 넓은 시각으로 데이터를 바라볼 수 있습니다.

장단점과 매개변수

회귀와 분류에 있어서 랜덤 포레스트는 현재 가장 널리 사용되는 머신러닝 알고리즘입니다. 랜덤 포레스트는 성능이 매우 뛰어나고 매개변수 튜닝을 많이 하지 않아도 잘 작동하며 데이터의 스케일을 맞출 필요도 없습니다.

기본적으로 랜덤 포레스트는 단일 트리의 단점을 보완하고 장점은 그대로 가지고 있습니다. 만약 의사 결정 과정을 간소하게 표현해야 한다면 단일 트리를 사용할 수 있습니다. 왜냐하면 수십, 수백 개의 트리를 자세히 분석하기 어렵고 랜덤 포레스트의 트리는 (특성의 일부만 사용하므로) 결정 트리보다 더 깊어지는 경향도 있기 때문입니다. 그러므로 비전문가에게 예측 과정을 시각적으로 보여주기 위해서는 하나의 결정 트리가 더 좋은 선택입니다. 대량의 데이터셋에서 랜덤 포레스트 모델을 만들 때 다소 시간이 걸릴 수 있지만 CPU 코어가 많다면 손쉽게 병렬 처리할 수 있습니다. 멀티 코어 프로세서일 때는 (요즘의 모든 컴퓨터는 코어가 둘 이상입니다) n_jobs 매개변수를 이용하여 사용할 코어 수를 지정할 수 있습니다. 사용하는 CPU 코어 개수에 비례해서 속도도 빨라집니다(코어를 두 개 사용하면 랜덤 포레스트의 훈련 속도도 두 배 빨라집니다). 하지만 n_jobs 매개변수를 코어 개수보다 크게 지정하는 것은 별로 도움이 되지 않습니다. n_jobs=-1로 지정하면 컴퓨터의 모든 코어를 사용합니다. 2

유념할 점은 랜덤 포레스트는 이름 그대로 랜덤합니다. 그래서 다른 random_state를 지정하면 (또는 random_state를 지정하지 않으면) 전혀 다른 모델이 만들어집니다. 랜덤 포레스트의 트리가 많을수록 random_state 값의 변화에 따른 변동이 적습니다. 만약 같은 결과를 만들어야 한다면 random_state 값을 고정해야 합니다.

랜덤 포레스트는 텍스트 데이터 같이 매우 차원이 높고 희소한 데이터에는 잘 작동하지 않습니다. 이런 데이터에는 선형 모델이 더 적합합니다. 랜덤 포레스트는 매우 큰 데이터셋에도 잘 작동하며 훈련은 여러 CPU 코어로 간단하게 병렬화할 수 있습니다. 하지만 랜덤 포레스트는 선형 모델보다 많은 메모리를 사용하며 훈련과 예측이 느립니다. 속도와 메모리 사용에 제약이 있는 애플리케이션이라면 선형 모델이 적합할 수 있습니다.

중요 매개변수는 n_estimators, max_features이고 max_depth 같은 사전 가지치기 옵션이 있습니다. 3 n_estimators는 클수록 좋습니다. 더 많은 트리를 평균하면 과대적합을 줄여 더 안정적인 모델을 만듭니다. 하지만 이로 인해 잃는 것도 있는데, 더 많은 트리는 더 많은 메모리와 긴 훈련 시간으로 이어집니다. 경험적으로 봤을 때 “가용한 시간과 메모리만큼 많이” 만드는 것이 좋습니다.

앞서 이야기한 것처럼 max_features는 각 트리가 얼마나 무작위가 될지를 결정하며 작은 max_features는 과대적합을 줄여줍니다. 일반적으로 기본값을 쓰는 것이 좋은 방법입니다. 분류는 max_features=sqrt(n_features)이고 회귀는 max_features=n_features입니다. 4 max_features나 max_leaf_nodes 매개변수를 추가하면 가끔 성능이 향상되기도 합니다. 또 훈련과 예측에 필요한 메모리와 시간을 많이 줄일 수도 있습니다.

그래디언트 부스팅 회귀 트리

그래디언트 부스팅 회귀 트리는 여러 개의 결정 트리를 묶어 강력한 모델을 만드는 또 다른 앙상블 방법입니다. 이름이 회귀지만 이 모델은 회귀와 분류 모두에 사용할 수 있습니다. 5 랜덤 포레스트와는 달리 그래디언트 부스팅은 이전 트리의 오차를 보완하는 방식으로 순차적으로 트리를 만듭니다. 기본적으로 그래디언트 부스팅 회귀 트리에는 무작위성이 없습니다. 대신 강력한 사전 가지치기가 사용됩니다. 그래디언트 부스팅 트리는 보통 하나에서 다섯 정도의 깊지 않은 트리를 사용하므로 메모리를 적게 사용하고 예측도 빠릅니다. 그래디언트 부스팅의 근본 아이디어는 이런 얕은 트리 같은 간단한 모델(약한 학습기weak learner라고도 합니다)을 많이 연결하는 것입니다. 각각의 트리는 데이터의 일부에 대해서만 예측을 잘 수행할 수 있어서 트리가 많이 추가될수록 성능이 좋아집니다. 6

그래디언트 부스팅 트리는 머신러닝 경연 대회에서 우승을 많이 차지하였고 업계에서도 널리 사용합니다. 랜덤 포레스트보다는 매개변수 설정에 조금 더 민감하지만 잘 조정하면 더 높은 정확도를 제공해줍니다.

앙상블 방식에 있는 사전 가지치기나 트리 개수 외에도 그래디언트 부스팅에서 중요한 매개변수는 이전 트리의 오차를 얼마나 강하게 보정할 것인지를 제어하는 learning_rate입니다. 학습률이 크면 트리는 보정을 강하게 하기 때문에 복잡한 모델을 만듭니다. n_estimators 값을 키우면 앙상블에 트리가 더 많이 추가되어 모델의 복잡도가 커지고 훈련 세트에서의 실수를 바로잡을 기회가 더 많아집니다.

아래는 유방암 데이터셋을 이용해 GradientBoostingClassifier를 사용한 예입니다. 기본값인 깊이가 3인 트리 100개와 학습률 0.1을 사용하였습니다.

In[73]:

from sklearn.ensemble import GradientBoostingClassifier X_train, X_test, y_train, y_test = train_test_split( cancer.data, cancer.target, random_state=0) gbrt = GradientBoostingClassifier(random_state=0) gbrt.fit(X_train, y_train) print(“훈련 세트 정확도: {:.3f}”.format(gbrt.score(X_train, y_train))) print(“테스트 세트 정확도: {:.3f}”.format(gbrt.score(X_test, y_test)))

Out[73]:

훈련 세트 정확도: 1.000 테스트 세트 정확도: 0.958

훈련 세트의 정확도가 100%이므로 과대적합된 것 같습니다. 과대적합을 막기 위해서 트리의 최대 깊이를 줄여 사전 가지치기를 강하게 하거나 학습률을 낮출 수 있습니다.

In[74]

gbrt = GradientBoostingClassifier(random_state=0, max_depth=1) gbrt.fit(X_train, y_train) print(“훈련 세트 정확도: {:.3f}”.format(gbrt.score(X_train, y_train))) print(“테스트 세트 정확도: {:.3f}”.format(gbrt.score(X_test, y_test)))

Out[74]:

훈련 세트 정확도: 0.991 테스트 세트 정확도: 0.972

In[75]:

gbrt = GradientBoostingClassifier(random_state=0, learning_rate=0.01) gbrt.fit(X_train, y_train) print(“훈련 세트 정확도: {:.3f}”.format(gbrt.score(X_train, y_train))) print(“훈련 세트 정확도: {:.3f}”.format(gbrt.score(X_test, y_test)))

Out[75]:

훈련 세트 정확도: 0.988 훈련 세트 정확도: 0.965

이상의 두 방식은 모델의 복잡도를 감소시키므로 예상대로 훈련 세트의 정확도가 낮아졌습니다. 이 예에서 학습률을 낮추는 것은 테스트 세트의 성능을 조금밖에 개선하지 못했지만, 트리의 최대 깊이를 낮추는 것은 모델 성능 향상에 크게 기여했습니다.

다른 결정 트리 기반의 모델처럼 특성의 중요도를 시각화하면 모델을 더 잘 이해할 수 있습니다(그림 2-25). 트리를 100개나 사용했으므로 깊이가 1이더라도 모든 트리를 분석하기는 쉽지 않습니다.

In[76]:

gbrt = GradientBoostingClassifier(random_state=0, max_depth=1) gbrt.fit(X_train, y_train) plot_feature_importances_cancer(gbrt)

그림 2-35 유방암 데이터로 만든 그래디언트 부스팅 분류기의 특성 중요도

그래디언트 부스팅 트리의 특성 중요도 그래프가 랜덤 포레스트의 특성 중요도와 비슷합니다. 다만 그래디언트 부스팅은 일부 특성을 완전히 무시하고 있습니다.

비슷한 종류의 데이터에서 그래디언트 부스팅과 랜덤 포레스트 둘 다 잘 작동합니다만, 보통 더 안정적인 랜덤 포레스트를 먼저 적용하곤 합니다. 랜덤 포레스트가 잘 작동하더라도 예측 시간이 중요하거나 머신러닝 모델에서 마지막 성능까지 쥐어짜야 할 때 그래디언트 부스팅을 사용하면 도움이 됩니다.

대규모 머신러닝 문제에 그래디언트 부스팅을 적용하려면 xgboost 패키지 7 와 파이썬 인터페이스를 검토해보는 것이 좋습니다. 이 글을 쓰는 시점에는 여러 가지 데이터셋에서 scikit-learn의 그래디언트 부스팅 구현보다 빨랐습니다(그리고 튜닝하기도 쉽습니다).

장단점과 매개변수

그래디언트 부스팅 결정 트리는 지도 학습에서 가장 강력하고 널리 사용하는 모델 중 하나입니다. 가장 큰 단점은 매개변수를 잘 조정해야 한다는 것과 훈련 시간이 길다는 것입니다. 다른 트리 기반 모델처럼 특성의 스케일을 조정하지 않아도 되고 이진 특성이나 연속적인 특성에서도 잘 동작합니다. 그리고 트리 기반 모델의 특성상 희소한 고차원 데이터에는 잘 작동하지 않습니다.

그래디언트 부스팅 트리 모델의 중요 매개변수는 트리의 개수를 지정하는 n_estimators와 이전 트리의 오차를 보정하는 정도를 조절하는 learning_rate입니다. 이 두 매개변수는 매우 깊게 연관되며 learning_rate를 낮추면 비슷한 복잡도의 모델을 만들기 위해서 더 많은 트리를 추가해야 합니다. n_estimators가 클수록 좋은 랜덤 포레스트와는 달리 그래디언트 부스팅에서 n_estimators를 크게 하면 모델이 복잡해지고 과대적합될 가능성이 높아집니다. 일반적인 관례는 가용한 시간과 메모리 한도에서 n_estimators를 맞추고 나서 적절한 learning_rate를 찾는 것입니다.

중요한 또 다른 매개변수는 각 트리의 복잡도를 낮추는 max_depth(또는 max_leaf_nodes)입니다. 통상 그래디언트 부스팅 모델에서는 max_depth를 매우 작게 설정하며 트리의 깊이가 5보다 깊어지지 않게 합니다.

옮긴이_ 예를 들어, 100개의 샘플 중 어떤 샘플 하나가 선택되지 않을 확률은 99100입니다. 뽑은 샘플을 제외하지 않고 100번 반복할 때 한 번도 선택되지 않을 확률은 (99100)100=0.366입니다. 옮긴이_ n_jobs의 기본값은 1입니다. 옮긴이_ 결정 트리와 마찬가지로 max_leaf_nodes, min_samples_leaf, min_samples_split 매개변수도 제공합니다. 옮긴이_ max_features의 기본값은 ‘auto’이며 RandomForestClassifier에서는 sqrt(n_features)를, RandomForestRegressor에서는 n_features를 의미합니다. 옮긴이_ scikit-learn에서 제공하는 GradientBoostingClassifier와 GradientBoostingRegressor 모두 회귀 트리인 DecisionTreeRegressor를 사용하여 그래디언트 부스팅 알고리즘을 구현하고 있습니다. 옮긴이_ 그래디언트 부스팅은 이전에 만든 트리의 예측과 타깃값 사이의 오차를 줄이는 방향으로 새로운 트리를 추가하는 알고리즘입니다. 이를 위해 손실 함수를 정의하고 경사 하강법(gradient descent)을 사용하여 다음에 추가될 트리가 예측해야 할 값을 보정해나갑니다. 옮긴이_ xgboost(https://xgboost.readthedocs.io/)는 대용량 분산 처리를 위한 그래디언트 부스팅 오픈 소스 라이브러리로 C++, 파이썬, R, 자바 등 여러 인터페이스를 지원합니다. 최근에는 GPU를 활용하는 플러그인도 추가되었습니다.

2.3.5 결정 트리 | 목차 | 2.3.7 커널 서포트 벡터 머신

이 글은 한빛미디어에서 출간한 “파이썬 라이브러리를 활용한 머신러닝“의 1장과 2장입니다. 이 책의 저작권은 한빛미디어(주)에 있으므로 무단 복제 및 무단 전제를 금합니다.

[Python 분류] 랜덤포레스트(Random Forest) iris 데이터 예측 :: 마이자몽

의사결정 트리(Decision Tree)

랜덤포레스트를 공부하기 전에 의사결정트리에 대해서 알아야한다. 말그대로 의사를 결정하는데 이진형 답변의 연속 모델이다. 쉬운 예시를 하나 들어보면 ‘스무고개’ 와 비슷하게 예 아니오의 대답으로 최종 답변이 결정되는 구조이다. 위 의사 결정 트리는 사망 생존 여부를 결정하는 트리이다. 처음 남자 인지 여부를 확인하고, 나이를 확인 하고, sibsp 지수를 확인하여 사망인지 생존인지 시각적이고 명시적인 방법으로 의사 결정을 내릴 수 있다.

랜덤포레스트(Random Forest)

랜덤포레스트는 수많은 의사결정 트리가 모여 만들어진 숲으로 표현한다. 위 의사결정 트리에서는 성별, 나이, sibsp 지수 딱 3가지 요소로 생존여부를 결정하였다. 하지만, 생존 여부는 이 세가지 요소뿐만 아니라 더 많은 요소를 고려하여 최종 판단하는 것이 정확도에 영향을 끼칠것이다. 더많은 요소를 무작위로 결합하여 여러 의사결정 트리를 생성하여 결과를 반환한다.

결과를 도출하는 과정에서 모든 의사결정트리가 같은 답을 반환하지는 않을 것이다. 한 사람에 대한 정보를 랜덤포레스트에 넣었을때, 같은 정보로 사망, 생존 두가지 결과가 반환될것이다. 의견이 통합되지 않는 경우에는 다수결의 원칙으로 더 많은 반환값을 최종 결과로 선정한다. 이렇게 결과를 합치고, 의견을 통합하는 방식을 앙상블(Ensemble method)이라고한다.

sklean iris 데이터 예측

sklearn에서 제공해주는 iris데이터를 이용해서 iris의 종을 예측하는 작업을 해볼거다.

작업을 진행하기 전에 iris 데이터가 어떤 형식으로 되어있는지 확인한다.

iris 데이터

sklearn에서 제공되는 iris 데이터는 sepal(꽃 받침)과 petal(꽃잎)의 너비와 길이와 iris(붓꽃)의 종을 나타내고 있다.

제공된 데이터를 DataFrame으로 변형시켜 작업을 진행한다.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import pandas as pd from sklearn import datasets if __name__ = = ‘__main__’ : iris = datasets.load_iris() print ( ‘아이리스 종류 :’ , iris.target_names) print ( ‘target : [0:setosa, 1:versicolor, 2:virginica]’ ) print ( ‘데어터 수 :’ , len (iris.data)) print ( ‘데이터 열 이름 :’ , iris.feature_names) # iris data Dataframe으로 data = pd.DataFrame( { ‘sepal length’ : iris.data[:, 0 ], ‘sepal width’ : iris.data[:, 1 ], ‘petal length’ : iris.data[:, 2 ], ‘petal width’ : iris.data[:, 3 ], ‘species’ : iris.target } ) print (data.head())

cs

학습 & 예측 데이터 나누기

학습할 데이터와 예측할 데이터로 나눈다.

1 2 3 4 5 6 7 8 9 10 11 from sklearn.model_selection import train_test_split x = data[[ ‘sepal length’ , ‘sepal width’ , ‘petal length’ , ‘petal width’ ]] y = data[ ‘species’ ] # 테스트 데이터 30% x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0. 3 ) print ( len (x_train)) print ( len (x_test)) print ( len (y_train)) print ( len (y_test))

cs

데이터 학습 & 예측 정확도 확인

70%의 학습데이터를 랜덤포레스트를 이용해서 학습 시킨 후, 30%의 예측데이터를 예측 분류하여 실제 데이터와 비교하여 정확도를 확인한다.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 from sklearn.ensemble import RandomForestClassifier from sklearn import metrics # 학습 진행 forest = RandomForestClassifier(n_estimators = 100 ) forest.fit(x_train, y_train) # 예측 y_pred = forest.predict(x_test) print (y_pred) print (list(y_test)) # 정확도 확인 print ( ‘정확도 :’ , metrics.accuracy_score(y_test, y_pred)) cs

전체 코드 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 import pandas as pd from sklearn import datasets from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn import metrics if __name__ = = ‘__main__’ : iris = datasets.load_iris() print ( ‘아이리스 종류 :’ , iris.target_names) print ( ‘target : [0:setosa, 1:versicolor, 2:virginica]’ ) print ( ‘데어터 수 :’ , len (iris.data)) print ( ‘데이터 열 이름 :’ , iris.feature_names) # iris data Dataframe으로 data = pd.DataFrame( { ‘sepal length’ : iris.data[:, 0 ], ‘sepal width’ : iris.data[:, 1 ], ‘petal length’ : iris.data[:, 2 ], ‘petal width’ : iris.data[:, 3 ], ‘species’ : iris.target } ) print (data.head()) x = data[[ ‘sepal length’ , ‘sepal width’ , ‘petal length’ , ‘petal width’ ]] y = data[ ‘species’ ] # 테스트 데이터 30% x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0. 3 ) print ( len (x_train)) print ( len (x_test)) print ( len (y_train)) print ( len (y_test)) # 학습 진행 forest = RandomForestClassifier(n_estimators = 100 ) forest.fit(x_train, y_train) # 예측 y_pred = forest.predict(x_test) print (y_pred) print (list(y_test)) # 정확도 확인 print ( ‘정확도 :’ , metrics.accuracy_score(y_test, y_pred)) cs

[Sklearn] 파이썬 랜덤 포레스트 모델 학습, 하이퍼파라미터 튜닝

반응형

이번 포스팅에서는 파이썬에서 대표적인 머신러닝 분류기 중 하나인 랜덤 포레스트를 사이킷런에서 사용하는 방법에 대해서 살펴보도록 하겠습니다.

Sklearn(사이킷런) 랜덤 포레스트 분류기

kaggle의 타이타닉 데이터셋을 대상으로 사용 예시를 보여드리도록 하겠습니다.

우선 다음 코드처럼 모듈을 임포트 한 뒤, train / test 데이터셋을 분리하도록 하겠습니다.

train feature는 Pclass, SibSp, 성별을 사용하는 것으로 가정하겠습니다.

단, 이 모듈에서는 ‘male’, ‘female’ 등의 텍스트를 feature로 인식할 수 없으므로, one-hot 인코딩을 진행해주도록 하겠습니다.(남성인지 아닌지를 1/0 혹은 True/False로 표현)

이제 위에서 정한 train feature를 기반으로 생존여부를 예측하는 간단한 모델을 작성해보도록 하겠습니다.

from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier df[‘is_male’] = (df[‘Sex’] == ‘male’) # 성별 column one-hot 인코딩 train_columns = [‘Pclass’, ‘SibSp’, ‘is_male’] # train_feature를 나타내는 column # train, test 데이터셋 분리(random state 지정시 항상 고정, test set 비율도 지정 가능) X_train, X_test, y_train, y_test = train_test_split(df[train_columns], df[‘Survived’], test_size = 0.25, random_state = 32)

이제 Train, Test 데이터 셋(X_train, X_test) 및 각 데이터 셋에 매칭되는 생존 여부 라벨(y_train, y_test) 분리가 완료되었습니다.

Sklearn(사이킷런) 랜덤 포레스트 모델 학습

위에서 전처리가 완료되었으면 이제 랜덤 포레스트 모델을 선언하고 학습을 진행할 차례입니다.

먼저, 모델의 구조를 선언하도록 하겠습니다.

model = RandomForestClassifier(n_estimators=5, random_state=0)

모델 구조 선언시 하이퍼파라미터를 지정할 수 있습니다. 이는 맨 뒷 부분에서 추가로 다루도록 하겠습니다.

이제 train 데이터셋 및 라벨을 가지고 모델을 학습하도록 하겠습니다. 코드는 매우 간단합니다.

model.fit(X_train, y_train)

마지막으로 학습된 모델을 바탕으로 test 데이터셋의 라벨을 예측하고 실제 라벨과 정확도를 비교해보겠습니다.

from sklearn.metrics import accuracy_score # test 데이터셋에 대해서 라벨 예측(0, 1로 이루어진 array) y_pred = model.predict(X_test) # 예측 결과와 실제 결과 사이의 정확도 반환 accuracy_score(y_pred, y_test)

여기서는 약 76% 정도의 정확도가 기록된 것을 확인할 수 있었습니다.

Sklearn(사이킷런) 랜덤 포레스트 하이퍼파라미터

모델의 구조 선언 단계에서 랜덤 포레스트의 세부 구조를 정하여 여러 실험을 진행할 수 있습니다.

많이 사용하는 대표적인 하이퍼파라미터의 리스트는 다음과 같으며, 더 자세한 내용은 공식 document를 참조해주시기를 바랍니다.

n_estimator : forest size, 의사결정나무의 개수, 클수록 성능은 좋아질 수 있지만 시간이 오래 걸림

criterion : ‘gini’, ‘entropy’ 중 선택 가능, 기본 값은 ‘gini’이며, 의사 결정 나무를 학습하는 과정에서 기준 선정

max_depth : 과적합을 방지하기 위하여 의사결정나무의 depth 최대 값을 제한

min_samples_split : split을 끝낼 node의 sample 최소 갯수 선정, 클수록 과적합이 방지되지만, 너무 크면 split이 제대로 되지 않을 수 있음

min_samples_leaf : leaf node의 최소 sample 개수를 의미

n_jobs : -1로 설정시 컴퓨팅 프로세서 최대한 활용

random_state : 임의의 정수로 설정시 실행시마다 결과가 바뀌지 않고 고정됨

키워드에 대한 정보 랜덤 포레스트 파이썬

다음은 Bing에서 랜덤 포레스트 파이썬 주제에 대한 검색 결과입니다. 필요한 경우 더 읽을 수 있습니다.

이 기사는 인터넷의 다양한 출처에서 편집되었습니다. 이 기사가 유용했기를 바랍니다. 이 기사가 유용하다고 생각되면 공유하십시오. 매우 감사합니다!

사람들이 주제에 대해 자주 검색하는 키워드 [파이썬 실습] Random Forest

  • 동영상
  • 공유
  • 카메라폰
  • 동영상폰
  • 무료
  • 올리기
[파이썬 #실습] #Random #Forest


YouTube에서 랜덤 포레스트 파이썬 주제의 다른 동영상 보기

주제에 대한 기사를 시청해 주셔서 감사합니다 [파이썬 실습] Random Forest | 랜덤 포레스트 파이썬, 이 기사가 유용하다고 생각되면 공유하십시오, 매우 감사합니다.

See also  인류 멸망 보고서 다시 보기 | 인류멸망보고서 24769 좋은 평가 이 답변

Leave a Reply

Your email address will not be published. Required fields are marked *