#!/usr/bin/env python3


Decision Tree Regression



ram 가격 데이터를 이용해 Decision Tree Regression을 알아보겠습니다.

먼저 ram 가격 데이터를 시각화하여 구조를 파악해보면

import pandas as pd

import os

import matplotlib.pyplot as plt

import mglearn

import numpy as np

path = os.path.join(mglearn.datasets.DATA_PATH, 'ram_price.csv')


ram_prices = pd.read_csv(path)

ram_prices = ram_prices.iloc[:, 1:] # iloc: 정수로 columns접근,  index number : 몇번째 인덱스 까지의 형태


plt.semilogy(ram_prices['date'], ram_prices['price'])

plt.xlabel('year', size=15)

plt.ylabel('price ($/Mbyte)', size=15)

plt.show()

log scale로 그린 램 가격 동향

시간이 지날수록 램 가격은 점점 감소하는 것을 알 수 있습니다.



DecisionTreeRegressor는 train set범위 밖의 데이터에 대해서는 예측을 할 수가 없는데 

다음의 코드는 이 것을 확인할 수 있습니다.

from sklearn.tree import DecisionTreeRegressor

from sklearn.linear_model import LinearRegression


data_train = ram_prices[ram_prices['date'] < 2000]

data_test = ram_prices[ram_prices['date'] >= 2000]


x_train = data_train['date'][:, np.newaxis] # train data를 1열로 만듭니다.

y_train = np.log(data_train['price'])


tree = DecisionTreeRegressor().fit(x_train, y_train)

lr = LinearRegression().fit(x_train, y_train)


# test는 모든 데이터에 대해 적용합니다.

x_all = ram_prices['date'].reshape(-1, 1) # x_all를 1열로 만듭니다.


pred_tree = tree.predict(x_all)

price_tree = np.exp(pred_tree) # log값 되돌리기


pred_lr = lr.predict(x_all)

price_lr = np.exp(pred_lr) # log값 되돌리기


plt.semilogy(ram_prices['date'], price_tree, label='tree predict', ls='--', dashes=(2,1))

plt.semilogy(ram_prices['date'], price_lr, label='linear reg. predict', ls=':')

plt.semilogy(data_train['date'], data_train['price'], label='train data', alpha=0.4)

plt.semilogy(data_test['date'], data_test['price'], label='test data')

plt.legend(loc=1)

plt.xlabel('year', size=15)

plt.ylabel('price ($/Mbyte)', size=15)

plt.show()

ram 가격 데이터로 만든 linear model과 regression tree의 예측값 비교

linear model은 직선으로 데이터를 근사합니다.

tree model은 train set을 완벽하게 fitting했습니다. 이는 tree의 complexity를 지정하지 않아서 전체 데이터를 fitting 하기 때문입니다.

그러나 tree model은 train 데이터를 넘어가버리면 마지막 포인트를 이용해 예측하는 것이 전부입니다.

Decision Tree의 주요 단점은 pre-pruning를 함에도 불구하고 overfitting되는 경향이 있어 일반화 성능이 좋지 않습니다.

이에 대안으로 ensemble 방법을 많이 사용합니다.




참고 자료: 

[1]Introduction to Machine Learning with Python, Sarah Guido

'python 머신러닝 -- 지도학습 > Regression' 카테고리의 다른 글

Lasso  (0) 2018.03.13
Ridge  (0) 2018.03.12
LinearRegression  (0) 2018.03.12
k_NN(k-최근접 이웃) Regression  (1) 2018.03.12

#!/usr/bin/env python3


Decision Tree


Decision Tree결정트리는 True/False 질문을 이어나가면서 학습합니다.


다음 코드는 decision tree의 algorithm을 보여줍니다.

from mglearn.plots import plot_animal_tree

import matplotlib.pyplot as plt


plot_animal_tree()

plt.show()

몇 가지 동물들을 구분하기 위한 결정 트리

여기에서 tree의 node는 질문이나 정답을 담은 네모 상자를 말하며

root node는 최상위 node이고

leaf node는 마지막 node입니다.


decision tree를 학습한다는 것은 정답에 가장 빨리 도달하는 True/False 질문 목록을 학습하는 것입니다.

머신러닝에서 이런 질문들을 'test'라 합니다.


만약 tree를 만들 때 모든 leaf node가 pure node가 될 때 까지 진행하면 model의 complexity는 매우 높아지고 overfitting됩니다. 즉 train set의 모든 데이터포인트가 leaf node에 있다는 뜻입니다.


overfittng을 막는 전략은 크게 2가지가 있습니다.

1. tree 생성을 사전에 중단합니다 : pre-pruning

2. 데이터 포인트가 적은 node를 삭제하거나 병합합니다 : post-pruning



이제는 실제 데이터셋(wine dataset)으로 decision tree 분석을 해보겠습니다.

from sklearn.datasets import load_wine

from sklearn.model_selection import train_test_split

from sklearn.tree import DecisionTreeClassifier


wine = load_wine()


x_train, x_test, y_train, y_test = train_test_split(wine.data, wine.target,

                                                    stratify=wine.target, random_state=0)


tree = DecisionTreeClassifier(random_state=0)

tree.fit(x_train, y_train)


score_tr = tree.score(x_train, y_train)

score_te = tree.score(x_test, y_test)


print('{:.3f}'.format(score_tr))

# 1.000


print('{:.3f}'.format(score_te))

# 0.889

모든 leaf noe가 pure node이므로 train set의 정확도는 100%입니다.

tree는 train set의 모든 포인트들을 완벽하게 구분할 만큼 깊게 만들어집니다. 따라서 overfitting의 가능성이 매우 높아집니다.



이런 overfitting을 막기위해 깊이를 제한하는 방법을 사용할 수 있습니다.

pre-pruning의 방법 중 하나는 깊이의 최대를 설정하는 것입니다.

tree = DecisionTreeClassifier(max_depth=2, random_state=0)

tree.fit(x_train, y_train)


score_tr = tree.score(x_train, y_train)

score_te = tree.score(x_test, y_test)


print('{:.3f}'.format(score_tr))

# 0.910


print('{:.3f}'.format(score_te))

# 756

train_set의 score가 낮아진 것으로 보아 overfitting은 감소한 것처럼 보이지만, test set의 score또한 낮아졌으므로 이 데이터셋에 tree model은 적합하지 않음을 알 수 있습니다.



tree module의 export_graphviz함수를 이용해 tree를 시각화할 수 있습니다.

graphviz를 설치한 후 사용가능합니다

import graphviz

from sklearn.tree import export_graphviz


export_graphviz(tree, out_file='tree.dot',

                class_names=wine.target_names,

                feature_names=wine.feature_names,

                impurity=False# gini 미출력

                filled=True) # filled: node의 색깔을 다르게


with open('tree.dot') as file_reader:

    dot_graph = file_reader.read()


dot = graphviz.Source(dot_graph) # dot_graph의 source 저장

dot.render(filename='tree.png'# png로 저장

tree.png

wine 데이터셋으로 만든 Decision Tree

가장 중요한 특성이 proline아미노산임을 알 수 있습니다.



tree는 어떻게 작동하는지 요약하는 속성들을 사용할 수 있습니다.

가장 널리 사용되는 속성은 tree를 만드는 결정에 각 특성이 얼마나 중요한지는 평가하는 feature importance특성 중요도가 있습니다.

이 값은 0과 1사이의 숫자로 0은 전혀 사용되지 않았다는 뜻이고 1은 완벽하게 예측했다는 뜻입니다.

feature_imp = tree.feature_importances_

print('{}'.format(feature_imp))

# [0.         0.         0.         0.02885475 0.         0.

#  0.         0.         0.         0.43979596 0.         0.

#  0.53134929]



더 자세히 알아보기 위해 feature_importance를 시각화를 하겠습니다.

import numpy as np

n_feature = wine.data.shape[1]

idx = np.arange(n_feature)


plt.barh(idx, feature_imp, align='center')

plt.yticks(idx, wine.feature_names)

plt.xlabel('feature importance', size=15)

plt.ylabel('feature', size=15)

plt.show()

feature importance와 feature

root node에서 사용한 특성 'proline'이 가장 중요한 특성으로 나타납니다.


feature_importances_ 값이 낮다고 해서 이 특성이 유용하지 않다는 뜻은 아닙니다.

단지 이 tree가 특성을 선택하지 않았을 뿐이며, 다른 특성이 동일한 정보를 가지고 있어서 일 수도 있습니다.


feature importance 값은 'proline'가 중요하다가 알려주지만 이 값이 양성인지 음성인지는 알 수 없습니다.




참고 자료: 

[1]Introduction to Machine Learning with Python, Sarah Guido

'python 머신러닝 -- 지도학습 > Classifier' 카테고리의 다른 글

Gradient Boosting Model  (0) 2018.03.15
Random Forest  (0) 2018.03.15
Multi Linear Classification  (0) 2018.03.14
Logistic Regression  (1) 2018.03.13
k_NN(k-최근접 이웃) Classifier[2]  (1) 2018.03.12

#!/usr/bin/env python3


Multi Linear Classification


Logistic Regression만 제외하고 많은 linear model은 binary classifier를 지원합니다.

binary classifier algorithm을 multi class classifier algorithm으로 확장하는 보편적인 기법은

one-vs.-rest일대다방법입니다.


one-vs.-rest방식은 각 class를 다른 모든 class와 구분하도록 binary classifier model을 학습합니다.

이렇게하면 class의 수만큼 binary classifier model이 만들어집니다.


예측을 할 때 이렇게 만들어진 모든 binary classifier가 작동하여 가장 높은 점수를 내는 classifier의 class를 예측값으로 선택합니다.


class별 binary classifier를 만들면 각 class가 계수 벡터(w)와 절편(b)를 하나씩 갖게 됩니다.

결국 classifer 신뢰도를 나타내는 다음 공식의 결과값이 가장 높은 class가 해당 데이터의 class 레이블로 할당됩니다.


formula :  w[0] * x[0] + w[1] * x[1] + … + w[p] * x[p] + b


multi class Logistic Regression는 one-vs.-rest 방식과는 다르지만 class마다 하나의 계수벡터와 절편을 만들며 예측방법도 같습니다.


인위적 데이터의 구조를 보기 위해 시각화를 해보겠습니다.

from sklearn.datasets import make_blobs

import matplotlib.pyplot as plt

import numpy as np


x, y = make_blobs(random_state=42)


idx_set = []

marker_set = ['o', 'v', '^']

for i in np.unique(y):

    idx = np.where(y==i)[0]

    idx_set.append(idx)


for i, m in enumerate(marker_set):

    plt.scatter(x[idx_set[i]][:, 0], x[idx_set[i]][:, 1],

                marker=m, label='class {}'.format(i))

plt.legend()

plt.xlabel('feature 0')

plt.ylabel('feature 1')

plt.show()

3개의 클래스를 가진 2차원 데이터셋



다음으로 LinearSVC의 결과의 속성을 알아보겠습니다.

from sklearn.svm import LinearSVC


linear_svc = LinearSVC().fit(x, y)


print('{}'.format(linear_svc.coef_.shape))

# (3, 2)


print('{}'.format(linear_svc.coef_))

# [[-0.17492614  0.23140501]

#  [ 0.47621354 -0.06937621]

#  [-0.18914141 -0.20400513]]


print('{}'.format(linear_svc.intercept_))

# [-1.07745335  0.13140664 -0.08604991]


print('{}'.format(linear_svc.intercept_.shape))

# (3,)



3개의 binary classifier가 만드는 경계를 시각화하는 코드는 다음과 같습니다.

from mglearn.plots import plot_2d_classification


plot_2d_classification(linear_svc, x, fill=True, alpha=0.5)


idx_set = []

market_set = ['o', '^', 'v']

for i in np.unique(y):

    idx = np.where(y==i)[0]

    idx_set.append(idx)


for i, m in enumerate(marker_set):

    plt.scatter(x[idx_set[i]][:, 0], x[idx_set[i]][:, 1], marker=m,

                label='class {}'.format(i), edgecolors='k')


line = np.linspace(-15, 15, num=50)

for i, (coef, icept) in enumerate(zip(linear_svc.coef_, linear_svc.intercept_)):

    dec_line = -(line*coef[0] + icept) / coef[1]

    plt.plot(line, dec_line, ls='--', dashes=(3, 1), label='class {} line'.format(i)) # dashes: dash간격, 3dot당 공간 1개


plt.xlabel('feature 0')

plt.ylabel('feature 1')

plt.legend(loc=(1.01, 0.9))

plt.show()

3개의 one vs.rest classifier가 만든 decision boundary

class 0에 속한 모든 포인트는 class 0을 구분하는 직선 위, 나머지 class는 아래에 있습니다.

class 1에 속한 모든 포인트는 class 1을 구분하는 직선 위, 나머지 class는 아래에 있습니다.

이런 방법으로 모든 class를 분류합니다.


중간에 삼각형 영역은 모두 나머지로 분류하는 영역입니다.

이 영역에 있는 데이터 classifier 공식의 결과가 가장 높은 class로 분류합니다.

즉 가장 가까운 직선의 class가 됩니다.


Linear model에서 주요 parameter는

regression model에서 alpha

LinearSVC, Logistic Regression에서는 C입니다.


alpha값이 클수록, C값이 작을수록 model이 단순해집니다.


Regularization: L1, L2중 선택하고 기본적으로L2를 사용합니다.(모든 특성 사용)

L1은 몇가지 특성만 사용하므로 해당 모델에 중요한 특성이 무엇이고 효과가 어느정도 인지 설명하기 쓉습니다.


데이터셋이 크다면

LogisticRegression과 Ridge에 solver='sag'옵션을 주면 더 빨리처리가 가능합니다.

sag: Stochastic Average Gradient descent(확률적 평균 경사 하강법)입니다.




참고 자료: 

[1]Introduction to Machine Learning with Python, Sarah Guido

'python 머신러닝 -- 지도학습 > Classifier' 카테고리의 다른 글

Random Forest  (0) 2018.03.15
Decision Tree  (0) 2018.03.14
Logistic Regression  (1) 2018.03.13
k_NN(k-최근접 이웃) Classifier[2]  (1) 2018.03.12
k_NN(k-최근접 이웃) Classifier[1]  (0) 2018.03.11

#!/usr/bin/env python3


Logistic Regression[1]


Logistic Regression의 공식은 아래와 같습니다.

formula = ŷ = w[0] * x[0] + w[1] * x[1] + … + w[p] * x[p] + b > 0


Linear Regression와 매우 비슷하지만 가중치(w) 합을 사용하는 대신 예측한 값을 critical value 0 과 비교합니다.

함수에서 계산한 값이 0보다 작으면 class를 -1, 0보다 크면 +1이라고 예측합니다.


이 규칙은 Classifier에 쓰이는 모든 Linear model에서 동일합니다.


가장 널리 알려진 두 개의 linear classifier algorithm은

1. Logistic Regression

2. Support Vector Classifier의 Linear SVC입니다.


이해를 돕기 위해 LogisticRegression과 LinearSVC model를 인위적 데이터인 forge 데이터셋을 분석해보겠습니다.

from mglearn.plots import plot_2d_separator

from mglearn.datasets import make_forge

import matplotlib.pyplot as plt

from sklearn.linear_model import LogisticRegression

from sklearn.svm import LinearSVC

import numpy as np


x, y = make_forge()


_, axes = plt.subplots(1, 2)

models = [LogisticRegression(), LinearSVC()]


for model, axe in zip(models, axes.ravel()):

    clf = model.fit(x, y)

    plot_2d_separator(clf, x, fill=True, eps=0.5, ax=axe, alpha=0.5) # eps: epsilon, ax:그림객체


    idx_set = []

    for i in np.unique(y):

        idx = np.where(y==i)[0] # np.where는 array의 index를 출력결과를 tuple형태로 리턴합니다.

        idx_set.append(idx)


    axe.scatter(x[idx_set[0]][:, 0], x[idx_set[0]][:, 1],

                label='class {}'.format(1), s=40, marker='^', edgecolors='k')

    axe.scatter(x[idx_set[1]][:, 0], x[idx_set[1]][:, 1],

                label='class {}'.format(2), s=40, edgecolors='k')

    axe.set_title('{}'.format(clf.__class__.__name__))

    axe.set_xlabel('feature 0')

    axe.set_ylabel('feature 1')

axes[0].legend(loc=1)

plt.show()

forge 데이터셋에 기본 매개변수를 사용해 만든LinearSVC와 Logistic Regression model의 경계

첫 번째 특성을 x축, 두번째 특성을 y축에 표현했습니다.

LinearSVC와 LogisticRegression으로 만든 결정 경계가 직선으로 표현되었고 위쪽은 class1, 아래쪽은 class0입니다.

즉 새로운 데이터가 직선 위쪽에 놓이면 class1, 아래쪽에 놓이면 class0으로 분류됩니다.



LinearSVC와 LogisticRegression은 모두 L2 Regularization(0으로 근사)를 사용합니다.

Regularization의 강도를 결정하는 parameter는 C입니다. C값이 낮을수록 계수를 0으로 근사하므로 regularization이 강화됩니다.


다음은 C값에 따른 LogisticRegression의 decision boundary를 보여주는 코드입니다.

c_set = [0.001, 1, 1000]

_, axes = plt.subplots(1, 3)


for c_arg, axe in zip(c_set, axes.ravel()):

    params = {'C':c_arg}

    clf = LogisticRegression(**params).fit(x, y)


    plot_2d_separator(clf, x, fill=True, ax=axe, eps=0.5, alpha=0.5)


    idx_set = []

    for i in np.unique(y): # np.unique: 유일한 값만 리턴

        idx = np.where(y==i)[0]

        idx_set.append(idx)


    axe.scatter(x[idx_set[0]][:, 0], x[idx_set[0]][:, 1], s=40, edgecolors='k'# edgecolors='k' : 'k'=black

                label='class 0', marker='^')

    axe.scatter(x[idx_set[1]][:, 0], x[idx_set[1]][:, 1], s=40, edgecolors='k',

                label='class 1', marker='o')

    axe.set_title('{}, C={}'.format(clf.__class__.__name__, c_arg))

    axe.set_xlabel('feature 0')

    axe.set_ylabel('feature 1')

axes[0].legend(loc=3)

plt.show()

forge 데이터셋에 다른 C값으로 만든 LogisticRegression의 decision boundary

왼쪽 그림은 작은 C 값으로 regularization이 많이 적용되었습니다.

Regularization이 강할수록 수평적으로 그려지고

Regularization C값이 클수록 decision boundary는 최대한 train data를 맞추려고 합니다. 즉 overfitting의 가능성이 증가합니다.



LogisticRegression은 linear_model과 성격이 비슷하므로 마찬가지로 coefficient를 가지고 있습니다.

다음은 C값에 따른 coefficient를 시각화하는 코드입니다.

C_set = [0.01, 1, 100]

n_feature = cancer.data.shape[1]

line = np.linspace(0, n_feature, num=n_feature).reshape(-1, 1)

marker_set = ['o', '^', 'v']


for c_args, m in zip(C_set, marker_set):

    params = {'C':c_args}

    logreg = LogisticRegression(**params).fit(x_train, y_train)

    plt.scatter(line, logreg.coef_, marker=m, label='C={}'.format(c_args))


plt.hlines(0, xmin=np.min(line), xmax=n_feature, lw=2, color='k')

plt.xticks(np.arange(n_feature), cancer.feature_names, rotation=90, ha='center') # ha: horizon alignment

plt.ylim(-5, 5)

plt.xlabel('feature', size=15)

plt.ylabel('coef_ size', size=15)

plt.legend(loc=1)

plt.show()

breast cancer 데이터셋에 다른 C 값을 사용하여 만든 LogisticRegression coef_



이번엔 Logistic Regression에서 L1 regularization(계수를 0으로)를 사용하여 시각화해보겠습니다.

C_set = [0.01, 1, 100]

n_feature = cancer.data.shape[1]

line = np.linspace(0, n_feature, num=n_feature).reshape(-1, 1)

marker_set = ['o', '^', 'v']


for c_args, m in zip(C_set, marker_set):

    params = {'C':c_args, 'penalty':'l1'}

    logreg = LogisticRegression(**params).fit(x_train, y_train)

    plt.scatter(line, logreg.coef_, marker=m, label='C={}'.format(c_args))


plt.hlines(0, xmin=np.min(line), xmax=n_feature, lw=2, color='k')

plt.xticks(np.arange(n_feature), cancer.feature_names, rotation=90, ha='center')

plt.ylim(-5, 5)

plt.xlabel('feature', size=15)

plt.ylabel('coef_ size', size=15)

plt.legend(loc=1)

plt.show()

breast cancer 데이터와 L1 Regularization을 사용하여, 다른 C값을 적용한 LogisticRegression coef_

Regularization에서 모든 특성을 이용할지 일부 특성만을 사용할지 결정하는 주요 parameter는 'penalty'입니다.




참고 자료: 

[1]Introduction to Machine Learning with Python, Sarah Guido

'python 머신러닝 -- 지도학습 > Classifier' 카테고리의 다른 글

Random Forest  (0) 2018.03.15
Decision Tree  (0) 2018.03.14
Multi Linear Classification  (0) 2018.03.14
k_NN(k-최근접 이웃) Classifier[2]  (1) 2018.03.12
k_NN(k-최근접 이웃) Classifier[1]  (0) 2018.03.11

#!/usr/bin/env python3


Lasso


Lasso는 linear regression에 regularization을 적용하는 Ridge의 대안으로 사용됩니다.

Ridge와는 coefficient를 0에 가깝게 만들지만 Lasso는 coefficient를 0으로 만듭니다.

이 것을 L2 Regularization이라 합니다.

Lasso는 model을 이해하기 쉬워지고, 이 model의 가장 중요한 특성이 무엇인지 파악하기가 쉽습니다.

Lasso model을 통한 데이터분석은 다음과 같습니다.

from mglearn.datasets import load_extended_boston

from sklearn.model_selection import train_test_split

from sklearn.linear_model import Lasso, Ridge

import numpy as np


boston_data, boston_target = load_extended_boston()


x_train, x_test, y_train, y_test = train_test_split(boston_data, boston_target,

                                                    random_state=0, test_size=0.3)


lasso = Lasso().fit(x_train, y_train)


print('{:.3f}'.format(lasso.score(x_train, y_train)))

# 0.265


print('{:.3f}'.format(lasso.score(x_test, y_test)))

# 0.214


print(lasso.coef_)

# array([-0.        ,  0.        , -0.        ,  0.        , -0.        ,

#         0.        , -0.        ,  0.        , -0.        , -0.        ,

#        -0.        ,  0.        , -4.38009987, -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.        ,

#        -4.39984433, -0.        , -0.        ,  0.        , -0.        ,

#        -0.        , -0.        ,  0.        , -0.        , -0.44131553,

#        -0.        , -0.        , -0.        , -0.        , -0.        ,

#        -0.        , -0.        , -0.        , -0.        , -0.        ,

#        -0.        ,  0.        , -0.        , -0.        ])


print(np.sum(lasso.coef_ != 0))

# 3

Lasso는 train set와 test set 모두 결과가 좋지 않습니다. 즉 underfitting 되었다고 볼 수 있습니다.

105개의 특성중 3개만 사용했음을 알 수 있습니다.



Lasso에서 regularization parameter는 alpha입니다.

alpha를 줄이면 가장 낮은 오차를 찾아가는 반복횟수가 늘어나야 합니다. 따라서 max_iter를 증가시켜야 합니다.

alpha와max_iter값에 따른 Lasso결과를 시각화 해보겠습니다.

import matplotlib.pyplot as plt


alpha_set = [0.0001, 0.01, 1]

max_inter_set = [10000000, 100000, 1000]


train_score = []

test_score = []

used_feature = []


for a, m in zip(alpha_set, max_inter_set):

    lasso = Lasso(alpha=a, max_iter=m).fit(x_train, y_train)

    la_tr_score = round(lasso.score(x_train, y_train), 3)

    la_te_score = round(lasso.score(x_test, y_test), 3)

    number_used = np.sum(lasso.coef_ != 0)


    train_score.append(la_tr_score)

    test_score.append(la_te_score)

    used_feature.append(number_used)


index = np.arange(len(alpha_set))

bar_width = 0.35

plt.bar(index, train_score, width=bar_width, label='train')

plt.bar(index+bar_width, test_score, width=bar_width, label='test')

plt.xticks(index+bar_width/2, alpha_set) # bar그래프 dodge를 하기 위해 기준값에 보정치를 더해줍니다.


for i, (ts, te) in enumerate(zip(train_score, test_score)):

    plt.text(i, ts+0.01, str(ts), horizontalalignment='center')

    plt.text(i+bar_width, te+0.01, str(te), horizontalalignment='center')


plt.legend(loc=1)

plt.xlabel('alpha')

plt.ylabel('score')

plt.show()

alpha와 max_iter값에 따른 test 점수



사용된 특성은 다음과 같습니다.

index = np.arange(len(alpha_set))

plt.bar(index, used_feature)

plt.xticks(index, alpha_set)

for i, u in enumerate(used_feature):

    plt.text(i, u+1, str(u), horizontalalignment='center')

plt.xlabel('alpha')

plt.ylabel('used_feature')

plt.show()

alpha값에 따른 특성 사용 수

alpha 값을 낮추면 model의 complexity는 증가하여 train set의 성능이 좋아집니다.

그러나 너무 낮추게 되면 regularization의 효과가 없어져 overfitting 되므로 liner regression과 비슷해집니다.

Ridge의 alpha 범위는 0 < alpha < Inf

Lasso의 alpha 범위는 0 < alpha ≦ 1 과 같습니다.



다음으로 alpha 값이 다른 model들의 coefficient를 시각화 해보겠습니다.

n_feature = boston_data.shape[1]

line = np.linspace(0, n_feature, num=n_feature)

alpha_set = [0.0001, 0.01, 1]

max_iter_set = [10000000, 100000,1000]

marker_set = ['v', '^', 's']


ridge = Ridge(alpha=0.01).fit(x_train, y_train)

plt.scatter(line, ridge.coef_, marker='o', label='Ridge alpha={}'.format(0.01))


for a, i, m in zip(alpha_set, max_iter_set, marker_set):

    param = {'alpha':a, 'max_iter':i}

    lasso = Lasso(**param).fit(x_train, y_train) # **kwargs parameter

    plt.scatter(line, lasso.coef_, marker=m, label='Lasso alpha={}'.format(a))

    

plt.legend(ncol=2, loc=(0, 1.05))

plt.ylim(-25, 25)

plt.hlines(y=0, xmin=0, xmax=n_feature)

plt.xlabel('coef_ list')

plt.ylabel('coef_ size')

plt.show()

alpha와 Ridge의 alpha값에 따른 특성의 값


Lasso alpha=1(빨강 정사각형)_일 때 계수 대부분이 0에 근접하였습니다.  ==> Regularization을 많이 했음을 의미합니다.

Lasso alpha=0.01(초록 정삼각형)일때 Regularization이 완화되어 분포가 약간 넓어진 것을 볼 수 있습니다.

Lasso alpha=0.00001(주황 역삼각형)일 때 Regularization이 거의 없어져 분포가 매우 넓어지는 것을 확인할 수 있습니다.

Ridge alapha=0.01(빨강 원)은 Lasso alpha=0.01과 분포가 비슷하지만 어떠한 계수도 0이 되지 않습니다.


보통은 Ridge Regression을 선호하지만 특성이 많고 일부분만 중요하다면 Lasso가 더 좋은 선택입니다.

분석하기 쉬운 model을 원하면 Lasso가 특성 중 일부만 사용하므로 쉡게 해석할 수 있는 model을 만듭니다.




참고 자료: 

[1]Introduction to Machine Learning with Python, Sarah Guido

'python 머신러닝 -- 지도학습 > Regression' 카테고리의 다른 글

Decision Tree Regressor  (0) 2018.03.14
Ridge  (0) 2018.03.12
LinearRegression  (0) 2018.03.12
k_NN(k-최근접 이웃) Regression  (1) 2018.03.12

#!/usr/bin/env python3


Ridge


Ridge는 linear model이므로 OLS(Ordinary Least Square)를 사용합니다.

Ridge Regression에서 가중치(w) 선택은 추가 제약 조건을 생성하여

가중치(w)의 절댓값을 가능학 작게 만드는 것(0으로 만드는 것이 아님)입니다.


기하학적으로 모든 특성의 기울기를 0에 가깝게 만드는 것이고 이 것을 regularization이라 합니다.

즉 model을 overfitting 하지 않도록 강제로 제한하는 것입니다.


Ridge Regression에 사용하는 regularization을 L2 regularization이라고도 합니다.


보스턴 주택가격으로 Ridge Regression과 linear regression을 사용하여 비교해보겠습니다.

from mglearn.datasets import load_extended_boston

from sklearn.linear_model import Ridge, LinearRegression

from sklearn.model_selection import train_test_split


boston_data, boston_target = load_extended_boston()

x_train, x_test, y_train, y_test = \

  train_test_split(boston_data, boston_target,

                   random_state=0, test_size=0.3)


ridge = Ridge()

ridge.fit(x_train, y_train)

lr = LinearRegression()

lr.fit(x_train, y_train)


print('{:.3f}'.format(ridge.score(x_train, y_train)))

# 0.882

print('{:.3f}'.format(lr.score(x_train, y_train)))

# 0.952

print('{:.3f}'.format(ridge.score(x_test, y_test)))

# 0.783

print('{:.3f}'.format(lr.score(x_test, y_test)))

# 0.645

train set정확도는 Ridge Reg. < Linear Reg.

test set정확도는 Ridge Reg. > Linear Reg. 입니다.


Linear Reg는 train set과 test set의 차이가 많이나므로 overfittng이 되지만

Ridge Reg는 regularization이 적용되기 때문에 train set과 test set의 차이가 적습니다.

따라서 model의 complexity가 낮아지게 되고 test set의 정확도는 상승합니다.



다음으로 Ridge의 Regularization에 대해서 알아보겠습니다.

Ridge Reg.는 alpha parameter로 model을 얼마나 단순화할지를 결정합니다.

default 값은 1이며 높을수록 Regularization을 강화하여 계수를 0에 가깝게 만듭니다.


alpha값에 따른 정확도비교는 아래코드로 확인할 수 있습니다.

alpha_train_score = []

alpha_test_score = []

alpha_set = [0.1, 1 ,10]


for i in alpha_set:

    ridge=Ridge(alpha=i)

    ridge.fit(x_train, y_train)


    ridge_tr_score = round(ridge.score(x_train, y_train), 3)

    ridge_te_score = round(ridge.score(x_test, y_test), 3)


    alpha_train_score.append(ridge_tr_score)

    alpha_test_score.append(ridge_te_score)


print(alpha_set)

# [0.1, 1, 10]


print(alpha_train_score)

# [0.927, 0.882, 0.78]


print(alpha_test_score)

# [0.797, 0.783, 0.678]

alpha값이 커질수록(규제가 강화될수록) 정확도는 낮아지는 것을 볼 수 있습니다.



Ridge도 Linear_model이므로 속성(coef_, intercept_)가 존재합니다.

Ridge의 alpha값에 따른 coef_를 조사하면

import numpy as np

import matplotlib.pyplot as plt


n_feature = boston_data.shape[1]

line = np.linspace(0, n_feature, num=n_feature).reshape(-1, 1)


lr = LinearRegression().fit(x_train, y_train)

plt.scatter(line, lr.coef_, marker='s', label='Linear Reg.') # marker = 's'  => square


alpha_set = [0.1, 1 ,10]

marker_set = ['o', '^', 'v']

for i, m in zip(alpha_set, marker_set):

    ridge = Ridge(alpha=i)

    ridge.fit(x_train, y_train)

    plt.scatter(line, ridge.coef_, marker=m, label='alpha={}'.format(i))


plt.ylim(-30, 30)

plt.hlines(y=0, xmin=0, xmax=n_feature)

plt.legend(loc=(0.01, 1.01))

plt.show()

Linar Regression과 몇 가지 alpha 값을 가진 Ridge Regression의 coefficient 비교

x축은 coef_의 원소를 위치대로 나열한 것입니다. 즉 x=0, x=1은 각각 첫번째 특성과 두번째 특성을 나타내는 것입니다.

alpha=10일 때(빨강 역삼각형)은 대부분 y=0에 위치하며

alpha=1(초록 정삼각형)은 alpha=10일 때보다는 약간 퍼진 상태입니다.

alpha=0.1(주황 원)은 매우 크게 확장되었으며

Linear Reg.(파랑 정사각형)은 자유롭게 퍼져있는 것을 확인할 수 있습니다.



이번엔 learning curve(데이터셋의 크기에 따른 모델의 성능 변화)를 알아보겠습니다.

train_ridge_set = []

train_linear_set = []

test_ridge_set = []

test_linear_set = []


for i in test_size_set:

    x_train, x_test, y_train, y_test = \

      train_test_split(boston_data, boston_target,

                       random_state=35, test_size=i)

    ridge = Ridge(alpha=1).fit(x_train, y_train)

    lr = LinearRegression(n_jobs=-1).fit(x_train, y_train) # n_jobs = 사용할 코어의 수, -1은 모든 코어사용


    rid_tr_score = ridge.score(x_train, y_train)

    rid_te_score = ridge.score(x_test, y_test)

    lr_tr_score = lr.score(x_train, y_train)

    lr_te_score = lr.score(x_test, y_test)


    train_ridge_set.append(rid_tr_score)

    train_linear_set.append(lr_tr_score)

    test_ridge_set.append(rid_te_score)

    test_linear_set.append(lr_te_score)


plt.plot(x_ticks, train_ridge_set, c='lightblue', ls='--', label='train ridge'# c = color, ls = linestyle

plt.plot(x_ticks, train_linear_set, c='orange', ls='--',label='train Linear_Reg')

plt.plot(x_ticks, test_ridge_set, c='lightblue', label='test ridge')

plt.plot(x_ticks, test_linear_set, c='orange', label='test Linear_Reg')


plt.legend(loc=(0.01, 1.01))

plt.ylim(0, 1.1)

plt.show()

보스턴 주택가격 데이터셋에 대한 Ridge vs Linear Reg,

train 데이터(점선)가 test 데이터(line)보다 높음을 알 수 있습니다.

Ridge에는 regularization이 적용되므로 Linear Reg보다 낮습니다.


일반화 데이터에서는 Ridge의 점수가 더 높으며, 데이터셋이 작을수록 두드러집니다.

데이터셋의 크기가 작을수록 Linear Reg.는 어떤 것도 학습하지 못합니다.


데이터가 충분히 크면 regularization이 덜 중요해지고(두 모델의 차이가 줄어듭니다.)

Linear_Reg의 경우 데이터셋이 클수록 train 데이터 성능이 감소합니다. 이는 데이터가 많아질수록 overfitting 하기가 어려움을 시사합니다




참고 자료: 

[1]Introduction to Machine Learning with Python, Sarah Guido

'python 머신러닝 -- 지도학습 > Regression' 카테고리의 다른 글

Decision Tree Regressor  (0) 2018.03.14
Lasso  (0) 2018.03.13
LinearRegression  (0) 2018.03.12
k_NN(k-최근접 이웃) Regression  (1) 2018.03.12
#!/usr/bin/env python3

LinearRegression


Linear Regression은 아래 식을 이용하여 추정합니다.

ŷ = w[i]*x + b 
w[i]는 기울기, b는 y절편에 해당하고 특성이 많아지면 w[i]는 각 특성에 해당하는 기울기를 모두 가집니다.

이해를 돕기위해 인위적 데이터셋으로 동작환경을 살펴보겠습니다.
import mglearn
import matplotlib.pyplot as plt

mglearn.plots.plot_linear_regression_wave()
plt.show()

wave 데이터셋에 대한 선형 모델의 예측

회귀를 위한 선형 모델은 특성이 하나일 땐 직선이고
특성이 두개일 땐 평면
더 높은 차원에서는 hyperpane초평면이 됩니다.


특성이 많은 데이터셋이라면 linear model은 매우 훌룡한 성능을 낼 수 있습니다.
보통 OLS(ordinary least squares)최소제곱법을 많이 사용합니다.
linear regression은 parameter가 없는 것이 장점이지만
model의 복잡도를 제어할 방법이 없는 것이 단점입니다.


linear regression을 이용하여 인위적 데이터를 학습해보겠습니다.
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from mglearn.datasets import make_wave

x, y = make_wave(n_samples=60)
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=0)

lr = LinearRegression()
lr.fit(x_train, y_train)

train_score = lr.score(x_train, y_train)
test_score = lr.score(x_test, y_test)
print('{:.3f}'.format(train_score))
# 0.659
print('{:.3f}'.format(test_score))
# 0.693
train set와 test set의 점수가 매우 비슷한 것으로 보아 overfitting된 것을 알 수 있습니다.


linear regression의 속성을 보는 코드는 다음과 같습니다.
coef_는 기울기를 나타내며, intercept_는 절편을 나타냅니다. 또한 '_'는 머신러닝에서 유도된 결과를 나타내는 기호입니다.
print('{s[0]:.3f}'.format(s=lr.coef_)) # lr.coef_는 리스트이므로 소숫점 3자리로 표현하기 위해서는 리스트 안에 원소를 이용합니다.
# 0.442
print('{:.3f}'.format(lr.intercept_))
# -0.017



참고 자료: 

[1]Introduction to Machine Learning with Python, Sarah Guido


'python 머신러닝 -- 지도학습 > Regression' 카테고리의 다른 글

Decision Tree Regressor  (0) 2018.03.14
Lasso  (0) 2018.03.13
Ridge  (0) 2018.03.12
k_NN(k-최근접 이웃) Regression  (1) 2018.03.12
#!/usr/bin/env python3

k_NN(k-최근접 이웃) Regression


k-NN 회귀모델을 알아보겠습니다.
k-NN regression의 동작환경은 다음과 같습니다.

import mglearn

import matplotlib.pyplot as plt

mglearn.plots.plot_knn_regression(n_neighbors=1)
plt.show()

n_neighbors=1 일때 algorithm

x축에 3개의 테스트 데이터를 녹색 별로 표시합니다.
최근접 이웃을 한 개만 사용할 때 예측은 가장 가까운 데이터 포인트의 값으로 인식합니다.

다음은 이웃의 수가 3일 때 knn algorithm의 동작 환경입니다.
mglearn.plots.plot_knn_regression(n_neighbors=3)
plt.show()

n_neighbors=3 일때 algorithm

마찬가지로 3개의 녹색 테스트 데이터를 기준으로 가장 이웃한 3개의 최근접 데이터 포인트를 구합니다.
그리고 나서 각 데이터포인트사이의 거리의 역수를 가중치로 타겟 값을 산정합니다.


이해를 돕기위해 인위적 데이터를 사용하여 k-NN Regression을 사용해보겠습니다.
from mglearn.datasets import make_wave
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsRegressor

x, y = make_wave(n_samples=40)

x_train, x_test, y_train, y_test = \
  train_test_split(x, y, 
                   random_state=0, test_size=0.3)

knn_reg = KNeighborsRegressor(n_neighbors=3, n_jobs=-1) n_jobs = 사용할 코어의 수, -1 => 모든 코어 사용
knn_reg.fit(x_train, y_train)

print('{:.3f}'.format(knn_reg.score(x_test, y_test)))
# 0.697


1차원 데이터 셋이므로 시각화가 가능하므로 n_neighbors의 값에 따라 어떻게 변하는지 확인해보겠습니다.
import numpy as np
_, axes = plt.subplots(1, 3)

line = np.linspace(-5, 5, num=1000)
line = line.reshape(-1, 1)

for i, ax in zip([1, 3, 9], axes.ravel()):
    knn_reg = KNeighborsRegressor(n_neighbors=i, n_jobs=-1)
    knn_reg.fit(x_train, y_train)

    prediction = knn_reg.predict(line)
    ax.plot(line, prediction, label='model predict', c='k'
    ax.scatter(x_train, y_train, marker='^', c='darkred', label='train target')
    ax.scatter(x_test, y_test, marker='v', c='darkblue', label='test target')
    
    train_score = knn_reg.score(x_train, y_train)
    test_score = knn_reg.score(x_test, y_test)
    ax.set_title('k={}\ntest score={:.3f}\ntrain score={:.3f}'.format(i, train_score, test_score))
    ax.set_xlabel('feature')
    ax.set_ylabel('target')
axes[0].legend(loc=2)
plt.show()

n_neighbors 값에 따라 최근접 이웃 회귀로 만들어진 예측 회귀 비교

이웃을 하나만 사용할 때는 훈련 세트의 각 데이터 포인트가 모든 선을 통과합니다. 이 것은 너무 복잡하게 모델이 짜여져 있는 것을 말하며 실제로 예측할 때는 그 결과가 좋지 못합니다. 반대로 이웃을 많이 사용할 수록 훈련 데이터에는 잘 안맞을 수 있지만 높은 정확도를 얻게 됩니다.


k-NN은 이해하기 매우 쉬운 모델입니다. 그러나 수백 개 이상의 많은 특성을 가진 데이터 셋에는 잘 동작하지 않으며 특성값이 0이 많은 데이터셋이는 잘 작동하지 않습니다.
또한 예측이 느리고, 많은 특성을 처리하는 능력이 부족하여 현업에서는 잘 쓰지 않습니다.
KNeighborsRegressor와 KNeighborsClassifier의 객체를 생성할 때 'metric' parameter를 사용하여 거리 측정 방식을 변경할 수 있습니다. 'metric' parameter의 기본값은 'minkowski', 거듭제곱의 크기를 정하는 parameter느 'p'입니다.
metric='minkowski', p=2는 metric='euclidean'과 같습니다.



참고 자료: 

[1]Introduction to Machine Learning with Python, Sarah Guido


'python 머신러닝 -- 지도학습 > Regression' 카테고리의 다른 글

Decision Tree Regressor  (0) 2018.03.14
Lasso  (0) 2018.03.13
Ridge  (0) 2018.03.12
LinearRegression  (0) 2018.03.12

#!/usr/bin/env python3


k_NN(k-최근접 이웃)  Classifier[2]


k-NN algorithm은 가장 가까운 데이터 포인트중 n_neighbors만큼 이웃으로 삼아 예측으로 사용합니다.

다음은 k-NN algorithm을 보여줍니다.

import matplotlib.pyplot as plt

import mglearn


mglearn.plots.plot_knn_classification(n_neighbors=1)

plt.xlabel('feature 0')

plt.ylabel('feature 1')

plt.title('n_neighbors=1')

plt.legend(feature_list, loc=(1.01, 0.4))

plt.show()

n_neighbors=1 일 때 algorithm


mglearn.plots.plot_knn_classification(n_neighbors=3)

plt.xlabel('feature 0')

plt.ylabel('feature 1')

plt.title('n_neighbors=3')

plt.legend(feature_list, loc=(1.01, 0.4))

plt.show()

n_neighbors=1 일 때 algorithm



이번에는 n_neighbors의 숫자에 따른 결정 경계를 그려보겠습니다.

먼저 임의로 데이터셋을 만들어보겠습니다.

from mglearn.datasets import make_forge


x, y = make_forge()


_, axes = plt.subplots(1, 3)

for i, ax in zip([1, 3, 9], axes.ravel()):

    knn = KNeighborsClassifier(i)

    knn.fit(x, y)


    mglearn.plots.plot_2d_separator(knn, x, fill=True,

                                    eps=0.5, alpha=0.5, ax=ax)

    mglearn.discrete_scatter(x[:, 0], x[:, 1],

                             y=y, ax=ax)

    ax.set_title('k={}'.format(i))

    ax.set_xlabel('feature 0')

    ax.set_ylabel('feature 1')

axes[0].legend(loc=(0.01, 1.01))

plt.show()

n_neighbors 값에 따른 k-NN모델이 만든 decision boundary

이 그림을 보면 제일 왼쪽인 k=1일 경우에 모든 데이터를 가장 정확하게 분류했으며 그 경계는 복잡합니다.

k의 값이 커질수록 경계선은 점점 수평에 가까워지며 경계는 완만해짐을 알 수 있습니다.



실제wine 데이터를 분석해보겠습니다.

분석하기전에 wine데이터의 전체적인 구조를 pandas의 scatter_matrix를 이용해서

확인해보겠습니다. 이 작업은 데이터틔 outlier가 있는지 쉽게 확인할 수 있는 장점이 있습니다.

from sklearn.datasets import load_wine

import pandas as pd


wine = load_wine()

print(wine.keys())

# dict_keys(['data', 'target', 'target_names', 'DESCR', 'feature_names'])


for i in range(len(wine.feature_names)):

    print('{}:{}'.format(i, wine.feature_names[i]))

# 0:alcohol

# 1:malic_acid

# 2:ash

# 3:alcalinity_of_ash

# 4:magnesium

# 5:total_phenols

# 6:flavanoids

# 7:nonflavanoid_phenols

# 8:proanthocyanins

# 9:color_intensity

# 10:hue

# 11:od280/od315_of_diluted_wines

# 12:proline    


wine_df = pd.DataFrame(wine.data, columns=range(len(wine.feature_names)))

pd.scatter_matrix(wine_df, # dataframe

                  c=wine.target, # color

                  hist_kwds={'bins':30}, # hist kwords

                  s=10, # size

                  alpha=0.5, # alpha

                  marker='o'# marker

plt.show()

wine의 scatter_plot

그래프가 복잡해 보일지 모르겠지만 전체적인 구조를 한 눈에 파악할 수 있습니다.



데이터를 파악했으니 k-NN 최근접 이웃 algorithm, n_neighbors=3으로 데이터를 분석해보겠습니다.

from sklearn.neighbors import KNeighborsClassifier

from sklearn.model_selection import train_test_split


x_train, x_test, y_train, y_test =\

  train_test_split(wine.data, wine.target, stratify=wine.target, # stratify = 계층화

                   random_state=0, test_size=0.3)  


knn = KNeighborsClassifier(n_neighbors=3, n_jobs=-1) # jobs =  사용할 코어의 수, -1 => 모든 코어

knn.fit(x_train, y_train)


print('{:.3f}'.format(knn.score(x_test, y_test)))

# 0.648

약 KNeighborsClassifier(n_neighbors=3)으로 와인의 품종을 테스트한 결과 약 70%의 정확도를 나타내는 것을

볼 수 있습니다.



이번엔 이 데이터로 모델의 복잡도와 일반화사이의 관계를 알아보겠습니다.

위의 임의로 만든 데이터로 알아본 결과 모델의 복잡도를 알아보았는데 실제 데이터셋으로 모델의 복잡도와 정확도를 알아보겠습니다.

from sklearn.datasets import load_wine

import matplotlib.pyplot as plt


wine = load_wine()


x_train, x_test, y_train, y_test = \

  train_test_split(wine.data, wine.target, stratify=wine.target,

                   test_size=0.3, random_state=0)


train_list = []

test_list = []

n_range = range(1, 20)


for i in n_range:

    knn = KNeighborsClassifier(n_neighbors=i, n_jobs=-1)

    knn.fit(x_train, y_train)


    tr_score = knn.score(x_train, y_train)

    te_score = knn.score(x_test, y_test)


    train_list.append(tr_score)

    test_list.append(te_score)


plt.plot(n_range, train_list, color='red', ls='--', lw=2, label='train accuracy') # ls = linestyle, lw= linewidth

plt.plot(n_range, test_list, color='green', lw=2, label='test accuracy')

plt.xticks(n_range)

plt.xlabel('n_neighbors')

plt.ylabel('accuracy')

plt.legend() 

plt.show()

n_neighbors 변화에 따른 훈련 정확도와 테스트 정확도

이웃의 수(n_neighbors)가 작을수록 모델이 복잡해지고 모델의 정확도는 100%입니다.

그러나 예측 정확도는 0.7정도인 것을 알수있으며

이웃의 수를 증가시켜도 예측 정확도는 많이 늘어나지는 않습니다.

따라서 이 데이터에는 k-NN 최근접 algorithm이 적합하지 않음을 알 수 있습니다.



참고 자료: 

[1]Introduction to Machine Learning with Python, Sarah Guido

'python 머신러닝 -- 지도학습 > Classifier' 카테고리의 다른 글

Random Forest  (0) 2018.03.15
Decision Tree  (0) 2018.03.14
Multi Linear Classification  (0) 2018.03.14
Logistic Regression  (1) 2018.03.13
k_NN(k-최근접 이웃) Classifier[1]  (0) 2018.03.11
#!/usr/bin/env python3

k_NN(k-최근접 이웃)  Classifier[1]


분석을 위해 iris데이터를 로드합니다.

from sklearn.datasets import load_iris


iris = load_iris()



iris데이터의 형태는 다음의 코드로 확인할 수 있습니다.

print('''iris's key ==> {}'''.format(iris.keys()))

# iris's key ==> dict_keys(['data', 'target', 'target_names', 'DESCR', 'feature_names'])


print('''iris's shape ==> {}'''.format(iris.data.shape))

# iris's shape ==> (150, 4)


print('''iris's data의 처음 6행 ==> \n{}'''.format(iris.data[:6]))

# iris's data의 처음 6행 ==> 

# [[5.1 3.5 1.4 0.2]

#  [4.9 3.  1.4 0.2]

#  [4.7 3.2 1.3 0.2]

#  [4.6 3.1 1.5 0.2]

#  [5.  3.6 1.4 0.2]

#  [5.4 3.9 1.7 0.4]]


print('''iris's feature names ==> \n{}'''.format(iris.feature_names))

# iris's feature names ==> 

# ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']



머신러닝 데이터학습을 위해 데이터를 분할합니다. 이 방법은 앞으로도 계속 사용합니다.

from sklearn.model_selection import train_test_split


x_train, x_test, y_train, y_test = \

  train_test_split(iris.data, iris.target,

                   test_size=0.3, random_state=0)



이제 데이터를 분할했으니 머신러닝을 사용할 때입니다.

이번 포스팅에서는 가장 기본적인 KNN 최근접이웃 머신러닝을 사용합니다.

머신러닝 algorithm을 사용하기 위해서는 학습시킬 데이터를 fitting해야합니다.

from sklearn.neighbors import KNeighborsClassifier


# n_neighbors는 가장 가까운 이웃을 몇개를 고를지에 대한 parameter며

# n_jobs는 사용할 코어의 갯수 입니다. -1이면 모든 코어를 사용합니다.

knn = KNeighborsClassifier(n_neighbors=1, n_jobs=-1)

knn.fit(x_train, y_train)



sample data를 만들어 확인해보겠습니다.

import numpy as np


# ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']

x_sample = np.array([[5, 2.9, 1, 0.2]])

prediction = knn.predict(x_sample)

results = {p:n for p, n in zip(prediction, iris.target_names[prediction])}

print('sample test ==> {}'.format(results))

# sample test ==> {0: 'setosa'}

knn(n_neighbors=1)를 이용하여 sample test 예측했을 때는 'setosa'라고 결과를 냈습니다.



이제 위에서 분할한 test data로 예측하면

prediction = knn.predict(x_test)

results = [iris.target_names[p] for p in prediction]

print('results의 처음 6개 ==> {}'.format(results[:6]))

# results의 처음 6개 ==> ['virginica', 'versicolor', 'setosa', 'virginica', 'setosa', 'virginica']


bins = np.bincount(prediction)

count = {n:c for n, c in zip(iris.target_names, bins)}

print('test 결과의 빈도수 ==> {}'.format(count))

# test 결과의 빈도수 ==> {'setosa': 16, 'versicolor': 17, 'virginica': 12}



정확도는 2가지 방법으로 구할 수 있습니다.

KNeighborsClassifier의 score메소드를 이용하거나 직접 계산하는 방법입니다.

print('score 메소드 이용 ==> {:.3f}'.format(knn.score(x_test, y_test)))

# score 메소드 이용 ==> 0.978


y_pred = knn.predict(x_test)

print('numpy 이용 ==> {:.3f}'.format(np.mean(y_pred == y_test)))

# numpy 이용 ==> 0.978



훈련 데이터를 시각화 해보겠습니다.

pandas를 이용할 것이기 때문에 훈련 데이터를 DataFrame으로 변환하고

열이름은 featre_names를 사용하겠습니다.

import pandas as pd

import matplotlib.pyplot as plt

import matplotlib


matplotlib.rc('font', family='AppleGothic') # 한글출력

plt.rcParams['axes.unicode_minus'] = False # 축 - 표시


iris_df = pd.DataFrame(x_train, columns=iris.feature_names)

pd.scatter_matrix(iris_df,

                  c=y_train, # 색깔로 구분할 데이터

                  hist_kwds={'bins':30}, # 히스토그램

                  marker='o', # marker

                  s=20, # size

                  alpha=0.5) # 투명도

plt.show()


pandas를 이용한 scatter_matrix

이 그래프를 통해 훈련데이터의 개괄적인 정보를 한번에 파악할 수 있습니다.




참고 자료: 

[1]Introduction to Machine Learning with Python, Sarah Guido


'python 머신러닝 -- 지도학습 > Classifier' 카테고리의 다른 글

Random Forest  (0) 2018.03.15
Decision Tree  (0) 2018.03.14
Multi Linear Classification  (0) 2018.03.14
Logistic Regression  (1) 2018.03.13
k_NN(k-최근접 이웃) Classifier[2]  (1) 2018.03.12

+ Recent posts