Statictics & Math & Data Science/파이썬 데이터 분석

[Regression] Ridge and Lasso Regression in Python (2) - Ridge

Taewon Heo 2019. 1. 31. 19:36

[Regression] Ridge and Lasso Regression in Python(2)


이번엔 Ridge Regression을 파이썬으로 구현해서 파라미터값에 따른 회귀식의 차이를 살펴보겠습니다.


L2와 L1 Regularization은 이전 포스팅의 내용을 참고해주세요.


1. 데이터를 생성합니다.


import numpy as np
import pandas as pd
from matplotlib.pylab import rcParams
rcParams['figure.figsize'] = 8, 5
from sklearn.linear_model import Ridge
import matplotlib.pyplot as plt

x = np.array([i*np.pi/180 for i in range(60, 300, 4)])
np.random.seed(10)
y = np.sin(x) + np.random.normal(0, 0.15, len(x))
data = pd.DataFrame(np.column_stack([x, y]), columns=['x', 'y'])
plt.plot(data['x'], data['y'], '.')
for i in range(2, 16): # power
colname = 'x_%d'%i #new var will be x_power
data[colname] = data['x']**i

2. 케이스를 구분하고 결과값을 저장할 테이블을 만듭니다.

Polynomial regression과 마찬가지로 predictors에 차수를 확장시켜 컬럼명(feature name)을 저장합니다.

파라미터값인 alpha_ridge를 케이스 별로 나눕니다.

# Initialize predictors to be set of 15 powers of x
predictors=['x']
predictors.extend(['x_%d'%i for i in range(2,16)])

# Set the different values of alpha to be tested
alpha_ridge = [1e-15, 1e-10, 1e-8, 1e-4, 1e-3,1e-2, 1, 5, 10, 20] #파라미터값인 alpha_ridge를 케이스 별로 나눕니다.

# Initialize the dataframe for storing coefficients.
col = ['rss', 'intercept'] + ['coef_x_%d'%i for i in range(1,16)]
ind = ['alpha_%.2g'%alpha_ridge[i] for i in range(0,10)]
coef_matrix_ridge = pd.DataFrame(index=ind, columns=col)

models_to_plot = {1e-15:231, 1e-10:232, 1e-4:233, 1e-3:234, 1e-2:235, 5:236}

3. Ridge regression 함수를 작성합니다.

여기서 추가로 필요한 파라미터는 alpha입니다.

def ridge_regression(data, predictors, alpha, models_to_plot):
# Fit the model
ridgereg = Ridge(alpha=alpha, normalize=True)
ridgereg.fit(data[predictors], data['y'])
y_pred = ridgereg.predict(data[predictors])

# Check if a plot is to be made for the entered alpha
if alpha in models_to_plot:
plt.subplot(models_to_plot[alpha])
plt.tight_layout()
plt.plot(data['x'], y_pred)
plt.plot(data['x'], data['y'], '.')
plt.title('Plot for alpha: %.3g'%alpha)

# Return the result in pre-defined format
rss = sum((y_pred-data['y'])**2)
ret = [rss]
ret.extend([ridgereg.intercept_])
ret.extend(ridgereg.coef_)
return ret

4. 결과 테이블을 계산합니다.

for i in range(10):
coef_matrix_ridge.iloc[i, ] = ridge_regression(data, predictors, alpha_ridge[i], models_to_plot)

계수를 잘 보면 α값이 작을수록 계수값이 커집니다. α값이 큰 경우 언더피팅이 발생하고 rss값이 큰 것을 알 수 있습니다.

pd.options.display.float_format = '{:,.2g}'.format
print(coef_matrix_ridge)
plt.show()

적당한 α값을 찾는 것이 중요합니다.

Ridge regression의 특징은 계수를 0으로 만들지는 않는다는 것입니다.


왜 계수가 0이 되지않는지 확인하기 위해 Cost function으로 돌아가보겠습니다.

Cost function을 최소화하는 방법 중 Gradient descent method를 생각해보겠습니다.

Cost function을 미분하면 아래와 같은 식이 나옵니다.

식을 다시 쓰면 아래와 같습니다.

wj 오른쪽을 제외하고 wj만 보면 일정한 비율로 t+1에서의 계수값이 작아진다는 것을 알 수 있습니다. 1-2λη가 계수의 크기보다 작아지면 부정확할 수 있다는 경고가 발생합니다.


즉, 계수가 %의 비율로 작아진다는 뜻입니다. 어떤 계수 값이 %로 작아진다고해도 0은 되지 않기때문에 L2 가중치 규제는 계수가 0이 되지 않습니다.

또 다른 설명으로는, 가중치 제한인 s의 범위에 따른 해석입니다.

B-hat은 최소제곱자승법으로 구한 최소 지점입니다. s가 점점 커지다보면 B-hat에 도달하는데 이 지점은 파라미터가 0이되는 때입니다.

B-hat 주변의 타원은 RSS를 나타내는데 RSS와 파란색 영역이 닿는 부분이 계수값이 됩니다.



왼쪽 그림은 Lasso의 경우인데 Lasso는 어쩌다가 꼭지점에서 RSS가 최소가 될 수 있습니다. 그렇게 되면 그 B1의 가중치가 0이 될것입니다. 반면 오른쪽 그림의 Rigde는 원이기 때문에 축에서 만나지 않으므로 가중치가 0이되는 일이 없습니다.


도움이 되셨다면 공감 부탁드려요!