앞에 글에서 선형 모델을 깨뜨리는 다중공선성 문제를 언급했었다.
다중 공선성이란 무엇일까?
입력 데이터가 갖고 있는 특징값들 사이에 상관 관계가 존재할 때 발생하는 문제 상황
이 상황에서는 머신 러닝 모델이 작은 데이터 변화에도 민감하게 반응
즉, 안정성과 해석력을 저하시킬 수 있음
다중공선성이 있는 데이터를 사용할 때,
정규 방정식으로 해를 구하는 상황에서는 치명적인 문제가 발생
이 상황을 해결하기 위해 SVD-OLS라는 회피 방법이 존재
SVD-OLS란 SVD를 활용해 선형 회귀 모델의 해를 구하는 방법이다.
학습 데이터를 모아둔 행렬 X에 SVD를 적용해 특이값 분해 (X = UΣVt)
• 특이값이 분해된 입력 X에 OLS 방식의 풀이를 적용



# SVD-OLS 방식을 이용한 선형 모델 풀이
# w = V @ SIGMA-1 @ U^T @ y
def calc_SVDOLS(X, y):
# svd를 적용해 U, SIGMA, V^T(Vt)를 구함
U, s, Vt = np.linalg.svd(X, full_matrices=False)
SIGMA = np.diag(s)
# SVD-OLS 수식 적용
w_svdols = Vt.T @ np.linalg.inv(SIGMA) @ U.T @ y
return w_svdols
w_svdols = calc_SVDOLS(X, y)
w_ols = calc_OLS(X, y)
print('SVD OLS로 예측한 w0 : ', w_svdols[0])
print('SVD OLS로 예측한 w1 : ', w_svdols[1])
print('-'*50)
print('OLS로 예측한 w0 : ', w_ols[0])
print('OLS로 예측한 w1 : ', w_ols[1])
print('-'*50)
print('실제 w0 : ', w0)
print('실제 w1 : ', w1)

SVD OLS로 예측한 것과 OLS로 예측한 것의 결과값이 거의 동일한 것을 볼 수 있다.
w_svdols = calc_SVDOLS(X_col, y_col)
print('SVD OLS로 예측한 w0 : ', w_svdols[0])
print('SVD OLS로 예측한 w1 : ', w_svdols[1])
print('SVD OLS로 예측한 w2 : ', w_svdols[2])
print('-'*50)
print('실제 w0 : ', w0_col)
print('실제 w1 : ', w1_col)
print('실제 w2 : ', w2_col)

SVD OLS 값이 엄청 이상하게 나온다.
과적합 문제 (Over-fitting)
과적합이 발생하면 파라미터인 w의 값이 매우 커지게 됨
따라서, w의 값이 너무 커지지 않도록 규제(regulation)를 가해 과적합 문제를 회피할 수 있음
선형 모델에서 규제를 추가해 일반화 성능에 도움이 되도록 설계한 모델이 있음
머신 러닝 모델의 목적은 비용 함수의 최소화
이에 따라 기존 비용 함수에 제어할 변수 항목을 추가하는 방식으로 규제를 진행
추가로 규제 강도를 조절할 수 있는 새로운 변수 a를 추가




릿지 회귀에 사용되는 L2 규제는 파라미터 값을 적당히 작게 만듦
이는 입력으로 받는 데이터의 모든 부분을 이용해 출력을 판단하는데 사용
따라서, 모든 특성이 출력 결과에 적당히 영향을 미치는 경우에 유용함

from sklearn.linear_model import Lasso, Ridge
lasso_reg = Lasso(alpha=0.1)
lasso_reg.fit(X, y)
print('Lasso 예측 w0 와 w1 : ', lasso_reg.intercept_, lasso_reg.coef_[1])
ridge_reg = Ridge(alpha=0.1)
ridge_reg.fit(X, y)
print('Ridge 예측 w0 와 w1 : ', ridge_reg.intercept_, ridge_reg.coef_[1])
print('-'*50)
print('실제 w0 : ', w0)
print('실제 w1 : ', w1)

Lasso에서 w1이 0이 아닌경우도 있다
Lasso에서 0으로 만드는 것은 의미가 없는 것만 0으로 만들기 때문!