Python 데이터 분석
Support Vector Machine(SVM) 예제 - 심장병 환자 데이터
코딩탕탕
2022. 11. 23. 18:33

<작성자 코드>
# [SVM 분류 문제] 심장병 환자 데이터를 사용하여 분류 정확도 분석 연습
# https://www.kaggle.com/zhaoyingzhu/heartcsv
# https://github.com/pykwon/python/tree/master/testdata_utf8 Heartcsv
#
# Heart 데이터는 흉부외과 환자 303명을 관찰한 데이터다.
# 각 환자의 나이, 성별, 검진 정보 컬럼 13개와 마지막 AHD 칼럼에 각 환자들이 심장병이 있는지 여부가 기록되어 있다.
# dataset에 대해 학습을 위한 train과 test로 구분하고 분류 모델을 만들어, 모델 객체를 호출할 경우 정확한 확률을 확인하시오.
# 임의의 값을 넣어 분류 결과를 확인하시오.
# 정확도가 예상보다 적게 나올 수 있음에 실망하지 말자. ㅎㅎ
#
# feature 칼럼 : 문자 데이터 칼럼은 제외
# label 칼럼 : AHD(중증 심장질환)
#
# 데이터 예)
# "","Age","Sex","ChestPain","RestBP","Chol","Fbs","RestECG","MaxHR","ExAng","Oldpeak","Slope","Ca","Thal","AHD"
# "1",63,1,"typical",145,233,1,2,150,0,2.3,3,0,"fixed","No"
# "2",67,1,"asymptomatic",160,286,0,2,108,1,1.5,2,3,"normal","Yes"
# ...
import pandas as pd
import numpy as np
from sklearn import svm, metrics
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
df = pd.read_csv('https://raw.githubusercontent.com/pykwon/python/master/testdata_utf8/Heart.csv', )
df = df.drop(['Unnamed: 0'], axis=1)
print(df.head(3), df.shape) # (303, 15)
print(df.describe())
print(df.info())
# print(df.isnull().sum())
df.fillna({'Ca':float(df['Ca'].mean())}, inplace=True)
df_x = df.drop(columns = ['ChestPain', 'Thal', 'AHD'])
df_y = df['AHD']
x_train, x_test, y_train, y_test = train_test_split(df_x, df_y, test_size = 0.2, random_state = 1)
print(x_train.shape, x_test.shape, y_train.shape, y_test.shape) # (242, 12) (61, 12) (242,) (61,)
print()
# model
model = svm.SVC(C=1).fit(x_train, y_train)
pred = model.predict(x_test)
print('예측값 :', pred[:10])
print('실제값 :', y_test[:10].values)
acc = metrics.accuracy_score(y_test, pred)
print('acc :', acc) # 0.67213
print()
# 교차 검증
from sklearn import model_selection
cross_vali = model_selection.cross_val_score(model, x_test, y_test, cv = 5)
print('각각의 검증 정확도 :', cross_vali)
print('평균 검증 정확도 :', cross_vali.mean())
# 새 값으로 예측
new_data = pd.DataFrame({'Age':[60, 65], 'Sex':[1, 0], 'RestBP':[145, 160], 'Chol':[250, 245], 'Fbs':[2, 0], 'RestECG':[1, 2], 'MaxHR':[150, 125], 'ExAng':[0, 1], 'Oldpeak':[2.3, 1.7], 'Slope':[3, 2], 'Ca':[3, 2]})
new_pred = model.predict(new_data)
print('새로운 예측값 :', new_pred)
<console>
Age Sex ChestPain RestBP Chol ... Oldpeak Slope Ca Thal AHD
0 63 1 typical 145 233 ... 2.3 3 0.0 fixed No
1 67 1 asymptomatic 160 286 ... 1.5 2 3.0 normal Yes
2 67 1 asymptomatic 120 229 ... 2.6 2 2.0 reversable Yes
[3 rows x 14 columns] (303, 14)
Age Sex RestBP ... Oldpeak Slope Ca
count 303.000000 303.000000 303.000000 ... 303.000000 303.000000 299.000000
mean 54.438944 0.679868 131.689769 ... 1.039604 1.600660 0.672241
std 9.038662 0.467299 17.599748 ... 1.161075 0.616226 0.937438
min 29.000000 0.000000 94.000000 ... 0.000000 1.000000 0.000000
25% 48.000000 0.000000 120.000000 ... 0.000000 1.000000 0.000000
50% 56.000000 1.000000 130.000000 ... 0.800000 2.000000 0.000000
75% 61.000000 1.000000 140.000000 ... 1.600000 2.000000 1.000000
max 77.000000 1.000000 200.000000 ... 6.200000 3.000000 3.000000
[8 rows x 11 columns]
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 303 entries, 0 to 302
Data columns (total 14 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Age 303 non-null int64
1 Sex 303 non-null int64
2 ChestPain 303 non-null object
3 RestBP 303 non-null int64
4 Chol 303 non-null int64
5 Fbs 303 non-null int64
6 RestECG 303 non-null int64
7 MaxHR 303 non-null int64
8 ExAng 303 non-null int64
9 Oldpeak 303 non-null float64
10 Slope 303 non-null int64
11 Ca 299 non-null float64
12 Thal 301 non-null object
13 AHD 303 non-null object
dtypes: float64(2), int64(9), object(3)
memory usage: 33.3+ KB
None
(242, 11) (61, 11) (242,) (61,)
예측값 : ['No' 'No' 'No' 'Yes' 'No' 'No' 'No' 'Yes' 'Yes' 'Yes']
실제값 : ['No' 'No' 'No' 'Yes' 'Yes' 'No' 'No' 'Yes' 'Yes' 'Yes']
acc : 0.6721311475409836
각각의 검증 정확도 : [0.53846154 0.58333333 0.58333333 0.58333333 0.5 ]
평균 검증 정확도 : 0.5576923076923077
새로운 예측값 : ['No' 'Yes']
<선생님 코드>
# [SVM 분류 문제] 심장병 환자 데이터를 사용하여 분류 정확도 분석 연습
# https://www.kaggle.com/zhaoyingzhu/heartcsv
# https://github.com/pykwon/python/tree/master/testdata_utf8 Heartcsv
#
# Heart 데이터는 흉부외과 환자 303명을 관찰한 데이터다.
# 각 환자의 나이, 성별, 검진 정보 컬럼 13개와 마지막 AHD 칼럼에 각 환자들이 심장병이 있는지 여부가 기록되어 있다.
# dataset에 대해 학습을 위한 train과 test로 구분하고 분류 모델을 만들어, 모델 객체를 호출할 경우 정확한 확률을 확인하시오.
# 임의의 값을 넣어 분류 결과를 확인하시오.
# 정확도가 예상보다 적게 나올 수 있음에 실망하지 말자. ㅎㅎ
#
# feature 칼럼 : 문자 데이터 칼럼은 제외
# label 칼럼 : AHD(중증 심장질환)
import pandas as pd
import numpy as np
from sklearn import svm, metrics
from sklearn.model_selection._split import train_test_split
heartdata = pd.read_csv("../testdata/Heart.csv")
print(heartdata.info())
data = heartdata.drop(["ChestPain", "Thal"], axis = 1) # object type은 제외
data.loc[data.AHD=="Yes", 'AHD'] = 1
data.loc[data.AHD=="No", 'AHD'] = 0
print(heartdata.isnull().sum()) # Ca 열에 결측치 4개
Heart = data.fillna(data.mean()) # CA에 결측치는 평균으로 대체
label = Heart["AHD"]
features = Heart.drop(["AHD"], axis = 1)
x_train, x_test, y_train, y_test = train_test_split(features, label, test_size = 0.3, random_state = 12)
print()
model = svm.SVC(C=0.1).fit(x_train, y_train)
pred = model.predict(x_test)
print('예측값 : ', pred)
print('실제값 : ', np.array(y_test))
# 분류 정확도
print(model.score(x_train, y_train))
print(model.score(x_test, y_test))
print('분류 정확도 : ', metrics.accuracy_score(y_test, pred))
# 새 값으로 예측
new_test = x_test[:2].copy()
print(new_test)
new_test['Age'] = 10
new_test['Sex'] = 0
print(new_test)
new_pred = model.predict(new_test)
print('예측결과 : ', new_pred)
<console>
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 303 entries, 0 to 302
Data columns (total 15 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Unnamed: 0 303 non-null int64
1 Age 303 non-null int64
2 Sex 303 non-null int64
3 ChestPain 303 non-null object
4 RestBP 303 non-null int64
5 Chol 303 non-null int64
6 Fbs 303 non-null int64
7 RestECG 303 non-null int64
8 MaxHR 303 non-null int64
9 ExAng 303 non-null int64
10 Oldpeak 303 non-null float64
11 Slope 303 non-null int64
12 Ca 299 non-null float64
13 Thal 301 non-null object
14 AHD 303 non-null object
dtypes: float64(2), int64(10), object(3)
memory usage: 35.6+ KB
None
Unnamed: 0 0
Age 0
Sex 0
ChestPain 0
RestBP 0
Chol 0
Fbs 0
RestECG 0
MaxHR 0
ExAng 0
Oldpeak 0
Slope 0
Ca 4
Thal 2
AHD 0
dtype: int64
예측값 : [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
실제값 : [0 0 0 0 1 0 1 1 0 1 0 1 1 1 1 0 1 0 0 0 1 0 1 0 0 1 0 1 0 0 0 0 1 0 1 0 0
0 1 1 0 1 1 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 1 1 0 0 1 1 0 1 0 1 0 0 1 0 0 0
1 1 0 0 1 1 1 1 1 0 1 1 0 1 0 0 0]
0.5330188679245284
0.5604395604395604
분류 정확도 : 0.5604395604395604
Unnamed: 0 Age Sex RestBP Chol ... MaxHR ExAng Oldpeak Slope Ca
92 93 62 1 130 231 ... 146 0 1.8 2 3.0
85 86 44 1 140 235 ... 180 0 0.0 1 0.0
[2 rows x 12 columns]
Unnamed: 0 Age Sex RestBP Chol ... MaxHR ExAng Oldpeak Slope Ca
92 93 10 0 130 231 ... 146 0 1.8 2 3.0
85 86 10 0 140 235 ... 180 0 0.0 1 0.0
[2 rows x 12 columns]
예측결과 : [0 0]