728x90

머신 러닝의 대표적인 문제

- 분류와 회귀 문제가 있음.

- 분류 : 주어진 데이터가 있으면 이 데이터가 어떤 카테고리에 속하는가에 대한 문제

- 회귀 : 데이터가 주어지면 이 데이터로 연속적인 값을 추정하는 문제

 

 

선형 회귀

- 독립 변수들과 하나의 종속 변수가 주어지고, 이에 대한 데이터들이 있을때 종속 변수를 가장 잘 추정하는 직선을 구하는 문제

- 새로운 데이터가 주어지면 학습 과정에서 구한 회귀선으로 연속적인 값을 추정할 수 있음.

- 선형 회귀 모델은 계수 벡터 beta = [beta0, . . ., beta_p], 독립 변수 벡터 x = [0, x1, ...., x_p]의 선형 결합의 형태가 됨.

- e는 오차 모형으로 기본적으로 평균 0, 분산이 1인 정규 분포를 따르고 있음.

 -> 회귀 선과 추정한 y 사이의 오차를 의미함.

 

- 실제 종속 변수를 y, 주어진 독립변수를 통해 예측한(추정한) y를 y hat로 표기

- 오차 e는 y - y_hat으로 아래와 같은 관계를 가지고 있음.

 

 

 

 

단순 선형 회귀 모형

- 독립 변수가 1개인 선형 회귀 모형

- 아래의 좌측과 같이 2차원 공간 상에 점들이 주어질때, 우측과 같은 선형 회귀 모델을 구할 수 있음

- 기존의 회귀 계수 beta를 여기선 가중치의 의미로 w로 표기함.

- 오차 = 실제 값 - 추정 값의 관계를 가짐.

 

 

 

 

최소 제곱 오차 MSE : Mean Sqaured Error

- 실제 결과(y_i) - 추정 결과(y_i hat)의 제곱한 것을 모든 데이터에 대해 합한 후 데이터 갯수(N) 만큼 나누어 구한 오차

- 위의 산점도 데이터가 주어질떄 MSE를 최소가 되게하는 회귀 계수들로 선형 회귀 모델을 만듬

 

회귀 계수 구하기 기초

- MSE를 최소로 만드는 회귀 계수는 편미분을 통해 구할 수 있음.

- y = x^2라는 그래프가 주어질때, argmin(y)를 구하는 x를 얻으려면, y를 x로 편미분하여 0이 나오게하는 x를 구하면됨.

- d/dx y = 2x = 0     => x = 0일때 기울기는 0으로 y는 최소 값을 가짐

- 단순 선형 회귀 모델의 회귀 계수 구하는 방법 : MSE를 w0, w1에 편미분 한 후 0이 되도록 하는 w0, w1를 구함. 

 

 

회귀 계수 구하기

- MSE를 w0, w1로 편미분하여 0이되는 w0, w1을 구하자

 

- n제곱 다항식의 미분에 대한 공식을 이용하여 w0, w1에 대해 편미분을 하면 아래와 같이 정리할 수 있음.

 

w0 회귀 계수 구하기

- 회귀 계수는 초기에 특정 값(주로 1)로 초기화 후 오차의 크기에 따라 갱신 값을 빼 조금씩 조정됨

- MSE를 w0로 편미분(갱신 값)하여 0이 되게 만드는 w0는 아래와 같이 구할 수 있음.

 => 기존의 회귀 계수(w0) - 기존 회귀 계수의 오차(갱신 값, d MSE/ d w0) = 새 회귀 계수(w0)

- 갱신 값이 너무 큰 경우, 올바른 회귀 모델을 구하기 힘들어짐

 -> 학습률 learning rate를 통해 조금씩 오차를 조정해 나감.

 

 

 

 

 

 

2차원 데이터로 부터 단순 선형 회귀 모델 구하기

 

 

1. 데이터 준비

import numpy as np
import matplotlib.pyplot as plt

# y = w0 + w1 * x 단순 선형 회귀 식 
# y = 4x + 6(w0 = 6, w1= 4)에 대한 선형 근사를 위해 값 준비
x = 2 * np.random.rand(100, 1) # 0 ~ 2까지 100개 임의의 점
y = 6 + 4 * x + np.random.randn(100, 1) # 4x + 6 + 정규 분포를 따르는 노이즈

plt.scatter(x, y)

 

 

 

 

2. 주어진 데이터에 적합한 회귀 모델 구하기

- 가중치(회귀 계수) 1로 초기화 -> 가중치 갱신 과정 수행(get_weight_update)

- x에 대한 추정한 y를 구함 -> 실제 y - 추정 y로 오차 diff 구함.

- 위에서 구한 가중치 갱신 공식에 따라 w0, w1의 갱신 값을 구함(w0/w1_update)

- 가중치 - 가중치 갱신 값. 이 연산을 지정한 횟수 만큼 수행

=> 회귀 계수는 일정한 값으로 수렴함 : 선형 회귀 모델의 회귀 계수.

def get_weight_update(w1, w0, x, y, learning_rate=0.01):
    # y는 길이가 100인 벡터, 길이 가져옴
    N = len(y)
    
    # 계수 w0, w1 갱신 값을 계수 w0, w1 동일한 형태로 초기화
    w1_update = np.zeros_like(w1)
    w0_update = np.zeros_like(w0)
    
    # 주어진 선형 회귀 식을 통한 값 추정
    y_pred = np.dot(x, w1.T) + w0
    # 잔차 y - hat_y
    diff = y - y_pred
    
    # (100, 1) 형태의 [[1, 1, ..., 1]] 행렬 생성, diff와 내적을 구하기 위함.
    w0_factors = np.ones((N, 1))
    
    # 우측의 식은 MSE를 w1과 w0에 대해 편미분을 하여 구함.
    # d mse/d w0 = 0 이 되게하는 w0이 mse의 최소로 함
    # d mse/d w1 = 0 이 되게하는 w1이 mse를 최소로 함
    # 급격한 w0, w1 변화를 방지 하기 위해 학습률 learning_rate 사용
    
    w1_update = -(2/N) * learning_rate * (np.dot(x.T, diff))
    w0_update = -(2/N) * learning_rate * (np.dot(w0_factors.T, diff))
    
    return w1_update, w0_update

def gradient_descent_steps(X, y, iters= 10000):
    
    w0 = np.zeros((1, 1))
    w1 = np.zeros((1, 1))
    
    for idx in range(0, iters):

        w1_update, w0_update = get_weight_update(w1, w0, X, y, learning_rate=0.01)
        # 갱신 값으로 기존의 w1, w0을 조정해 나감
        w1 = w1 - w1_update
        w0 = w0 - w0_update
    
    return w1, w0

def get_cost(y, y_pred):
    N = len(y)
    cost = np.sum(np.square(y- y_pred))/N
    return cost

w1, w0 = gradient_descent_steps(x, y, iters=1000)
print("w1:{0:.4f}, w0:{0:.4f}".format(w1[0, 0], w0[0, 0]))
y_pred = w1[0, 0] * x + w0
print("gradient descent total cost : {0:.4f}".format(get_cost(y, y_pred)))

 

 

 

 

 

 

확률적 경사 하강법 stochastic gradient descent

- 위의 경사 하강법을 이용한 계수 추정 과정에서 주어진 모든 데이터를 사용함

 -> 반복 횟수, 변수, 데이터 량이 많을 수록 느려짐

- 전체 데이터가 아닌 임의로 추출한 일부 데이터만 사용

- 아래의 경우 위(전체 데이터 100개)와 달리 10개만 추출하여 회귀 계수를 구함

def stochastic_gradient_descent_steps(x, y, batch_size=10, iters=1000):
    w0 = np.zeros((1,1))
    w1 = np.zeros((1,1))
    prev_cost = 1000000
    iter_idx = 0
    
    for idx in range(iters):
        # x의 크기만큼 임의의 인덱스 추출
        stochastic_random_idx = np.random.permutation(x.shape[0])
        # 임의의 인덱스의 x, y를 배치 사이즈만큼 샘플링
        sample_x = x[stochastic_random_idx[0:batch_size]]
        sample_y = y[stochastic_random_idx[0:batch_size]]
        
        w1_update, w0_update = get_weight_update(w1, w0, sample_x, sample_y,learning_rate=0.01)
        w1 = w1 - w1_update
        w0 = w0 - w0_update
    return w1, w0

w1, w0 = stochastic_gradient_descent_steps(x, y, iters=1000)
print("w1:{0:.4f}, w0:{0:.4f}".format(w1[0, 0], w0[0, 0]))
y_pred = w1[0, 0] * x + w0
print("gradient descent total cost : {0:.4f}".format(get_cost(y, y_pred)))
300x250
728x90

스태킹 Stacking

- 여러 모델들을 결합하여 결과를 도출하는 앙상블 기법 중 하나.

- 각 모델들의 예측 결과를 학습하여 최종 예측결과를 도출

 

 

1. 라이브러리 임포트

- 기본 모델로 knn, random forest, adaboost, decisiont tree 4가지

- 마지막 모델로 logistic regression

import numpy as np
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.linear_model import LogisticRegression

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from utils.common import show_metrics

 

 

2. 데이터 로드 및 조회

- 행 569, 열 30개 데이터

- 악성과 양성사이 큰 비율 차이는 없음

data = load_breast_cancer()
X = data.data
y = data.target
print(data.DESCR)

import pandas as pd
print(pd.Series(y).value_counts())

 

 

 

3. 각 분류기 학습, 성능 확인

- 각 분류기 학습 및 성능 출력, 예측 데이터 쌓기

- lr_final에 학습 용 데이터를 만들기 위해 예측 데이터 shape가 (4, 114) 인것을 전치. 114행 4열 데이터로 변환

 

def get_model_train_eval(model, ftr_train=None, ftr_test=None,
                        tgt_train=None, tgt_test=None):
    model.fit(ftr_train, tgt_train)
    y_pred = model.predict(ftr_test)
    show_metrics(y_test, y_pred)
    return model, y_pred

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2,
                                                   random_state=10)
knn = KNeighborsClassifier()
rf = RandomForestClassifier(random_state=10)
dt = DecisionTreeClassifier()
ada = AdaBoostClassifier()
lr_final = LogisticRegression()

clfs = [knn, rf, dt, ada]
y_preds = []
for idx, clf in enumerate(clfs):
    print("\n", clf.__class__.__name__)
    clfs[idx], y_pred = get_model_train_eval(clf, ftr_train=X_train, ftr_test=X_test,
                        tgt_train=y_train, tgt_test=y_test)
    y_preds.append(y_pred)

y_preds = np.array(y_preds)
print(y_preds.shape)
y_preds = y_preds.T

 

 

4. 최종 스태킹 모델 학습 결과

- 랜덤 포레스트 하나만 사용한 경우 보다는 성능이 저하되었으나, 타 분류기들보다는 개선된 결과를 보임

- 실제 사용시 하이퍼 파라미터를 최적으로 튜닝한 후에 사용하여야 함.

 

final, y_pred = get_model_train_eval(lr_final, ftr_train=y_preds, ftr_test=y_preds,
                    tgt_train=y_test, tgt_test=y_test)

 

300x250
728x90

캐글 신용사기 검출 대회

- 2013년 9월 유럽 신용카드 트랜잭션 데이터

- 2일간 284,807 트랜잭션중 492건이 사기로 전체중 0.172%뿐으로 데이터가 매우 불균형함

ref : www.kaggle.com/mlg-ulb/creditcardfraud

 

 

 

The datasets contains transactions made by credit cards in September 2013 by european cardholders.
This dataset presents transactions that occurred in two days, where we have 492 frauds out of 284,807 transactions. The dataset is highly unbalanced, the positive class (frauds) account for 0.172% of all transactions.

 

 

 

 

언더 샘플링, 오버샘플링

- 불균형 레이블 분포를 적절한 학습데이터로 만드는 방법, 오버 샘플링이 유리

- 언더 샘플링 : 클래스가 많은 데이터를 클래스가 적은 데이터 만큼 축소

 ex. 정상 10,000건, 비정상 100건시 정상을 100건으로 줄임. *너무 많은 정상 데이터를 제거

- 오버 샘플링 : 클래스가 적은 데이터를 클래스가 많은 데이터 만큼 증가

 * 단순 증강 시 오버피팅이 발생. 원본 데이터 피처를 약간씩 변형하여 증감

 ex. SMOTE(Syntheic Minority Over sampling techinuqe : knn으로 적은 클래스 데이터 간의 차이로 새 데이터 생성

 * imbalanced-learning 사용

 

 

 

 

 

 

 

1. 데이터로드

 

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")

path = "./res/credit card fraud detection/creditcard.csv"
df = pd.read_csv(path)
df.head()

 

2. 전처리 및 훈련, 테스트 데이터 셋 분리 정의

 

from sklearn.model_selection import train_test_split

def get_preprocessed_df(df=None):
    """
    input
    df : before preprocessing

    output
    res : after dropping time columns
    """
    res = df.copy()
    res.drop("Time", axis=1, inplace=True)
    return res

def get_train_test_datasets(df=None):
    df_copy = get_preprocessed_df(df)
    X_features = df_copy.iloc[:,:-1]
    y_target= df_copy.iloc[:,-1]
    
    X_train, X_test, y_train, y_test = train_test_split(X_features, y_target,
                                                       test_size=0.2,
                                                       stratify=y_target,
                                                       random_state=100)
    return X_train, X_test, y_train, y_test
    

 

 

 

3. 로지스틱 회귀 모델로 성능 확인

- 정확도는 좋으나 재현률과 F1 스코어가 크게 떨어짐

 

X_train, X_test, y_train, y_test = get_train_test_datasets(df)

from sklearn.linear_model import LogisticRegression
from utils.common import show_metrics


lr = LogisticRegression()
lr.fit(X_train, y_train)
y_pred = lr.predict(X_test)
show_metrics(y_test, y_pred)

 

 

 

4. 모델, 데이터를 줄때 학습 및 성능을 출력하는 함수 정의

 

def get_model_train_eval(model, ftr_train=None, ftr_test=None,
                        tgt_train=None, tgt_test=None):
    model.fit(ftr_train, tgt_train)
    y_pred = model.predict(ftr_test)
    show_metrics(y_test, y_pred)
    return model

 

 

 

5. LightGBM 성능 확인

- LR 보다 평가 지표들이 좋은 결과를 보임

 

from lightgbm import LGBMClassifier

lgbm = LGBMClassifier(n_estimators=1000, num_leaves=32,
                       n_jobs=-1, boost_from_average=False)
lgbm = get_model_train_eval(lgbm, ftr_train=X_train, ftr_test=X_test,
                    tgt_train=y_train, tgt_test = y_test)

 

 

6. 거래 금액 시각화

 

- df의 time, amount를 제외한 컬럼들은 PCA를 통해 얻은 주성분 요소들

- 로지스틱 회귀는 정규분포를 따르는 데이터를 사용하는것이 좋음 -> 표준화 정규기 사용

sns.distplot(df["Amount"])

 

 

 

7. amount 정규화 후 성능 비교

- 로지스틱 분류기나 LGBM이나 큰 성능 차이가 생기지는 않음

from sklearn.preprocessing import StandardScaler

def get_preprocessed_df(df=None):
    res = df.copy()
    scaler = StandardScaler()
    #res["Amount_Scaled"] = scaler.fit_transform(df["Amount"].values.reshape(-1,1))
    amount_scaled = scaler.fit_transform(df["Amount"].values.reshape(-1,1))
    res.insert(0, "Amount_Scaled", amount_scaled)
    res.drop(["Time","Amount"], axis=1, inplace=True)
    return res
    
X_train, X_test, y_train, y_test = get_train_test_datasets(df)
lr = LogisticRegression()
print("logistic regression classification evaluation")
get_model_train_eval(model=lr, ftr_train=X_train, ftr_test=X_test,
                    tgt_train=y_train, tgt_test=y_test)

lgbm = LGBMClassifier(n_estimators=1000, num_leaves=64,
                      n_jobs=-1,boost_from_average=False)
print("\nLGBM classification evaluation")
get_model_train_eval(model=lgbm, ftr_train=X_train, ftr_test=X_test,
                    tgt_train=y_train, tgt_test=y_test)

 

 

 

8. 로그 변환후 성능 비교

- 라벨 분포가 심하게 왜곡된 경우 사용

- log 연산을 통해 매우 큰값도 작은 값으로 변환

 -> 큰 변화는 생기지 않아보임. 교차 검증 필요

 

 

def get_preprocessed_df(df=None):
    res = df.copy()
    amount_scaled = np.log1p(res["Amount"])
    res.insert(0, "Amount_Scaled", amount_scaled)
    res.drop(["Time","Amount"], axis=1, inplace=True)
    return res


X_train, X_test, y_train, y_test = get_train_test_datasets(df)
lr = LogisticRegression()
print("logistic regression classification evaluation")
get_model_train_eval(model=lr, ftr_train=X_train, ftr_test=X_test,
                    tgt_train=y_train, tgt_test=y_test)

lgbm = LGBMClassifier(n_estimators=1000, num_leaves=64,
                      n_jobs=-1, boost_from_average=False)
print("\nLGBM classification evaluation")
get_model_train_eval(model=lgbm, ftr_train=X_train, ftr_test=X_test,
                    tgt_train=y_train, tgt_test=y_test)

 

 

9. 이상치 제거를 위한 히트맵 시각화

- 클래스와 가장 강한 음의 상관 관계를 갖는 변수로 V17이 있는걸 확인할수 있음.

card_df = get_preprocessed_df(df)
plt.figure(figsize=(12,12))
corr = card_df.corr()
sns.heatmap(corr, cmap="RdBu")

 

 

10. 이상치 제거 후 성능 비교

- 25% - 1.5 * IQR보다 작거나 75% + 1.5 * IQR보다 큰 경우 아웃라이어판단.

- V17의 아웃라이어들 제거 후 성능 평가.

- LGBM의 평가 지표들이 약간 개선됨

def get_outlier(df=None, column=None, weight=1.5):
    fraud = df[df["Class"] == 1][column]
    quatile_25 = np.percentile(fraud.values, 25)
    quatile_75 = np.percentile(fraud.values, 75)
    
    iqr = quatile_75 - quatile_25
    iqr_weight = iqr * weight
    lowest_val = quatile_25 - iqr_weight
    highest_val = quatile_75 + iqr_weight
    outlier_idx = fraud[(fraud < lowest_val) | (fraud > highest_val)].index
    return outlier_idx


def get_preprocessed_df(df=None):
    res = df.copy()
    amount_scaled = np.log1p(res["Amount"])
    res.insert(0, "Amount_Scaled", amount_scaled)
    res.drop(["Time","Amount"], axis=1, inplace=True)
    
    outlier_index = get_outlier(df=res, column = "V14", weight=1.5)
    res.drop(outlier_index, axis=0, inplace=True)
    return res
    
X_train, X_test, y_train, y_test = get_train_test_datasets(df)
lr = LogisticRegression()
print("logistic regression classification evaluation")
get_model_train_eval(model=lr, ftr_train=X_train, ftr_test=X_test,
                    tgt_train=y_train, tgt_test=y_test)

lgbm = LGBMClassifier(n_estimators=1000, num_leaves=64,
                      n_jobs=-1, boost_from_average=False)
print("\nLGBM classification evaluation")
get_model_train_eval(model=lgbm, ftr_train=X_train, ftr_test=X_test,
                    tgt_train=y_train, tgt_test=y_test)

 

 

 

11. SMOTE 사용하기 위한 imblanced-learn 설치. cannot import six 에러 해결(버전 매칭)

원랜 아래와 같이 하면되나

pip install imbalanced-learn

pypi.org/project/imbalanced-learn/#description

 

최신 imbalanced-learn이 scikit-learn 0.23 이상 버전을 요구

-> 자동 업그레이드 중 문제 발생했는지 cannot import six 에러로 사용불가

 

pip install -U imbalanced-learn==0.6.2

pip install -U scikit-learn==0.22.2

로 다운그레이드 하여 해결

 

 

12. over sampling

- SMOTE oversampling을 통해 작은 라밸을 큰 라밸과 크기를 맞춤

- lr의 경우 재현율은 좋아졌으나 정밀도와 f1 score는 크게저하

- lgbm은 성능 지표들이 대채로 저하

 

from imblearn.over_sampling import SMOTE
smote = SMOTE(random_state=100)
X_train_over, y_train_over = smote.fit_sample(X_train, y_train)
print("berfore smote : ",X_train.shape, y_train.shape)
print("after smote : ", X_train_over.shape, y_train_over.shape)
print("label distribution after smote \n", pd.Series(y_train_over).value_counts())

 

 

 

 

 

 

13. 성능 지표 정리

 

 

300x250
728x90

 

파이토치과정 - 6. 구글드라이브,코랩에서 kaggle-api연동

ref : throwexception.tistory.com/1018

 

 

일단 캐글 api로 데이터 부터 준비하자

 

다운되면 압축 풀고 로드 준비

!kaggle competitions download -c santander-customer-satisfaction

 

 

일단 필요한 모듈들과 데이터부터 로드하자

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from lightgbm import LGBMClassifier
from sklearn.model_selection import GridSearchCV

path = "./res/santander-customer-satisfaction/"
test = pd.read_csv(path+"test.csv")
train = pd.read_csv(path+"train.csv")

 

 

일단 info를 보면

 

총 76020개, 371개 속성

 

마지막 컬럼이 타겟으로 되어있다.

 

 

결측치가 존재하는지 보려고, 했으나

 

속성이 너무많아 잘 보이지가 않는다.

 

 

 

sum에 또 sum해보니 없다고 한다.

 

일단 타겟으로 만족여부를 살펴보자.

 

불만족 고객이 매우 적어보인다.

 

이 문제에서 대부분 고객들이 만족하므로 정확도 대신 ROC-AUC를 사용하여야한다.

train["TARGET"].value_counts()

 

 

 

lgbm 모델로

 

accuracy_score와 roc_auc_score를 살펴보았는데

 

roc-auc score가 많이 낮더라

 

데이터 전처리를 제대로 안해서 그런것같다.

 

from sklearn.metrics import roc_auc_score,accuracy_score
from sklearn.model_selection import train_test_split

X = train.iloc[:,:-1]
y = train.iloc[:,-1]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

lgbm = LGBMClassifier()
lgbm.fit(X_train, y_train)
y_pred = lgbm.predict(X_test)

print("accuracy Score : {}".format(accuracy_score(y_test, y_pred)))
print("ROC-AUC Score : {}".format(roc_auc_score(y_test, y_pred)))

 

 

 

전처리 단계에서

 

결측치를 확인했다.

 

트리 모델이니 스케일링은 필요없고,

 

이상치 문제인것같았다.

 

train.describe()로 다시 살펴보았더니 일부 기술통계량이 이상한 값들이 존재한다.

 

var3의 경우 min인 -9999999인 데이터가 존재하는데 평균과 표준편차를 고려하면 너무 엇나간 값이다.

 

imp_ent_var16_ult1도 마찬가지다.

 

 

 

 

 

 

이상치를 다루는 방법은 제거하거나 이 값을 대치시켜주어야 한다.

 

한 변수에 이상치가 많으면 제거 대신, 평균을 구하여 넣어주곤 한다.

 

평균 +- 3 * std를 기준으로 이상치 갯수부터 살펴보자

 

var3 변수의 경우 이상치가 116개가 존재한다.

 

var = train["var3"]
var_mean = train["var3"].mean()
var_std = train["var3"].std()

lower_bound_idx = var < var_mean - 3* var_std
upper_bound_idx = var > var_mean + 3* var_std

print(lower_bound_idx.sum())
print(upper_bound_idx.sum())

 

이 외에 다른 변수들은 이상치가 몇개씩 있을까 확인해보자

 

mean +- 3* std를 넘어가는걸 아웃라이어로 볼때

 

이상치가 100개 넘어가는 변수들이 총 187개가 있다고 한다.

 

num_over_th = 0
num_outlier_th = 100
columns = train.columns
for col in columns:
    var = train[col]
    var_mean = train[col].mean()
    var_std = train[col].std()

    lower_bound_idx = var < var_mean - 3* var_std
    upper_bound_idx = var > var_mean + 3* var_std

    num_outliers = lower_bound_idx.sum() + upper_bound_idx.sum()
    if num_outliers > num_outlier_th:
        num_over_th += 1
        print("  columns : {}".format(col))
        print("    -> num of oulier : {}\n".format(num_outliers))

print("num over th : []".format(num_over_th))

 

 

 

내가 중간에 빠트린 작업이 있는데

 

"ID"열을 삭제 해주지 않았었다.

 

할일 다시 정리하면

 

1. ID열을 삭제하고

2. 각 열의 아웃라이어들을 해당 열의 최빈값으로 바꿔주자

 

 

아웃라이어 대치 전후를 비교할수 있도록

 

 

우선 바꾸기전에 한번 결과보고

 

아웃라이어를 바꾼 후 결과를 보겠다.

 

 

 

 

 

 

정확도는 0.9632333596421995

roc-auc는 0.8345281581059178

describe()한결과 이상치들이 많아보인다.

 

 

X.drop(columns="ID", inplace=True)


X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

lgbm = LGBMClassifier()
lgbm.fit(X_train, y_train)

print("before replace outlier")
print("accuracy Score : {}".format(accuracy_score(y_test, lgbm.predict(X_test))))
print("ROC-AUC Score : {}\n".format(roc_auc_score(y_test, lgbm.predict_proba(X_test)[:, 1])))


X.describe()

 

 

 

 

 

최빈값으로 대치한 결과

 

describe()를 보면 이상치들이 많이 줄어든걸 볼수 있지만

 

정확도와 roc-auc가 많이 줄어들었다.

 

교차 검증이 필요해보인다.

 

 

columns = X.columns
for col in columns:
    var = X[col]
    var_mean = X[col].mean()
    var_std = X[col].std()

    lower_bound_idx = var < var_mean - 5* var_std
    upper_bound_idx = var > var_mean + 5* var_std
    X.loc[lower_bound_idx, col] = X[col].mode()
    X.loc[upper_bound_idx, col] = X[col].mode()



X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

lgbm = LGBMClassifier()
lgbm.fit(X_train, y_train)
print("after replace outlier")
print("accuracy Score : {}".format(accuracy_score(y_test, lgbm.predict(X_test))))
print("ROC-AUC Score : {}".format(roc_auc_score(y_test, lgbm.predict_proba(X_test)[:, 1])))

X.describe()

 

 

 

 

 

 

아까 0.83에서 0.82로 떨어진것보다 정도는 덜하지만

 

여전히 전처리 후 더 줄어들어 있다.

 

아웃라이어를 너무 많이 잡아서 그런것 같아 

 

5 * std 대신 100* std로 심각한 아웃라이어들만 대치시키도록 바꿔보았다.

from sklearn.model_selection import cross_val_score

X = train.iloc[:,:-1]
X.drop(columns="ID", inplace=True)
lgbm = LGBMClassifier()

scores = cross_val_score(lgbm, X, y, cv= 5, scoring="roc_auc")
print("before replace outlier")
print("ROC-AUC Score : {}\n".format(np.mean(scores)))



columns = X.columns
for col in columns:
    var = X[col]
    var_mean = X[col].mean()
    var_std = X[col].std()

    lower_bound_idx = var < var_mean - 5* var_std
    upper_bound_idx = var > var_mean + 5* var_std
    X.loc[lower_bound_idx, col] = X[col].mode()
    X.loc[upper_bound_idx, col] = X[col].mode()



lgbm = LGBMClassifier()
scores = cross_val_score(lgbm, X, y, cv= 5, scoring="roc_auc")
print("after replace outlier")
print("ROC-AUC Score : {}\n".format(np.mean(scores)))

 

 

 

위 코드에서 5를 100으로 바꿧더니

 

아까보다 전처리 후 성능은 좋아졌지만

 

전처리 전보다 떨어지는건 여전하다..

 

describe()로 봤더니

 

100이 너무 커 아웃라이어들을 너무 많이 놓쳣더라

 

대신 15 정도로 바꿔 보았다.

 

    lower_bound_idx = var < var_mean - 100* var_std
    upper_bound_idx = var > var_mean + 100* var_std

 

 

 

 

또 떨어졌다..

    lower_bound_idx = var < var_mean - 15* var_std
    upper_bound_idx = var > var_mean + 15* var_std

 

 

 

std * 300으로 바꿔주었더니

 

바꾸기 전이랑 동일한 결과가 나왔다.

    lower_bound_idx = var < var_mean - 300* var_std
    upper_bound_idx = var > var_mean + 300* var_std

 

 

ID 제거하는것 빼고

 

전처리를 안한 결과를 봐도

 

성능 변화가 없는걸 봐서

* ID 같은 정말 의미없는 데이터를 없애는것 빼곤

 

LightGBM에서 전처리는 큰의미가 없는것 같았다.

X = train.iloc[:,:-1]
X.drop(columns="ID", inplace=True)
lgbm = LGBMClassifier()

scores = cross_val_score(lgbm, X, y, cv= 5, scoring="roc_auc")
print("ROC-AUC Score : {}\n".format(np.mean(scores)))

300x250
728x90

LightGBM 

- GBM Gradient Boost Machine이나, XGBoost보다 학습 시간이 적은 모델

- 데이터가 적은 경우(10000개 이하) 과적합이 발생하기 쉬움

- 기존의 트리 기반 알고리즘들은 균형 트리 분할 방식을 따르나 LightGBM은 리프위주 분할을 함.

 -> 손실이 큰 리프 노드를 분할해나감. 트리구조가 비대칭적이나 손실을 최소화할수 있음.

- XGBoost와 마찬가지로 병렬 처리 수행 가능.

 

 

LightGBM 하이퍼 파라미터

- num_iteration : 디폴트 100, 반복 수행하는 트리 개수

- learning_rate : 디폴트 0.1

- max_depth : 디폴트 -1

- min_data_in_leaf : 디폴트 20, 리프노드 최소 데이터 개수

- num_leaves : 디폴트 31, 한 트리의 최대 리프개수 등

=> num_leaves를 중심으로, min_data_in_leaf, max_depth 위주로 하이퍼파라미터 조정

 

 

 

 

pip로 설치하여

 

유방암 데이터를 교차 검증 수행

!pip install lightgbm

from lightgbm import LGBMClassifier
import pandas as pd
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import cross_val_score

data = load_breast_cancer()
X = data.data
y = data.target

lgbm = LGBMClassifier()
res = cross_val_score(lgbm, X, y, cv= 5, n_jobs=-1, scoring="accuracy")
print(res)
print(np.mean(res))

 

평균 정확도 0.968

 

300x250
728x90

부스팅 기법

- 여러개의 약분류기를 순차 적으로 배치

- 앞의 모델에서 틀린 데이터에 가중치를 주어 이후 분류기에서 더 잘 분류할수 있게 도움

- 약 분류기의 분류 기준과 가중치들을 결합하여 강한 분류기를 만듬.

=> 아다부스트

 

 

GBM Gradient Boost Machine

- 아다부스트와 동일하나 가중치 갱신을 경사 하강법을 이용.

- 랜덤포래스트와 달리 가중치 갱신을 순차적으로 수행하여 병렬처리가 불가함

 => 좋은 성능을 보이나, 학습시 오랜 시간이 걸림.

 * 랜덤 포레스트로 우선 모델을 만들기도 함.

 

 

GBM으로 사용자 행동 인식 분류하기

 

이전과 동일하게 사용한 결과

gbm acc : 0.9379029521547336로

랜덤 포래스트보다 개선된 성능을 보임.

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.metrics import accuracy_score
import warnings
warnings.filterwarnings("ignore")

path = "./res/UCI HAR Dataset/features.txt"

features_df = pd.read_csv(path,sep="\s+",
                         header=None, names=["column_index", "column_name"])

feature_names = features_df["column_name"].values.tolist()

path = "./res/UCI HAR Dataset/"

X_train = pd.read_csv(path+"train/X_train.txt",sep="\s+", names=feature_names)
X_test = pd.read_csv(path+"test/X_test.txt",sep="\s+", names=feature_names)


y_train = pd.read_csv(path+"train/y_train.txt", sep="\s+", header=None,
                     names=["action"])

y_test = pd.read_csv(path+"test/y_test.txt", sep="\s+", header=None,
                     names=["action"])
                     
gbm = GradientBoostingClassifier(random_state=100)
gbm.fit(X_train, y_train)
y_pred = gbm.predict(X_test)
print("gbm acc : {}".format(accuracy_score(y_test, y_pred)))

300x250
728x90

랜덤 포레스트

- 배깅 알고리즘 중 하나로 비교적 빠르며, 높은 성능을 보이고 있음.

- 배깅 알고리즘인 만큼 결정 트리 기반으로 하며, 많은 양의 트리를 이용하여 편향-분산을 잘 상쇄시킴.

 

 

 

 

랜덤 포레스트 모델로

 

이전에 결정트리로 풀어본 사용자 행동 인식 데이터셋을 다뤄보겠습니다.

 

ref : throwexception.tistory.com/1039

 

일단 단순하게 성능을 확인해봅시다.

 

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score

path = "./res/UCI HAR Dataset/features.txt"

features_df = pd.read_csv(path,sep="\s+",
                         header=None, names=["column_index", "column_name"])

feature_names = features_df["column_name"].values.tolist()

path = "./res/UCI HAR Dataset/"

X_train = pd.read_csv(path+"train/X_train.txt",sep="\s+", names=feature_names)
X_test = pd.read_csv(path+"test/X_test.txt",sep="\s+", names=feature_names)


y_train = pd.read_csv(path+"train/y_train.txt", sep="\s+", header=None,
                     names=["action"])

y_test = pd.read_csv(path+"test/y_test.txt", sep="\s+", header=None,
                     names=["action"])



rf = RandomForestClassifier(random_state=100)
rf.fit(X_train, y_train)
y_pred = rf.predict(X_test)
print("rf acc : {}".format(accuracy_score(y_test, y_pred)))

 

 

기본 상태로 랜덤 포레스트의 성능이 0.9015948422124194으로 나오고 있습니다.

 

 

중요한 변수들을 한번 살펴봅시다.

 

워낙 변수들이 많아서인지 각 변수들의 중요도가 매우 작은 값들을 가지고 있습니다.

ftr_importance_val = rf.feature_importances_
ftr_importances = pd.Series(ftr_importance_val, index=X_train.columns)
ftr_top30 = ftr_importances.sort_values(ascending=False)[:30]

sns.barplot(x=ftr_top30, y=ftr_top30.index)

 

 

 

성능 개선을 위해 

 

gridsearchcv로 한번 최적 파라미터를 찾아봅시다.

 

그리드 탐색 결과를 보면

 

 

max depth : 10

min samples leaf 18

min samples split 12일때

 

아까 정확도가 0.9015948422124194 나온것 보다는 

 

아주 약간 개선된 0.910092가 나옵니다.

 

이 부근으로 탐색을 더해보면 더 나은 하이퍼 파라미터들을 찾을수 있을것같습니다.

* 모델이나 gridsearchcv의 파라미터로  n_jobs=-1로 설정하면 모든 CPU 코어를 사용하게 됨.

from sklearn.model_selection import GridSearchCV

param = {
    "min_samples_leaf": [4, 12, 18],
    "min_samples_split": [6, 12],
    "max_depth" :[10, None]
}

rf = RandomForestClassifier(random_state=100, n_jobs=1)
gs = GridSearchCV(rf, param_grid=param, cv=3, n_jobs=-1)
gs.fit(X_train, y_train)


res_df = pd.DataFrame.from_dict(gs.cv_results_)
res_df[['param_max_depth', 'param_min_samples_leaf', 'param_min_samples_split' ,'mean_test_score']]

 

위 표를 보면 min samples leaf가 커질수록 성능이 개선되었고,

 

min samples split은 6, 12이든 별 차이가 나지는 않았습니다.

 

하지만 max_depth는 None보다 10일때 타 파라미터 동일 조건에서 더 좋은 성능이 나왔으니

 

 

 

min samples split은 빼고

 

대신 n_estimators를 추가하여

 

다음과 같이 파라미터를 조정하여 돌려보았습니다.

 

param = {
    "min_samples_leaf": [18, 25, 30],
    "max_depth" :[10, 15],
    "n_estimators" :[50, 100, 200]
}

rf = RandomForestClassifier(random_state=100, n_jobs=1)
gs = GridSearchCV(rf, param_grid=param, cv=3, n_jobs=-1)
gs.fit(X_train, y_train)


res_df = pd.DataFrame.from_dict(gs.cv_results_)
res_df[['param_min_samples_leaf','param_max_depth', 'param_n_estimators' ,'mean_test_score']]

 

결과는

 

min samples leaf : 25

max depth : 10

n estimators : 100

 

일때 

 

최대 스코어가 0.917982로 나왔습니다.

 

이전 성능인 0.910092보다 0.007정도 개선되었습니다.

 

 

 

 

일단 대체로 보면 n estimator 100부근에서 좋은 성능이 나왔고

 

min samples leaf는 타 파라미터에따라 조금씩 바뀌는것 같습니다.

 

max depth의 경우 더 깊을수록 성능이 떨어지고 있습니다.

 

 

다시 하이퍼 파라미터를 다음과 같이 조정해서 동작시켜보았습니다.

 

 

param = {
    "min_samples_leaf": [21, 24, 27],
    "max_depth" :[4, 6, 8],
    "n_estimators" :[80, 100, 120]
}

rf = RandomForestClassifier(random_state=100, n_jobs=1)
gs = GridSearchCV(rf, param_grid=param, cv=3, n_jobs=-1)
gs.fit(X_train, y_train)


res_df = pd.DataFrame.from_dict(gs.cv_results_)
res_df[['param_min_samples_leaf','param_max_depth', 'param_n_estimators' ,'mean_test_score']]

 

최대 스코어가 0.914로 이전보다 0.003정도 줄어들었습니다.

 

 

 

이번에는 최대 특징 개수를 추가했습니다.

 

param = {
    "min_samples_leaf": [25, 27],
    "max_depth" :[9, 10, 11],
    "n_estimators" :[100],
    "max_features": [200, "auto"]
}

rf = RandomForestClassifier(random_state=100, n_jobs=1)
gs = GridSearchCV(rf, param_grid=param, cv=3, n_jobs=-1)
gs.fit(X_train, y_train)


res_df = pd.DataFrame.from_dict(gs.cv_results_)
res_df[['param_min_samples_leaf','param_max_depth', 'param_max_feature' ,'mean_test_score']]

 

아까와 동일하게

 

min samples leaf 25

 

max depth 10

 

n estimator 100

 

일때와 스코어가 0.917982로 가장 좋은 성능을 보였습니다.

 

이전에 결정 트리로 0.86425 나왔을때보다는 랜덤 포레스트 모델을 통해 분류 성능을 크개 개선할수 있었습니다.

 

 

300x250
728x90

사이킷런의 데이터셋 모델에서

 

위스콘신 유방암 데이터셋을 제공하고 있습니다.

 

 

 

voting classifier를 사용할 건데

 

여기서 로지스틱 회귀 모델, K최근접 이웃 이 두 가지를 사용하겠습니다.

 

일단 필요한 라이브러리들 부터 임포트 해줍시다.

 

from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn.ensemble import VotingClassifier
from sklearn.metrics import accuracy_score
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

 

 

load_breast_cancer()로 유방암 관련 데이터를 읽어줍시다.

 

sklearn.dataset에서 load 혹은 fetch 함수로 가져온 데이터들은

 

sklearn.utils.Bunch 타입으로

 

이 데이터는 기본적으로

 

데이터셋에 대한 설명인 DESCR, 타겟변수명 target_names, 피처명 feature_names, data, target 등 변수들을

 

가지고 있습니다.

 

description을 읽어보면

 

데이터수는 569개

 

속성은 30개 정도 된다고 합니다.

 

타겟은 악성, 양성 종양 2개

cancer = load_breast_cancer()
print(type(cancer))

 

 

 

bunch 클래스 내용을 참고해서 바로 데이터프레임으로 만들어줍시다.

 

df = pd.DataFrame(data=cancer.data, columns=cancer.feature_names)
df["class"] = cancer.target
df.head()

 

데이터들을 분리해주고

 

모델들을 만들어줍시다.

 

voting_classifier(분류기 리스트, voting="보팅기법")으로 선언해주어야 합니다.

 

X_train, X_test, y_train, y_test = train_test_split(df.iloc[:,:-1], df.iloc[:,-1],test_size=0.2)


lr = LogisticRegression()
knn = KNeighborsClassifier()

vo = VotingClassifier([("lr", lr), ("knn", knn)], voting="soft")

vo.fit(X_train, y_train)
y_pred = vo.predict(X_test)

print("acc : {}".format(accuracy_score(y_test, y_pred)))

for clf in [lr, knn]:
    clf_name = clf.__class__.__name__
    clf.fit(X_train, y_train)
    y_pred = clf.predict(X_test)
    acc = accuracy_score(y_test, y_pred)
    print("{}'s acc : {}'".format(clf_name,acc))

 

분류기 정확도는 0.956140350877193

 

두 뷴류기의 성능을 보면

 

로지스틱 회귀가 0.9385964912280702

 

K최근접이웃은 0.9473684210526315으로 k 최근접 이웃이 조금 더 좋은 성능을 보이고 있습니다.

 

 

 

 

 

 

로지스틱 회귀의 경우 전처리로

 

데이터셋을 표준 정규분포로 정규화 시키면 더 좋은 성능을 보인다고 합니다.

 

preprocessing 모듈의 StandardScaler를 사용해봅시다.

 

 

보팅 분류기가 0.9561403에서 0.973684로

 

로지스틱 회귀가 0.93859에서 0.964912

 

K최근접이웃이 0.947368에서 0.973684로 조금더 성능이 개선되었습니다.

from sklearn.preprocessing import StandardScaler


scaler1 = StandardScaler()
scaler2 = StandardScaler()

X_train = scaler1.fit_transform(X_train)
X_test = scaler2.fit_transform(X_test)

lr = LogisticRegression()
knn = KNeighborsClassifier()

vo = VotingClassifier([("lr", lr), ("knn", knn)], voting="soft")

vo.fit(X_train, y_train)
y_pred = vo.predict(X_test)

print("acc : {}".format(accuracy_score(y_test, y_pred)))

for clf in [lr, knn]:
    clf_name = clf.__class__.__name__
    clf.fit(X_train, y_train)
    y_pred = clf.predict(X_test)
    acc = accuracy_score(y_test, y_pred)
    print("{}'s acc : {}'".format(clf_name,acc))

 

 

전처리 후 성능이 개선된건 좋지만

 

매번 할때마다 성능이 조금씩 변하고 있습니다.

 

cross_val_score() 함수로 교차검증 까지 해봅시다.

 

 

교차 검증 결과 확실히 성능이 개선됨을 알수 있었습니다.

 

VotingClassifier : 0.9753443632166217

LogisticRegression : 0.9806848787995384

KNeighborsClassifier : 0.9595075028857252

from sklearn.model_selection import cross_val_score

for clf in [vo, lr, knn]:
    scores = cross_val_score(clf, np.concatenate((X_train,X_test)), 
                             np.concatenate((y_train, y_test)),
                            scoring="accuracy", cv=5)
    print(clf.__class__.__name__)
    print(scores)
    print(np.mean(scores))
    print()

 

300x250
728x90

앙상블

- 기존의 머신러닝 모델들이 단일 모델을 이용하여 값을 추정하였다면,

- 앙상블은 여러개의 모델로부터 결과를 얻는 방법

- 보팅, 배깅, 부스팅, 스태킹 등 다양한 기법들이 있음.

 

 

보팅

- 말그대로 서로 다른 분류기들간에 투표를 통해서 결정

- 하드 보팅 : 가장 많은 표를 받은 클래스를 선정

- 소프트 보팅 : 모든 분류기들의 클래스 라벨 확률들을 다 더한후 평균을 취한 후 가장 높은 값의 클래스 선정

ex. 사이킷런에서 votingclassifier 제공

 

배깅 bagging

- boostrap aggregation의 줄임말

- 보팅과 달리 한 종류의 알고리즘을 사용하나, 부트스트랩 기법으로 서로 다른 데이터셋으로 학습시킴

 * 부트스트랩 : 기존 데이터셋에서 일부 데이터셋을 추출하여 사용. 각 모델들은 동일하지 않은 데이터셋에 학습 

ex. 랜덤 포레스트

 

 

부스팅 boosting

- 여러 개의 약 모델들을 생성하여, 연결되어 순차 학습 수행

- 잘못 예측한 데이터에 가중치를 주어, 다음 모델에서 학습/예측 수행

- 오류들을 점점 더 줄여나갈수 있도록 개선한 방식

ex. 아다부스트(adaboost : adaptive boosting), XGBoost, LightGBM

300x250
728x90

UCI 대학교에서 휴대폰 데이터로 사용자 행동 인식에 대한 데이터셋을 공개하고 있다.

 

Human Activity Recognition Using Smartphones Data Set

archive.ics.uci.edu/ml/datasets/human+activity+recognition+using+smartphones

 

 

대강 훑어보면

 

데이터는 1만개, 속성수는 561개 ...,

 

분류하려는 행동 갯수는 6개로 걷기, 계단 올라가기, 계단 내려가기, 앉아있기, 서있기, 눕기 정도가 있다.

 

데이터들은 갤럭시 S2의 가속도/자이로계에서 선각속도 등 정보들을 50Hz로 받았다고 한다.

 

전체 데이터 중 70%가 훈련용, 30%는 테스트 용이라고 하내..

 

 

 

일단 속성수만 해도 장난아니게 많다..

 

csv형태도 아니다보니

 

피처명 파일이랑 데이터 파일이 별도로 나누어져 있다.

 

 

피처 목록

 

 

훈련용 데이터들

- 독립 변수 데이터들과 종속 변수 데이터도 분리되있고

 

- 피처 데이터도 장난아니게 길다. 뒤에 보니 이 데이터는 ,가 아니라 \n으로 행이 구분되있는것같다.

 

 

 

 

 

 

일단 피처명들부터 읽어야하는데

 

피처 인덱스와 피처명이 스페이스로 구분되어있고, 해더가 존재하지 않는다.

 

 

일단 이 데이터들을 읽고 보자

 

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

path = "./res/UCI HAR Dataset/features.txt"

features_df = pd.read_csv(path,sep="\s+",
                         header=None, names=["column_index", "column_name"])

features_df.head()

 

 

여기서 column_name은 피처 데이터를 읽을때 컬럼으로 필요하니 리스트로 변환하자

feature_names = features_df["column_name"].values.tolist()
print(type(feature_names))
print(feature_names)

 

 

 

 

이제 훈련, 테스트 데이터를 읽자
* 아까 본 피처 데이터들은 스페이스로 구분되어있었으니 세퍼레이터를 지정하자

+ 라벨 데이터도 읽고

path = "./res/UCI HAR Dataset/"

X_train = pd.read_csv(path+"train/X_train.txt",sep="\s+", names=feature_names)
X_test = pd.read_csv(path+"test/X_test.txt",sep="\s+", names=feature_names)


y_train = pd.read_csv(path+"train/y_train.txt", sep="\s+", header=None,
                     names="action")

y_test = pd.read_csv(path+"test/y_test.txt", sep="\s+", header=None,
                     names="action")

 

 

 

데이터도 많고 속성 갯수도 장난아니다보니, info도 평소 보던거랑 조금 다르게 나온다.

 

 

라벨 데이터는 속성이 1개 뿐이고, 대부분 행동들 갯수가 균일하게 나온다.

y_train["action"].value_counts()

 

 

일단 기본 결정트리로 학습하고 성능을 살펴보자

 

기본 설정대로 한 경우 0.857482 정도의 성능이 나온다.

 

 

이번에 그리드 탐색 교차 검증으로 최적 하이퍼 파라미터를 찾아보려고 한다.

 

이전 글에서 파람 썻던걸 참고해서 사용해보자

ref: throwexception.tistory.com/1038

 

데이터는 많지만 다음과 같이 파라미터들을 지정해서 동작시켜보면 ..

 

데이터 수도 많은데다 파라미터도 다양하게 주다보니 조금 오래걸린다.

from sklearn.model_selection import GridSearchCV

param = {
    "max_depth" : [10, 20, None],
    "min_samples_leaf" : [1, 6],
    "max_features" : [100, None]
}


gs = GridSearchCV(dt,param_grid=param,cv=5, refit=True)
gs.fit(X_train, y_train)

 

 

최적의 하이퍼 파라미터와 성능

 

 

 

다른 경우들을 비교해보면 0.84~ 0.85대 정도 나오고 있다.

gs_result_df = pd.DataFrame(gs.cv_results_)
gs_result_df[["params", "mean_test_score", "mean_train_score"]]

 

 

 

분류에서 가장 중요한 변수들을 살펴보자

best_dt = gs.best_estimator_
feature_importances = best_dt.feature_importances_
ftr_importances = pd.Series(feature_importances, index=X_train.columns)

ftr_top10 = ftr_importances.sort_values(ascending=False)[:10]

plt.title("Feature importance top 10")
sns.barplot(x=ftr_top10, y=ftr_top10.index)

300x250

+ Recent posts