콘텐츠로 이동

Chapter 3. 회귀(Regression)

1절. 회귀

2절. 경사 하강법

3절. 과잉 적합과 과소 적합

4절. 회귀 구현

1절. 회귀

회귀와 분류

RC

선형 회귀

  • 데이터들을 2차원 공간에 찍은 후 데이터들을 가장 잘 설명하는 직선 OR 곡선을 찾는 문제
  • 입력 데이터를 가장 잘 설명하는 기울기와 절편값을 찾는 문제
  • \(y = f(x)\)에서 출력 \(y\)와 입력 \(x\)가 실수일 때, 함수 \(f(x)\) 예측

RCT

  • 직선의 방정식 : \(f(x) = mx + b\)
  • 선형 회귀 기본식 : \(f(x) = Wx + b\)
  • 기울기 -> 가중치
  • 절편 -> 바이어스

선형 회귀 예시

  • 부모의 키와 자녀 키의 관계 조사
  • 면적에 따른 주택 가격
  • 연령에 따른 실업율 예측
  • 공부 시간과 학점과의 관계
  • CPU 속도와 프로그램 실행 시간 예측

선형 회귀 종류

  • 단순 선형 회귀
  • 독립 변수(\(x\))가 하나인 경우
  • \(f(x) = wx + b\)
  • 다중 선형 회귀
  • 독립 변수가 여러 개인 경우

MLP

선형 회귀 원리

import numpy as np
from sklearn.linear_model import LinearRegression

X = 10 * np.random.randn(100, 1)
y = 3 + X + np.random.randn(100, 1)

plt.plot(X, y, 'o')
plt.show()

RES

  • 최선의 것은 데이터 간의 오차가 작은 경우

RES2

손실 함수(Loss Function)

  • 손실 함수 또는 비용 함수(Cost Function)
  • 직선과 데이터 사이의 간격을 제곱하여 합한 값

LF

  • 선형 회귀 선과의 차이가 큰 경우 손실이 큼
  • 선형 회귀 선과의 차이가 작은 경우 손실이 작음

LF2

선형 회귀에서 손실 함수 최소화 방법

  • 분석적인 방법
  • 독립 변수와 종속 변수가 각각 하나인 선형 회귀

MinLR

2절. 경사 하강법

경사 하강법(Gradient descent method)

  • Cost 함수 그래프를 그리면 아래와 같은 2차 포물선 생성
  • 손실 함수가 어떤 형태이더라도, 매개 변수가 아무리 많아도 적용 가능한 일반적인 방법
  • 점진적인 학습 가능

GDM

import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf

def forward(wa, x):
   return wa * x

X = np.array([1., 2., 3.])
Y = np.array([1., 2., 3.])

W_val = []
cost_val = []
m = n_samples = len(X)

for i in range(-30, 50):
   W_val.append(i )
   print(forward(i ,X))
   cost_val.append(tf.reduce_sum(tf.pow(forward(i ,X)-Y, 2))/(m))

plt.plot(W_val, cost_val, 'ro')
plt.ylabel('Cost')
plt.xlabel('W')
plt.show()

GDM2

학습률

LP

지역 최솟값 문제

LM

선형 회귀에서의 경사 하강법

LRGDM

경사 하강법 코드 구현

import numpy as np
import matplotlib.pyplot as plt

X = np.array([0.0, 1.0, 2.0])
y = np.array([3.0, 3.5, 5.5])

W = 0 # 기울기
b = 0 # 절편

lrate = 0.01 # 학습률
epochs = 1000 # 반복 횟수

n = float(len(X))                      # 입력 데이터의 개수

# 경사 하강법
for i in range(epochs):
   y_pred = W*X + b                    # 예측값
   dW = (2/n) * sum(X * (y_pred-y))
   db = (2/n) * sum(y_pred-y)
   W = W - lrate * dW                  # 기울기 수정
   b = b - lrate * db                  # 절편 수정

# 기울기와 절편을 출력
print (W, b)

# 예측값
y_pred = W*X + b

# 입력 데이터를 그래프에 plot
plt.scatter(X, y)

# 예측값은 선그래프
plt.plot([min(X), max(X)], [min(y_pred), max(y_pred)], color='red')
plt.show()

# 1.2532418085611319 2.745502230882486 (기울기 절편 순서)

선형 회귀 예제

  • 아나콘다에 포함된 Scikit-Learn 라이브러리를 사용하여 회귀 함수를 구현하는 방법
모델 생성 및 학습
import matplotlib.pylab as plt
from sklearn import linear_model

# 선형 회귀 모델을 생성
reg = linear_model.LinearRegression()

# 데이터는 파이썬의 리스트와 넘파이의 배열 모두 가능
X = [[0], [1], [2]]          # 2차원으로 만들어야 함
y = [3, 3.5, 5.5]            # y = x + 3

# 학습
reg.fit(X, y)
학습 데이터 생성
  • 학습 데이터는 반드시 2차원 배열
  • 한 열만 있더라도 반드시 2차원 배열 형태
  • 리스트의 리스트를 생성하여 2차원 배열 생성
값 확인
# 직선의 기울기
reg.coef_
# array([1.25])

# 직선의 y-절편
reg.intercept_
# 2.7500000000000004

reg.score(X, y)
# 0.8928571428571429

reg.predict([[5]])
# array([8.])
그래프 생성
# 학습 데이터와 y 값을 산포도화
plt.scatter(X, y, color='black')

# 예측값을 계산
y_pred = reg.predict(X)

# 학습 데이터와 예측값을 선그래프로
# 계산된 기울기와 y 절편을 가지는 직선
plt.plot(X, y_pred, color='blue', linewidth=3)
plt.show()
실행 결과

RES

선형 회귀 실습

  • 인간의 키와 몸무게는 어느 정도 비례할 것으로 예상
  • 아래의 데이터가 있을 경우 선형 회귀를 이용하여 학습시켜 키가 165cm일 때의 예측값 계산

RES3

정답 코드
import matplotlib.pylab as plt
from sklearn import linear_model

reg = linear_model.LinearRegression()

X = [[174], [152], [138], [128], [186]]
y = [71, 55, 46, 38, 88]

# 학습
reg.fit(X, y)

print(reg.predict([[165]]))

# 학습 데이터와 y값 산포도화
plt.scatter(X, y, color='black')

# 학습 데이터를 입력으로 하여 예측값을 계산
y_pred = reg.predict(X)

# 학습 데이터와 예측값으로 선그래프로
# 계산된 기울기와 y 절편을 가지는 직선
plt.plot(X, y_pred, color='blue', linewidth=3)
plt.show()

RES4

선형 회귀 예제 - 당뇨병

  • sklearn 라이브러리에 기본적으로 포함된 당뇨병 환자들의 데이터 사용
import matplotlib.pylab as plt
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn import datasets

# 당뇨병 데이터 세트
diabetes_X, diabetes_y = datasets.load_diabetes(return_X_y=True)

# 하나의 특징(BMI)으로 2차원 배열화
# BMI 특징의 인덱스가 2
diabetes_X_new = diabetes_X[:, np.newaxis, 2]

# 학습 데이터와 테스트 데이터를 분리
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(diabetes_X_new, diabetes_y, test_size = 0.1, random_state = 0)
regr = linear_model.LinearRegression()
regr.fit(X_train, y_train)

# 테스트 데이터로 예측
y_pred = model.predict(X_test)

# 실제 데이터와 예측 데이터를 비교
plt.plot(y_test, y_pred, '.')
plt.xlim([-0.13,0.15])
plt.scatter(X_test, y_test,  color ='black')
plt.plot(X_test, y_pred, color ='blue', linewidth = 3)

RES6

3절. 과잉 적합과 과소 적합

과잉 적합(overfitting)

  • 학습하는 데이터는 성능이 뛰어나지만 새로운 데이터(일반화)에 대해서는 성능이 잘 나오지 않는 모델을 생성하는 것

과소 적합(underfitting)

  • 학습 데이터에서도 성능이 좋지 않은 경우
  • 이 경우에는 모델 자체가 적합 지 않은 경우 존재
  • 더 나은 모델 탐색 필요

과잉 적합과 과소 적합 비교

OU

  • 1차 : 과소 적합
  • 모델의 용량이 작아 오차가 클 수밖에 없는 현상
  • 2차, 3차, 4차의 순서가 지날 수록 오차가 감소하는 모습

  • 12차 : 과잉 적합

  • 다항식 곡선을 채택한다면 훈련집합에 대해 거의 완벽하게 근사화
  • '새로운' 데이터를 예측한다면 큰 문제가 발생
    • \(x_0\)에서 빨간 막대 근방을 예측해야 하지만 빨간 점을 예측하는 상황이 발생할 수 있음
  • 용량이 크기 때문에 학습 과정에서 잡음까지 수용(과잉 적합 현상)
  • 적절한 용량의 모델을 선택하는 모델 선택 작업 필요

set12

  • 그래프에서 보는 과잉 적합과 과소 적합의 비교

COU

4절. 로지스틱 회귀

선형 회귀 vs 로지스틱 회귀(Logistic Regression)

  • 선형 회귀

  • MSE(Mean Squared Error)라는 Loss 함수 사용

    • 직선과 데이터의 차이를 제곱한 값의 평균
    • 즉, 분산을 최소화 시키는 방향으로 학습
  • 로지스틱 회귀

  • 분류 모델은 이진 분류 모델
  • 클래스가 2개 있을 경우에만 사용 가능
  • 선형 회귀 다음으로 간단한 분류, 회귀 알고리즘
  • 데이트 샘플에 맞는 최적의 로지스틱 함수 계산
    • 이를 통해(데이터 특성으로) 예측 값 추출
  • 선형 회귀 모델 => 연속성
    • 선형 회귀의 출력값 분류 방법
    • 전체의 절반을 넘었으면 반올림 후 출력을 1로 설정
    • 전체의 절반을 넘기지 못했으면 출력을 0으로 설정

Logistic

  • 직선의 중간쯤을 넘어가면 불합격
  • 직선의 중간쯤을 넘어가면 합격

Logistic2

  • 데이터(\(y\))와 직선(\(^y\))간의 평균을 최소화하기 위한 직선의 기울기 움직임

Logistic3

  • 기울기 \(y = wx + b\) 에서 \(w\)의 변화에 따른 0.5 의 기준 변화
  • 함숫값이 0.5를 지나는 구간의 변경
    • 이에 다른 데이터들의 정답 여부 변경
  • 원래 정답이었으나 기준 선이 오른쪽으로 움직여서 오답

선형 회귀와 로지스틱 회귀의 비교

LL

시그모이드 함수(Sigmoid)

Sig

  • Logistic Regression에서는 Linear Regression의 결과값을 인풋값으로 사용
  • 시그모이드 함수는 곧 베이즈 정리
  • 기존에 사용했던 선형회귀 모델의 출력을 그대로 시그모이드 함수의 입력으로 넣으면 0 OR 1의 값을 출력
  • 위의 값으로 예측 수행
  • 기존의 출력은 \(y = wx + b\)
  • 위 출력을 시그모이드 함수 \(sigmoid(z)\)의 입력으로 넣을 경우
    • y = \(\frac{1}{1+e^{-(wx+b)}}\)
    • 위 값은 0 또는 1에 가까운 분류값

가장 좋은 가중치 W의 값

  • Cost Function 초기화
  • Linear Regression은 MSE로 최솟값 가능

Sig2

  • 하지만 Logistics Regression은 불가
  • Log Loss(Cross Entropy 사용)

Cross Entropy Loss 함수

  • 로지스틱 모델의 예측 분포는 \(sigmoid(wx + b)\)

CE

CEL

로지스틱 회귀

  • 장점

  • Cross Entropy Loss 함수를 적용한 알고리즘

  • Cross Entropy Loss 함수를 가장 처음으로 이해하기 좋은 알고리즘
  • 선형적인 문제를 간단하게 풀 때 매우 효과적
  • 전세계적으로 가장 사랑받는 머신러닝 알고리즘

  • 단점

  • 이진 분류만 가능(클래스가 2개 있을 때만 사용 가능)
  • 복잡한 비선형 문제를 해결하는데 큰 어려움
  • 다중공선성과 같은 문제 자체적 해결 불가

예제 - 유방암 분류

import pandas as pd
from sklearn import datasets
from sklearn.linear_model import LogisticRegression

# 0 : 양성 / 1 : 악성
cancer_ds = datasets.load_breast_cancer()

clf = LogisticRegression(multi_class = 'ovr', solver='liblinear') #one-vs-rest (OvR)
clf.fit(cancer_ds.data , cancer_ds.target)
clf.predict(cancer_ds.data)- cancer_ds.target

clf.score(cancer_ds.data, cancer_ds.target)