본문 바로가기
study/Python

[Python] 46. 분류 : 지도학습, 원핫인코딩, 정규화, 모형 성능 평가데이터, 혼동행렬 : 분류 결과, SVM(Support Vector Machine), Decision Tree

by 금이패런츠 2022. 7. 7.
728x90
반응형

1. 분류 : 지도학습

2. 원핫인코딩

3. 정규화

4. 모형 성능 평가데이터

5. 혼동행렬 : 분류 결과

6. SVM(Support Vector Machine)

7. Decision Tree

# -*- coding: utf-8 -*-
"""
Created on Thu Jul  7 09:06:34 2022

@author: p011v
20220707.py
"""
'''
    sklearn 모듈을 이용한 머신러닝
    지도학습: 기계학습시 정답을 제시.
        회귀분석: 회귀선을 이용하여 분석
           독립변수(설명변수): 종속변수에 영향을 미칠 수 있는 데이터
           종속변수(예측변수): 예측해야할 데이터
           단순회귀분석 : 독립변수 1개, 종속변수 1개
           다중회귀분석 : 독립변수 여러개, 종속변수 1개
        방식
            직선 : 1차함수. 단항회귀분석
            곡선 : n차함수. 다항회귀분석
        알고리즘
            선형회귀분석(LinearRegression)
            
'''
########## 1. 분류 : 지도학습
'''
    분류 : 지도학습
        설명변수(독립변수)
        목표변수(종속변수)
        알고리즘 : KNN(k-Nearset-Neighbors)
'''
# titanic 데이터 로드
import seaborn as sns
import pandas as pd
df = sns.load_dataset("titanic")
df.info()
# deck 컬럼 제거 : 결측값이 너무 많다.
# embark_town 컬럼 제거 : embarked 컬럼과 중복 의미
df[["embarked", "embark_town"]].head()
rdf = df.drop(['deck', 'embark_town'], axis=1)
rdf.info()
# embarked 컬럼의 결측값을 많이 출현한 값(최빈값)을 변경하기
rdf[rdf["embarked"].isnull()]
rdf.iloc[[61, 829]]["embarked"]
rdf["embarked"].value_counts(dropna=False)
most_freq = rdf["embarked"].value_counts().idxmax()
most_freq
rdf["embarked"].fillna(most_freq, inplace=True)
rdf["embarked"].value_counts(dropna=False)
rdf.iloc[[61, 829]]["embarked"]

# 분석에 필요한 컬럼 선택
ndf = rdf[['survived', 'pclass', 'sex', 'age', 'sibsp', 'parch', 'embarked']]
ndf.info()
ndf.describe(include='all')
# age 컬럼에 결측값 존재 => 결측값이 있는 행을 제거
ndf = ndf.dropna(subset=['age'], axis=0)
ndf.info()

########## 2. 원핫인코딩
'''
    원핫인코딩 : 문자열형 범주데이터를 모형이 인식할 수 있도록 숫자형으로 변환이 필요
        pd.get_dummies() : 컬럼의 값으로 이루어진 컬럼 생성.
                           컬럼의 값인 경우 1, 다른경우는 0으로 처리
'''
# sex 컬럼을 원핫인코딩 하기
onehot_sex = pd.get_dummies(ndf['sex'])
onehot_sex
# ndf, onehot_sex 데이터를 합하기
ndf = pd.concat([ndf, onehot_sex], axis=1) #concat : 물리적으로 합침
ndf.info()
# sex 컬럼 삭제하기
del ndf["sex"]
ndf.info()

# embarked 컬럼을 원핫인코딩 하기
onhot_embarked = pd.get_dummies(ndf["embarked"], prefix="town")
onhot_embarked
# ndf, onhot_embarked 데이터를 합하기
ndf = pd.concat([ndf, onhot_embarked], axis=1) #concat : 물리적으로 합침
# embarked 컬럼 삭제하기
del ndf["embarked"]
ndf.info()

# 설명변수, 목표변수 결정
# 설명변수 : survived 컬럼 제외한 변수들
# 목표변수 : survived 컬럼
# ndf[ndf.columns.difference(['survived'])] : survived 컬럼을 제외한 다른 컬럼들
X = ndf[ndf.columns.difference(['survived'])] # 설명변수
Y = ndf['survived']                           # 목표변수
X.info()
X[:5]

########## 3. 정규화
'''
    설명변수의 정규화 필요
    - 분석시 사용되는 설명 변수의 값의 크기에 따라 분석에 영향을 미침
        age 컬럼의 값의 범위 : 0 ~ 100 사이.
    - 정규화 과정을 통해서 모든 설명변수의 값을 기준 단위로 변경 필요
'''
from sklearn import preprocessing
import numpy as np
# 정규화 : 모든 컬럼들의 값의 범위를 일정하게 만들어 줌. 
X = preprocessing.StandardScaler().fit(X).transform(X) 
X[:5]
# 훈련데이터, 테스트데이터 분리
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = \
    train_test_split(X, Y, test_size=0.3, random_state=10)
x_train.shape
x_test.shape
# KNN 분류 관련 알고리즘을 이용
# KNN : 최근접 이웃알고리즘. k-Nearset-Neighbors

from sklearn.neighbors import KNeighborsClassifier
# n_neighbors=5 : 5개의 최근접이웃 확인
knn = KNeighborsClassifier(n_neighbors=5) # KNN 객체
knn.fit(x_train, y_train) # 학습. knn 객체는 학습완료 객체
y_hat = knn.predict(x_test) # 예측. knn 객체로 예측하기
y_hat[:20] # 예측한 데이터
y_test.values[:20] # 실제 데이터

########## 4. 모형 성능 평가데이터
# 모형의 성능 평가하기
from sklearn import metrics
# 모형 성능 평가 : 평가지표
# y_test : 실제 정답 데이터
# y_hat  : 예측 정답 데이터
type(y_test)
type(y_hat)
knn_report = metrics.classification_report(y_test, y_hat)
print(knn_report)
'''
    accuracy(정확도) : 정확한 예측 / 전체 데이터
    precision(정밀도) :생존자 중 생존자로 예측한 인원 / 생존자로 예측한 인원
    recall(재현율, 민감도) : 생존자로 예측한 인원 / 실제 생존자 인원
    f1-score(조화평균) : 정밀도 재현율 값을 이용한 성능 평가
                        2 * (정밀도 * 재현율) / (정밀도 + 재현율)
    macro avg : 평균의 평균
    weighted avg : 가중 평균
    
    실제생존자   10명 중 6명 생존
                0 0 0 0 1 1 1 1 1 1
         예측 : 0 0 0 0 1 1 1 1 1 0
         
        정확도 : 9 / 10 = 0.9
        정밀도 : 5 / 5 = 1
        재현율 : 5 / 6 = 0.83
'''
########## 5. 혼동행렬 : 분류 결과
knn_matrix = metrics.confusion_matrix(y_test, y_hat)
print(knn_matrix)
'''
        예측   0    1
    실제
      0      [110  15]
      1      [ 26  64]
    
    True, False, Positive, Negative
      
    TN : 110 => 실제 : 0, 예측 : 0
    FP :  15 => 실제 : 0, 예측 : 1
    FN :  26 => 실제 : 1, 예측 : 0
    TP :  64 => 실제 : 1, 예측 : 1
    
    정답과 같은 예측 : TN, TP
    정답과 다른 예측 : FN, FP
    
    accuracy(정확도) : 정확한 예측 / 전체 데이터 
                      TP + TN / TP + TN + FP + FN = 
                      174 / 215 = 0.8093023255813953
    precision(정밀도) :생존자 중 생존자로 예측한 인원 / 생존자로 예측한 인원
                       TP / TP + FP =
                       64 / 79 = 0.810126582278481
    recall(재현율, 민감도) : 생존자로 예측한 인원 / 실제 생존자 인원
                            TP / TP + FN = 
                            64 / 90 = 0.7111111111111111
'''
########## 6. SVM(Support Vector Machine)
# SVM(Support Vector Machine) 분류 알고리즘으로 모델 구현하기
# SVM : 공간을 (선/면)으로 분류하는 방식
from sklearn import svm
# kernel='rbf' : 공간분리 방식 결정하는 함수 지정
#                rbf(기본값), linear, poly
svm_model = svm.SVC(kernel='rbf') # SVM 객체 설정
svm_model.fit(x_train, y_train) # 학습하기
y_hat = svm_model.predict(x_test) # 예측하기
y_hat[:10]
y_test.values[:10]
svm_report = metrics.classification_report(y_test, y_hat)
print(svm_report)
svm_matrix = metrics.confusion_matrix(y_test, y_hat)
svm_matrix
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
# 함수들을 이용하여 정확도, 정밀도, 재현율, F1-Score 값 출력하기
print("정확도(accuracy) : %.2f" % accuracy_score(y_test, y_hat))
print("정밀도(precision) : %.3f" % precision_score(y_test, y_hat))
print("재현율(recall) : %.3f" % recall_score(y_test, y_hat))
print("F1-Score : %.3f" % f1_score(y_test, y_hat))

########## 7. Decision Tree
'''
    분류 알고리즘
        KNN : 최근접 이웃알고리즘
        SVM : 선, 면을 이용하여 영역분리
        Decision Tree : 의사결정나무
            노드(Node), 가지(Branch), 깊이(depth) : Tree 구조
'''
# Decision Tree (의사결정나무)
# UCI 데이터 : 암세포 진단 데이터
# https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data

from sklearn import metrics
from sklearn import tree
from sklearn.model_selection import train_test_split
from sklearn import preprocessing
import pandas as pd
import numpy as np
# uci 데이터 : 유방암 진단 데이터
uci_path = "https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data"
# header=None : 기본은 0행을 header로 설정
#           None : header데이터가 없음. 전부데이터
'''
컬럼설명
1.id : ID번호 
2.clump : 덩어리 두께
3.cell_size : 암세포 크기
4.cell_shape:세포모양
5.adhesion : 한계
6.epithlial: 상피세포 크기
7.bare_nuclei : 베어핵
8.chromatin : 염색질 
9.normal_nucleoli : 정상세포
10.mitoses : 유사분열
11.class : 2 (양성), 4(악성)
'''
df = pd.read_csv(uci_path, header=None) # header 없이 모두 데이터
#                                           컬럼명이 없음. 0 ~ 컬럼명 설정
df.info()
df.head()
# df 컬럼명 설정하기
df.columns=['id', 'clump', 'cell_size', 'cell_shape', 'adhesion', 'epthlial', \
            'bare_nuclei', 'chromatin', 'normal_nucleoli', 'mitoses', 'class']
df.info()
# 양성, 악성 데이터의 건수 조회하기
df['class'].value_counts()
# 문자열 형인 bare_nuclei 데이터의 값을 조회하기
df['bare_nuclei'].unique()
# bare_nuclei 데이터에 ? 데이터를 조회하기
df[df["bare_nuclei"] == '?']
df.loc[df["bare_nuclei"] == '?'], ['id', 'bare_nuclei', 'class']
# bare_nuclei 데이터에서 ? 데이터를 포함한 행을 삭제하고,
# 자료형을 정수형으로 변경하기
#   ?를 결측값으로 변경 -> 결측값 행을 삭제 -> float형으로 변경
#   1.?를 결측값으로 변경
df["bare_nuclei"].replace("?", np.nan, inplace=True)
df[df["bare_nuclei"].isnull()]
#   2. 결측값 행을 삭제
df.dropna(subset=["bare_nuclei"], axis=0, inplace=True)
#   3. 정수형(int)으로 변경
df["bare_nuclei"] = df["bare_nuclei"].astype(int)
df['bare_nuclei'].unique()
df.info()
# 설명변수(독립변수) : id, class 컬럼을 제외한 컬럼
X = df[df.columns.difference(['id', 'class'])]
# 목표변수(종속변수) : class 컬럼
Y = df['class'] 
X.info()
Y.info()
type(X)
# 설명변수 정규화하기
X = preprocessing.StandardScaler().fit(X).transform(X) 
X[:5]
# 훈련데이터, 테스트데이터 분리
X_train, X_test, Y_train, Y_test = \
    train_test_split(X, Y, test_size=0.3, random_state=10)
X_train.shape
X_test.shape

# 알고리즘선택 : Decision Tree
'''
    criterion : 불순도. 불순도 계산을 위한 함수 지정. 순수도에 도달할 때 까지 반복
              gini : 지니지수. 2가지인 경우 효과. 기본값.
              entropy : 엔트로피 지수값이 가장 작은 경우. 
              log_loss : 분산의 감소량을 최대화
    max_depth=5 : 트리의 단계. 트리의 깊이 지정. 기본값 : None
            트리의 깊이가 길어지면 과대적합이 생길 수 있다.
                과대적합 : 학습이 지나침. 테스트 점수가 낮다.
'''
tree_model = tree.DecisionTreeClassifier(criterion='entropy', max_depth=5)
tree_model.fit(X_train, Y_train) # 학습하기
y_hat = tree_model.predict(X_test) # 예측하기
y_hat[:10] # 예측된 데이터
Y_test.values[:10] # 실제 데이터

# 혼동행렬, 평가레포트, 정확도, 정밀도, 재현율, f1_score 조회하기
# 혼동행렬
tree_matrix = metrics.confusion_matrix(Y_test, y_hat)
print(tree_matrix)
# 평가레포트
tree_report = metrics.classification_report(Y_test, y_hat)
print(tree_report)
# 정확도, 정밀도(오류), 재현율(오류), f1_score(오류) => 0, 1인 경우만 처리 가능
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
print("정확도(accuracy) : %.2f" % accuracy_score(Y_test, y_hat))
print("정밀도(precision) : %.3f" % precision_score(Y_test, y_hat))
print("재현율(recall) : %.3f" % recall_score(Y_test, y_hat))
print("F1-Score : %.3f" % f1_score(Y_test, y_hat))

# 정밀도, 재현율, f1_score 함수로 출력하기
df = pd.read_csv(uci_path, header=None) # header 없이 모두 데이터
df.columns=['id', 'clump', 'cell_size', 'cell_shape', 'adhesion', 'epthlial', \
            'bare_nuclei', 'chromatin', 'normal_nucleoli', 'mitoses', 'class']
df["bare_nuclei"].replace("?", np.nan, inplace=True)
df.dropna(subset=["bare_nuclei"], axis=0, inplace=True)
df["bare_nuclei"] = df["bare_nuclei"].astype(int)
df.info()
X = df[df.columns.difference(['id', 'class'])]
Y = df['class'] 
Y_test.replace(2, 0, inplace=True) # 0 : 양성
Y_test.replace(4, 1, inplace=True) # 1 : 악성
# 목표변수(종속변수) : class 컬럼
X = preprocessing.StandardScaler().fit(X).transform(X) 
X[:5]
X_train, X_test, Y_train, Y_test = \
    train_test_split(X, Y, test_size=0.3, random_state=10)
X_train.shape
X_test.shape
tree_model = tree.DecisionTreeClassifier(criterion='entropy', max_depth=5)
tree_model.fit(X_train, Y_train) # 학습하기
y_hat = tree_model.predict(X_test) # 예측하기
y_hat[:10] # 예측된 데이터
Y_test.values[:10] # 실제 데이터

# 혼동행렬, 평가레포트, 정확도, 정밀도, 재현율, f1_score 조회하기
# 혼동행렬
tree_matrix = metrics.confusion_matrix(Y_test, y_hat)
print(tree_matrix)
# 평가레포트
tree_report = metrics.classification_report(Y_test, y_hat)
print(tree_report)
# 정확도, 정밀도(오류), 재현율(오류), f1_score(오류) => 0, 1인 경우만 처리 가능
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
print("정확도(accuracy) : %.2f" % accuracy_score(Y_test, y_hat))
print("정밀도(precision) : %.3f" % precision_score(Y_test, y_hat))
print("재현율(recall) : %.3f" % recall_score(Y_test, y_hat))
print("F1-Score : %.3f" % f1_score(Y_test, y_hat))
728x90
반응형