분류문제(레이블이 0과 1)에 대한 알고리즘으로 판별모델에 해당함
뒤에 배울 서포트 벡터 머신 의 특별한 경우이며, 신경망(neural network), 심층망(deep learning)의 시초
특성벡터 $X=(x_1,…,x_2)^t$에 대해 판별함수를
로 정의하고, 성능이 좋아지도록 $w_0,w_1,…,w_n$을 결정하는 과정이 학습 알고리즘
$w_0$를 편향, $w_i$를 가중치라 함.
정확도=1-(오분류된 훈련 샘플의 개수/m)
: 모델 파라미터의 초깃값 $w^(0)$을 임의로 설정한 후, 오분류된 각각의 샘플 $(x_i,y_i)$에 대해 $w^(k)$를 반복하여 업데이트 (레이블 $y_i$는 0 또는 1)
$ w^{(k+1)} = w^{(k)}+(y_i-\hat y_i) x_i \text{ 또는 } w^{(k+1)} = w^{(k)}+\alpha (y_i-\hat y_i) x_i $
(단, 학습률 0< $\alpha$ < 1는 하이퍼 파라미터)
선형분리가능: 레이블이 1인 특성벡터(n차원 벡터)들과 레이블이 0인 특성벡터들이 초평면의 서로 다른 영역에 각각 위치하도록 초평면을 잡을 수 있음을 의미
(단층 퍼셉트론에서는 한 직선으로 두 영역을 나눌 수 있는 ‘선형분리가능’ 해야만 한다. »다중 퍼셉트론으로 해결)
자세하고 좋은 설명은 Live Your IT 를 참고하면서 공부했다.
import numpy as np #numpy
class Perceptron(): #class 정의
def __init__ (self,thresholds=0.0, eta=0.01,n_iter=10): #생성자 정의 및 default값 설정
self.thresholds=thresholds
self.eta=eta
self.n_iter=n_iter
def fit(self, X ,y):
self.w_ = np.zeros(1+X.shape[1]) #0으로 이루어진 +1 된 리스트
self.errors_=[] # 오류 회수를 저장하는 변수
for _ in range(self.n_iter): #반복
errors=0
for xi.target in zip(X,y): #zip은 두 리스트를 행렬로 붙여줌
update=self.eta*(target-self.predict(xi)) #xi는 트레이닝 데이터의 모든 입력값 ,x0=1 로 정해져 있다.
self.w_[1:] +=update*xi
self.w_[0] +=update
errors += int(update!=0.0)
self.errors_.append(errors)
print(self.w_)
return self
def net_input(self, X):
return np.dot(X, self.w_[1:])+self.w_[0] #가중치와 X값을 곱한 총합
def predict(self, X):
return np.where(self.net_input(X) > self.thresholds, 1, -1) #임계값보다 크면 1 작으면 -1
import numpy as np
import pandas as pd
from sklearn.linear_model import Perceptron #퍼셉트론 분류기 API 생성
from sklearn.model_selection import train_test_split # 훈련 데이터셋과 테스트 데이터셋 나누기
data =pd.read_csv('./datasets/data.csv') #데이터 불러오기
data.columns # 데이터 열이름 확인하기
data.subset =data.loc[:,['col1','col2','result']] #내가 관심있는 특성을 뽑아냈다
data.head(n=5) #가장 상위 5개 행 데이터 추출; EDA의 일종,
data.tail() # 하위 5개 데이터 행
X=data_subset.loc[:,['col1','col2']] #특성벡터와 레이블의 구분
y=data_subset.loc[:,['result']]
X_train, X_test, y_train, y_test = train_test_split(X,y, random_state=20)
#훈련 데이터셋과 테스트 데이터셋 구성; random_state=정수 난수 순서의 시드, 값을 정해주면 일정한 순서로 데이터셋을 구성한다.
len(X_train)/len(X)
#아무 설정 안했으면 이 값은 0.75 가 나올 것 기본적으로 훈련셋 75%, 테스트 셋 25%으로 나눈다.
#이 값도 변경이 가능하다. test_size=0.2 를 추가하면 테스트 사이즈 20%로 하겠다는 뜻이다.
train_test_split 에 관한 참고 테디 노트님 자료:) 자세하고 좋은 설명 감사합니다.
classifierP=Perceptron()
classifierP.fit(X_train,y_train) #추정기 객체 생성 및 추정
y_test_hat=classifierP.predict(X_test) #predict() 메소드를 이용한 예측
예측 메소드를 이용해서 나온 결과는 numpy의 ndarray 타입을 띄고, 우리가 나누어줬던 y_test는 pandas의 Series 타입을 띈다.
참고
ndarry는 숫자 인덱싱만 가능, Series는 문자를 이용한 인덱싱도 가능하다.
ndarry는 null에 관한 표현이 어려운 반면, Series는 null값을 NaN이라는 문자로 표시해줌
인덱스없이 일부 작업을 수행하는 경우는 배열로 접는 하는 것이 유용: Series.to_numpy()
ndarry는 array([1,2,3,4]) 꼴
Series는 인덱스와 인덱스의 값이 세로로(인덱스열 값열) 표시됨
y_test_org = y_test.to_numpy() #시리즈로 나온 test결과값을 array 객체로 변경
correct_prediction = (y_test_hat == y_test) #bool 값을 예측에 저장
correct_prediction[:10]
correct_prediction.mean() #True는 1로, False는 0으로 이해하기 떄문에 평균을 내어도 정확도를 구할 수 있다.
classifierP.score(X_test,y_test) #score로 테스트 결과 성능 평가를 할 수 있다.
classifierP.score(X_train,y_train) #훈련셋의 성능 평가
테스트의 성능평가 결과가 좋지 않다면 훈련셋 자체의 성능을 의심해볼 필요가 있다.
import matplotlib.pyplot as plt #산점도를 그려보기 위한 plt
%matplotlib inline # 주피터 노트북 내 그래프를 그리게 하는 명령어
plt.scatter(data_subset['col1'], data_subset['col2'],c=data_subset['result'], alpha=0.4)
# 순서대로 특성을 x,y로 넣고 c는 점의 색을 넣어 데이터셋 자체가 선형분리가능인지 확인하는 그래프,
# alpha는 점의 투명도 1로 갈수록 불투명
Reference: