본문 바로가기
IT & 데이터 사이언스/데이터 분석 실습

[DACON] 심장질환예측 경진대회(Basic)(1)

by 바른 호랑이 2021. 12. 18.
728x90
반응형

※ DACON 링크

 

심장 질환 예측 경진대회 - DACON

좋아요는 1분 내에 한 번만 클릭 할 수 있습니다.

dacon.io

※ 변수 분석시 참고한 사이트

 

변수의 종류와 통계 기법

변수의 종류 수량적 특성에 의한 구분 질적 변수 (qualitative variables) 비서열 질적 변수 (unordered-qu...

blog.naver.com

해당 경진대회는 데이터 분석에 관심이 있는 사람들의 학습을 돕고, 실제 데이터 분석능력을 함양할 수 있게 해주는 DACON에서 진행중인 온라인 기반 경진대회이다. Basic에 해당되어 분석할 때 참고할 수 있는 Baseline코드를 제공해주고 있기에 데이터 분석에 관심이 있지만, 어디서부터 시작해야할 지 고민인 사람들이 부담없이 참여하기 좋은 대회여서 실력을 기르기 위해 참여를 해보았다. 데이터를 다운로드 받은 후 가장 먼저 데이터의 구조를 확인해보았다.

 

Basic_dir = os.path.dirname(os.path.dirname(os.path.realpath('EDA.ipynb')))
PATH = Basic_dir + '\\Data\\Data(HeartD_B)'
df_train = pd.read_csv(PATH + '\\train.csv')
df_train.info()

 

확인 결과, 결측값은 없었으며, 데이터의 변수들이 전부 숫자형으로 되어있어 범주형 변수들을 따로 인코딩할 필요가 없는 것으로 확인하였다. 결측치가 없다는 것을 확인한 후, 변수들에 대해 특별한 전처리를 하지 않았을때와 전처리를 했을때의 정확도 차이를 확인해보기 위해 기본적인 변수처리들만 해주기로 생각을 했고, 실시한 처리내용은 아래와 같다.

1. 연속형 변수와 범주형 변수들을 분리, 종속변수를 순위변수로 가정하고 분석 진행

2. 나이 변수는 연령대로 변경하여 분석에 활용(10대, 20대, 30대의 형태로 분류후 사용)

3. 연속형 변수는 스피어만 상관계수분석을 통해 연관성 식별 후 연관있는 변수들만 사용

4. 범주형 변수들은 크루스칼 왈리스 검정을 통해 연관성 식별 후 연관있는 변수들만 사용

위의 내용으로 변수들을 분석한 코드는 아래와 같다.

 

# 연령층을 범위 단위로 변환
df_train['age_gr'] = np.where(df_train.age < 20, 10, 
                     np.where(df_train.age < 30, 20, 
                     np.where(df_train.age < 40, 30, 
                     np.where(df_train.age < 50, 40,
                     np.where(df_train.age < 60, 50,
                     np.where(df_train.age < 70, 60, 70))))))
df_train.head()

# target을 순위변수로 보았을때
# 스피어만 상관계수 분석 실시
from scipy import stats
x_list = []
print(val_list1)
for col in val_list1:
    if stats.spearmanr(df_train[col], df_train.target)[1] < 0.05:
        x_list.append(col)
        print(f'{col} : {round(stats.spearmanr(df_train[col], df_train.target)[0], 3)}, {round(stats.spearmanr(df_train[col], df_train.target)[1], 5)}')
# 분석결과 : trestbps, chol은 연관성이 있다고 보기 어려움. 귀무가설 기각 불가
print(x_list)

# 질적 변수들을 모두 명목변수로, target을 순위 변수로 보고 연관성 테스트
# 크루스칼 왈리스 검정 실시 # 등분산성 및 정규성 검정은 미실시
import statsmodels.api as sm
from statsmodels.formula.api import ols

# p-value가 0.05이하이므로 귀무가설(관계가 없다)기각 - sex는 관계가 있음
stats.kruskal(df_train[df_train.sex == 0].target,\
              df_train[df_train.sex == 1].target)

# p-value가 0.05이하이므로 귀무가설(관계가 없다)기각 - cp는 관계가 있음
stats.kruskal(df_train[df_train.cp == 0].target, df_train[df_train.cp == 1].target,\
              df_train[df_train.cp == 2].target, df_train[df_train.cp == 3].target)

# p-value가 0.05이상이므로 귀무가설(관계가 없다)기각불가 - fbs는 관계가 없음.
stats.kruskal(df_train[df_train.fbs == 0].target,\
              df_train[df_train.fbs == 1].target)

# restecg는 값이 2를 가지는 행이 1개밖에 존재하지 않음 - 추후 반영하여 분석실시
# p-value가 0.05이상이므로 귀무가설(관계가 없다)기각불가 - restecg는 관계가 없음.
stats.kruskal(df_train[df_train.restecg == 0].target, df_train[df_train.restecg == 1].target,\
              df_train[df_train.restecg == 2].target)

# p-value가 0.05이하이므로 귀무가설(관계가 없다)기각 - exang는 관계가 있음
stats.kruskal(df_train[df_train.exang == 0].target,\
              df_train[df_train.exang == 1].target)

# p-value가 0.05이하이므로 귀무가설(관계가 없다)기각 - thal은 관계가 있음
stats.kruskal(df_train[df_train.thal == 0].target, df_train[df_train.thal == 1].target,\
              df_train[df_train.thal == 2].target, df_train[df_train.thal == 3].target)   

# p-value가 0.05이하이므로 귀무가설(관계가 없다)기각 - age_gr은 관계가 있음
stats.kruskal(df_train[df_train.age_gr == 30].target, df_train[df_train.age_gr == 40].target,\
              df_train[df_train.age_gr == 60].target, df_train[df_train.age_gr == 70].target,\
              df_train[df_train.age_gr == 70].target)

 

간단하게 예측결과를 탐색해보는 것이 목적이었기에 변수들을 처리하면서 데이터의 정규성, 등분산성, 이상치는 고려하지 않았으며, 데이터 예측을 하는 데 있어서도 가장 간단한 KNN 모델과 의사결정나무 모델만 가지고 우선 결과물을 확인해보기로 했다. 사용할 변수들을 선정한 뒤 연속형 변수들만 간단하게 가장 기본적인 scaler인 standardscaler를 사용하여 정규화를 해준 후 분석을 진행해보았으며, 분석한 코드와 결과는 아래와 같다.

 

# EDA에서 선별한 변수리스트
x_list = ['thalach', 'oldpeak', 'slope', 'ca', 'sex', 'cp', 'exang', 'thal', 'age_gr']

# KNN 모델
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import classification_report, confusion_matrix
# 정확도 테스트(훈련데이터 셋)
from sklearn.metrics import accuracy_score
n = 7
neigh_n = KNeighborsClassifier(n_neighbors = n, weights = 'distance')
neigh_n.fit(df_train[x_list], list(df_train.target))

# 의사결정나무 모델
from sklearn.tree import DecisionTreeClassifier, plot_tree, export_text
from sklearn.metrics import classification_report, confusion_matrix
model = DecisionTreeClassifier()
model.fit(df_train[x_list], list(df_train.target))

 

KNN모델과 의사결정나무 모델만 가지고 결과물을 분석한 결과, 정확도는 80%정도로 나타났고, 다른 사람들의 결과물을 확인해보니 90%가 넘는 정확도로 예측한 결과물이 있는 것을 확인하였다. 추후 이상치 제거 등과 같은 추가 변수처리 및 나이브 베이지안 분류기, 로지스틱 회귀모델, 텐서플로우를 활용한 딥러닝 분류를 시도하여 결과물을 확인해보고 정확도 개선을 해봐야겠다고 생각을 했다.

 

P.S 개발자가 되기위해 공부중입니다. 잘못된 부분을 댓글로 남겨주시면 학습하는데 큰 도움이 될 거 같습니다.

세부코드가 궁금하신 분들은 아래 GitHub를 참고해주시기 바랍니다.

 

※ Github

 

GitHub - Jeong-Beom/TIL: 교육받은 내용을 기록하기 위한 레파지토리입니다.

교육받은 내용을 기록하기 위한 레파지토리입니다. Contribute to Jeong-Beom/TIL development by creating an account on GitHub.

github.com

728x90
반응형

댓글