- 주요 단어
- 지도 학습(Supervised Learning)
- 레이블된 데이터(정답이 확실한 데이터)
- 직접 피드백
- 출력 �� 미래 예측
- 비지도 학습(Unsupervise Learning)
- 레이블 및 타깃 없음
- 피드백 없음
- 데이터에서 숨겨진 구조 찾기
- 강화 학습(Reinforcement Learnig)
- 결정 과정
- 보상 시스템
- 여속된 행동에서 학습
- 지도 학습(Supervised Learning)
- 희망하는 출력 레이블(신호)가 있는 일련의 샘필 즉, 예측 성공한 학습 형태
위 그림에서 새로운 데이터는 레이블 즉 정답이 없는 데이터를 예측 모델에 입력하여 예측하고 원하는 값이 나올경우 레이블이라고 볼 수 있다.
- 분류(개별 클래스 레이블이 있는 지도 학습)
- 이진 분류 = 결정경계로 음성 클래스와 양성 클래스로 구분 가능한 데이터 값들의 분류 방법
- 다중 분류 = 순서가 없는 범주나 클래스 레이블로 표현되는 데이터 값들의 분류 방법
- 이진 분류 = 결정경계로 음성 클래스와 양성 클래스로 구분 가능한 데이터 값들의 분류 방법
- 회귀(연속적인 값을 출력하는 방법)
- 회귀 예측
- 연속적인 출력 값을 예측하는 분석 방법
- 예측변수(특성)와 연속적인 반응 변수(타깃) 사이의 출력값을 예측하는 방법
- 회귀 예측
- 선형 회귀
- 특성 x와 타깃 y가 주어진 경우 데이터 포인트와 직선 사이의 최소 거리의 직선을 이용하여 새로운 데이터 출력 값을 예측하는 방법
(출처: https://www.secmem.org/blog/2020/02/08/snake-dqn/)
위 그림에서 환경은 소프트웨어의 시뮬레이션, 에이전트는 모델의 관계를 나타낸 것이다.
=> 행동을 수행하고 즉시 얻거나 지연된 피드백을 통하여 얻은 전체 보상을 최대화 하는 학습 행동이다.
- 레이블되지 않거나 구조를 알 수 없는 데이터를 다루는 학습 방법
- 군집(사전 정보 없이 쌓여 있는 그룹 정보를 의미 있는 서브그룸 또는 클러스터로 조직하는 탐색적 데이터 분석 기법)
- 각 클러스터는 서로 유사성을 공유하고 다른 클러스터와 비슷하지 않은 샘플 그룹을 형성한다.
- 비지도 분류라고 불리기도 한다.
- 클러스터링 = 정보를 조직화하고 데이터에서 의미 있는 관계를 유도하는 도구
- 차원 축소: 데이터 압축
- 쉽게 말하면 많은 특성 => 적은 특성으로 압축하는 방법
- 잡음 데이터를 제거하기 위해 특성 전처리 단계에서 종종 적용하는 방법
용어 정리
- 훈련 샘플: 데이터셋을 나타내는 테이블의 행
- 훈련: 특성과 샘플들을 알고리즘에 돌리는 행위
- 특성(x): 데이터 테이블이나 데이터 행렬의 열
- 타깃(y): 특성에 따른 출력, 레이블
- 손실 함수: 전체 데이터셋에 대해 계산한 손실 즉, 정확도를 나타내는 척도이다.
- 머신 러닝의 작업 흐름도
- 전처리: 데이터 형태 갖추기
- 머신 러닝 알고리즘에서 최적의 성능을 내리기 위해서는 선택된 특성이 같은 스케일을 가져야한다.
- 만일 선택된 특성이 상관관계가 심할 경우 차원 축소 기법을 사용하여 압축한다, 이는 저장 공간이 덜 필요하고 학습 알고리즘을 더 빨리 실행 시킬 수 있다.
- 신호 대 잡음비가 높은 경우 차원 축소 기법을 통해 예측 성능을 높이기도 한다.
- 인공 뉴런
- 두 클래스가 있는 이진 분류 작업
- 1(양성 클래스)
- -1(음성 클래스)
- 입력 값 x와 가중치 벡터 w의 선형 조합으로 결정 함수 ?(z)를 정의한다.
- 따라서 z = 가중치 벡터 w 와 입력 값 x의 곱을 처음부터 m까지의 합으로 나타난다.
- 임계 값(θ)를 지정하고 결정 함수 ?(z)가 임계 값보다 크거나 같을 경우 양성 클래스로 작을 경우 음성 클래스로 지정한다.
- 퍼셉트론 알고리즘에서 결정 함수 ?(z)는 단위 계단 함수를 변형한 것이다.
- 위 식을 간단하게 만들기 위해서 가중치 벡터의 첫번째를 -θ, 첫번째 입력 값을 0으로 정의하고 가중치 벡터를 행 벡터로 변환하여 계산하면 결국 결정 함수가 0보다 크거나 같을경우 양성 클래스 작을 경우 음성 클래스로 정의됩니다.
- 두 클래스가 있는 이진 분류 작업
- 퍼셉트로 알고리즘
import numpy as np
# numpy: C언어로 구현된 파이썬 라이브러리로 벡터 및 행렬 연산시 유용하게 사용된다.
class Perceptron(object):
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: 클래스 내부 함수인 메서드 정의
# self: 객체의 인스턴스 그자체, 자기 자신을 참조하는 매개변수
def fit(self, X, y):
# 훈련 데이터 학습 매서드
rgen = np.randem.RandomState(self.random_state)
# 난수발생기로 난수를 random-state로 초기화 시킨다
self.w_ + rgen.normal(loc=0.0, scale=0.01,
size=1 + X.shape[1])
#X.shape[1]: 절편의 값이 있기 때문에 크기를 1만큼 증가한다
self.errors_ = [ ]
# errors 리스트 생성
for _ in range(self.n_iter):
errors = 0
for xi, target in zip(X, y):
# zip 함수: x와y의 값을 하나씩 xi, target에 저장한다
update = self.eta * (target - self.predict(xi))
# self.predict(xi): 예측 가중치 설정
self.w_[1:] += update * xi
# 가중치 1부터는 변화
self.w_[0] += update
# x의 첫번째 입력값은 1
errors += int(update != 0.0)
# 업데이트 값이 0.0이 아닐 경우 즉 타깃 정확도가 떨어질 경우
self.errors_.append(errors)
# append 함수를 이용하여 리스트에 요소를 추가한다
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)
v1 = np.array([1, 2, 3])
v2 = 0.5 * v1
np.arccos(v1.dot(v2) / (np.linalg.norm(v1) * np.linalg.norm(v2)))
# np.arccos: 역코사인 삼각 함수
# np.linalg.norm: 벡터 길이를 계산하는 함수
퍼셉트론 알고리즘을 입력한 후 위 알고리즘을 실행하면 업데이트 값이 0이 출력되는 것을 볼 수 있다, 이는 즉 정확하다는 의미입니다.
import os
import pandas as pd
#pandas: 데이터분석을 위한 파이썬 라이브러리
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')
#pd.read_csv: 경로를 병합하여 새 경로를 생성한다
df.tail()
#tail(n): 많은 데이터를 밑에서부터 n개 만큼 잘라서 출력한다, 만약 ()의 입력이 없을 경우 5로 자동 입력된다.
위 코드의 출력 결과는 다음과 같다.
- 위 그림에서 0,1,2,3은 특성을 나타낸다.
- 위 그림에서 4는 타깃값을 나타낸다.
import matplotlib.pyplot as plt
# 차트나 플롯을 그리기 위한 라이브러리 패키지
import numpy as np
y = df.iloc[0:100, 4].values
#df.iloc[n:m, x]: 리스트의 n행과 m열 중에서 x개의 데이터를 추룰하는 함수
y = np.where(y == 'Iris-setosa', -1, 1)
#np.where: numpy 라이브러리의 함수로 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.scatter: setosa와 versicolor을 구분하여 범위를 지정한다.
plt.xlabel('sepal length [cm]')
plt.ylabel('petal length [cm]')
plt.legend(loc='upper left')
# plt.savefig('images/02_06.png', dpi=300)
plt.show()
위 코드의 출력 결과는 다음과 같다.
- 붓꽃 데이터셋 150개 중 100개를 추출한 데이터셋의 산점도를 그린것이다, 위 그림을 보면 선형 결정 경계로 두 데이터셋을 나눌수 있다는 것을 볼 수 있다.
ppn = Perceptron(eta=0.1, n_iter=10)
# Perceptron 알고리즘 동기화 객체 생성, 반복횟수: 10회
ppn.fit(X, y)
plt.plot(range(1, len(ppn.errors_) + 1), ppn.errors_, marker='o')
# 그래프 그리는 matplotlib.pyplot 함수
# ppn.errors: 매 반복 횟수 마다 오류난 획수
# range: ppn.errors_: 10회 반복했으므로 10, range의 범위 끝 부분은 -1 이기때문에 +1을 해준다.
plt.xlabel('Epochs')
plt.ylabel('Number of updates')
plt.show()
- Perceptron 알고리즘을 이용하여 10회 반복을 통해 결과값을 비교해본 결과 6해부터 0으로 값이 일정하다는 것을 볼 수 있다.
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))])
# cmap: color map에서 색상을 선태갛여 len(np.nuiaue(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))
#np.meshgrid: 정해준 범위 내의 모든 x, y값을 반환해주는 함수
Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)
# ravel(): 다차원 배열을 1차원 배열로 나열해주는 함수
#predict(): 데이터를 1, 0으로 분류해주는 함수
Z = Z.reshape(xx1.shape)
plt.contourf(xx1, xx2, Z, alpha=0.3, cmap=cmap)
#plt.contourf: 값에 따른 등고선을 그리는 함수
plt.xlim(xx1.min(), xx1.max())
plt.ylim(xx2.min(), xx2.max())
# 샘플의 산점도를 그립니다
for idx, cl in enumerate(np.unique(y)):
# enumerate: 반복문의 반복 횟수를 알려주는 함수
# np.unique(): 다차원 배열을 1차원 배열로 나열하기 위한 함수
plt.scatter(x=X[y == cl, 0],
y=X[y == cl, 1],
alpha=0.8,
c=colors[idx],
marker=markers[idx],
label=cl,
edgecolor='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()
- 위 알고리즘에서 선형 분산도의 데이터 샘플들이 확실히 나눠지는 결정 경계를 그립니다.
-
아달린(Adaline) vs 퍼셉트론 알고리즘
- 페섭트론 알고리즘은 진짜 클래스 레이블과 예측 클래스 레이블을 비교하여 오차가 생길 경우 가중치 값을 업데이트 합니다.
- 아달린의 경우 진짜 클래스 레이블과 선형 활성화 함수의 실수 출력 값을 비교하여 모델의 오차를 계산하고 가중치를 업데이트 합니다.
-
경사 하강법
- 함수의 기울기를 구하여 기울기가 낮은 쪽으로 계속 이동시켜 최정값에 이를 ��까지 반복하는 방법
-
아달린 알고리즘
class AdalineGD(object):
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
"""
eta: 학습률
n_iter: 훈련 데이터셋 반복 횟수
random_satate: 가중치 무작위 초기화를 위한 난수 생성기
"""
def fit(self, X, y):
rgen = np.random.RandomState(self.random_state)
self.w_ = rgen.normal(loc=0.0, scale=0.01, size=1 + X.shape[1])
self.cost_ = []
# self: fit 클래스에 정의된 인스턴스
for i in range(self.n_iter):
net_input = self.net_input(X)
output = self.activation(net_input)
errors = (y - output)
self.w_[1:] += self.eta * X.T.dot(errors)
self.w_[0] += self.eta * errors.sum()
cost = (errors**2).sum() / 2.0
self.cost_.append(cost)
return self
def net_input(self, X):
return np.dot(X, self.w_[1:]) + self.w_[0]
def activation(self, X):
return X
def predict(self, X):
return np.where(self.activation(self.net_input(X)) >= 0.0, 1, -1)
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(10, 4))
ada1 = AdalineGD(n_iter=10, eta=0.01).fit(X, y)
ax[0].plot(range(1, len(ada1.cost_) + 1), np.log10(ada1.cost_), marker='o')
ax[0].set_xlabel('Epochs')
ax[0].set_ylabel('log(Sum-squared-error)')
ax[0].set_title('Adaline - Learning rate 0.01')
ada2 = AdalineGD(n_iter=10, eta=0.0001).fit(X, y)
ax[1].plot(range(1, len(ada2.cost_) + 1), ada2.cost_, marker='o')
ax[1].set_xlabel('Epochs')
ax[1].set_ylabel('Sum-squared-error')
ax[1].set_title('Adaline - Learning rate 0.0001')
plt.show()