멋사 AISCOOL 7기 Python/INPUT
[머신러닝] pima 데이터를 사용한 분류: Random Forest
dundunee
2022. 11. 17. 17:16
3️⃣Random Forest
✏️ 다수의 결정크리들을 학습하는 앙상블 방법이다.
✏️ 머신러닝에서 랜덤 포레스트는 분류, 회귀 분석 등에 사용되는 앙상블 학습 방법의 일종으로, 훈련 과정에서 구성한 다수의 결정트리로 부터 분류 또는 평균 예측치를 출력함으로써 동작한다.
- sklearn.ensemble 모듈에 무작위 결정트리를 기반으로 하는 두가지 평균 알고리즘 중 하나로 분류기 구성에 임의성을 도입하여 다양한 분류기 집합이 생성된다.
- 랜덤 포레스트는 다양한 트리를 결합하며 분산을 줄이며, 전반적으로 더 나은 모델을 생성할 수 있다.
- 실제로 개별 의사결정트리는 일반적으로 높은 분산을 나타내며 과적합되는 경향이 있다.
- 따라서 랜덤 포레스트의 무작위성은 예측 오류가 다소 분리된 의사결정트리를 생성하며, 이러한 예측의 평균을 취하면 일부 오류가 상쇄될 수 있다.
✅배깅(bagging)을 이용한 포레스트 구성
- bootstrap aggregating의 약자로, 부트스트랩(boorstrap)을 통해 조금씩 다른 훈련 데이터에 대해 훈련된 기초 분류기(base learner)들을 결합(aggregating)시키는 방법
- **부트스트랩**이란 주어진 훈련 데이터에서 중복을 허용하여 원 데이터셋과 같은 크기의 데이터셋을 만드는 과정을 말한다.
- 배깅은 서로 다른 데이터셋들에 대해 훈련시킴으로써 트리들을 비상관화 시키는 과정이다.
- 배깅을 통해 랜덤포레스트를 훈련시키는 과정은 아래와 같다.
- 부트스트랩 방법을 통해 T개의 훈련 데이터셋을 생성한다.
- T개의 기초 분류기(트리)들을 훈련시킨다.
- 기초 분류기(트리)들을 하나의 분류기(랜덤 포레스트)로 결합한다(평균 또는 과반수투표 방식 이용).
- 이는 결정트리의 과적합(overfitting) 문제를 예방할 수 있다. 부트스트랩과정은 트리들의 편향은 그대로 유지하면서 분산을 감소시키기 때문에 포레스트의 성능을 향상시킨다.
- 즉 한개의 결정 트리의 경우 훈련 데이터에 있는 노이즈에 대해 매우 민감하지만, 트리들이 서로 상관화 되어있지않다면(비상관화) 여러 트리들의 평균은 노이즈에 대해 강해진다.
✅중요 매개변수
1️⃣n_estimators: 트리의 개수
- 총 포레스트를 몇개의 트리로 구성할지를 결정하는 매개변수
- 포레스트가 작으면 트리들을 구성하고 테스트하는데 시간이 짧은 대신 일반화 능력이 떨어진다.
- 포레스트 크기가 크다면 훈련과 테스트 시간은 증가하지만결과값이 상대적으로 연속적이며 일반화 능력이 뛰어나다.
2️⃣ max_depth
- 하나의 트리에서 루드노트부터 종단 노드까지 최대 몇개의 노드를 거칠 것인지를 정하는 매개변수
- 최대 허용 깊이가 작으면 과소적합이 일어나고, 최대 허용 깊이가 크면 과대 적합이 일어난다.
3️⃣ max_features
- 노드를 분할할 때 고려해야할 기능의 임의의 하위집합 크기이다.
- 낮을 수록 분산의 감소가 크지만 치우짐의 증가도 커진다.
RandomForestClassifier(
n_estimators=100,
criterion='gini',
max_depth=None,
min_samples_split=2,
min_samples_leaf=1,
min_weight_fraction_leaf=0.0,
max_features='sqrt',
max_leaf_nodes=None,
min_impurity_decrease=0.0,
bootstrap=True,
oob_score=False,
n_jobs=None,
random_state=None,
verbose=0,
warm_start=False,
class_weight=None,
ccp_alpha=0.0,
max_samples=None,
)
Best nodes are defined as relative reduction in impurity
✅ 모델링
#feature engineering
# 수치형 변수의 범주화
df["Pregnancies_high"] = df["Pregnancies"] > 6
#결측치처리
#결측치가 있는 데이터는 학습시킬 수 없다
df["Insulin_nan"] = df["Insulin"].replace(0, np.nan)
Insulin_mean = df.groupby("Outcome")["Insulin_nan"].mean()
df["Insulin_fill"] = df["Insulin_nan"]
df.loc[(df["Insulin_nan"].isnull())&(df["Outcome"]==1), "Insulin_fill"] = Insulin_mean[1]
df.loc[(df["Insulin_nan"].isnull())&(df["Outcome"]==0), "Insulin_fill"] = Insulin_mean[0]
#이상치
desc = df["Insulin_nan"].describe()
IQR = desc['75%'] - desc['25%']
max_out = desc['75%'] + (1.5*IQR)
df = df[df["Insulin_fill"] < max_out]
df.shape
>>> #(744, 12)
#모델링
split_count = int(df.shape[0] * 0.8)
train = df[:split_count]
test = df[split_count:]
train.shape, test.shape
>>> #(595, 11), (149, 11)
label_name = "Outcome"
feature_names = df.columns.tolist()
feature_names.remove("Outcome")
feature_names.remove("Insulin")
feature_names.remove("Insulin_nan")
X_train = train[feature_names]
y_train = train[label_name]
X_test = test[feature_names]
y_test = test[label_name]
from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier(n_estimators=1000,
max_depth=6,
n_jobs=-1,
random_state=42)
model.fit(X_train, y_train)
y_predict = model.predict(X_test)
(y_test == y_predict).mean()
>>> #0.8926174496644296
sns.barplot(x = model.feature_importances_, y = model.feature_names_in_)