[Do it 딥러닝 입문] 03장

선형 회귀

선형 회귀 모델을 만들어 문제 해결하기 : 미리 준비한 입력과 타깃을 가지고 절편과 기울기를 찾아 모델을 만든 다음 예측

1. 당뇨병 환자 데이터 준비

  • 사이킷런의 datasets 모듈의 load_diabetes 함수로 당뇨병 데이터 저장
from sklearn.datasets import load_diabetes 
diabetes = load_diabetes()
  • 입력과 타깃 데이터의 크기 확인하기
    • 입력과 타깃 데이터가 넘파이 배열로 저장된 상태
    • 넘파이 배열의 크기는 shape 속성에 저장되어 있음
print(diabetes.data.shape, diabetes.target.shape)

data : 442x10 크기의 2차원 배열
target : 442개의 요소를 가진 1차원 배열

2. 당뇨병 환자 데이터 시각화하기

  • 세번째 특성과 타깃 데이터로 산점도 그리기
import matplotlib.pyplot as plt
plt.scatter(diabetes.data[:,2], diabetes.target)
plt.xlabel('x')
plt.ylabel('y')
plt.show()


x축 : diabetes.data의 세번째 특성
y축 : diabetes.target
⇒ 입력 데이터의 세번째 특성과 타깃 데이터 사이에 정비례 관계가 있음을 확인

  • 입력 데이터의 세번째 특성을 x에, target을 y에 저장
x = diabetes.data[:,2]
y = diabetes.target

경사하강법으로 학습시키기

경사하강법

  • 모델이 데이터를 잘 표현할 수 있도록 기울기를 사용하여 모델을 조금씩 조정하는 최적화 알고리즘
  • 많은 양의 데이터에 사용하기 좋음

예측값으로 올바른 모델 찾기

  1. 무작위로 가중치 w와 절편 b 정하기 (무작위로 모델 생성)
  2. x에서 샘플 하나를 선택해 예측값 y^을 계산 (무작위로 모델 예측)
  3. y^과 선택한 샘플의 진짜 타겟값 y를 비교
  4. y^이 y와 더 가까워지도록 w와 b 조정 (모델 조정하기)
  5. 모든 샘플을 처리할 때까지 2~4 반복
  1. w와 b 초기화하기
w=1.0
b=1.0
  1. 훈련데이터의 첫 번째 샘플 데이터로 y^얻기
y_hat = x[0]*w+b
print(y_hat)
  1. 타깃과 에측 데이터 비교하기
print(y[0])
  1. w값 조절해 에측값 바꾸기
w_inc = w+0.1 #w값 0.1만큼 증가
y_hat_inc =x[0]*w_inc +b
print(y_hat_inc)
  1. w값 조정한 후 예측값 증가 정도 확인하기
w_rate = (y_hat_inc - y_hat)/(w_inc - w) #y^증가한 양을 w가 증가한 양으로 나누기
print(w_rate)

변화율로 가중치 업데이트하기

  • 변화율이 양수일 때 w가 증가하면 y^이 증가, 변화율이 양수임 → w에 변화율 더하기
  • 변화율이 음수일 때 w가 증가하면 y^은 감소, w가 감소하면 y^은 증가 → w에 변화율 더하기
w_new = w+w_rate
print(w_new)

변화율로 절편 업데이트하기

b_inc = b+0.1 #b값 0.1만큼 증가
y_hat_inc = x[0]*w+b_inc
print(y_hat_inc)

b_rate = (y_hat_inc - y_hat) / (b_inc -b) #y^증가한 양을 b가 증가한 양으로 나누기
print(b_rate)

⇒변화율로 w와 b를 업데이트 하는것은 수동적인 방법

  • y^이 y에 한참 미치지 못하는 값인 경우 w와 b를 더 큰 폭으로 수정할 수 없음
  • y^이 y보다 커지면 y^을 감소시키지 못함

오차 역전파로 가중치와 절편 업데이트

: y^과 y의 차이를 이용해 w와 b를 업데이트

  1. 오차와 변화율을 곱하여 가중치 업데이트하기
err = y[0] - y_hat #오차 
w_new = w+w_rate*err #w의 변화율은 w_rate = (y_hat_inc - y_hat)/(w_inc - w)
b_new = b +1*err #b의 변화율은 1
print(w_new,b_new)
  1. 두번째 샘플로 오차 구하고 새로운 w와 b 구하기
y_hat = x[1]*w_new + b_new
err = y[1] - y_hat #오차
w_rate =x[1] 
w_new = w_new + w_rate*err 
b_new = b_new +1*err 
print(w_new, b_new)

=> 이런 방식으로 모든 샘플을 사용해 가중치와 절편 업데이트

  1. 전체 샘플을 반복하기
for x_i,y_i in zip(x,y): #zip()함수를 사용하여 여러개의 배열에서 동시에 요소를 하나씩 빼냄; 입력x와 타깃y의 배열에서 요소를 하나씩 꺼냄
  y_hat = x_i*w+b
  err = y_i - y_hat
  w_rate = x_i
  w = w+w_rate*err
  b=b+1*err
print(w,b)
  1. 3을 통해 얻은 모델의 그래프 그리기 (산점도 위에 w와 b를 사용한 직선 그리기
plt.scatter(x,y)
pt1=(-0.1,-0.1*w+b)
pt2=(0.15,0.15*w+b)
plt.plot([pt1[0],pt2[0]],[pt1[1],pt2[1]])
plt.xlable('x')
plt.ylable('y')
plt.show()

  1. 여러 에포크 반복하기

    에포크 : 전체 훈련 데이터를 모두 이용하여 한 단위의 작업을 진행하는 것

for i in range(1,100):
  for x_i,y_i in zip(x,y):
   y_hat = x_i*w+b
   err = y_i - y_hat
   w_rate = x_i
   w = w+w_rate*err
   b=b+1*err
print(w,b)
  1. 4번 과정을 다시 하면

    4번에서보다 전체 데이터의 경향을 잘 따라가는 그래프가 만들어짐

    ⇒ 데이터의 머신러닝 모델은

    y^=913.6x + 123.4

  2. 모델로 예측하기

x_new = 0.18
y_pred = x_new *w +b
print(y_pred)

경사하강법

: 어떤 손실함수가 정의되었을 때 손실함수의 값이 최소가 되는 지점을 찾아가는 방법

손실함수 (=비용함수, 목적함수)

: 예상한 값과 실제 타깃값의 차이를 함수로 정의한 것

제곱 오차
: 타깃값과 예측값을 뺀 다음 제곱한 것

  • 제곱 오차가 최소가 되면 산점도 그래프를 가장 잘 표현한 직선이 그려짐
  • 제곱 오차 함수의 최솟값을 알아내려면 기울기에 따라 함수의 값이 낮은 쪽으로 이동해야 함
  • 기울기는 제곱 오차를 가중치나 절편에 미분하여 구함
  1. 가중치에 대하여 제곱 오차 미분하기
y_hat = x_i*w+b
err = y_i - y_hat
w_rate = x_i
w = w+w_rate*err
  1. 절편에 대하여 제곱 오차 미분하기
err = y_i-y_hat
b = b+1*err

선형 회귀를 위한 뉴런(유닛) 만들기

Neuron 클래스 만들기

#뉴런 클래스는 다음과 같은 구조로 구성 
class Neuron:
  def __init__(self):
		...... #초기화 작업 수행
		...... #필요한 메서드 추가 
class Neuron:
  def __init__(self):

    #1.__init__() 메서드 작성; 가중치와 절편 초기화
    self.w = 1.0    #학습할 때 가중치 w와 절편 b는 시작값이 있어야 함 -> 임의로 1.0으로 지정
    self.b = 1.0 

    #2.정방향 계산(w,x,b가 뉴런의 왼쪽에서 오른쪽 방향으로 흘러 y^이 되는 구조의 계산; y^ = w*x + b) 만들기 
    def forpas(self,x):
      y_hat = x*self.w+self.b   #직선 방정식 계산 
      return y_hat

    #3.역방향 계산(오차가 뉴론의 오른쪽에서 왼쪽 방향으로 흐름; 오차가 역전파 됨 ) 만들기 
    def backprop(self,x,err):
      w_grad = x*err    #가중치에 대한 그레디언트 계산
      b_grad = 1*err    #절편에 대한 그레디언트 계산 
      return w_grad, b_grad
    
    #4.훈련을 위한 fit()메서드 구현
    def fit(self, x, y, epochs=100):
      for i in range(epochs):   #에포크만큼 반복
        for x_i,y_i in zip(x,y):    #모든 샘플에 대하여 반복
          y_hat = self.forpass(x_i)   #정방향 계산 
          err = -(y_i-y_hat)    #오차 계산
          w_grad, b_grad = self.backprop(x_i,err)   #역방향 계산
          self.w -= w_grad    #가중치 업데이트 
          self.b -= b_grad    #절편 업데이트
    
#5.모델 훈련하기(학습시키기) 
neuron = Neuron()
neuron.fit(x,y)

좋은 웹페이지 즐겨찾기