단순 선형 회귀: 독립 변수 1개, 종속 변수 1개인 선형 회귀
-> 직선 형태 y = α + β * x
: 점진적으로 반복적인 계산을 통해 파라미터 값을 업데이트하면서 오류 값이 최소가 되는 파라미터를 구하는 방식 (=RSS(비용함수)가 최소가 되는 파라미터 구하는 방식)
ex. RSS(w) = R(w) 가 이차함수인 경우
Step 1: 임의의 값으로 첫 비용함수의 값 계산
Step 2: 편미분 결과값에 학습률(보정계수)를 곱한 것을 마이너스하면서 계산하여 이전 값 업데이트
Step 3: 비용함수 값이 최소가 될 때 반복을 중지, 최적 파라미터 구함
# 비용함수
def get_cost(y, y_pred):
N = len(y)
cost = np.sum(np.square(y - y_pred))/N # RSS
return cost
#### 경사하강법 함수
# 업데이트 함수
def get_weight_updates(w1, w0, X, y, learning_rate=0.01):
N = len(y)
# 초기값: 각각 w1, w0의 shape와 동일한 크기를 가진 0 값
w1_update = np.zeros_like(w1) # np.zeros_like(w1): w1의 크기가 1x5이면, 0으로 채워진 1x5 행렬 생성
w0_update = np.zeros_like(w0)
y_pred = np.dot(X, w1.T) + w0 # np.dot(): 내적 계산
diff = y-y_pred # 실제, 예측 값의 차이 계산
# w0_update를 dot 행렬 연산으로 구하기 위해 모두 1값을 가진 행렬 생성
w0_factors = np.ones((N,1))
# w1과 w0을 업데이트할 w1_update와 w0_update 계산
w1_update = -(2/N)*learning_rate*(np.dot(X.T, diff))
w0_update = -(2/N)*learning_rate*(np.dot(w0_factors.T, diff))
return w1_update, w0_update
# 경사하강 함수
def gradient_descent_steps(X, y, iters=10000):
# w0와 w1을 모두 0으로 초기화.
w0 = np.zeros((1,1)) # [0] 행렬
w1 = np.zeros((1,1))
# iters 만큼 반복적으로 get_weight_updates() 호출하여 w1, w0 업데이트
for ind in range(iters):
w1_update, w0_update = get_weight_updates(w1, w0, X, y, learning_rate=0.01)
w1 = w1 - w1_update
w0 = w0 - w0_update
return w1, w0
w1, w0 = gradient_descent_steps(X, y, iters=1000)
def stochastic_gradient_descent_steps(X, y, batch_size=10, iters=1000):
w0 = np.zeros((1,1))
w1 = np.zeros((1,1))
prev_cost = 100000
iter_index =0
for ind in range(iters):
np.random.seed(ind)
# 전체 X, y 데이터에서 랜덤하게 batch_size만큼 데이터 추출
stochastic_random_index = np.random.permutation(X.shape[0])
sample_X = X[stochastic_random_index[0:batch_size]]
sample_y = y[stochastic_random_index[0:batch_size]]
# 랜덤하게 batch_size만큼 추출된 데이터로 w1_update, w0_update 계산 후 업데이트
w1_update, w0_update = get_weight_updates(w1, w0, sample_X, sample_y, learning_rate=0.01)
w1 = w1 - w1_update
w0 = w0 - w0_update
return w1, w0
w1, w0 = stochastic_gradient_descent_steps(X, y, iters=1000)
y_pred = np.dot(Xmat, w.T) + w0
: RSS를 최소화해 OSL 추정 방식으로 구현한 클래스
: 피처 간의 상관관계가 매우 높은 경우 분산이 매우 커져서 오류에 민감해지는 현상
-> 독립적인 중요한 피처만 남기고 제거 or 규제 / PCA를 통한 차원 축소
** scoring 함수에 회귀 평가 지표를 적용할 때는 평가 지표 값에 -1을 곱하여 작은 오류값이 더 큰 숫자로 인식하게 함
@
다항 회귀: 독립변수의 단항식이 아닌, 다항식으로 표현되는 선형 회귀
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import Pipeline
import numpy as np
def polynomial_func(X):
y = 1 + 2*X[:,0] + 3*X[:,0]**2 + 4*X[:,1]**3 # y=1+2x1+3x1^2+4x2^3
return y
# Pipeline 객체로 Streamline 하게 Polynomial Feature변환과 Linear Regression을 연결
model = Pipeline([('poly', PolynomialFeatures(degree=3)),
('linear', LinearRegression())])
X = np.arange(4).reshape(2,2)
y = polynomial_func(X)
model = model.fit(X, y)
Polynomial 회귀 계수
[0. 0.18 0.18 0.36 0.54 0.72 0.72 1.08 1.62 2.34]
다항 회귀는 직선적 관계가 아닌 복잡한 다항 관계를 모델링할 수 있지만, 차수를 높일수록 학습 데이터에만 맞춘 학습이 이루어져 과적합 문제가 발생할 수 있음
일반적으로 편향과 분산은 트레이드오프 관계에 있음
: 편향이 높으면 분산이 낮아지고(과소적합), 반대로 분산이 높으면 편향이 낮아짐(과적합)
=> 따라서, 편향과 분산이 서로 트레이드오프를 이루면서 오류 Cost 값이 최대로 낮아지는 모델 구축하는 것이 가장 효율적