본문 바로가기
머신러닝 딥러닝

0827Machine Learning에서Linear Regression

by 대금부는개발자 2021. 8. 27.
SMALL

지도 학습 : 학습된 결과를 바탕으로 Model을 만들고 이 Model이 어떤 값을 예측하느냐에 따라 크게 2가지로 나눠져요.

1. Regression : 연속적인 숫자 값
2.classification

 

Regression  

Training Data Set → Linear Regression Machine Learning System →Learning 

→ Model(예측하고자 하는 Data가 들어감)→ 결과

 

Training Data Set을 2차원 평면상의 산점도(scatter)를 이용해서 표현해 보아요!

 

 

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame({
    '공부시간(x)': [1,2,3,4,5,7,8,10,12,13,14,15,18,20,25,28,30],
    '시험점수(t)' : [5,7,20,31,40,44,46,49,60,62,70,80,85,91,92,98,99]
})
# display(df)
plt.scatter(df['공부시간(x)'],df['시험점수(t)'])
#scatter는 Data의 분포와 경향을 파악할 때 많이 써요!
plt.show()

 

 

 

 

우리는 y = ax + b 형태의 모델을 만들어야 해요!!

Machine learning에서는 독립변수가 하나이면서 Linear Regression모델에서 직선을 표현할 때

y = Wx + b라는 표현을 써요!

W : 대문자 b : 소문자

W : Weight(가중치) , b : bias(바이어스)

 

 

 

단순 선형 회귀(직선)

a와 b에 따라 다양한 직선이 나올 수 있어요!

우리는 y = ax + b 형태의 모델을 만들어야 해요!!

 

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame({
    '공부시간(x)': [1,2,3,4,5,7,8,10,12,13,14,15,18,20,25,28,30],
    '시험점수(t)' : [5,7,20,31,40,44,46,49,60,62,70,80,85,91,92,98,99]
})
# display(df)
plt.scatter(df['공부시간(x)'],df['시험점수(t)'])
# a와 b에 따라 다양한 직선이 나올 수 있어요!
#우리는 y = ax + b 형태의 모델을 만들어야 해요!!
plt.plot(df['공부시간(x)'],df['공부시간(x)']*2+3, color='r') #기울기 2, 절편 3
plt.plot(df['공부시간(x)'],df['공부시간(x)']*5+-7, color='g') #기울기 5, 절편-7
plt.plot(df['공부시간(x)'],df['공부시간(x)']*1+8, color='b') #기울기 1, 절편 8
plt.plot(df['공부시간(x)'],df['공부시간(x)']*4+-10, color='magenta') #기울기 4, 절편-10

#우리는 데이터를 가장 잘 표현하고 있는 직선을 찾아야 해요! 
plt.show()

 

처음에는 a(기울기)와 b(절편)를 random 하게 잡아요! → 시간이 지남에 따라 Data에 맞춰 가요.
학습 : Data를 가장 잘 표현하는 직선을 찾아가는 과정.

 

 

y = Wx +b에서 오차(error)에 대해 알아보아요!

오차(error) : 실제 값과 계산된 값의 차이

 

위 코드 초록색선을 예를 들어보아요!

plt.plot(df['공부시간(x)'],df['공부시간(x)']*5+-7, color='g') #기울기 5, 절편-7

→ y = 5x - 7(예측 값) , 점 y(실제 값)

 

error = t(실제 값) - y(계산된 값 ) = t - (Wx+b)

error의 값이 크다면, 직선이 Data를 잘 표현하지 못하고 있다는 거예요.

당연히 오차는 작으면 작을수록 좋아요!. 최적의 값 = 오차 0

오차(error)의 합이 최소가 되는 W와 b를 찾아야 해요!

 

→ Loss Function(손실 함수)라는 표현이 등장해요. Cost Function(비용 함수)라고도 해요!

 

 

 

Loss Function(손실 함수)

Training Data Set의 정답 t(Label)과 우리가 만든 Model( y=Wx+b, 예측 값)의 예측값(y)을 더해서 수식으로 표현한 것이에요. 그런데 이 error의 값이 부호가 있어요. → 어떨 때는 양수, 어떨 때는 음수, 그래서 사람들이 절댓값을 이용해서(부호를 날림) 합을 구하려고 했어요→ 이 방법보다 더 좋은 방법을 찾아냈어요!

오차(error) 제곱의 평균을 이용해요 → 평균 제곱 오차(MSE : Mean squared error)

Loss fuctiond은 제곱을 했기 때문에 최솟값이 0이에요.

 

우리의 목적은 Loss fuction의 값이 최소가 되게 하는 W와 b를 구하는 것이에요.

→ 최소 제곱 법(least square method)을 이용해서 loss 함수의 값이 최소가 되게 할 거예요

 


 Loss fuction 함수를 수식으로 표현해 보아요!

 

 

t ← Label(입력 값)

y = Wx + b ← Model(예측 값)

 

 

 

t(Label)와 x(입력 값)는 정해져 있어서 고정되어 있기 때문에 W와 b에 의해 loss 함수가 결졍돼요!

 

→ loss 함수를 최소로 하는 W와 b를 구해서 Model을 완성해 보아요!

 

 

E(W, b)를 최소로 만드는 W, b를 구하기 위해 경사 하강법(gradient descent 알고리즘)을 이용할 거예요!

쉽게 설명하자면 한 점에서 경사가 가장 급한 쪽으로 내려간 후 다시 가장 급한 쪽.. 반복..

 

loss에 대한 graph를 그려볼 거예요. y = Wx + b
가중치 w(1차, 2차 계수 값)는 살리고 고정치 b(상숫값)은 제외하여 단순화시켜서 graph를 그려볼 거예요.

 

 

 loss function의 대략적인 모습을 알아보기 위해 그래프를 그려보아요!

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# Training data set
# 지금 우리는 독립변수가 1개인 경우에 대해서 알아보고 있어요!
x = np.arange(1,101)  # 입력 값
t = np.arange(1,101)  # 정답

W = np.arange(-10,30) # loss 함수 그래프를 보기 위해 W가 있다고 가정해 보아요!

loss = [] # W에 대해서 loss값을 계산해서 w와 loss함수의 그래프를 그려볼 거예요!

for tmp in W:
    loss.append(np.power((t-tmp*x),2).mean()) #b를 제외한 loss 값의 식# tmp*2 = wx ← Broadcasting
    
plt.plot(W,loss)    

plt.show()    
    

 

 

 

 

1. 임의의 가중치 W를 선택할 거예요.

2. 이 W 지점에서 loss 함수에 접하는 직선의 기울기를 구해요.→ 미분계수(값)를 구해요.

3. 기존 w에서 새로운 w를 빼줘요. 한 번에 많이 움직이는 것을 방지하기 위해(목푯값을 지나칠 수 있어요) α값( learning rate 상수)을 곱해줘서 조금씩 이동해 줘요.

 

↑ 반복 → learning rate와 반복 횟수를 조절해 최소한의 방법으로 최대한 효과를 찾아야 해요.

목표는 = 0 , 단 조건을 0으로 주면 안 나올 수 있기 때문에 무조건 0으로 주면 안 돼요! (최솟값이 목표)

 

 

 

 

 

 

 

Simple Linear Regression Model

1. Training Data Set 준비

2. Model을 정의 : y = Wx+b → 가설(hypothesis)

3. Loss function정의

4. learning rate 설정

5. Gradient Descent algorithm을 이용한 반복학습 진행

 

2차원으로 바꿔줘요 ↓

 

y = wx + b에서 Y = X ⋅ W +b로 식이 바뀌어요!

 

 

 

# python을 이용해서 간단하게 구현해 보아요!

import numpy as np

# 1. Training Data Set 준비
x_data = np.array([1,2,3,4,5]).reshape(5,1)
t_data = np.array([3,5,7,9,11]).reshape(5,1)

# 2. Weight & bias를 정의
W = np.random.rand(1,1)
b = np.random.rand(1)

# 3. loss function 구현(w, b를 loss 함수로 편미분)
def loss_func(input_value):
    # input_value에는 W와 b의 값이 들어가 있어요!   => [W의 값, b의 값]
    W = input_value[0].reshape(1,1)
    b = input_value[1]
    
    # model
    # y = XW + b
    y = np.dot(x_data,W) + b
    
    return np.mean(np.power(t_data-y,2))
    

# 4. 미분을 수행할 함수
def numerical_derivative(f, x):
    # f : loss함수가 들어가요
    # x : w(가중치) , b(바이어스)가 들어가요!
    
    delta_x = 1e-4
    derivative_x = np.zeros_like(x)  # [0.0   0.0]
    
    it = np.nditer(x, flags=['multi_index'])
    
    while not it.finished:
        
        idx = it.multi_index


        # tmp를 준비하는 이유는 편미분 할 때 값이 변경되지 않아야 하기 때문에 준비해요.
        tmp = x[idx]    # x : [1.0 2.0]  , tmp = 1.0
        
        # 중앙 차분으로 수치 미분하는 식 : (f(x + delta_x) - f(x-delta_x)) / 2 * delta_x
        
        x[idx] = tmp + delta_x   # x : [1.0001  2.0]
        fx_plus_deltax = f(x)
        
        x[idx] = tmp - delta_x   # x : [0.9999  2.0]
        fx_minus_deltax = f(x)
        
        derivative_x[idx] = (fx_plus_deltax - fx_minus_deltax) / (2 * delta_x)
        
        x[idx] = tmp     # x : [1.0   2.0]
        
        it.iternext()

    return derivative_x

# 5. learning rate 정의
learning_rate = 1e-4

# 6. 반복 학습을 진행해 보아요!

for step in range(100000):
    
    # 최적의 loss값인가요? => 판단하는 게 쉽지 않아요!
    # 넘겨줄 파라미터를 넣어줘요.
    input_param = np.concatenate((W.ravel(), b.ravel()), axis=0)   # [W의 값, b의 값]
    tmp = learning_rate * numerical_derivative(loss_func,input_param)  # [W의 편미분 값, b의 편미분 값]
    
    W = W - tmp[0].reshape(1,1)
    b = b - tmp[1]
    
    if step % 10000 == 0:# 만으로 나눴을 때 0이 되면 10번이 걸릴 때 잘 작동하는지 찍어줘요
        print('W의 값은 {}, b의 값은 : {}'.format(W,b))
        

# 수행시키면 W와 b의 값이 생성이 돼요!        

 

W의 값은 [[0.97765224]], b의 값은 : [0.67371499]
W의 값은 [[2.00790869]], b의 값은 : [0.9714471]
W의 값은 [[2.00563987]], b의 값은 : [0.97963828]
W의 값은 [[2.00402192]], b의 값은 : [0.9854796]
W의 값은 [[2.00286812]], b의 값은 : [0.98964518]
W의 값은 [[2.00204532]], b의 값은 : [0.99261574]
W의 값은 [[2.00145856]], b의 값은 : [0.99473412]
W의 값은 [[2.00104014]], b의 값은 : [0.99624478]
W의 값은 [[2.00074174]], b의 값은 : [0.99732207]
W의 값은 [[2.00052895]], b의 값은 : [0.99809031]

 

predict_value = np.array([[7]])

H = np.dot(predict_value,W) + b    # Hypothesis(Model)

print(H)  # 결괏값 예측

 

[[15.00127866]]

 

 

 

Loss function의 최솟값을 구하기 위해 이용하는 알고리즘  :gradient descent 알고리즘(편미분 해서 갱신)

loss funtion의 모양이 convex function(볼록 함수)이 돼야 해요.

→ 어디에서 시작하던지 최솟값(global minima)으로 갈 수 있어요.

 

볼록 함수가 아닐 경우 local minima(지역적인 최솟값)을 찾아 최적의 최솟값(global minima)을 찾을 수 없어요!

 

LIST

댓글