Linear Regression

Posted by on June 24, 2019

Recently by the same author:


Python에서 Singleton 구현

You may find interesting:


Naive Bayes Classifier

Linear Regression

2019. 06. 24 (Mon)


Regression problem


종속 변수 yrhk 한 개 이상의 독립 변수 x와의 선형 상관 관계를 모델링하는 회귀분석 기법

주어진 x값에 대해 y값을 예측한다.

line-fitting을 수행하여 값을 찾아내는 작업


Line-fitting

데이터 set이 그래프 상에서 표현할 수 있을때, 여러 라인을 그릴 수 있다.

그중, 데이터 set에 가장 적합한 라인(y = ax + b)을 수학적으로 구하는 과정 \(xy(x) = w^t*x + e\) 의 형태에서 w와 e의 값을 찾는다.


non-linear-fitting

x대신 non-linear function 추가 \(y=w^t*pi(x)+e~~(pi(x):non-linear~funtion,~w^t:coeffcient~array)\) polynomial regression: degree(차수)가 높은 regression 모델. 차수를 높이면 적합한 line을 찾을 수 있지만, 복잡도가 너무 높으면 overfit 될 수 있다.


Multivariate linear regression

2개 이상의 x변수에 대한 line-fitting

3차 이상의 차원에서 line-fitting


적합한 w?

Residual Sum of Squares

[sum(y_i - w^t*x_i)^2~~(i = 1~to~n)]

fitting한 line과 실제 데이터들의 차의 크기

실제 데이터와 예측값 사이의 오차를 의미하며, 이 차이를 줄이는 weight를 찾는다.


linear-fitting & RSS 예시
import elice_utils
import matplotlib as mpl
mpl.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
eu = elice_utils.EliceUtils()

def loss(x, y, beta_0, beta_1):
    N = len(x)
    
    '''
    x, y, beta_0, beta_1 을 이용해 loss값을 계산한 뒤 리턴합니다.
    '''
    
    length = len(x)
    err = 0
    for i in range(length):
        real_data = y[i]
        pred_data = beta_0*x[i]+beta_1
        err += (real_data-pred_data)**2
    
    return err

X = [8.70153760, 3.90825773, 1.89362433, 3.28730045, 7.39333004, 2.98984649, 2.25757240, 9.84450732, 9.94589513, 5.48321616]
Y = [5.64413093, 3.75876583, 3.87233310, 4.40990425, 6.43845020, 4.02827829, 2.26105955, 7.15768995, 6.29097441, 5.19692852]

beta_0 = 0.5 # 기울기
beta_1 = 2 # 절편

print("Loss: %f" % loss(X, Y, beta_0, beta_1))

plt.scatter(X, Y) # (x, y) 점을 그립니다.
plt.plot([0, 10], [beta_1, 10 * beta_0 + beta_1], c='r') # y = beta_0 * x + beta_1 에 해당하는 선을 그립니다.

plt.xlim(0, 10) # 그래프의 X축을 설정합니다.
plt.ylim(0, 10) # 그래프의 Y축을 설정합니다.
plt.savefig("test.png") # 저장 후 엘리스에 이미지를 표시합니다.
eu.send_image("test.png")


Sciket-learn

numpy내 기능으로, 자동으로 가장 적합한 line을 찾아주는 기능


Scikit-learn을 이용한 linear regression
'''
여기에서 모델을 트레이닝.
'''
lrmodel = LinearRegression()
lrmodel.fit(train_X, train_Y)

# line의 기울기, 절편
beta_0 = lrmodel.coef_[0]
beta_1 = lrmodel.intercept_

print("beta_0: %f" % beta_0)
print("beta_1: %f" % beta_1)


Ridge Regression

Linear Regression에 L2 regularization을 사용하는 방법으로, 모델의 복잡도를 줄여서 좀 더 간단하고 부드러운 모델로 만들때 사용

linear-fitting을 할 때 over-fitting하지 않도록 주의한다.

즉, 너무 complex한 모델(over-dimensioned curve, over-estimated weight)을 사용하면 오히려, fitting이 잘 안되는 경우가 있다.


(l2)Regularization

정규화 (Regularization): weight가 너무 큰 값들을 갖지 않도록 하여 모델의 복잡도를 낮추는 방법

polynomial non-linear-fitting에 대해 미리 찾아놓은 좋은 w값을 제공

근데 미리 찾아놓은 값이 너무 크기 때문에 fitting을 복잡하게 한다.

그러니까 큰 w값에 penalty를 부여하여 over-fitting을 방지한다.


error를 사용하여 실제 선형 회귀 구현
import numpy as np
import elice_utils
import matplotlib.pyplot as plt
import matplotlib as mpl
mpl.use("Agg")
eu = elice_utils.EliceUtils()
#학습률(gradient step)을 설정한다.(권장: 0.0001~0.01)
learning_rate = 0.0005
#반복 횟수(iteration)를 설정한다.(자연수)
iteration = 5000
def prediction(a,b,x):
    # 넘파이 배열 a,b,x를 받아서 'x*(transposed)a + b'를 계산하는 식을 만든다.
    equation = x*a + b
    
    return equation
    
def update_ab(a,b,x,error,lr):
    # a, b에 대해 error를 미분한 식(gradient)
    # a를 업데이트하는 규칙을 정의한다.
    delta_a = -(lr*(2/len(error))*(np.dot(x.T, error)))
    # b를 업데이트하는 규칙을 정의한다.
    delta_b = -(lr*(2/len(error))*np.sum(error))
    
    return delta_a, delta_b
    
    
def gradient_descent(x, y, iters):
    #초기값 a= 0, a=0
    a = np.zeros((1,1))
    b = np.zeros((1,1))
    
    for i in range(iters):
        #실제 값 y와 예측 값의 차이를 계산하여 error를 정의한다.
        error = -(prediction(a, b, x) - y)
        a_delta, b_delta = update_ab(a,b,x,error,lr=learning_rate)
        a -= a_delta
        b -= b_delta
        
    return a, b

def plotting_graph(x,y,a,b):
    y_pred=a[0,0]*x+b
    plt.scatter(x, y)
    plt.plot(x, y_pred)
    plt.savefig("test.png")
    eu.send_image("test.png")

def main():

    x = 5*np.random.rand(100,1)
    y = 3*x + 5*np.random.rand(100,1)
    
    a, b = gradient_descent(x,y,iters=iteration)
    
    print("a:",a, "b:",b)
    plotting_graph(x,y,a,b)
    
main()