야나두 딥러닝 강의를 하는 데, 질문이 나왔다. linear regression(회귀 분석)을 할 때, 경사 하강 법에 의해 계산 된 것이 좋은지 , 아니면, 통계학은 계산 된 최소 제곱법을 간단 하게 정리 하여 계산 한것이 좋은지 확인 해 보라는 것이였다.
|
선형 VS 경사하강 |
그런데, 야나두 딥러닝에서 경사 하강법을 가지고 회귀 분석하는 것은 교육용으로 쓰이는 것이다. 실무 용으로 쓰이는 것이 아니다.
경사 하강법 설명
경사 하강법을 설명 하기 위해서, w(가중치),b(기울기)에 학습값을 조금씩 조정 해서, 적정의 가중치를 조정 해서, 적정의 회귀 분석 기울기 찾는 것이 목적이다. 아래와 같은 것은 이미, 설명이 되어서, 아래 URL 에 링크가 되어 있다.
https://rdmkyg.blogspot.com/2021/05/gradient-descent.html
최소 제곱법에 의한 계산
최소 제곱법은 회귀식에서 계산 된 예측치 $\hat{y}_i$와 관찰치 $y_i$의 차이인 잔차들의 제곱이 최소가 되도록 회귀 계수를 추정하는 방법으로 다음의 식을 최소화 하는 a와 b를 구한다.
$$ \sum_{i =1}^n e^2_i = \sum_{i=1}^n (y_i - \hat{y}_i)^2$$
$$ = \sum_{i=1}^n(y_i - a - bx_i)^2 $$
아래의 구체적인 계산 법은 아래 링크에 이미 구현 되어 있다.
https://rdmkyg.blogspot.com/2021/05/blog-post_0.html
질문에 대한 답변 (결론)
위와 같이 회귀 모델에 대한 평가는 관측치 $Y_i$ , 예측치 $hat{y}_i$의 차이의 제곱을 한다음에 관측 수를 나눈 다음 루트를 적용 한 다음에 평가 하는 것이다.
|
rmse |
아래와 같이 당뇨병 데이터 셋을 이용하였다.
패키지 로딩과 데이터 셋 불러오기
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split
diabets = load_diabetes()
데이터셋 불러오기, 이번에는 BMI는 feature 로 하였고, 당뇨는 target으로 하였다.
x = diabets.data
y = diabets.target # 당뇨수치
데이터 셋을 불러 오면 데이터의 구조를 봐야 한다.
print(diabets.data.shape, diabets.target.shape)
(442, 10) (442,)
데이터 Train Set과 Test Set 을 나눈다. 당뇨병 데이터 셋이 442개라 Train Set 을 0.9로 하였고,
test Set은 0.1로 하였다.
X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.1,
shuffle=False, random_state=1004)
최소 제곱법에 의한 선형회귀를 계산 하고자, train Set, test Set과, 관측수 n을 정의 하였다.
이것은 관측치와 예측치 값의 거리를 계산 해서 최소화 하는 것이다.
x_train = X_train[:,2] # BMI
x_test = X_test[:,2] #BMI
n = x_train.shape[0]
모델 수행 후 예측 통계학적인 방법
통계학적으로 계산 한 최소 제곱법을 이용하여, 함수를 만들고 실행 하였다. 여기에서 b1는 절편, b0는 기울기이다.
def linear_regx(x, y):
# X, Y bar를 구함
Y_bar = y.mean()
X_bar = x.mean()
# sum(X_i,Y_i)를 구함
prod_XY= np.sum(x * y)
# sum(X^2)을 구함
X_squar = sum(x**2)
# b1을 구함
S_XY = prod_XY - n * X_bar * Y_bar
S_XX = X_squar - n*(X_bar**2)
b1 = S_XY/ S_XX
# b0를 구함
b0 = Y_bar - b1*X_bar
return(b0, b1)
b0, b1 = linear_regx(x_train, y_train)
953.0248497594562 152.5445622274684
예측하는 함수를 만들었다. np.zeros 함수를 만들어서, array 변수의 초기화를 하였다.
이 함수는 통계학적 최소 제곱법과 경사하강법을 이요하여, 에포크 수행시 나온 모델 식 가지고
직접 예측 하였다. 모델에 의한 평가는 통계학 개론 같은 데서 나오지 않고, 통계학부 4학년 2학기
정도에 나온다.
hat_list = np.zeros(len(x_test))
def predict(w,b,x):
for i in range(len(x)):
x_i = x[i]
y_hat = w*x + b
list = y_hat
return list
y_hat_stat = predict(b1, b0, x_test)
y_hat_stat.shape
(45,)
통계학 적인 최소제곱법에 의한 rmse 구하기
# 사이킨런에서 mese 가져오기
from sklearn.metrics import mean_squared_error
rmse_stat = np.sqrt(mean_squared_error(y_test, y_hat_stat))
rmse_stat = np.round(rmse_stat, decimals=0)
rmse_stat
57.0
모델 수행 후 예측 경사 하강법
경사 하강법을 적용할때도 최소제곱법을 미분 하여, error 값을 만들었다. . loss 값이 최소가 되는
값을 찾기 위해서 절편의 기울기를 계산 하기 때문이다. 최소 제곱법 미분 한것에 대한 상세 한것의
위의 링크에 있다. 가중치 w , 기울기 b는 1로 초기화 시켰다.
for i in range(1, 100):
for x_i, y_i in zip(x_train, y_train):
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)
968.0559725285722 72.82884492499304
위의 가중치와 기울기 값을 이용해서 예측을 하였다. predict 함수는 앞서 만든 사용자 함수 이다.
y_hat_w = predict(w,b,x_test)
그리고 RSME 값을 구하였다. 사이킨런에서 mse 값을 구한 것이 있는데, 거기에다 root 를
적용하여 계산하였다.
rmse_w = np.sqrt(mean_squared_error(y_test, y_hat_w))
rmse_w = np.round(rmse_w, decimals=0)
rmse_w
94.0
결론
통계모형의 rmse 값이 적게 나왔다 rmse 적다는 것은 최소제곱오차가 적다는 것인데 적은 것이
모형 평가에서 설명력 또는 성능이 더 좋다는 것이다. 즉 경사하강법과 역방향 계산에 의해 수행
하는 것은 파라메터를 더욱 많이 조정 해야 좋은 성능이 나온다.
아래 코드는 RMSE 코드를 비교한 스크립트 코드이다.
print('통계학적방법의 RMSE값은 {} 이고 경사하강법에 의한 RSME는 {} 입니다.'.format(rmse_stat,rmse_w))
통계학적방법의 RMSE값은 57.0 이고 경사하강법에 의한 RSME는 94.0 입니다
|
모델 비교 RMSE |
위와 같이 그래프를 그렸을대, 통계학적인 방법이 경사 하강법보다 RMSE 값이 낮다.
댓글 없음:
댓글 쓰기