Ordinary day

파이썬 머신러닝 (2) 본문

Study/ML 실습 - Python 기초

파이썬 머신러닝 (2)

minung14 2017. 1. 25. 01:42

파이썬에서 perceptron learning algorithm 구현

import numpy as np

class Perceptron(object):
    """Perceptron classifier.

    Parameters
    ------------
    eta : float
        Learning rate (between 0.0 and 1.0)
    n_iter : int
        Passes over the training dataset.

    Attributes
    -----------
    w_ : 1d-array
        Weights after fitting.
    errors_ : list
        Number of misclassifications (updates) in each epoch.

    """
    def __init__(self, eta=0.01, n_iter=10):
        self.eta = eta
        self.n_iter = n_iter

    def fit(self, X, y):
        """Fit training data.

        Parameters
        ----------
        X : {array-like}, shape = [n_samples, n_features]
            Training vectors, where n_samples is the number of samples and
            n_features is the number of features.
        y : array-like, shape = [n_samples]
            Target values.

        Returns
        -------
        self : object

        """
        self.w_ = np.zeros(1 + X.shape[1])
        self.errors_ = []

        for _ in range(self.n_iter):
            errors = 0
            for xi, target in zip(X, y):
                update = self.eta * (target - self.predict(xi))
                self.w_[1:] += update * xi
                self.w_[0] += update
                errors += int(update != 0.0)
            self.errors_.append(errors)
        return self

    def net_input(self, X):
        """Calculate net input"""
        return np.dot(X, self.w_[1:]) + self.w_[0]

    def predict(self, X):
        """Return class label after unit step"""
        return np.where(self.net_input(X) >= 0.0, 1, -1)

이 퍼셉트론을 구현해서 우리는 주어진 learning rate와 반복횟수로 새로운 퍼셉트론 객체를 초기화할 수 있다.
fit 함수를 통해 우리는 self.w 가중치를 제로벡터로 초기화한다.
가중치가 초기화된 이후, fit 함수는 트레이닝셋에서 모든 샘플을 반복하고, perceptron learning rule에 따라 가중치를 업데이트한다.
클래스label은 predict 함수에 의해 예측되고, 이는 가중치 업데이트의 클래스 label을 예측하기 위해 fit 함수에서도 호출되지만, predict함수는 우리가 모델을 적용한 이후에 새로운 데이터의 클래스 label을 예측하기 위해 사용된다.
게다가 우리는 self.errors 목록에서 각 단계를 반복하는 동안 잘못 분류한 수를 모아서 이후에 퍼셉트론이 트레이닝되는 동안 얼마나 잘 수행되었는지 분석할 수 있다.
np.dot 함수는 net_input 함수에서 단순히 벡터 wTx를 계산하는데 사용된다.

아이리스 데이터 셋에서 퍼셉트론 모델

트레이닝 퍼셉트론 구현을 테스트하기 위해 아이리스 데이터 셋으로부터 두 개의 꽃 클래스 Setosa와 Versicolor를 로드해야한다. 퍼셉트론 룰이 2차원으로 제한되지 않아도 꽃받침 길이와 꽃잎 길이 두 개의 특징을 고려할 것이다. 그리고 Setosa와 Versicolor 두 개의 클래스 중에서만 선택했다. 그러나 퍼셉트론 알고리즘은 다중 클래스 분류로 확장될 수 있다.

import pandas as pd

df = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data', header=None)
df.tail()
0 1 2 3 4
145 6.7 3.0 5.2 2.3 Iris-virginica
146 6.3 2.5 5.0 1.9 Iris-virginica
147 6.5 3.0 5.2 2.0 Iris-virginica
148 6.2 3.4 5.4 2.3 Iris-virginica
149 5.9 3.0 5.1 1.8 Iris-virginica

다음으로 Setosa 50개와 Versicolor 50개에 각각 해당하는 첫번째 100개의 클래스 label을 추출하고 클래스 label을 두 정수의 클래스 label(1:Versicolor, -1:Setosa)로 변환한다.

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np

# 100개의 데이터 가져와서 setosa면 -1, 아니면 1로 분류
y = df.iloc[0:100, 4].values
y = np.where(y == 'Iris-setosa', -1, 1)

# 꽃잎 길이와 꽃받침 길이 추출
X = df.iloc[0:100, [0, 2]].values

# plot data
plt.scatter(X[:50, 0], X[:50, 1], color='red', marker='o', label='setosa')
plt.scatter(X[50:100, 0], X[50:100, 1], color='blue', marker='x', label='versicolor')

plt.xlabel('sepal length [cm]')
plt.ylabel('petal length [cm]')
plt.legend(loc='upper left')

plt.tight_layout()
#plt.savefig('./images/02_06.png', dpi=300)
plt.show()


퍼셉트론 모델 트레이닝을 해보자.
우리는 각 단계에서 두 개의 클래스를 잘 구분했는지 확인하기 위해 잘못 예측한 것에 대해 표시할 것이다.

ppn = Perceptron(eta=0.1, n_iter=10)

ppn.fit(X, y)

plt.plot(range(1, len(ppn.errors_) + 1), ppn.errors_, marker='o')
plt.xlabel('Epochs')
plt.ylabel('Number of updates')

plt.tight_layout()
# plt.savefig('./perceptron_1.png', dpi=300)
plt.show()


위 그래프를 보면 퍼셉트론이 6번째 단계에서 이미 수렴한 것을 알 수 있다. 그리고 이제는 트레이닝 샘플을 완벽하게 분류할 수 있어야한다.
꽃잎 길이와 꽃받침 길이에 대해 구분되는 그래프를 그려보자.

from matplotlib.colors import ListedColormap


def plot_decision_regions(X, y, classifier, resolution=0.02):

    # setup marker generator and color map
    markers = ('s', 'x', 'o', '^', 'v')
    colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan')
    cmap = ListedColormap(colors[:len(np.unique(y))])

    # plot the decision surface
    x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1
    x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1
    xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution), np.arange(x2_min, x2_max, resolution))
    Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)
    Z = Z.reshape(xx1.shape)
    plt.contourf(xx1, xx2, Z, alpha=0.4, cmap=cmap)
    plt.xlim(xx1.min(), xx1.max())
    plt.ylim(xx2.min(), xx2.max())

    # plot class samples
    for idx, cl in enumerate(np.unique(y)):
        plt.scatter(x=X[y == cl, 0], y=X[y == cl, 1], alpha=0.8, c=cmap(idx), marker=markers[idx], label=cl)

plot_decision_regions(X, y, classifier=ppn)
plt.xlabel('sepal length [cm]')
plt.ylabel('petal length [cm]')
plt.legend(loc='upper left')

plt.tight_layout()
# plt.savefig('./perceptron_2.png', dpi=300)
plt.show()


두 피쳐(꽃잎 길이, 꽃받침 길이)의 최소값과 최대값을 결정하고 NumPy meshgrid 함수를 통해 배열 xx1과 xx2 쌍을 만들기 위해 피쳐 벡터를 사용한다.
그리고 두 피쳐에 대해 분류한 결과 값을 그래프로 나타내면 위의 그래프 처럼 그려진다.

'Study > ML 실습 - Python 기초' 카테고리의 다른 글

파이썬 머신러닝 (3)  (0) 2017.01.25
파이썬 머신러닝 (1)  (0) 2017.01.25
Comments