인공지능

Tabular Data - 당뇨병에 걸릴지 안걸릴지 분류

별은_StarIs_Dev 2025. 2. 3. 23:52
반응형

활용파일

diabetes_testset30.csv
0.00MB
diabetes_testset30_answer.csv
0.00MB
diabetes_train.csv
0.03MB

 

목적

- 여러 파라미터를 통해 당뇨병에 걸릴 확률을 예측해보자

 

1. 라이브러리 임포트 및 데이터 불러오기

from sklearn.model_selection import train_test_split #데이터를 학습/데이터용으로 분리
from sklearn.metrics import accuracy_score #모델의 예측 정확도 평가
import pandas as pd #데이터 관리
import pickle #모델을 파일로 저장하거나 불러옴
import joblib

 

folder_path='./data_folder'
train = pd.read_csv(folder_path + '/diabetes_train.csv')
test30 = pd.read_csv(folder_path + '/diabetes_testset30.csv')

 

2. 데이터 전처리  - 범주형 데이터 변환

train_copy = train
train_copy['Sex'] = train_copy['Sex'].map({'Male':0,'Female':1})

 - 범주형 데이터를 숫자로 매핑함

 

 

3. 카이제곱 검정을 통한 범주형 변수 중요도 확인

from scipy.stats import chi2_contingency
col_list = train_copy.columns
for i in col_list:
    cross_outcome = pd.crosstab(train_copy[i], train_copy['Outcome'])
    chi2_result = chi2_contingency(cross_outcome)
    print(f"{i}에 따라 당뇨병에 영향이 있다. : {chi2_result[1]}")

 

  • chi2_contingency: 범주형 변수와 타겟(Outcome) 간의 연관성을 검정합니다.
  • pd.crosstab: 각 변수와 Outcome 간의 빈도표를 만듭니다.
  • 각 변수마다 p-value(검정 결과의 두 번째 값, chi2_result[1])를 출력합니다.
    • 예: 만약 p-value가 높으면(예: Sex의 경우 0.86) 해당 변수는 당뇨병(Outcome)과 큰 관련성이 없다고 판단하여 제외할 수 있습니다.

 - 검정 결과 Sex변수가 p-value 0.05이상으로 제

 

train_filtered = train_copy.drop(columns=['Sex'])

 

4. ANOVA 검정을 통한 연속형 변수 중요도 확인

from scipy.stats import f_oneway
col_list = train_filtered.columns
for i in col_list:
    data_list = []
    for outcome in train_filtered['Outcome'].unique():
        data_list.append(train_filtered[train_filtered['Outcome'] == outcome][i])
    f_statistics, p_value = f_oneway(*data_list)
    print(f"{i} {f_statistics} , p_value : {p_value}")

 

  • f_oneway: ANOVA 검정으로, 연속형 변수(예: 나이, 혈당 등)가 Outcome에 따라 유의미하게 차이가 있는지 확인합니다.
  • Outcome(당뇨병 진단 여부)의 각 그룹별로 해당 변수의 값들을 비교합니다.
  • 출력된 결과를 바탕으로, 예제에서는 BloodPressure(혈압)가 p-value가 높아 의미가 없다고 판단하여 제거합니다.

 

train_filtered = train_filtered.drop(columns=['BloodPressure'])
test30_copy = test30.drop(columns=['BloodPressure', 'Sex'])

 - Sex와 BloodPressure를 제거

 

5. 모델 학습을 위한 데이터 분리

x = train_filtered.drop(columns=['Outcome'])
y = train_filtered['Outcome']
train_x, test_x, train_y, test_y = train_test_split(x, y, test_size=0.3, random_state=2024, stratify=y)

데이터를 학습용과 테스트용으로 나눔

stratify = y : 타깃의 비율을 학습데이터와 테스트데이터에서 모두 비슷하도록 분리

 

6. 머신러닝 모델 학습 및 평가

1) 결정 트리 모델

from sklearn.tree import DecisionTreeClassifier
model_DTC = DecisionTreeClassifier()
model_DTC.fit(train_x, train_y)
pred_DTC = model_DTC.predict(test_x)
print(accuracy_score(test_y, pred_DTC))

 

  • DecisionTreeClassifier: 결정 트리 모델을 생성하고 학습합니다.
  • model_DTC.fit: 학습 데이터로 모델을 학습시킵니다.
  • model_DTC.predict: 테스트 데이터를 사용하여 예측합니다.
  • accuracy_score: 테스트 데이터에 대한 예측 정확도를 계산합니다.

 

 

 

2) 랜덤 포레스트 모델

from sklearn.ensemble import RandomForestClassifier
model_RFC = RandomForestClassifier()
model_RFC.fit(train_x, train_y)
pred_RFC = model_RFC.predict(test_x)
print(accuracy_score(test_y, pred_RFC))

 

  • RandomForestClassifier: 여러 결정 트리를 사용해 앙상블 기법으로 예측하는 모델입니다.
  • 학습, 예측, 평가 과정은 결정 트리와 유사합니다.

 

 

3) XGBoost 모델

from xgboost import XGBClassifier
model_XGC = XGBClassifier()
model_XGC.fit(train_x, train_y)
pred_XGC = model_XGC.predict(test_x)
print(accuracy_score(test_y, pred_XGC))
  • XGBClassifier: XGBoost 모델을 사용하여 학습합니다.
  • XGBoost는 부스팅 알고리즘을 기반으로 한 강력한 모델입니다.
  • 학습 후 테스트 데이터로 예측하고 정확도를 출력합니다.

 

4) Keras를 사용한 딥러닝 모델

from keras.models import Sequential
from keras.layers import Dense
import numpy as np

model_DNN = Sequential()
model_DNN.add(Dense(4, activation='softmax'))
model_DNN.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
history = model_DNN.fit(train_x, train_y, epochs=30, verbose=1)
pred_DNN = model_DNN.predict(test_x)
acc_DNN = accuracy_score(test_y, np.argmax(pred_DNN, axis=1))
print(acc_DNN)

 

  • Sequential: 순차적으로 층을 쌓는 딥러닝 모델을 만듭니다.
  • Dense(4, activation='softmax'):
    • 입력층과 출력층이 결합된 형태로, 출력 뉴런의 수가 4개입니다.
    • softmax 활성화 함수를 사용하여 출력값을 확률로 변환합니다.
    • (참고: 출력 뉴런의 수는 문제에 따라 다르게 설정할 수 있으며, 이 경우 출력 클래스가 2개인 당뇨병 분류 문제에 맞게 조정할 필요가 있을 수 있습니다.)
  • compile: 모델을 학습하기 위한 설정을 합니다.
    • optimizer='adam': Adam 옵티마이저를 사용합니다.
    • loss='sparse_categorical_crossentropy': 정수 레이블을 사용하는 다중 클래스 분류에 적합한 손실 함수입니다.
  • fit: 학습 데이터를 사용해 모델을 30 에포크 동안 학습합니다.
  • predict: 테스트 데이터를 입력하여 예측합니다.
  • np.argmax: softmax의 출력에서 가장 높은 확률을 가진 인덱스를 선택해 예측 결과(클래스)를 얻습니다.
  • 마지막으로 accuracy_score를 통해 딥러닝 모델의 정확도를 계산합니다.
print('DecisionTreeClassifier : ', accuracy_score(test_y,pred_DTC))
print('RandomForestClassifier : ', accuracy_score(test_y, pred_RFC))
print('XGBClassifier : ', accuracy_score(test_y, pred_XGC))
print('DNN : ', acc_DNN)

DecisionTreeClassifier : 0.6486486486486487

RandomForestClassifier : 0.7162162162162162

XGBClassifier : 0.7297297297297297

DNN : 0.5135135135135135

 

=> XGBC 사용

 

7. 모델 저장 및 불러오기

 - 모델 저장

import joblib
joblib.dump(model_RFC, 'RFC.pkl')

 - 모델 불러오기 및 재사용

load_model = joblib.load('RFC.pkl')
predictions = load_model.predict(test_x)
accuracy = accuracy_score(test_y, predictions)
print(accuracy)

 - 추가 테스트 데이터에 대한 예측

load_model.predict(test30_copy)

 

#정답파일 만들기
result_pd = pd.DataFrame(test_x)
result_pd['Outcome'] = predictions
result_pd.to_csv('./result.csv', index=False)

result = pd.read_csv('./result.csv')
result.head()

 

 

정리

1. 데이터 준비

2. 변수 선택

3. 데이터 분할

4. 모델 학습

5. 모델 저장 및 재사용

 

전체 코드

from sklearn.model_selection import train_test_split #데이터를 학습/데이터용으로 분리
from sklearn.metrics import accuracy_score #모델의 예측 정확도 평가
import pandas as pd #데이터 관리
import pickle #모델을 파일로 저장하거나 불러옴
import joblib

folder_path='./data_folder'
train = pd.read_csv(folder_path + '/diabetes_train.csv')
test30 = pd.read_csv(folder_path + '/diabetes_testset30.csv')

train_copy = train
train_copy['Sex'] = train_copy['Sex'].map({'Male':0,'Female':1})


from scipy.stats import chi2_contingency
col_list = train_copy.columns
for i in col_list:
    cross_outcome = pd.crosstab(train_copy[i], train_copy['Outcome'])
    chi2_result = chi2_contingency(cross_outcome)
    print(f"{i}에 따라 당뇨병에 영향이 있다. : {chi2_result[1]}")

train_filtered = train_copy.drop(columns=['Sex'])

from scipy.stats import f_oneway
col_list = train_filtered.columns
for i in col_list:
    data_list = []
    for outcome in train_filtered['Outcome'].unique():
        data_list.append(train_filtered[train_filtered['Outcome'] == outcome][i])
    f_statistics, p_value = f_oneway(*data_list)
    print(f"{i} {f_statistics} , p_value : {p_value}")

train_filtered = train_filtered.drop(columns=['BloodPressure'])
test30_copy = test30.drop(columns=['BloodPressure', 'Sex'])

x = train_filtered.drop(columns=['Outcome'])
y = train_filtered['Outcome']
train_x, test_x, train_y, test_y = train_test_split(x, y, test_size=0.3, random_state=2024, stratify=y)

from sklearn.tree import DecisionTreeClassifier
model_DTC = DecisionTreeClassifier()
model_DTC.fit(train_x, train_y)
pred_DTC = model_DTC.predict(test_x)
print(accuracy_score(test_y, pred_DTC))

from sklearn.ensemble import RandomForestClassifier
model_RFC = RandomForestClassifier()
model_RFC.fit(train_x, train_y)
pred_RFC = model_RFC.predict(test_x)
print(accuracy_score(test_y, pred_RFC))

from xgboost import XGBClassifier
model_XGC = XGBClassifier()
model_XGC.fit(train_x, train_y)
pred_XGC = model_XGC.predict(test_x)
print(accuracy_score(test_y, pred_XGC))

from keras.models import Sequential
from keras.layers import Dense
import numpy as np

model_DNN = Sequential()
model_DNN.add(Dense(4, activation='softmax'))
model_DNN.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
history = model_DNN.fit(train_x, train_y, epochs=30, verbose=1)
pred_DNN = model_DNN.predict(test_x)
acc_DNN = accuracy_score(test_y, np.argmax(pred_DNN, axis=1))
print(acc_DNN)

print('DecisionTreeClassifier : ', accuracy_score(test_y,pred_DTC))
print('RandomForestClassifier : ', accuracy_score(test_y, pred_RFC))
print('XGBClassifier : ', accuracy_score(test_y, pred_XGC))
print('DNN : ', acc_DNN)

import joblib
joblib.dump(model_RFC, 'RFC.pkl')

load_model = joblib.load('RFC.pkl')
predictions = load_model.predict(test_x)
accuracy = accuracy_score(test_y, predictions)
print(accuracy)

load_model.predict(test30_copy)

#정답파일 만들기
result_pd = pd.DataFrame(test_x)
result_pd['Outcome'] = predictions
result_pd.to_csv('./result.csv', index=False)

result = pd.read_csv('./result.csv')
result.head()
반응형