책/파이썬 데이터과학통계학습(23.01.03-23.01.09)(정보문화사)

part04분류-2

정지홍 2023. 1. 8. 23:46

k최근접 이웃

-신규데이터와 거리가 가장 가까운 k개 데이터의 정보를 이용해 분류 및 예측을 한다.

-k최근접 이웃은 사전에 분류 모형을 만들지 않고 신규 데이터 분류가 필요할때 분류를 수행한다.

-주로 k개 이웃의 반응변수의 평균값이나 중앙값을 이용

-더 나은 방법으로 가중 평균법이 이용

-거리계산방법

  • 유클리드 거리--->두 점 사이의 직선거리를 측정(일반적으로 많이 사용)
  • 코사인 거리--->거리적 유사도보다 각 설명 변수 방향 유사도가 중요한 경우
  • 맨해튼 거리--->설명 변수가 이항 변수인 경우
  • 해밍 거리--->설명 변수가 이항 변수인 경우

-k값 선택:k값에 따라 개별 학습 데이터에 받는 영향도가 달라짐. 

-->k값이 작은 경우 인접 데이터의 작은 변화에 민감히 반응--->안전성 낮아짐

-->k값이 큰 경우 인접 데이터의 작은 변화에 영향 안받음--->안전성 높음--->예측력 감소

=>k값의 크기에 따라 안전성와 예측력 간 반비례 관계. 따라서 적절한 k값을 선택해야함

 

-k최근접이웃은 학습용 데이터에 의존도가 절대적이며 대표성이 떨어지는 데이터라면 제거하는 것이 좋다.

-설명 변수를 이용하여 거리를 계산하니 척도에 영향을 많이 받는 단점이 있다.



import numpy as np
import pandas as pd
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import GridSearchCV
from matplotlib import pyplot as plt
from matplotlib.colors import ListedColormap
from pylab import rcParams
%matplotlib inline
import warnings
warnings.filterwarnings('ignore')
df_knn = pd.read_csv('./data/classification/df_titanic.csv')

df_knn.head()


# X(Fare, Age) / y(Survived)
X = np.array(df_knn[['Fare','Age']])
y = np.array(df_knn['Survived'])

# uniform: 거리에 가중치 부여하지 않음
clf = KNeighborsClassifier(3, weights='uniform')
clf.fit(X, y)

# KNN 시각화 함수
def graph_knn(n_neighbors, weights):
    h = .02  

    cmap_light = ListedColormap(['#FFAAAA', '#AAAAFF'])
    cmap_bold  = ListedColormap(['#FF0000', '#0000FF'])

    x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
    y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1

    xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
                         np.arange(y_min, y_max, h))
    pred_ = np.c_[xx.ravel(), yy.ravel()]

    Z = clf.predict(pred_)
    Z = Z.reshape(xx.shape)
    plt.figure()
    plt.pcolormesh(xx, yy, Z, cmap=cmap_light)

    plt.scatter(X[:,0], X[:, 1], c=y, cmap=cmap_bold,
                edgecolor='k', s=20)
    plt.xlim(xx.min(), xx.max())
    plt.ylim(yy.min(), yy.max())
    plt.title("KNN (k = %i, weights = '%s')" % (n_neighbors, weights))

    plt.xlabel("Fare")
    plt.ylabel("Age")
    plt.show()

# 시각화 함수 호출
graph_knn(clf.n_neighbors, clf.weights)


knn = KNeighborsClassifier()
k_range = list(range(1,100))
# uniform: 거리에 가중치 부여하지 않음 / distance: 거리에 가중치 부여

weights_options = ['uniform','distance'] 

k_grid = dict(n_neighbors=k_range, weights = weights_options)
clf = GridSearchCV(knn, k_grid, cv=10, scoring = 'accuracy') 
clf.fit(X, y)

GridSearchCV(cv=10, estimator=KNeighborsClassifier(),
             param_grid={'n_neighbors': [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, ...],
                         'weights': ['uniform', 'distance']},
             scoring='accuracy')


# K-NN 시각화 함수 호출
graph_knn(clf.best_params_['n_neighbors'], clf.best_params_['weights'])


def make_meshgrid(x, y, h=.02):
    x_min, x_max = x.min() - 1, x.max() + 1
    y_min, y_max = y.min() - 1, y.max() + 1
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
                         np.arange(y_min, y_max, h))
    return xx, yy

def plot_contours(ax, clf, xx, yy, **params):
    Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    out = ax.contourf(xx, yy, Z, **params)
    return out

cmap_light = ListedColormap(['#FFAAAA', '#AAAAFF'])
cmap_bold  = ListedColormap(['#FF0000', '#0000FF'])

# "figure.figsize": 그림(figure)의 크기. (가로,세로) 인치 단위
# default 값으로 다시 설정 하고 싶을 경우 사용전 default 값 미리 확인
rcParams['figure.figsize'] = 14, 12

models = (KNeighborsClassifier(1, weights='uniform'),
         KNeighborsClassifier(3, weights='uniform'),
         KNeighborsClassifier(9, weights='uniform'),
         KNeighborsClassifier(21, weights='uniform'), 
         KNeighborsClassifier(51, weights='uniform'),
         KNeighborsClassifier(99, weights='uniform'))
                              
models = (clf.fit(X, y) for clf in models)

# K-NN 수이 따른 타이틀
titles=('kNN neighbor = 1',
        'kNN neighbor = 3',
        'kNN neighbor = 9',
        'kNN neighbor = 21',
        'kNN neighbor = 51',
        'kNN neighbor = 99')

# 2 x 3 플로팅 
fig, sub=plt.subplots(2, 3)
plt.subplots_adjust(wspace=0.4, hspace=0.4)

X0, X1=X[:, 0], X[:, 1]
xx, yy=make_meshgrid(X0, X1)

for clf, title, ax in zip(models, titles, sub.flatten()):
    plot_contours(ax, clf, xx, yy,
                  cmap=cmap_light, alpha=0.8)
    ax.scatter(X0, X1, c=y, cmap=cmap_bold, s=20, edgecolors='k')
    ax.set_xlim(xx.min(), xx.max())
    ax.set_ylim(yy.min(), yy.max())
    ax.set_xlabel('Fare')
    ax.set_ylabel('Age')
    ax.set_xticks(())
    ax.set_yticks(())
    ax.set_title(title)

plt.show()


서포트 벡터 머신

초평면:p차원 공간에서 차원이 p-1인 아핀 부분 공간이다. ex)2차원의 부분공간은 선, 3차원의 초평명은 면이 된다.

분리 초평면: 특정 점X가 초평면 상의 점이 아니고 다음 식을 만족하면 초평면 상단에 속함을 알 수 있다. B0 + B1*X1 + ..... + BP*XP > 0

서포트 벡터:최대 마진 초평면 결정에 영향을 주는 관측치들

 

서포트 벡터 머신의 분류 방법론

  • 분리 초평면 이용
  • 최대 마진 분류기
  • 서포트 벡터 분류기-->분류 경계면에 일부 위반이 발생해도 다른 관측치들을 잘 분류할수 있는 초평면 찾음
  • 서포트 벡터 머신

선형 서포트 벡터 머신:비선형 관계를 설명 할 수 없는 서포트 벡터 머신 분류기의 한계를 극복하기 위한 방법

-서포트 벡터 머신은 한 차원 높은 공간에서 초평면을 가지며 이는 내적으로 표현 가능

 

서포트 벡터 머신 회귀: 두 그룹 사이의 거리를 충분히 멀리 유지하고 마진 위반을 예방하는 것 대신 제한된 마진 오류 안에서 가능한 많은 샘플이 마진 위에 있도록 학습하는 방법

import numpy as np
import pandas as pd
from sklearn import svm
from sklearn.model_selection import GridSearchCV 
from matplotlib import pyplot as plt
from mlxtend.plotting import plot_decision_regions
%matplotlib inline
import warnings
warnings.filterwarnings('ignore')
df_svm = pd.read_csv('./data/classification/df_titanic.csv')
df_svm.head()

SurvivedAgeSibSpParchFarePclass_2Pclass_3Sex_101234

0 22.0 1 0 1.981001 0 1 1
1 38.0 1 0 4.266662 0 0 0
1 26.0 0 0 2.070022 0 1 0
1 35.0 1 0 3.972177 0 0 0
0 35.0 0 0 2.085672 0 1 1

print("선형 커널 실습")
print("x를 Fare,Age와 같이 수치형 변수로 사용")
print("C는 마진 너비 조절 변수값이 클수록 마진 너비가 좁아짐")
X = np.array(df_svm[['Fare','Age']])
y = np.array(df_svm['Survived'])
clf = svm.SVC(kernel='linear', C=0.01)
clf.fit(X,y)

선형 커널 실습
x를 Fare,Age와 같이 수치형 변수로 사용
C는 마진 너비 조절 변수값이 클수록 마진 너비가 좁아짐
Out[2]:
SVC(C=0.01, kernel='linear')

print("x축은 요금, y축은 나이에 따라 생존 여부를 svm으로 구분함. 네모는 사망, 세모는 생존이다.")
print("이를 통하여 Fare가 높고 나이가 어릴수록 생존 확률이 높았다.")
plt.scatter(X[:, 0], X[:, 1], c=y, s=30, cmap=plt.cm.Paired)
ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()


xx = np.linspace(xlim[0], xlim[1], 30)
yy = np.linspace(ylim[0], ylim[1], 30)
YY, XX = np.meshgrid(yy, xx)
xy = np.vstack([XX.ravel(), YY.ravel()]).T
Z = clf.decision_function(xy).reshape(XX.shape)


ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1], alpha=0.5,
           linestyles=['--', '-', '--'])

ax.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], s=50,
           linewidth=1, facecolors='none', edgecolors='k')


plt.xlabel("Fare")
plt.ylabel("Age")

plot_decision_regions(X=X, 
                      y=y,
                      clf=clf, 
                      legend=2)

plt.title('SVM Decision Region Boundary - Linear', size=14)
L = plt.legend()
L.get_texts()[0].set_text('Survived=0')
L.get_texts()[1].set_text('Survived=1')

plt.show()

x축은 요금, y축은 나이에 따라 생존 여부를 svm으로 구분함. 네모는 사망, 세모는 생존이다.
이를 통하여 Fare가 높고 나이가 어릴수록 생존 확률이 높았다.

 
 
<div><br class="Apple-interchange-newline">clf.score(X, y)</div>
 
 
clf.score(X, y)
Out[6]:
0.6481303930968361

<div><br class="Apple-interchange-newline">clf = svm.SVC(kernel="rbf", gamma=0.1, C=10) clf.fit(X,y)</div>
 
 
clf = svm.SVC(kernel="rbf", gamma=0.1, C=10)
clf.fit(X,y)
Out[8]:
SVC(C=10, gamma=0.1)

plt.scatter(X[:, 0], X[:, 1], c=y, s=30, cmap=plt.cm.Paired)

# 결정 함수 플로팅
ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()

# 모델 평가를위한 그리드 생성
xx = np.linspace(xlim[0], xlim[1], 30)
yy = np.linspace(ylim[0], ylim[1], 30)
YY, XX = np.meshgrid(yy, xx)
xy = np.vstack([XX.ravel(), YY.ravel()]).T
Z = clf.decision_function(xy).reshape(XX.shape)

# 결정 경계와 마진
ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1], alpha=0.5,
           linestyles=['--', '-', '--'])

# 서포트 벡터 플로팅
ax.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], s=50,
           linewidth=1, facecolors='none', edgecolors='k')

plt.xlabel("Fare")
plt.ylabel("Age")

# X축, y축 라벨링
plot_decision_regions(X=X, 
                      y=y,
                      clf=clf, 
                      legend=2)

plt.title('SVM Decision Region Boundary - RBF', size=14)
L = plt.legend()
L.get_texts()[0].set_text('Survived=0')
L.get_texts()[1].set_text('Survived=1')


plt.show()


의사결정나무

 

종속변수가 범주형,수치형 모두 사용 가능

결과에 대한 해석이 용이하여폭넓게 사용됨

 

의사결정나무의 단계

-규칙만들기->가지치기->타당성 평가->결과해석 및 활용

 

구조가 단순하여 해석이 쉬우나 분류 기준값 경계선 부근의 자료에 대하여 오차가 클 수 있다

df=pd.read_csv('data/classification/df_titanic.csv')
f_c=(df.columns.difference(['Survived']))
x=df[f_c]
y=df['Survived']
dt=tree.DecisionTreeClassifier(random_state=777)
dt.fit(x,y)

DecisionTreeClassifier

DecisionTreeClassifier(random_state=777)

sns.barplot(x=dt.feature_importances_,y=f_n)


앙상블 기법

-다양한 분석 방법론을 조합해 하나의 예측 모형을 만듬--->반응변수가 연속형,범주형 다 가능

-다양한 분석 방법론을 조합하여 해석이 어려우나 성능은 우수하다.

-앙상블 모형의 유형 4가지---> 데이터를 조절 , 변수의 수를 조절 , 집단명을 조절 , 분류 모형의 가정을 조절하는 방법

 

 

배깅:데이터를 조절하는 방법

부스트트랩:표본추출방법을 이용하여 각 모형의 다양성을 높여 앙상블하는 기법

' > 파이썬 데이터과학통계학습(23.01.03-23.01.09)(정보문화사)' 카테고리의 다른 글

part05그룹화  (1) 2023.01.09
part04분류-1  (0) 2023.01.08
part03회귀(05~07)  (0) 2023.01.07
part03회귀(01~04)  (0) 2023.01.06
part02데이터과학을 위한 파이썬  (0) 2023.01.05