분류

분류

  • 사이킷럿 모듈 설치

    • pip install scikit-learn
  • 내장된 예제 데이터

    • 사이킷런에는 별도의 외부 웹사이트에서 데이터 세트를 다운로드 받을 필요없이 예제로 활용할 수 있는 간단하면서도 좋은 데이터 세트가 내장되어 있다. 이 데이터는 datasets 모듈에 있는 여러 API를 호출해 만들 수 있다.

<분류나 회귀 연습용 예제 데이터>

API명 설명
datasets.load_digits() 분류용, 0에서 9까지 숫자 이미지 픽셀 데이터셋
datasets.load_iris() 분류용, 붓꽃에 대한 피처를 가진 데이터셋
datasets.load_breast_cancer() 분류용, 위스콘신 유방암 피처들과 악성/음성 레이블
datasets.load_boston() 회귀용, 미국 보스톤 집 피처들과 가격 데이터셋
datasets.load_diabetes() 회귀용, 당뇨 데이터셋

1. 분류

  • 분류(Classification)는 지도 학습의 한 영역으로, 학습 데이터를 학습한 후에 이미지의 데이터를 분류하는 것을 의미한다.

  • 분류 알고리즘

Types Tasks Algorithms
지도 학습
(Supervised Learning)
분류
(Classification)
KNN : K Nearest Neighbor
SVM : Support Vector Machine
Decision Tree (의사결정 나무)
Logistic Regression
  • digits 데이터셋
    • digits 데이터셋은 0부터 9까지 손으로 쓴 숫자 이미지 데이터로 구성되어 있다.
    • 이미지 데이터는 8 x 8픽셀 흑백 이미지로, 1797장이 들어 있다.
# To add a new cell, type '# %%'
# To add a new markdown cell, type '# %% [markdown]'
# %%
# digits 데이터셋
# digits 데이터셋은 0부터 9까지 손으로 쓴 숫자 이미지 데이터로 구성되어 있다.
# 이미지 데이터는 8 x 8픽셀 흑백 이미지로, 1797장이 들어 있다.


# %%
from sklearn import datasets
import matplotlib.pylab as plt 

# digits 데이터 로드 - 2차원 배열 형태임 
digits = datasets.load_digits()
print(digits)


# %%
print(digits.target)
# 이미지의 라벨 출력 
print(digits.images)
# 2차원 배열


# %%
# 0~9 이미지를 2행 5열로 출력 
# 앞에서 10개를 불러올려면 슬라이싱으로 불러오기 (전체 1797장 중)
for label, img in zip(digits.target[ :10], digits.images[ :10]) : 
    plt.subplot(2, 5, label+1)              # 2행 5열의 이미지 배치 
    plt.axis('off')                         # x축 라벨 없애기
    plt.imshow(img, cmap=plt.cm.gray)       # 이미지 붙이기, 그레이 스케일 이미지 cmap=plt.cm.gray
    plt.title('Digit:{0}'.format(label))    # 제목 

plt.show()

2. 분류기를 만들어 정답률 평가

  • scikit-learn 을 사용해 3과 8 이미지 데이터를 분류하는 분류기를 만든 후에 분류기의 성능을 테스트 해보자.
  • digits 데이터셋은 0부터 9까지 손으로 쓴 숫자 이미지는 8 x 8픽셀 흑백 이미지로, 1797장이 들어 있다. 이 중에서 숫자 3과 8 이미지는 357개 이미지로 되어 있다.

1) 학습에 사용할 데이터

  • digits 데이터셋의 전체 이미지 개수 : 1797 개
  • 숫자 3과 8 이미지 갯수 : 357 개
  • 학습 데이터 개수 : 214 개 ( 3과 8 전체 이미지의 60% )

2) 분류기 종류

  • 의사결정 나무 분류기( Decision Tree Classifier )

classifier = tree.DecisionTreeClassifier()

  • 분류기를 이용해서 학습

classifier.fit()

# To add a new cell, type '# %%'
# To add a new markdown cell, type '# %% [markdown]'
# %%
import numpy as np
from sklearn import datasets

# 난수 시드 : 동일한 결과를 출력하기 위해서 설정
np.random.seed(0)

# 손으로 쓴 숫자 데이터 읽기
digits=datasets.load_digits()

# 3과 8의 데이터 위치를 구하기
flag_3_8=(digits.target == 3) + (digits.target == 8)
print(flag_3_8) 


# %%
# 3과 8 이미지와 레이블을 구해서 변수에 저장
images = digits.images[flag_3_8]
print(images.shape)
# 357개 , 8행 8열 2차원 

labels = digits.target[flag_3_8]
print(labels.shape)


# %%
# 3과 8이 이미지 데이터를 2차원에서 1차원으로 변환
images = images.reshape(images.shape[0], -1)    # -1은 가변적
print(images.shape)


# %%
from sklearn.model_selection import train_test_split

x_train, x_test, y_train, y_test = train_test_split(images, 
                                                    labels, 
                                                    test_size=0.3, 
                                                    random_state=10)
# x_train     # 훈련 이미지
# x_test      # 테스트 이미지
# y_train     # 훈련 라벨
# y_test      # 테스트 이미지
print(x_train.shape)
print(y_test.shape)


# %%
# 결정 트리 분류기 모델 생성
from sklearn import tree

# 모델 생성 
classifier = tree.DecisionTreeClassifier()

# 모델 학습
classifier.fit(x_train, y_train)


# %%
from sklearn import metrics

predict_label = classifier.predict(x_test)
print(predict_label)    # 예측 라벨값


# %%
# 정답률 계산
print(metrics.accuracy_score(y_test, predict_label))

3. 분류기의 성능평가 지표

  • 분류기의 성능을 평가하는 지표로는 정답률(Accuracy), 적합률(Precision), 재현율(Recall), F 값 등이 있다.

  • 분류기의 성능 지표를 확인하는 방법하는 방법을 알아보자.

    • Positive와 Negtive 중 하나를 반홖하는 분류기를 살펴보자. 이때 Positive와 Negtive 각각에서 정답(True)과 오답(False)이 있기 때문에 조합이 4개가 생긴다.
    • 이 경우의 수 로 만들어진 행렬을 혼돈행렬(confusion matrix) 이라고 하며, 분류기 평가에서 자주 사용한다.
  • 혼돈 행렬

혼돈행렬(confusion matrix) : metrics.confusion_matrix()

예측 : Predicted
실제 : Actual

구분 Predicted
Positive
Predicted
Negtive
Actual
Positive
True Positive (TP) False Negtive (FN)
Actual
Negtive
False Positive (FP) True Negtive (TN)

TP : Ture로 예측하고 실제값도 True
TN : False로 예측하고 실제값도 False
FP : True로 예측하고 실제는 False
FN : False로 예측하고 실제는 True

1) 정답률(Accuracy)

  • 전체 예측에서 정답이 있는 비율(전체 중에서 올바르게 예측한 것이 몇 개인가)

    • 정답률 (Accuracy) = ( TP + TN ) / ( TP + FP + FN + TN )

    • 정답률 (Accuracy) : metrics.accuracy_score()

2) 적합률(Precision)

  • 분류기가 Positive로 예측했을 때 진짜로 Positive한 비율
  • Positive로 예측하는 동안 어느 정도 맞았는지, 정확도가 높은지를 나타내는 지표 (내가 푼 문제 중에서 맞춘 정답 개수)

    • 적합률 (Precision) = TP / ( TP + FP )

    • 적합률 (Precision) : metrics.precision_score()

3) 재현율(Recall)

  • 진짜로 Positive인 것을 분류기가 얼마나 Positive라고 예측했는지 나타내는 비율 (전체 중에서 내가 몇 개를 맞췄는가)
  • 실제로 Positive인 것 중에서 어느 정도 검춗핛 수 있었는지 가늠하는 지표

    • 재현율 (Recall) = TP / ( TP + FN )

    • 재현율 (Recall) : metrics.recall_score()

4) F값(F-measure )

  • 적합률과 재현율의 조화 평균. 지표 2개를 종합적으로 볼 때 사용
  • F값이 높을수록 분류 모형의 예측력이 좋다고 할 수 있다.

    • F값(F-measure ) = 2 x Precision x Recall / Precision + Recall

    • F값(F-measure) : metrics.f1_score()

일반적으로 분류기의 성능을 이야기 할 때, 정답률(Accuracy)을 보지만 그것만으로 충분하지 않을 경우에 다른 성능평가 지표를 같이 살펴봐야 된다.

# To add a new cell, type '# %%'
# To add a new markdown cell, type '# %% [markdown]'
# %%
import numpy as np
from sklearn import datasets

# 난수 시드 : 동일한 결과를 출력하기 위해서 설정
np.random.seed(0)

# 손으로 쓴 숫자 데이터 읽기
digits=datasets.load_digits()

# 3과 8의 데이터 위치를 구하기
flag_3_8=(digits.target == 3) + (digits.target == 8)
print(flag_3_8) 


# %%
# 3과 8 이미지와 레이블을 구해서 변수에 저장
images = digits.images[flag_3_8]
print(images.shape)
# 357개 , 8행 8열 2차원 

labels = digits.target[flag_3_8]
print(labels.shape)


# %%
# 3과 8이 이미지 데이터를 2차원에서 1차원으로 변환
images = images.reshape(images.shape[0], -1)    # -1은 가변적
print(images.shape)


# %%
from sklearn.model_selection import train_test_split

x_train, x_test, y_train, y_test = train_test_split(images, 
                                                    labels, 
                                                    test_size=0.3, 
                                                    random_state=10)
# x_train     # 훈련 이미지
# x_test      # 테스트 이미지
# y_train     # 훈련 라벨
# y_test      # 테스트 이미지
print(x_train.shape)
print(y_test.shape)


# %%
# 결정 트리 분류기 모델 생성
from sklearn import tree

# 모델 생성 
classifier = tree.DecisionTreeClassifier()

# 모델 학습
classifier.fit(x_train, y_train)


# %%
from sklearn import metrics

predict_label = classifier.predict(x_test)
print(predict_label)    # 예측 라벨값


# %%
print('정답률(Accuracy):', metrics.accuracy_score(y_test, predict_label))


# %%
print('혼돈행렬(Confusion matrix): \n', metrics.confusion_matrix(y_test, predict_label))


# %%
# pos_label=3 -> 3 라벨의 적합률이 잘나온지
print('3라벨 적합률(Presision):', metrics.precision_score(y_test, predict_label, pos_label=3))   
print('8라벨 적합률(Presision):', metrics.precision_score(y_test, predict_label, pos_label=8))


# %%
print('3라벨 재현율(Recall):', metrics.recall_score(y_test, predict_label, pos_label=3))
print('8라벨 재현율(Recall):', metrics.recall_score(y_test, predict_label, pos_label=8))


# %%
print('3라벨 F값(F-measure):', metrics.f1_score(y_test, predict_label, pos_label=3))
print('8라벨 F값(F-measure):', metrics.f1_score(y_test, predict_label, pos_label=8))

분류기

  • 분류기의 종류

    • 결정 트리 (Decision Tree)
    • 랜덤 포레스트 (Random Forest)
    • 에이다부스트 (AdaBoost)
    • 서포트 벡터 머신 (Support Vector Machine)

1. 결정 트리(Decision Tree)

  • 결정 트리는 데이터를 여러 등급으로 분류하는 지도 학습 중의 하나로, 트리 구조를 이용한 분류 알고리즘이다.
  • 결정 트리 학습에서는 학습 데이터에서 트리 모델을 생성한다. 무엇을 기준으로 분기할 지에 따라 결정 트리는 몇 가지 방법으로 분류할 수 있다.
  • 결정 트리의 장점은 분류 규칙을 트리 모델로 가시화할 수 있어, 분류 결과의 해석이 비교적 용이하다는 점이다.
  • 생성한 분류 규칙도 편집핛 수 있으며, 학습을 위한 계산 비용이 낮다는 점도 장점이다.
  • 결정 트리는 과적합 하는 경향이 있고, 취급하는 데이터의 특성에 따라 트리모델을 생성하기 어렵다는 단점도 있다.
  • 결정 트리는 과적합 하는 경향이 있어 결정 트리 단독으로 사용하지 않고, 앙상블 학습을 조합해서 사용하는 경우가 많다.(분류기 성능이 떨어질때)
# To add a new cell, type '# %%'
# To add a new markdown cell, type '# %% [markdown]'
# %%
import numpy as np
from sklearn import datasets

# 난수 시드 : 동일한 결과를 출력하기 위해서 설정
np.random.seed(0)

# 손으로 쓴 숫자 데이터 읽기
digits=datasets.load_digits()

# 3과 8의 데이터 위치를 구하기
flag_3_8=(digits.target == 3) + (digits.target == 8)
print(flag_3_8) 


# %%
# 3과 8 이미지와 레이블을 구해서 변수에 저장
images = digits.images[flag_3_8]
print(images.shape)
# 357개 , 8행 8열 2차원 

labels = digits.target[flag_3_8]
print(labels.shape)

# 3과 8이 이미지 데이터를 2차원에서 1차원으로 변환
images = images.reshape(images.shape[0], -1)    # -1은 가변적
print(images.shape)


# %%
from sklearn.model_selection import train_test_split

x_train, x_test, y_train, y_test = train_test_split(images, 
                                                    labels, 
                                                    test_size=0.3, 
                                                    random_state=10)
# x_train     # 훈련 이미지
# x_test      # 테스트 이미지
# y_train     # 훈련 라벨
# y_test      # 테스트 이미지
print(x_train.shape)
print(y_test.shape)


# %%
# 결정 트리 분류기 모델 생성
from sklearn import tree

# 모델 생성 
# 트리 모델의 최대깊이를 max_dapth=3로 설정
classifier = tree.DecisionTreeClassifier(max_depth=3)

# 모델 학습
classifier.fit(x_train, y_train)


# %%
from sklearn import metrics

predict_label = classifier.predict(x_test)
print(predict_label)    # 예측 라벨값


# %%
print('정답률(Accuracy):', metrics.accuracy_score(y_test, predict_label))
print('혼돈행렬(Confusion matrix): \n', metrics.confusion_matrix(y_test, predict_label))
# pos_label=3 -> 3 라벨의 적합률이 잘나온지
print('3라벨 적합률(Presision):', metrics.precision_score(y_test, predict_label, pos_label=3))   
print('8라벨 적합률(Presision):', metrics.precision_score(y_test, predict_label, pos_label=8))
print('3라벨 재현율(Recall):', metrics.recall_score(y_test, predict_label, pos_label=3))
print('8라벨 재현율(Recall):', metrics.recall_score(y_test, predict_label, pos_label=8))
print('3라벨 F값(F-measure):', metrics.f1_score(y_test, predict_label, pos_label=3))
print('8라벨 F값(F-measure):', metrics.f1_score(y_test, predict_label, pos_label=8))

2. 랜덤 포레스트(Random Forest)

  • 간단히 설명하면 train data를 무작위로 sampling해서 만든 다수의 Decision tree를 기반으로 다수결로 결과를 추출한다.

    • 랜덤 포레스트(Random Forest)는 앙상블 학습의 배깅(bagging)으로 분류되는 알고리즘이다.
    • 전체 학습 데이터 중에서 중복이나 누락을 허용해 학습 데이터셋을 여러 개 추출하여, 그 일부의 속성을 사용해 결정 트리(약한 학습기)를 생성한다.
    • 랜덤 포레스트는 학습과 판별을 빠르게 처리하고, 학습 데이터의 노이즈에도 강하다는 장점이 있다.
    • 랜덤 포레스트는 분류 외에도 회귀나 클러스터링에도 사용 할 수 있다.
    • 학습 데이터의 개수가 적을 경우에는 과적합이 발생하기 때문에, 학습데이터 적은 경우에는 사용하지 않는 것이 좋다.

image-20200319151137762

1) 앙상블 학습(Ensenbles)

  • 앙상블 학습은 몇 가지 성능이 낮은 분류기(약한 학습기)를 조합해 성능이 높은 분류기를 만드는 방법이다.
  • 약한 학습기 알고리즘은 정해진 것이 없으므로 적절히 선택해서 사용해야 한다.
  • 앙상블 학습 결과는 약한 학습기의 결과 값 중 다수결로 결정한다.
  • 앙상블 학습은 약한 학습기 생성 방법에 따라 배깅(bagging)과 부스팅(boosting)으로 나눌 수 있다.

2) 배깅(bagging)

  • 학습 데이터를 빼고 중복을 허용 해 그룹 여러 개로 분핛하고 학습 데이터의 그룹마다 약한 학습기를 생성하는 방법이다.
  • 배깅으로 여러 그룹으로 분할한 학습 데이터 그룹에서 약한 학습기를 각각 생성하고, 약한 학습기를 조합해 성능 좋은 분류기를 만들 수 있다.

image-20200319151205260

3) 부스팅(boosting)

  • 약한 학습기를 여러 개 준비하고 가중치가 있는 다수결로 분류하는 방법이다.
  • 그 가중치도 학습에 따라 결정한다.
  • 난이도가 높은 학습 데이터를 올바르게 분류할 수 있는 약한 학습기의 판별 결과를 중시하도록 가중치를 업데이트해 나간다.
# To add a new cell, type '# %%'
# To add a new markdown cell, type '# %% [markdown]'
# %%
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets

# 손으로 쓴 숫자 데이터 읽기
digits=datasets.load_digits()

# 이미지를 2행 5열로 표시
for label, img in zip(digits.target[:10], digits.images[:10]):
    plt.subplot(2, 5, label + 1)
    plt.axis('off')
    plt.imshow(img, cmap=plt.cm.gray_r, interpolation='nearest')
    plt.title('Digit: {0}'.format(label))
plt.show()


# %%
# 3과 8의 데이터 위치를 구하기
flag_3_8=(digits.target == 3) + (digits.target == 8)

# 3과 8 이미지와 레이블을 구해서 변수에 저장
images = digits.images[flag_3_8]
# 357개 , 8행 8열 2차원 

labels = digits.target[flag_3_8]

# 3과 8이 이미지 데이터를 2차원에서 1차원으로 변환
images = images.reshape(images.shape[0], -1)    # -1은 가변적

from sklearn.model_selection import train_test_split

x_train, x_test, y_train, y_test = train_test_split(images, 
                                                    labels, 
                                                    test_size=0.3, 
                                                    random_state=10)
# x_train     # 훈련 이미지
# x_test      # 테스트 이미지
# y_train     # 훈련 라벨
# y_test      # 테스트 이미지


# %%
# 결정 트리 분류기 모델 생성
from sklearn import ensemble

# 모델 생성 
#  n_estimators는 약한 학습기 갯수로 20을 지정, max_depth는 트리모델의 최대깊이, 
classifier =  ensemble.RandomForestClassifier(n_estimators=20, max_depth=3) 

# 모델 학습
classifier.fit(x_train, y_train)


from sklearn import metrics

predict_label = classifier.predict(x_test)# 예측 라벨값

print('정답률(Accuracy):', metrics.accuracy_score(y_test, predict_label))
print('혼돈행렬(Confusion matrix): \n', metrics.confusion_matrix(y_test, predict_label))
# pos_label=3 -> 3 라벨의 적합률이 잘나온지
print('3라벨 적합률(Presision):', metrics.precision_score(y_test, predict_label, pos_label=3))   
print('8라벨 적합률(Presision):', metrics.precision_score(y_test, predict_label, pos_label=8))
print('3라벨 재현율(Recall):', metrics.recall_score(y_test, predict_label, pos_label=3))
print('8라벨 재현율(Recall):', metrics.recall_score(y_test, predict_label, pos_label=8))
print('3라벨 F값(F-measure):', metrics.f1_score(y_test, predict_label, pos_label=3))
print('8라벨 F값(F-measure):', metrics.f1_score(y_test, predict_label, pos_label=8))

3. 에이다부스트(AdaBoost)

  • 에이다부스트는 앙상블 학습의 부스팅(boosting)으로 분류하는 알고리즘이다.
  • 에이다부스트에서는 난이도가 높은 데이터를 제대로 분류핛 수 있는 약한 학습기(weak learner)의 분류 결과를 중시하므로 약한 학습기에 가중치를 준다.
  • 난이도가 높은 학습 데이터와 성능이 높은 약핚 학습기에 가중치를 주어서 정확도를 높인다.
  • 에이다부스트는 분류 정밀도가 높지만, 학습 데이터의 노이즈에 쉽게 영향을 받는다.

image-20200319150445904

  • 각기 다른 데이터에 강점을 가지는 학습기를 여러개 구축
  • 이전 학습기의 에러에 따라 데이터에 부여되는 가중치 조정

image-20200319150532011

# To add a new cell, type '# %%'
# To add a new markdown cell, type '# %% [markdown]'
# %%
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets

# 손으로 쓴 숫자 데이터 읽기
digits=datasets.load_digits()

# 이미지를 2행 5열로 표시
for label, img in zip(digits.target[:10], digits.images[:10]):
    plt.subplot(2, 5, label + 1)
    plt.axis('off')
    plt.imshow(img, cmap=plt.cm.gray_r, interpolation='nearest')
    plt.title('Digit: {0}'.format(label))
plt.show()


# %%
# 3과 8의 데이터 위치를 구하기
flag_3_8=(digits.target == 3) + (digits.target == 8)

# 3과 8 이미지와 레이블을 구해서 변수에 저장
images = digits.images[flag_3_8]
# 357개 , 8행 8열 2차원 

labels = digits.target[flag_3_8]

# 3과 8이 이미지 데이터를 2차원에서 1차원으로 변환
images = images.reshape(images.shape[0], -1)    # -1은 가변적

from sklearn.model_selection import train_test_split

x_train, x_test, y_train, y_test = train_test_split(images, 
                                                    labels, 
                                                    test_size=0.3, 
                                                    random_state=10)
# x_train     # 훈련 이미지
# x_test      # 테스트 이미지
# y_train     # 훈련 라벨
# y_test      # 테스트 이미지


# %%
# 결정 트리 분류기 모델 생성
from sklearn import ensemble, tree

# 모델 생성 
# base_estimator는 약한 학습기를 지정하는 파라미터로 여기서는 결정트리를 지정,
# n_estimators는 약한 학습기 갯수를 지정
classifier = ensemble.AdaBoostClassifier(base_estimator=tree.DecisionTreeClassifier(max_depth=3), n_estimators=20)
# 모델 학습
classifier.fit(x_train, y_train)

from sklearn import metrics

predict_label = classifier.predict(x_test)# 예측 라벨값

print('정답률(Accuracy):', metrics.accuracy_score(y_test, predict_label))
print('혼돈행렬(Confusion matrix): \n', metrics.confusion_matrix(y_test, predict_label))
# pos_label=3 -> 3 라벨의 적합률이 잘나온지
print('3라벨 적합률(Presision):', metrics.precision_score(y_test, predict_label, pos_label=3))   
print('8라벨 적합률(Presision):', metrics.precision_score(y_test, predict_label, pos_label=8))
print('3라벨 재현율(Recall):', metrics.recall_score(y_test, predict_label, pos_label=3))
print('8라벨 재현율(Recall):', metrics.recall_score(y_test, predict_label, pos_label=8))
print('3라벨 F값(F-measure):', metrics.f1_score(y_test, predict_label, pos_label=3))
print('8라벨 F값(F-measure):', metrics.f1_score(y_test, predict_label, pos_label=8))

4. 서포트 벡터 머신 (Support Vector Machine)

  • 분류 및 회귀 모두 사용 가능한 지도 학습 알고리즘이다.
  • 서포트 벡터 머신에서는 분할선부터 근접 샘플 데이터까지 마진을 최대화하는 직선을 가장 좋은 분할선으로 생각한다.
  • 서포트 벡터 머신은 학습 데이터의 노이즈에 강하고 분류 성능이 매우 좋다는 특징이 있다.
  • 다른 알고리즘에 비교하면 학습 데이터 개수도 많이 필요하지 않는다.

image-20200319151035506

5. 분류 (Classification) 예제

  • 분류(classification) 알고리즘은 예측하려는 대상의 속성(변수)을 입력받고, 목표 변수가 가지고 있는 카테고리(범주형) 값 중에서 어느 핚 값으로 분류하여 예측하는 것이다.
  • 훈련 데이터에 목표 변수(0 또는 1)을 함께 입력하기 때문에 지도 학습에 속하는 알고리즘이다.
  • 분류 알고리즘은 고객 분류, 질병 진단, 스팸 메일 필터링, 음성 인식 등 목표 변수가 카테고리 값을 갖는 경우에 사용핚다.
  • 분류 알고리즘에는 KNN, SVM, Decision Tree, Logistic Regression 등 다양한 알고리즘이 있다

6. KNN (K Nearest Neighbor)

1) K 최근접 이웃(KNN) 알고리즘

  • KNN은 K Nearest Neighbor 의 약칭이다. K개의 가까운 이웃이라는 뜻이다. 새로운 관측값이 주어지며 기존 데이터 중에서 가장 속성이 비슷핚 K개의 이웃을 먼저 찾는다. 그리고 가까운 이웃들이 가지고 있는 목표값과 같은 값으로 분류하여 예측핚다.

  • K값에 따라 예측의 정확도가 달라지므로, 적절한 K값을 찾는 것이 매우 중요하다.

  • K=1이면 가장 가까운 이웃인 Class1으로 분류된다.
  • K=3이면 가장 가까운 이웃중 가장 많은 Class2로 분류된다.

2) 실습

  • seaborn 라이브러리에서 제공되는 titanic 데이터셋의 탑승객의 생존여부를 KNN 알고리즘으로 분류해보자
# To add a new cell, type '# %%'
# To add a new markdown cell, type '# %% [markdown]'
# %%
import pandas as pd 
import seaborn as sns 

df = sns.load_dataset('titanic')
print(df)


# %%
# Ipython 디스플레이 설정 - 출력할 열의 개수를 15개로 늘리기
pd.set_option('display.max_columns', 15)
print(df.head())


# %%
# 데이터 자료형 확인 : 데이터를 확인하고 NaN이 많은 열 삭제
print(df.info())


# %%
# NaN값이 많은 deck(배의 갑판)열을 삭제 : deck 열은 유효핚 값이 203개
# embarked(승선핚)와 내용이 겹치는 embark_town(승선 도시) 열을 삭제
# 전체 15개의 열에서 deck, embark_town 2개의 열이 삭제되어서 13개의 열이름만 춗력
rdf = df.drop(['deck', 'embark_town'], axis=1)
print(rdf.columns.values)
print(rdf.info())


# %%
# 승객의 나이를 나타내는 age 열에 누락 데이터가 177개 포함되어 있다.
# 누락 데이터를 평균 나이로 치홖하는 방법도 가능하지만, 누락 데이터가 있는 행을 모두 삭제
# 즉, 177명의 승객 데이터를 포기하고 나이 데이터가 있는 714명의 승객만을 분석 대상
# age 열에 나이 데이터가 없는 모든 행을 삭제 - age 열(891개 중 177개의 NaN 값)
rdf = rdf.dropna(subset=['age'], how='any', axis=0)
print(len(rdf)) # 714 (891개 중 177개 데이터 삭제)


# %%
# 각 데이터에 NaN 값 있는지 여부 확인 - embarked 에서 2개 확인
print(rdf.isnull().sum(axis=0))


# %%
# embarked열에는 승객들이 타이타닉호에 탑승핚 도시명의 첫 글자가 들어있다.
# embarked열에는 누락데이터(NaN)가 2개에 있는데, 누락데이터를 가장많은 도시명(S)으로치환
# embarked 열의 NaN값을 승선도시 중에서 가장 많이 출현한 값으로 치환하기
# value_counts()함수와 idxmax()함수를 사용하여 승객이 가장 많이 탑승한 도시명의 첫글자는 S
most_freq = rdf['embarked'].value_counts(dropna=True).idxmax()
print(most_freq)


# %%
# embarked 열의 최빈값(top)을 확인하면 S 로 출력됨
print(rdf.describe(include='all'))

# embarked 열에 fillna() 함수를 사용하여 누락 데이터(NaN)를 S로 치환 한다.
rdf['embarked'].fillna(most_freq, inplace=True)


# %%
# NaN 이 없는지 확인 - 통과
print(rdf.isnull().sum(axis=0))


# %%
# 분석에 활용할 열(속성)을 선택
ndf = rdf[['survived', 'pclass', 'sex', 'age', 'sibsp', 'parch', 'embarked']]
print(ndf.head()) 


# %%
# KNN모델을 적용하기 위해 sex열과 embarked열의 범주형 데이터를 숫자형으로 변환
# 이 과정을 더미 변수를 만든다고 하고, 원핫인코딩(one-hot-encoding)이라고 부른다.

# 원핫인코딩 - 범주형 데이터를 모델이 인식할 수 있도록 숫자형으로 변환 하는것
# sex 열은 male과 female값을 열 이름으로 갖는 2개의 더미 변수 열이 생성된다.
# concat()함수로 생성된 더미 변수를 기존 데이터프레임에 연결한다.

onehot_sex = pd.get_dummies(ndf['sex'])
print(onehot_sex.head())

ndf = pd.concat([ndf, onehot_sex], axis=1)
print(ndf.head())


# %%
# embarked 열은 3개의 더미 변수 열이 만들어지는데, prefix='town' 옵션을
# 사용하여 열 이름에 접두어 town을 붙인다. ( town_C, town_Q, town_S)
onehot_embarked = pd.get_dummies(ndf['embarked'], prefix='town')
ndf = pd.concat([ndf, onehot_embarked], axis=1)
print(ndf.head())


# %%
# 기존 sex 열과 embarked 열 삭제 
ndf.drop(['sex', 'embarked'], axis=1, inplace=True)
print(ndf.head())   # 더미 변수로 출력된다. 


# %%
# 변수 정의
x = ndf[['pclass', 'age', 'sibsp', 'parch', 'female', 'male','town_C', 'town_Q', 'town_S']] # 독립 변수(x)
y = ndf['survived'] # 종속 변수(y)

# 독립 변수 데이터를 정규화(normalization)
# 독립 변수 열들이 갖는 데이터의 상대적 크기 차이를 없애기 위하여 정규화(0과 1로 변환)를 한다.
from sklearn import preprocessing
x = preprocessing.StandardScaler().fit(x).transform(x)


# %%
# train data 와 test data로 분할 (7:3 비율)
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)

print('train data 개수: ', x_train.shape) # train data 개수: (499, 9)
print('test data 개수: ', x_test.shape) # test data 개수: (215, 9)


# %%
# sklearn 라이브러리에서 KNN 분류 모델 가져오기
from sklearn.neighbors import KNeighborsClassifier

# KNN 모델 객체 생성 (k = 5로 설정) 
# K값에 따라서 범위가 달라진다.
knn = KNeighborsClassifier(n_neighbors=5)

# train data를 가지고 모델 학습
knn.fit(x_train, y_train)


# %%
# test data를 가지고 y_hat을 예측(분류)
y_hat = knn.predict(x_test)         # 예측값 구하기 

# 첫 10개의 예측값(y_hat)과 실제값(y_test) 비교 : 10개 모두 일치함 ( 0:사망자, 1:생존자)
print(y_hat[ :10])
print(y_test.values[ :10])


# %%
# KNN모델 성능 평가 - Confusion Matrix(혼동 행렬) 계산 
from sklearn import metrics

knn_matrix = metrics.confusion_matrix(y_test, y_hat)    #(실제값, 예측값)
print(knn_matrix)

# 결과
# TP(True Positive) : 215명의 승객 중에서 사망자를 정확히 분류핚 것이 109명
# FP(False Positive) : 생존자를 사망자로 잘못 분류핚 것이 25명
# FN(False Negative) : 사망자를 생존자로 잘못 분류핚 것이 16명
# TN(True Negative) : 생존자를 정확하게 분류핚 것이 65명


# %%
# KNN 모델 성능 평가 - 평가지표 계산
knn_report = metrics.classification_report(y_test, y_hat)
print(knn_report)

# 결과
# f1지표(f1-score)는 모델의 예측력을 종합적으로 평가하는 지표이다.
# f1-score 지표를 보면 사망자(0) 예측의 정확도가 0.84이고, 
# 생존자(1) 예측의 정확도는 0.76으로 예측 능력에 차이가 있다. 
# 평균적으로 0.81 정확도를 갖는다.

7. 결정트리 (Decision Tree) 알고리즘

  • UCI(University of California, Irvine) 머신러닝 저장소에서 제공하는 암세포 진단 데이터셋을 이용하여 악성종양 여부를 Decision Tree 알고리즘으로 분류해보자

results matching ""

    No results matching ""