*본 포스팅은 머신러닝 교과서를 참고하여 작성되었습니다~!
2.2 파이썬으로 퍼셉트론 학습 알고리즘 구현
2.2.1 객체 지향 퍼셉트론 API
import numpy as np
class Perceptron(object):
"""퍼셉트론 분류기
매개변수
---------------
eta : float
학습률 (0.0과 1.0 사이)
n_iter : int
훈련 데이터셋 반복 횟수
random_state : int
가중치 무작위 초기화를 위한 난수 생성기 시드
속성
---------------
w_ : 1d-array
학습된 가중치
errors_ : list
에포크마다 누적된 분류 오류
"""
def __init__(self, eta=0.01, n_iter=50, random_state = 1):
self.eta = eta
self.n_iter = n_iter
self.random_state = random_state
def fit(self, X, y):
"""훈련 데이터 학습
매개변수
------------------
X : {array-like}, shape = [n_samples, n_features]
n_samples개의 샘플과 n_features 개의 특성으로 이루어진 훈련 데이터
y : array-like, shape = [n_samples]
타깃 값
반환값
-------------------
self : object
"""
rgen = np.random.RandomState(self.random_state)
self.w_ = rgen.normal(loc=0.0, scale = 0.01,
size = 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):
"""입력 계산"""
return np.dot(X, self.w_[1:]) + self.w_[0]
def predict(self, X):
"""단위 계산 함수를 사용하여 클래스 레이블을 반환합니다"""
return np.where(self.net_input(X) >= 0.0, 1, -1)
- fit 메서드에서 self.w_ 가중치를 벡터로 초기화한다. 여기서 m은 데이터셋에 있는 차원(특성) 개수이다. 벡터의 첫 번째 원소인 절편을 위해 1을 더했다. 즉, 이벡터의 첫 번째 원소 self.w_[0] 는 앞서 언급한 절편이다.
이 벡터는 rgen.normal(loc=0.0, scale=0.01, size=1 + X.shape[1]) 을 사용하여 표준 편차가 0.01인 정규 분포에서 뽑은 랜덤한 작은 수를 담고 있다. 여기서 regen 은 넘파이 난수 생성기로 사용자가 지정한 랜덤 시드로 이전과 동일한 결과를 재현할 수 있다.
가중치를 0으로 초기화하지 않는 이유는 가중치가 0이 아니어야 학습률이 분류 결과에 영향을 주기 때문이다.
fit 메서드는 가중치를 초기화한 후 훈련 데이터셋에 있는 모든 개개의 샘플을 반복 순회하면서 이전 절에서 설명한 퍼셉트론 학습 규칙에 따라 가중치를 업데이트 한다.
클래스 레이블은 predict 메서드에서 예측한다. fit 메서드에서는 훈련하는 동안 가중치를 업데이트하기 위해 predict 메서드를 호출하여 클래스 레이블에 대한 예측을 얻는다. predict 메서드는 모델이 학습되고 난 후 새로운 데이터 클래스 레이블을 예측하는 데도 사용할 수 있다. 에포크마다 self.errors_ 리스트에 잘못 분류된 횟수를 기록한다. 나중에 훈련하는 동안 얼마나 퍼셉트론을 잘 수행했는지 분석할 수 있다.
net_input 메서드에서 사용한 np.dot 함수는 벡터 점곱을 계산한다.
2.2.2 붓꽃 데이터셋에서 퍼셉트론 훈련
퍼셉트론 규칙이 2차원에 국한된 것은 아니지만 학습 목적으로 산점도에 훈련 모델의 결정 경계를 그리기 위해 꽃받침 길이와 꽃잎 길이만 사용한다.
import os
import pandas as pd
s = 'https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data'
print('URL:', s)
df = pd.read_csv(s, header=None, encoding='utf-8')
df.tail()
50개의 Iris-setosa 와 50개의 Iris-versicolor 꽃에 해당하는 처음 100개의 클래스 레이블을 추출한다. 클래스 레이블을 두 개의 정수 클래스 1(versicolor)과 -1(setosa)로 바꾼 후 벡터 y에 저장한다. 판타스 DataFrame의 values 속성은 넘파이 배열을 반환한다.
import matplotlib.pyplot as plt
import numpy as np
# setosa와 versicolor를 선택한다
y = df.iloc[0:100, 4].values
y = np.where(y == 'Iris-setosa', -1, 1)
# 꽃받침 길이와 꽃잎 길이를 추출한다
X = df.iloc[0:100, [0, 2]].values
# 산점도를 그린다.
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.show()
- 이 산점도는 붓꽃 데이터셋에 있는 샘플들이 꽃받침 길이와 꽃임 길이 두 개의 특성 축을 따라 분포된 형태를 보여 준다. 이런 2차원 부분 공간에서는 선형 결정 경계로 setosa와 Versicolor 꽃을 구분하기 충분하다.
따라서 퍼셉트론 같은 선형 분류기가 이 데이터셋의 꽃을 완벽하게 분류할 것이다.
이제 붓꽃 데이터셋에서 추출한 일부 데이터에서 퍼셉트론 알고리즘을 구현해보자.
# 퍼셉트론 모델 훈련하기
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.savefig('images/02_07.png', dpi=300)
plt.show()
위 그림에서 볼 수 있듯이 퍼셉트론은 여섯 번째 에포크 이후에 수렴했고 훈련 샘플을 완벽하게 분류했다. 간단한 함수를 만들어 2차원 데이터셋의 결정 경계를 시각화해 보자
from matplotlib.colors import ListedColormap
def plot_decision_regions(X, y, classifier, resolution=0.02):
# 마커와 컬러맵을 설정합니다
markers = ('s', 'x', 'o', '^', 'v')
colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan')
cmap = ListedColormap(colors[:len(np.unique(y))])
# 결정 경계를 그립니다
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.3, cmap=cmap)
plt.xlim(xx1.min(), xx1.max())
plt.ylim(xx2.min(), xx2.max())
# 샘플의 산점도를 그립니다
for idx, cl in enumerate(np.unique(y)):
plt.scatter(x=X[y == cl, 0],
y=X[y == cl, 1],
alpha=0.8,
c=colors[idx],
marker=markers[idx],
label=cl,
edgecolor=None if idx==1 else 'black')
plot_decision_regions(X, y, classifier=ppn)
plt.xlabel('sepal length [cm]')
plt.ylabel('petal length [cm]')
plt.legend(loc='upper left')
# plt.savefig('images/02_08.png', dpi=300)
plt.show()
퍼셉트론이 핛브한 결정 경계는 두 개의 붓꽃으로 구성된 데이터셋의 모든 샘플을 완벽하게 분류한다.
아...너무 어렵다..퍼셉트론 알고리즘을 구현하는 수식이나.. 구현도.. 설명도.. 밑바닥부터 시작하는 딥러닝에 비해 어렵다 ㅜㅜㅜ아... 런하고 싶어진다..
'소소하지만 소소하지 않은 개발 공부 > 머신 러닝 교과서' 카테고리의 다른 글
Chapter3.7 k-최근접 이웃: 게으른 학습 알고리즘, 머신러닝교과서, python (1) | 2022.11.29 |
---|---|
Chapter 3.6 결정 트리 학습, 머신러닝교과서, pyhon (0) | 2022.11.29 |
Chapter 3.4 서포트 벡터 머신을 사용한 최대 마진 분류, 머신러닝교과서, python (0) | 2022.11.25 |
Chapter3.3 로지스틱 회귀 모델을 사용한 클래스 확률 모델링, 머신러닝 교과서, python (0) | 2022.11.23 |
Chapter3 머신러닝 교과서, python (0) | 2022.11.22 |