🛠머신러닝

[머신러닝] 캐글(kaggle)예제 - 위스콘신 유방암 예측 데이터 분석 (Wisconsin Diagnostic breast cancer dataset) / 데이터 다운

빅데희터 2021. 3. 9. 18:37
반응형

위스콘신 유방암 데이터 세트는 종양의 크기, 모양 등의 다양한 속성 값을 기반으로 해당 종양이 악성(malignmant)인지 양성 (benign)인지를 분류한 데이터 세트이다. 이 데이터 세트를 앙상블(투표, 배깅, 부스팅) 기법을 이용하여 분석하고자 한다.

 

 

 

 

1️⃣ 기본 패키지 설정

## 1.기본
import numpy as np  # numpy 패키지 가져오기
import matplotlib.pyplot as plt # 시각화 패키지 가져오기

## 2.데이터 가져오기
import pandas as pd # csv -> dataframe으로 전환
from sklearn import datasets # python 저장 데이터 가져오기

# 4. 훈련/검증용 데이터 분리
from sklearn.model_selection import train_test_split 

## 5.분류모델구축
from sklearn.tree import DecisionTreeClassifier # 결정 트리
from sklearn.neighbors import KNeighborsClassifier # K-최근접 이웃
from sklearn.linear_model import LogisticRegression # 로지스틱 회귀 모델

## 5_1.앙상블 모델 구축
from sklearn.ensemble import VotingClassifier # 과반수 투표(Majority Voting) 

## 6.모델검정
from sklearn.metrics import confusion_matrix, classification_report # 정오분류표
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score # 정확도, 민감도 등
from sklearn.metrics import roc_curve, auc # ROC 곡선 그리기

## 7.최적화
from sklearn.model_selection import learning_curve, validation_curve # 학습곡선, 검증곡선
from sklearn.model_selection import GridSearchCV # 하이퍼파라미터 튜닝
from sklearn.model_selection import cross_val_score # 교차타당도 # 추가

가장 먼저, 분석에 필요한 기본 패키지를 설정을 해준다.

 

 

 

 

2️⃣ 데이터 가져오기

2-1 원본 데이터를 데이터 프레임 형태로 가져오기

df1 = pd.read_csv('data.csv')
df1

 

 

 

2-2 데이터 파악

df1.info()

info( )를 이용하여 데이터 프레임에 있는 데이터들을 확인해 보면 종양의 크기와 모양에 관련된 속성들이 숫자형태(float)로 구성되어 있으며 타깃(y) 값인 diagnosis는 문자 형태(object)로 구성되어 있음을 알 수 있다.

 

 

 

df1.isnull().sum()

isnull( ).sum( )을 이용하여 결측값을 확인해 봤을 때 모든 columns에서 결측 값이 없음을 알 수 있다. ('Unnamed: 32' columns는 원본 데이터를 확인해 봤을 때 불필요한 columns이므로 drop 시킬 예정이다.)

 

 

 

 

3️⃣ 데이터 전처리

현재 데이터에서 전처리가 필요한 부분은 1)문자 형태인 타깃 값을 숫자 형태로 변환해주는 것 2) 필요 없는 columns을 drop 시키는 작업이 필요하다.

 

3-1 타겟값(y = diagnosis) 숫자 형태로 변환

df1['diagnosis'].unique()

 

먼저 unique( )를 사용해서 df1['diagnosis']에 있는 값의 특성을 확인해보면 'M'(malignant)와 'B'(benign)라는 문자 형태의 값들로 이루어져 있음을 알 수 있다. 따라서 'M'(malignant) = 1, 'B'(benign) = 0으로 변환해주도록 한다. (보편적으로 내가 관심 있게 보는 항목을 1로 설정하기 때문에 악성 종양(=암)을 1로 설정하였다.)

 

def func1(row):
    if 'M' in row:
        return 1
    else:
        return 0 
    
df1['판정'] = df1['diagnosis'].apply(func1)
df1.head()

해당 문자들을 숫자로 변환 시키는 방법에는 여러 가지가 있지만, 함수를 사용하여 해당 문자들을 0과 1로 각각 변환시킨 후, 변환된 결과를 df1의 데이터 프레임에 '판정'이라는 새로운 columns를 만들어 넣어준다.

 

 

 

3-2 필요 없는 columns drop 시키기

total = df1.drop(columns=['id','diagnosis','Unnamed: 32'])
total.head()

drop( )을 이용하여 필요없는 columns('id', 'diagnosis', 'Unnamed: 32')을 삭제하고, 나머지를 total로 지정한다. 그 후 total.head()로 데이터 프레임을 확인해보면 해당 columns이 삭제되었음을 알 수 있다.

 

 

 

 

4️⃣ train / test data set 분할

X = total.drop(['판정'],axis=1)
y = total['판정']

먼저 전체 데이터 프레임(total)에서 타겟값(column ['판정'])을 제외한 나머지 columns를 X로 설정하고, total ['판정']을 y로 설정해준다. 

 

 

X_train, X_test, y_train, y_test = train_test_split(X,y, test_size=0.3, random_state=1234, stratify=y)

그 후, train_test_split를 이용하여 7:3의 비율로 train set / test set을 분할한다.

 

 

 

 

5️⃣ 모델 구축

✔️ 1 ~ 4번 항목까지는 각 앙상블 기법들이 동일하지만, 5번의 모델 구축 단계에서부터는 각 기법들에 따라 코드가 달라지기 때문에 필요한 부분만 선택적으로 보면 된다.

 

🖇 앙상블 기법에 대한 이론적 내용은 이전 게시물을 참고

[〚머신러닝〛] - [머신러닝] 앙상블 - 투표(Majority Voting) / 배깅(Bagging)/ 랜덤포레스트(Random Forest) / 부스팅(Boosting)

 

[머신러닝] 앙상블 - 투표(Majority Voting) / 배깅(Bagging)/ 랜덤포레스트(Random Forest) / 부스팅(Boosting)

[〚머신러닝〛] - [머신러닝] 의사결정나무(Decision tree) -1 : 장단점, 활용분야, 구조, 분석절차, 과적합 [머신러닝] 의사결정나무(Decision tree) -1 : 장단점, 활용분야, 구조, 분석절차, 과적합 1. 의사

bigdaheta.tistory.com

 

 

 

➰ 투표 (voting) 기법

logistic = LogisticRegression(solver='liblinear',
                              penalty='l2',
                              C=0.001,
                              random_state=1)

tree = DecisionTreeClassifier(max_depth=None,
                              criterion='entropy',
                              random_state=1)

knn = KNeighborsClassifier(n_neighbors=1,
                            p=2,
                            metric='minkowski')

voting_estimators = [('logistic', logistic), ('tree', tree), ('knn', knn)]

voting = VotingClassifier(estimators = voting_estimators,
                          voting='soft')

clf_labels = ['Logistic regression', 'Decision tree', 'KNN', 'Majority voting']

all_clf = [logistic, tree, knn, voting]

다음으로는 logistic(로지스틱 회귀분석), tree(의사결정나무), knn(k-최근접 이웃)에 대한 모델링을 시행한다. 보팅 유형에는 예측한 결괏값 중 다수의 분류기가 결정한 예측값을 최종 보팅 결괏값으로 선정하는 하드 보팅(Hard Voting)과 분류기들의 레이블 값 결정 확률을 모두 더하여 이를 평균 내어 확률 값이 가장 높은 레이블을 최종 보팅 결괏값으로 선정하는 소프트 보팅(Soft Voting)이 있다. (일반적으로 소프트 보팅 방법이 적용된다.)

 

 

 


➰ 배깅 - 랜덤 포레스트

tree = DecisionTreeClassifier(max_depth=None,
                              criterion='entropy',
                              random_state=1)

forest = RandomForestClassifier(criterion='gini',
                                n_estimators=500, 
                                random_state=1)

clf_labels = ['Decision tree', 'Random forest']

all_clf = [tree, forest]

배깅 기법은 여러 가지 분류 모델 들 중 한 가지 모델에만 집중하여 모델을 구축한 것인데, 이때 의사결정 나무만을 구축하게 되면 '랜덤 포레스트'라고 부르게 된다. 랜덤 포레스트 모델을 구축 시 n_estimators는 '데이터 샘플을 몇 개까지 만들 것인가?'라는 의미이며 n_estimators = 500이라는 것은 의사결정나무를 500개 만든다고 이해하면 된다.

 

 

 


➰ 부스팅 (AdaBoost)

tree = DecisionTreeClassifier(max_depth=1, # 수정
                              criterion='entropy',
                              random_state=1)

adaboost = AdaBoostClassifier(base_estimator=tree, # 수정
                              n_estimators=500,
                              learning_rate = 0.1, # 수정
                              random_state=1)

clf_labels = ['Decision tree', 'Ada boost']

all_clf = [tree, adaboost]

이번에는 의사결정나무와 AdaBoost 기법을 이용하여 모델을 구축한다.

 

 

 

 

6️⃣ 모델 검정

6-1 AUC 검정

( 투표, 랜덤 포레스트, 부스팅 기법 모두 코드는 동일 )

for clf, label in zip(all_clf, clf_labels):
    scores = cross_val_score(estimator=clf,
                             X=X_train,
                             y=y_train,
                             cv=10,
                             scoring='roc_auc')
    print("ROC AUC: %0.3f (+/- %0.3f) [%s]"
          % (scores.mean(), scores.std(), label))

 

 

 

➰ 투표 기법

AUC 결과, 로지스틱 회귀분석은 96%, 의사결정 나무는 92%, KNNdms 89%, 투표 기법을 사용한 결과는 97%로 투표 기법을 사용했을 때 모델 성능이 가장 좋다는 것을 알 수 있다.

 

 

 

➰ 랜덤 포레스트 기법

의사결정나무만을 사용했을 때는 AUC값이 92%인 반면, 랜덤 포레스트를 적용했을 때는 AUC값이 99%로 증가함을 알 수 있다.

 

 

 

➰ 부스팅

의사결정나무만을 사용했을때는 AUC값이 88%인 반면, AdaBoost를 적용했을때는 AUC값이 98%로 증가했음을 알 수 있다.

 

 

 

6-2 ROC 곡선 그리기

 

(코드 동일)

colors = ['black', 'orange', 'blue', 'green']
linestyles = [':', '--', '-.', '-']

for clf, label, clr, ls \
        in zip(all_clf, clf_labels, colors, linestyles):

    clf.fit(X_train, y_train)
    y_pred = clf.predict_proba(X_test)[:, 1]
    fpr, tpr, thresholds = roc_curve(y_true=y_test,
                                     y_score=y_pred)
    roc_auc = auc(x=fpr, y=tpr)
    plt.plot(fpr, tpr,
             color=clr,
             linestyle=ls,
             label='%s (auc = %0.3f)' % (label, roc_auc))

plt.legend(loc='lower right')
plt.plot([0, 1], [0, 1],
         linestyle='--',
         color='gray',
         linewidth=2)

plt.xlim([-0.1, 1.1])
plt.ylim([-0.1, 1.1])
plt.grid(alpha=0.5)
plt.xlabel('False positive rate (FPR)')
plt.ylabel('True positive rate (TPR)')

plt.show()

 

 

 

➰ 투표 기법 (로지스틱 회귀 분석, 의사결정나무, KNN, 보팅)

 

 

 

 

➰ 랜덤 포레스트

 

 

 

 

➰ 부스팅(AdaBoost)

 

 

 

 

6-3 정오 분류표로 검정

➰ 랜덤 포레스트

forest.fit(X_train, y_train)
y_pred = forest.predict(X_test)
print('잘못 분류된 샘플 개수: %d' % (y_test != y_pred).sum())
print('정확도: %.3f' % accuracy_score(y_test, y_pred))
print('정밀도: %.3f' % precision_score(y_true=y_test, y_pred=y_pred))
print('재현율: %.3f' % recall_score(y_true=y_test, y_pred=y_pred))
print('F1: %.3f' % f1_score(y_true=y_test, y_pred=y_pred))

정오 분류표로 랜덤 포레스트 모델을 검정한 결과 위와 같음을 알 수 있다.

 

 

 

➰ 부스팅

adaboost.fit(X_train, y_train)

y_pred = adaboost.predict(X_test)

print('잘못 분류된 샘플 개수: %d' % (y_test != y_pred).sum())
print('정확도: %.3f' % accuracy_score(y_test, y_pred))
print('정밀도: %.3f' % precision_score(y_true=y_test, y_pred=y_pred))
print('재현율: %.3f' % recall_score(y_true=y_test, y_pred=y_pred))
print('F1: %.3f' % f1_score(y_true=y_test, y_pred=y_pred))

부스팅 기법을 적용한 모델의 정오 분류표를 확인한 결과 위와 같음을 알 수 있다.

 

 

 

 

7️⃣ 최적화

➰ 투표 기법 - 하이퍼 파라미터 튜닝

일반적으로 모델링 후, 구축된 모델을 검정하기 위해 파이프라인을 시행하지만, 보팅(voting)의 경우 보팅 자체가 파이프라인 역할을 같이 하기 때문에 따로 파이프라인을 시행하지 않고 바로 하이퍼 파라미터 튜닝 단계로 넘어간다.

voting.get_params()

get_params( )를 사용하여 사용할 수 있는 파라미터를 확인한다.

 

 

params = {'logistic__C': [0.001, 0.1, 100.0],
          'tree__max_depth': [1, 2, 3, 4, 5],
          'knn__n_neighbors': [1, 2, 3, 4, 5]}

grid = GridSearchCV(estimator=voting,
                    param_grid=params,
                    cv=10,
                    scoring='roc_auc',
                    iid=False)
grid.fit(X_train, y_train)

for r, _ in enumerate(grid.cv_results_['mean_test_score']):
    print("%0.3f +/- %0.3f %r"
          % (grid.cv_results_['mean_test_score'][r], 
             grid.cv_results_['std_test_score'][r] / 2.0, 
             grid.cv_results_['params'][r]))

 

 

 

print('최적의 파타미터: %s' % grid.best_params_)
print('ACU: %.3f' % grid.best_score_)

grid.best_params_를 사용하여 최적의 파라미터 값을 구하고, 그것을 적용했을 때 나온 AUC의 값(98.8%)이 투표기법을 사용하여 분석했을 때 모델의 정확도이다.

 

 

 


➰ 랜덤 포레스트 -  특성 중요도 확인

본문 5번의 모델 구축 단계에서 랜덤 포레스트 샘플을 500개 만들었다. 샘플을 500개 만든다는 것은 나무의 가지가 1개일 때부터 여러 개일 때까지 무수히 많은 옵션을 만든다는 것이고, 이렇게 만들어진 샘플 중 최적의 브런치들만 모아서 하나의 최적의 모델을 만드는 것이 랜덤 포레스트의 원리이다. 때문에 랜덤 포레스트 기법을 사용 시 별도의 파라미터 튜닝을 하지 않는다.(필요하지 않다.)

 

이번 단계에서는 특성들(X) 별로 타겟값 (y)에 미치는 중요도(영향도)를 확인해보자.

feat_labels = X.columns

importances = forest.feature_importances_

indices = np.argsort(importances)[::-1]

for f in range(X_train.shape[1]):
    print("%2d) %-*s %f" % (f + 1, 30, 
                            feat_labels[indices[f]], 
                            importances[indices[f]]))

plt.title('Feature Importance')
plt.bar(range(X_train.shape[1]), 
        importances[indices],
        align='center')

plt.xticks(range(X_train.shape[1]), 
           feat_labels[indices], rotation=90)
plt.xlim([-1, X_train.shape[1]])
plt.tight_layout()
plt.show()

 

feature_importances_를 이용하여 확인한 각 특성 별 중요도는 다음과 같다.

 

 

 

 

 

🖇 데이터 다운로드

www.kaggle.com/uciml/breast-cancer-wisconsin-data

 

Breast Cancer Wisconsin (Diagnostic) Data Set

Predict whether the cancer is benign or malignant

www.kaggle.com

 

반응형