H20 AutoML로 유방암 종양 판별하기
0. 들어가며¶
데이터셋 설명¶
여기서 사용한 데이터셋은 위스콘신 유방암 진단 데이터 입니다.[1] 이 데이터셋에는 30개의 특성(features)값이 들어있고 유방암의 진단결과가 포함되어 있습니다. 총 데이터의 수는 596개이며 위스콘신 대학교에서 제공한 유방암 진단결과 데이터 입니다. 데이터셋에 포함된 특성에 대한 간략한 설명을 아래 표에 나타내었습니다.
특성 | 설명 |
---|---|
id | 환자 식별 번호 |
dignosis | 유방암 종양(M=악성, B=양성) |
radius | 세포의 크기 |
texture | 질감(흑백 처리했을때의 표준편차 값으로 계산) |
perimeter | 둘레 |
area | 면적 |
smoothness | 매끄러움(반경의 국소적 변화 측정) |
compactness | 작은 정도($perimeter^2/area-1$로 계산) |
concavity | 오목함(윤곽의 오목한 부분의 정도) |
concave points | 오목한곳의 수 |
symmetry | 대칭성 |
fractal dimension | 프랙탈 차원($coastline approximation-1$로 계산) |
각각의 측정값들은 _mean
(평균값), _SE
(표준오차), _worst
(제일 큰값 3개의 평균)으로 나타내어 총 30개의 특성값을 갖는다.
H2O¶
H2O 는 자바(Java) 기반의 소프트웨어로 데이터 모델링에 사용된다. H2O의 첫번째 목적은 병렬 컴퓨팅을 통해 많은 CPU와 메모리를 프로세스 하는 것이다. 자바 기반이지만 파이썬과 R
인터페이스를 제공합니다[2].
분석하기¶
먼저 유방암 진단에 대하여 이해하기 위해 데이터셋의 특성값을 분석해봅니다. 그런 다음 두 가지 알고리즘을 사용하여 모델을 생성하고 모델을 사용하여 유방암을 예측해봅니다.
1. 라이브러리 불러오기¶
분석에 사용할 라이브러리를 불러옵니다.
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import h2o
from h2o.estimators.gbm import H2OGradientBoostingEstimator
%matplotlib inline
데이터를 불러오는데 H2O를 사용합니다. 먼저 H2O를 초기화해야 합니다.
1.1. H2O 시작하기¶
H2O는 먼저 기존 인스턴스에 연결을 시도합니다. 그리고 사용 가능한 것이 없다면 새로 인스턴스를 만듭니다. 새 인스턴스에 대한 정보가 콘솔창에 출력되면 H2O를 사용할 준비는 모두 된 것입니다.
h2o.init()
H2O 클러스터 가동 시간, 시간대, 버전, 버전 수명, 클러스터 이름, 할당 된 하드웨어 리소스 (노드 수, 메모리, 코어 수), 연결 URL, 노출 된 H2O API 확장 및 사용 된 파이썬 버전과 같은 추가 정보가 출력되었습니다.
2. 데이터 불러오기¶
이제 아래 코드를 사용해 H2O를 사용하여 데이터를 가져옵니다.
data_df = h2o.import_file("../input/data.csv", destination_frame="data_df")
3. 데이터 확인하기¶
H2O의 describe()
기능을 사용해 불러온 데이터셋을 확인합니다.
describe()
함수를 호출하는 것은summary()
를 호출하는 것과 동일한 기능을 합니다.
data_df.describe()
569개의 행(rows)과 33개의 열columns)로 구성이 되어 있습니다. 이것으로 각각의 열에 대하여 데이터 타입, 최대 최소 값등의 정보를 알 수 있습니다.
4. 데이터 탐색하기¶
H2O에서 제공하는 기능을 사용해 데이터를 탐색해봅니다.
종양의 진단에 관한 diagnosis 값으로 그룹을 만들어 양성과 악성 종양의 데이터 수를 확인해 봅니다.
df_group = data_df.group_by("diagnosis").count()
df_group.get_frame()
양성(B)과 악성(M)이 각각 357, 212개 존재하는 것을 알 수 있습니다.
이제 각 특성(feature)값에 따라 양성과 악성 종양의 분포가 어떻게 되는지 시각화를 통해 살펴봅니다.
features = [f for f in data_df.columns if f not in ["id", "diagnosis", "C33"]]
i = 0
t0 = data_df[data_df["diagnosis"] == "M"].as_data_frame()
t1 = data_df[data_df["diagnosis"] == "B"].as_data_frame()
# sns.set_style('whitegrid')
plt.figure()
fig, ax = plt.subplots(6, 5, figsize=(16, 24))
for feature in features:
i += 1
plt.subplot(6, 5, i)
sns.kdeplot(t0[feature], bw=0.5, label="Malignant")
sns.kdeplot(t1[feature], bw=0.5, label="Benign")
plt.xlabel(feature, fontsize=12)
locs, labels = plt.xticks()
plt.tick_params(axis="both", which="major", labelsize=12)
plt.show()
위 그림을 통해 우리는 양성과 악성 종양을 구분할 수 있는 특성을 알 수 있습니다. 아래에는 그런 특성들의 목록입니다.
- radius_mean
- texture_mean
- perimeter_mean
- area_mean
- radius_worst
- texture_worst
- perimeter_worst
- area_worst
그러나 양성과 악성을 전혀 구분할 수 없는 특성들도 있습니다. 다음과 같은 특성은 두 가지 종양에서 차이가 나타나지 않습니다.
- compactness_se
- concavity_se
- concave_points_se
- simmetry_se
- smoothness_se
이제 특성간의 상관관계(correlation) Heat map을 그려봅니다.
plt.figure(figsize=(16, 16))
corr = data_df[features].cor().as_data_frame()
corr.index = features
sns.heatmap(
corr,
annot=True,
cmap="coolwarm",
linecolor="white",
vmin=-1,
vmax=1,
cbar_kws={"orientation": "vertical"},
)
plt.title("Correlation Heatmap", fontsize=14)
plt.show()
아래 일부 특성은 서로 밀접하게 관련되어 있습니다.
- radius_mean 과 perimeter_mean
- radius_mean 과 texture_mean
- perimeter_worst 와 radius_worst
- perimeter_worst 와 area_worst
- area_se 와 perimeter_se
train_df, valid_df, test_df = data_df.split_frame(ratios=[0.6, 0.2], seed=2018)
target = "diagnosis"
train_df[target] = train_df[target].asfactor()
valid_df[target] = valid_df[target].asfactor()
test_df[target] = test_df[target].asfactor()
print(
"학습, 검증, 테스트 데이터셋의 수 : ",
train_df.shape[0],
valid_df.shape[0],
test_df.shape[0],
)
5.2. GBM(Gradient Boosting Algorithm) 모델로 학습하기¶
GBM 모델을 사용해 기계 학습을 합니다.
predictors = features
gbm = H2OGradientBoostingEstimator()
gbm.train(x=predictors, y=target, training_frame=train_df)
5.3. 모델 평가하기¶
훈련 된 모델을 검사 해봅니다. 먼저 모델에 대한 요약을 출력합니다.
gbm.summary()
이것은 우리가 만든 모델이 50개의 tree와 50 개의 internal tree를 사용했음을 보여줍니다. 또한 최소 4개 최대 5개의 tree 깊이, 최소 7개 최대 14개의 leaf 수를 알 수 있습니다.
추가적으로 검증 데이터셋에 대한 모델의 성능을 확인해 봅시다.
print(gbm.model_performance(valid_df))
혼동 행렬을 통해 오직 하나의 값만 잘못 예측되었음을 알 수 있습니다. 모델의 성능은 AUC가 0.9987이고 Gini coeff
가 0.997, LogLoss
는 0.05 임을 알 수 있습니다.
이와 같이 좋은 결과값을 얻으면 더이상 모델을 더 조정할 필요가 없습니다. 이제 테스트 데이터셋을 이용해 값을 예측할 수 있습니다. 그러기전에 먼저 모델에 들어가는 변수들의 중요도 플롯을 확인해봅니다.
gbm.varimp_plot()
pred_val = list(gbm.predict(test_df[predictors])[0])
true_val = list(test_df[target])
prediction_acc = np.mean(pred_val == true_val)
print("Prediction accuracy: ", prediction_acc)
정확도는 1입니다(100 % 정확하게 예측 된 값).
6.참고¶
[1] Breast Cancer Wisconsin (Diagnostic) Data Set, https://www.kaggle.com/uciml/breast-cancer-wisconsin-data
[2] SRK, Getting started with H2O, https://www.kaggle.com/sudalairajkumar/getting-started-with-h2o