공부

BDA X 이지스퍼블리싱 서평단 이벤트 [Do it! 데이터 과학자를 위한 실전 머신러닝]/ 2장: 최소 제곱 모델

무른2 2023. 12. 11. 18:59

 

2장 : 최소 제곱 모델

 

최소 제곱 모델(=OLS) 정의

 

1) 개념:  목표값과 본 모델에서 도출되는 예측값을 이용해 정의한 비용 함수가 평균 제곱 오차 (MSE)인 모델

 

 

예측값과 목표값의 차이인 잔차 제곱합을 최소화하는 파라미터 w를 찾는 모델

 

 

2) 방법: 정규방정식 이용/특잇값 분해 이용/tsvd-ols 이용/패키지로 표현

 

 

정규 방정식을 이용한 풀이 이론

 

- 가장 기본적이고 직관적인 방법

 

- X = n*p인 피처 행렬, y = 목표값

 

 

- X는 다중공선성이 X인 상태 =  풀칼럼랭크일 때! = ols 적용을 위한 최소한의 필요조건


 

1) OLS 식

 

y = X*w  +

 

      - 선형 결합

      - 차항

 

- 목표: 오차 제곱의 합 최소화 (모델 성능을 높이기 위해)

 

 

위 과정을 통해 해를 구할 수 있다.

 

- 극값이 최솟값인지 확인하는 방법은 헤시안(H)을 사용하면 된다.

 

 


2) 풀이 구현

- 모델 성능은 MAE로 측정

import numpy as np
from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split
X,y = load_diabetes(return_X_y = True, as_frame = False) #X, y를 numpy 배열로 입력 받음
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.33, random_state =42)
y_train = y_train.reshape(-1,1) #y의 두번째 차원을 1차원으로 설정
y_test = y_test.reshape(-1,1) #y의 두번째 차원을 1차원으로 설정
n_train, n_test = X_train.shape[0]. X_test.shape[0]
O(np )
2
2장 최소 제곱법 모델 3
X_train = np.append(np.ones((n_train,1)), X_train, axis = 1) #X_train 가장 왼쪽에 상수피처 추가
w = np.linalg.inv(X_train.T @ X_train) @(X_train.T @ y_train)
#@는 행렬곱
#np.linalg.inv() 는 역행렬로 만드는 함수
y_pred_trian = X_train @ w
print(f'학습 데이터 셋 MAE: {np.abs(y_pred_train - y_train).mean(): .3f}')
X_test = np.append(np.ones((n_test, 1)), X_test, axis =1)
y_pred = X_test @ w
print(f'테스트 데이터 셋 MAE: {np.abs(y_pred_train - y_test).mean(): .3f}')

정규 방정식 구현의 단점

 

피처 사이의 종속성이 커질수록, 즉 다중공선성이 발생할 때, ols의 추정값은 목표값의 변동 과 오차에 영향을 준다.

 

 

이때는 정규방정식을 이용한 ols는 적절하지 않다고 볼 수 있겠다.

 

 

특잇값 분해(SVD)를 이용한 최소제곱법 모델 구현

 

정의: 행렬을 특수한 형태의 세 행렬의 곱으로 분해하는 것

 

- X 는 nxp(n>p) 차원을 가지는 풀 칼럼 랭크 행렬

- X(n*p) = U(n*n) ∑(n*p) V^t (p*p)     (U,V 는 직교 행렬, ∑ 는 직각 대각 행렬)

 

 

 

SVD_OLS의 풀이 시간 복잡도

 

- 전체 과정의 시간 복잡도는 정규 방정식 풀이의 시간 복잡도와 동일하다.

import numpy as np
from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test split
X, y = load_ diabetes(return_X_y=True, as_frame-False)
X train, X_test, y_train, y_test = train_test split(X,y,test_size-0.33, random state=42)
train y_train.reshape(-1, 1)
y_test = y_test.reshape(-1, 1)
n_train, n_test = X_train.shape[0], x_test.shape[0]
X_train = np.append(np.ones((n_train, 1)), x_train, axis-1)
X_test = np.append(np.ones((n_test, 1)), X_test, axis=1)
u,s,vh = np.linalg.svdX_train, full_matrices-False)
W = vh.T @ np.linalg.inv(np.diag(s)) @ u.T @ y-train
y-pred_train = Xtrain @ w
print(f'학습 데이터셋 MAE:(np.abs(y-pred_train -y_train)
.mean(): .3f)')
(n ∗ p) U(n ∗ n) Σ(n ∗ p) V (p ∗
T p) U, V Σ
2장 최소 제곱법 모델 4
y_pred = Xtest W
print(f'테스트 데이터셋 MAE: [np.abs(y_pred - y_test).mean(): .3f)")

 

정규 방정식 풀이의 단점과 SVD-OLS의 장점

 

1. 정규 방정식 풀이와 SVD-OLS 풀이는 수학적으로 동일한 해를 산출힌다.

 

2. 행렬이 특이행렬에 가까울수록 OLS는 다중공선성이 커져 조건수가 증가한다.

 

3. 조건수는 x의 작은 변화에 w의 해가 얼마나 변동하는지의 측정치를 나타낸다.

 

4. w의 불안정성은 SVD에 비해 정규 방정식을 이용할 때 많이 늘어난다.

 

5. 따라서 수치적으로 다른 해를 산출하게 된다.

 

6. 또한 정규방정식의 풀이는 과다한 메모리 사용 문제도 있다.

 

 

 


TSVD-OLS를 이용한 모델 구현하기

 

- 정규방정식 풀이와 SVD 풀이는 피처가 불안정할 때, 해의 불안정성도 크다.

- 이를 해결하기 위해 파라미터의 크기를 규제하는 방법이 사용되는데, 그 중 하나가 TSVD이다.

 

 

1) 개념

: 작은 특잇값을 제거하여 피처 행렬을 안정적인 형태로 근사하고 해를 풀이하는 방법

 

- s의 모든 특잇값 대신 k개()<k<p)의 가장 큰 특잇값만 선택 후 나머지 부분을 제거하고,

그 부분에 대응하는 u의 열과 v의 행을 버려 x를 근사한다.

 

- 기존의 해와 다르게 학습 데이터의 최적해가 아닌 편향된 해이지만 불안정한 피처행렬에도 강건한 성질을 가진다.

 

- k의 선택 기준: x의 조건수가 일정 임계값 밑으로 내려가게 하는 것.

일부 특잇값을 제거하여 분모를 일정 수준 이상으로 올리면 된다.

 

- 시간 복잡도는 정규 방정식 풀이 혹은 SVD-OLS와 같다.

 

 

2) 풀이 구현

import numpy as np
from sklearn.datasets import load_diabetes
import matplotlib.pyplot as plt
omatplotlib inline
X, y = load_diabetes(return_X y=True, as_frame-False)
2장 최소 제곱법 모델 5
X_train, X_test, y_train, y_test = train test_split(X, y, test_size-0.33,random_state=1234)
y_train = y_train.reshape(-1, 1)
y_test = y_test.reshape(-1, 1)
ntrain, n test = X train.shape[0], x_ test.shape[0]
X_train = np.append(np.ones((n train, 1)), X_train, axis-1)
X_test " np.append(np.ones((n_test, 1)), x_test, axis=1)
u, s, vh = np.linalg.svd(x_train, full matrices=False)
print("Sigma Zk:', s)
num_trunc = 2
vh = vh[:-num_trunc, :]
s=s[:-num_trunc]
u = u[: :-num_trunc]
w = vh.T a np.Linalg.inv(np.diag(s)) D U.T y_train
y-pred_train = X_train @ w
print(f'학습 데이터셋 MAE:(np.abs(y_pred_train - y_train).mean(): .3f)')
y_pred =X_test a w
print(f'테스트 데이터셋 MAE:fnp.abs(y_pred - y_test).mean(): .3f))
train_maes = []
test_maes = []
num_ truncs = range(X train.shape[1])
for num trunc in num_truncs, :]
u, s, vh = np.linalg.svd(x_train, full_matrices-False)
if num_ trunc != 0:
vh = vh[:-num_trunc,
s = s[:-num_trunc]
u= u[:, :-num_trunc]
w=Vh.T np.linalg.inv(np.diag(s)) a U.T a y_train
y_pred_train= X_train @ w
train_maes. append(np.abs(y_pred_train - y_train).mean())
y_pred = X_test @ w
test_maes.append(np.abs(y_pred - y_test).mean())
plt.plot(num truncs, train maes, label='Train Set MAE')
plt.plot(num truncs, test_ maes, label='TEST Set MAE')
plt. legend()

 


 

패키지로 표현하기

 

- sklearn.linear_model.LinearRegression 클래스 사용 → OLS 모델을 SVD를 이용해 추정 

 

1) 주요 하이퍼파라미터

- fit_intercept : 절편 포함 여부를 결정, 기본값 = True

 

- positive : 비음수 최소 제곱법 적용 여부를 결정

(비음수 최소 제곱법: 유클리드 표준 값을 최소로 하며, 양수값을 가지는 가중치를 찾는 것)

 

- 모든 계수가 0 이상이라는 조건에서 유용함 2장 최소 제곱법 모델 ( 예: 상품의 가격이나 빈도 값 추정 시)

 

2) 구현하기

import numpy as np
from sklearn.datasets import load diabetes
from sklearn.model _selection import train test _split
from sklearn. linear model import LinearRegression
X, y = load_diabetes(return_X_y=True)
X train, X_test, y_train, y_test = train_ test split(X,y, test size-0.33.random_state=42)
reg = LinearRegression()
reg = reg.fit(x_ train, y_train)
y_pred_train = reg.predict(X_train)
print(f'학습 테이터셋 MAE:fnp.abs(y_pred_train -y_train).mean(): .3f)')
y_pred = reg.predict(X test)
print(f'테스트 데이터셋 MAE:[np.abs(y_pred - y_test).mean(): .3f)')

 

최소 제곱법 모델 보충

 

1) 통계 모델로서의 OLS

- statsmodels 패키지를 통해 신뢰구간과 p-value(유의확률) 등을 계산할 수 있다.

 

 

2) 결정계수(R^2)

- 예측력의 성과 지표로 사용

 

- 항상 1 이하의 값을 가지며, 학습데이터에 대한 결정계수 값은 0 이상

 

- 다만, 적합 후 테스트 데이터로 결정계수를 구할 때는 음수가 나올 수 있다.

 

- 상수 모델을 학습 데이터에 적용할때는 결정계수가 0이 된다.

 

 

3) 화이트 박스 모델과 블랙 박스 모델

 해석력: 학습한 모델의 예측 결과를 사람이 얼마나 쉽게 해석할 수 있는지를 나타낸다.

 

- 내부 구조와 판단 논리를 이해하기 쉬울수록/산출 이유를 쉽게 파악할 수 있을수록 해석력이 높다고 볼 수 있다.

 

- 개발자에게는 학습의 질을, 사용자에게는 신뢰도를 주기에 활용도가 높다.

 

- 예측력이 높아도 해석력이 낮으면 예측의 리스크를 가진다.

 

1) 화이트 박스 모델: 해석력이 높은 모델

2) 블랙 박스 모델: 해석력이 낮은 모델