일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- App
- 딥러닝
- 전국국밥
- Ros
- 리액트네이티브
- 강화학습
- TeachagleMachine
- ReactNative
- 머신러닝
- JavaScript
- coding
- 정치인
- 클론코딩
- Instagrame clone
- clone coding
- React
- 크롤링
- 조코딩
- kaggle
- redux
- expo
- 사이드프로젝트
- 강화학습 기초
- pandas
- FirebaseV9
- 카트폴
- selenium
- python
- 앱개발
- 데이터분석
- Today
- Total
qcoding
[데이터분석실습][이진분류_결정트리]소득 예측 모델 만들기 본문
https://github.com/youngwoos/Doit_Python/tree/main/Data
## 소득예측 모델 만들기
import pandas as pd
import numpy as np
import seaborn as sns
df=pd.read_csv('./adult.csv')
df
변수명 | 의미 |
age | 나이 |
workclass | 근로 형태 |
fnlwgt | 인구통계 가중치 |
education | 최종학력 |
education_num | 교육기간 |
marital_status | 결혼상태 |
occupation | 직종 |
relationship | 가구주와의 관계 |
race | 인종 |
sex | 성별 |
capital_gain | 자본소득(USD) |
capital_loss | 자본손실(USD) |
hours_per_week | 주당 근무시간 |
native_country | 출신국가 |
income | 연소득 |
# 전처리
1) 타켓변수 전처리
## 데이터 전처리
# 타켓변수 전처리
# nomarlize = True 시 범주의 비율을 계산함
df['income'].value_counts( normalize = True)
# >50k 경우를 high 그렇지 않은 경우를 low로 변경함
df['income']=np.where(df['income']== ">50K" , "high" ,"low")
df['income'].value_counts( normalize = True)
2) 필요없는 변수 제거
df=df.drop(columns=['fnlwgt'])
df
3) 문자 타입 변수를 숫자 타입으로 바꾸기
-> One-hot encoding 을 사용하여 문자 타입 변수를 숫자 타입으로 변함
## one-hot 인코딩을 하기 위하여 target 제외 후 다시 합침
target=df['income']
df=df.drop(columns=['income'])
df
# one-hot encoding 진행
df=pd.get_dummies(df)
df['income']=target
# info() 옵션은 변수가 100개 이하일때만 변수 정보가 출력되므로, max_cols=np.inf 옵션을 사용
df.info(max_cols=np.inf)
# 데이터 분할하기
-> Train / Test set 분리
## 데이터 분할하기
from sklearn.model_selection import train_test_split
df_train, df_test=train_test_split(
df,
test_size=0.3,
#타켓 변수 비율 유지
stratify=df['income'],
random_state=1234
)
print("train" , df_train.shape)
print("test", df_test.shape)
# 위에서 data split 시에 stratify 옵션을 통해서 타켓 비율을 유지하였음
# 비율유지 확인
train=df_train['income'].value_counts(normalize=True)
print("train\n",train)
print("-----------------------")
test=df_test['income'].value_counts(normalize=True)
print("test\n",test)
# 모델 설정하기
# 모델 설정하기
from sklearn import tree
clf=tree.DecisionTreeClassifier(random_state=1234, max_depth=3)
# 모델 만들기
x_train=df_train.drop(columns=['income'])
y_train=df_train['income']
model=clf.fit(x_train,y_train)
model
# 모델 구조 시각화하기
#시각화
import matplotlib.pyplot as plt
plt.rcParams.update({
'figure.figsize' :[12,8],
'figure.dpi' :'100'
})
tree.plot_tree(model);
# 그래프 수정
# 그래프 수정
tree.plot_tree(model,
# 예측 변수명
feature_names=x_train.columns,
# target 변수 클래스, 알파벳순
class_names=["high","low"],
# 비율표기,
proportion=True,
filled=True,
rounded=True,
# 불순도 표시
impurity=False,
# label표시위치
label='root',
fontsize=10
);
# 그래프해석
1) 맨위의 marital ... 은 조건으로 One-hot encoding을 통해 만들어진 변수임. 0(미혼) , 1(기혼)으로 전체 샘플의 100%를 놓고 가장 크게 나눌 수 있는 조건이 됨.
2) value=[0.239 , 0.761] 의 의미는 target변수의 비율로 "high " , "low" 알파벳순서로 나타내며, 전체 100% 중 low의 비율이 76.1% 가 된다는 의미이다.
3) class는 우세한 class의 종류를 나타내므로, 앞에서 low의 비율이 우세하므로 low일 확률 이 높다는 것이다.
1) 두번 째 node를 보면 왼쪽은 미혼(0) 이고 오른쪽은 기혼(1)로 나뉘어져 있다.
2) 왼쪽에서 미혼(0) 의 경우는 전체의 54.2%에 해당되며, value=[0.064, 0.936] 으로 low일 확률이 93.6%가 된다.
색이 짙을 수록 비율이 높다는 것을 의미한다.
3) 오른쪽에서는 비혼(1)의 경우는 전체의 45.8%에 해당되며, value=[0.447 , 0.553] 으로 거의 비슷하지만 low일 확률이 55.3%더 높으므로 low에 해당하고 색은 옅은 편이다.
# 모델 예측하기
# 모델 예측하기
x_test=df_test.drop(columns=['income'])
y_test=df_test['income']
df_test['pred']=model.predict(x_test)
df_test[['income','pred']]
# 평가하기
# confusion matrix 만들기
from sklearn.metrics import confusion_matrix
conf_mat=confusion_matrix(
y_true=df_test['income'],
y_pred=df_test['pred'],
labels=['high','low']
)
conf_mat
## confusion mastirx heat map 사용하기
#그래프 설정 되돌리기
plt.rcParams.update(plt.rcParamsDefault)
from sklearn.metrics import ConfusionMatrixDisplay
p=ConfusionMatrixDisplay(
confusion_matrix=conf_mat,
display_labels=('high' , 'low')
)
p.plot(cmap='Blues')
# 성능지표
1) Accuracy (정확도)
-> 예측해서 맞춘 비율로 (TP + TN) / 전체합산
import sklearn.metrics as metrics
metrics.accuracy_score(
y_true=df_test['income'],
y_pred=df_test['pred']
)
-> 기본적으로 자료에서 low인 사람이 76%로 매우 많았기 때문에, 항상 low만 말하는 모델을 만든다면 적어도 76% 확률은 될 것 이므로 accuracy만 보아서는 안된다.
2)Precision (정밀도)
-> Positive라고 해서 실제 맞춘비율
-> TP / (TP +FP)
metrics.precision_score(
y_true=df_test['income'],
y_pred=df_test['pred'],
# 관심 클래스
pos_label='high'
)
-> 소득을 high라고 예측한 사람 중에 75%가 high 이고 나머지는 low인데 high라고 말하였다.
3) Recall (재현율)
-> 실제 데이터가 Positive인 경우에서 내가 Positive라고 해서 맞은 확률
-> TP / (TP+FN)
metrics.recall_score(
y_true=df_test['income'],
y_pred=df_test['pred'],
# 관심 클래스
pos_label='high'
)
-> 실제로 소득이 'high' 인 사람에서 51.3%를 'high' 라고 찾아냈고, 나머지 48.7%는 'low'라고 예측을 해서 틀리 경우이다.
4) F1 socre
-> recall 과 precision의 조화평균 , 성능이 좋을 수록 1이 됨.
metrics.f1_score(
y_true=df_test['income'],
y_pred=df_test['pred'],
# 관심 클래스
pos_label='high'
)
# 어떤 지표를 사용해야 되는가
1) precision : 관심 클래스가 분명할때 // 관심 클래스로 예측해서 틀릴때 손실이 더 클때
-> 모델을 사용하는 목적이 타멧 변수의 클래스 중에서 관심을 두는 한쪽 클래스를 정확하게 예측하는 것일때
-> 구매 가능성이 낮은 저소득자에게 값비싼 선물을 보내는 손실이 구매할 가능성이 있는 고소득자에게 선물을 보내지 않는 것보다 손실이 크므로, 고소득자라고 예측하는 것이 분명해야 할 때
--> 'Positive' 라고 말해서 틀리는 확률을 줄여야 할 때 , FP를 줄어야 할때
2) recall :관심 클래스를 최대한 많이 찾아내야 할때 // 관심 클래스를 놓칠 때 손실이 더 클 때
-> 모델을 사용하는 목적이 관심 클래스를 최대한 많이 찾아 내는 것 일 때
-> 전염병에 걸린 사람을 찾지 못해서 전염병이 확산되는 것이 정상인 환자를 격리하는 것보다 손실이 더 클 때
-> 'Negative' 라고 말해서 틀리는 확률을 줄여야 할 때, FN을 줄어야 할 때
'Python 데이터분석' 카테고리의 다른 글
[데이터분석실습][회귀_RF/RIDGE/LASSO]자전거 수요예측 (0) | 2022.07.01 |
---|---|
[데이터전처리]LabelEncoding / OneHotEncoding (0) | 2022.06.29 |
[데이터분석실습]통계 분석 기법을 이용한 가설검정 (0) | 2022.06.28 |
[데이터분석실습]인터랙티브 그래프 (0) | 2022.06.28 |
[데이터분석실습]지도 시각화 (0) | 2022.06.28 |