함께하는 데이터 분석

[Python] 규제 회귀 모델 본문

학회 세션/비어플

[Python] 규제 회귀 모델

JEONGHEON 2022. 4. 2. 16:03

이어서 Python으로

 

규제 회귀 모델인

 

라쏘, 릿지, 엘라스틱넷 regression을 알아보겠습니다.

 

 

모듈 및 데이터 불러오기

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression, Lasso, Ridge, ElasticNet, LassoCV, RidgeCV, ElasticNetCV
from sklearn.preprocessing import StandardScaler
from sklearn import metrics
from sklearn.metrics import mean_squared_error

import warnings
warnings.simplefilter('ignore')

train데이터와 test데이터를 분리하고

 

선형회귀, 라쏘, 릿지, 엘라스틱넷 회귀모델을 사용하고

 

mse와 표준화 작업을 하기위해

 

사이킷런 모듈을 불러왔습니다.

 

from sklearn.datasets import load_boston

boston = load_boston()
df = pd.DataFrame(boston.data, columns = boston.feature_names)
df['price'] = boston.target
df.head()

보스턴 데이터를 불러와줬고

 

데이터 프레임으로 바꿔줬습니다.

 

 

변수 설명

CRIM 범죄율
ZN 25,000 평방 피트 당 주거용 토지의 비율
INDUS 비소매(non-retail) 비즈니스 면적 비율
CHAS 찰스 강 더미 변수 (통로가 하천을 향하면 1; 그렇지 않으면 0)
NOX 산화 질소 농도 (천만 분의 1)
RM 주거 당 평균 객실 수
AGE 1940 년 이전에 건축된 자가 소유 점유 비율
DIS 5 개의 보스턴 고용 센터까지의 가중 거리
RAD 고속도로 접근성 지수
TAX 10,000 달러 당 전체 가치 재산 세율
PTRATIO 도시 별 학생-교사 비율
B 1000 (Bk-0.63) ^ 2 여기서 Bk는 도시 별 검정 비율
LSTAT 인구의 낮은 지위
price 자가 주택의 중앙값 (1,000 달러 단위)

 

 

데이터 구조

df.info()

 

df.describe()

 

 

데이터 전처리

# X, y 분할
X = df.drop(['price', 'CHAS'], axis = 1)
y = df['price']

X와 y로 분리시켜줬고

 

X를 설명변수,  y를 타깃변수로 지정해줬습니다.

 

타깃변수를 price로 설정했죠.

 

print("X : ", X.shape)
print("y : ", y.shape)

>>> X :  (506, 12)
    y :  (506,)

설명변수인 X는 506행 12열

 

타깃변수인 y는 506행 1 열인 것을 알 수 있습니다.

 

# StandardScaler
X_scaled = StandardScaler().fit_transform(X)
X_scaled = pd.DataFrame(X_scaled, columns = X.columns)
X_scaled.head()

앞서 이론에서 말씀드린 것처럼

 

변수 간의 값 차이가 많이 나므로

 

표준화 작업을 진행해줬습니다.

 

# train, test 데이터 분할
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size = 0.3, random_state = 1234)

X와 y 각각 train데이터와 test데이터로 분리해줬는데

 

test데이터의 사이즈를 전체의 30%

 

즉, train데이터를 70%로 만들어줬습니다.

 

print("X_train : ", X_train.shape)
print("y_train : ", y_train.shape)
print("X_test : ", X_test.shape)
print("y_test : ", y_test.shape)

>>> X_train :  (354, 12)
    y_train :  (354,)
    X_test :  (152, 12)
    y_test :  (152,)

따라서 train데이터가 354행으로 구성되고

 

test데이터가 152행으로 구성된 것을 볼 수 있죠.

 

 

모델링

1. Linear Regression

model = LinearRegression()
model.fit(X_train, y_train)
pred_train = model.predict(X_train)
pred_test = model.predict(X_test)

rmse_train = np.sqrt(mean_squared_error(y_train, pred_train))
rmse_test = np.sqrt(mean_squared_error(y_test, pred_test))

print("-----Linear regression-----")
print("train RMSE : ", round(rmse_train,3))
print("test RMSE : ", round(rmse_test,3))

>>> -----Linear regression-----
    train RMSE :  4.731
    test RMSE :  4.934

Linear regression 결과 train데이터의 RMSE는 4.731

 

test데이터의 RMSE는 4.934가 나왔습니다.

 

model.coef_

>>> array([-0.84140014,  1.52655434, -0.03424108, -2.46775466,  1.82310149,
            0.21601194, -3.98417659,  3.37876671, -2.61704632, -2.4071317 ,
            0.87645959, -4.12483541])

model.coef_ 를 통해 각각의 회귀계수 추정치를 알아봤습니다.

 

model.intercept_

>>> 22.447346745312675

model.intercept_를 통해 회귀선의 절편을 알아봤습니다.

 

 

2. Lasso Regression

model = Lasso(alpha = 0.1, random_state = 1234)
model.fit(X_train, y_train)
pred_train = model.predict(X_train)
pred_test = model.predict(X_test)

rmse_train = np.sqrt(mean_squared_error(y_train, pred_train))
rmse_test = np.sqrt(mean_squared_error(y_test, pred_test))

print("-----Lasso regression-----")
print("train RMSE : ", round(rmse_train,3))
print("test RMSE : ", round(rmse_test,3))

>>> -----Lasso regression-----
    train RMSE :  4.788
    test RMSE :  4.811

Lasso regression에서 알파를 0.1을 주었을 때

 

train데이터의 RMSE값이 4.788

 

test데이터의 RMSE값이 4.811인 것을 확인할 수 있습니다.

 

plt.figure(figsize = (6, 3))

coef = pd.Series(model.coef_, index = X_train.columns).sort_values()
plt.bar(coef.index, coef.values)
plt.title("Lasso / alpha = 0.1")
plt.xticks(rotation = 90)

Lasso regression을 활용할 때 각각의 회귀계수를 시각화한 결과입니다.

 

이번에는 알파 값을 여러 가지로 바꿔볼까요?

 

alpha_list = [0.001, 0.01, 0.1, 0.5, 1]

for alpha in alpha_list:
    model = Lasso(alpha = alpha, random_state = 1234)
    model.fit(X_train, y_train)
    pred = model.predict(X_test)
    rmse = np.sqrt(mean_squared_error(y_test, pred))
    print("alpha = ", alpha, "일 때, RMSE = ", round(rmse,3))
    
>>> alpha =  0.001 일 때, RMSE =  4.932
    alpha =  0.01 일 때, RMSE =  4.914
    alpha =  0.1 일 때, RMSE =  4.811
    alpha =  0.5 일 때, RMSE =  5.006
    alpha =  1 일 때, RMSE =  5.27

알파 값이 여러 가지로 바뀜에 따라

 

test데이터의 RMSE값이 바뀌는 것을 볼 수 있죠.

 

이제 alpha 값의 변화에 따른 각각의 회귀 계수를 시각 해보겠습니다.

 

fig, axs = plt.subplots(figsize = (18, 6), nrows = 1, ncols = 5)

for pos, alpha in enumerate(alpha_list):
    model = Lasso(alpha = alpha, random_state = 1234)
    model.fit(X_train, y_train)
    coef = pd.Series(model.coef_, index = X_train.columns).sort_values()
    sns.barplot(x = coef.values, y = coef.index, ax = axs[pos])
    axs[pos].set_title("alpha = " + str(alpha))
    axs[pos].set_xlim(-5, 4)
    
plt.show()

앞서 말씀드린 것처럼 Lasso regression은 회귀계수 값을 0으로 만들 수 있는 것을 볼 수 있습니다.

 

 

3. Ridge Regression

model = Ridge(alpha = 10, random_state = 1234)
model.fit(X_train, y_train)
pred_train = model.predict(X_train)
pred_test = model.predict(X_test)

rmse_train = np.sqrt(mean_squared_error(y_train, pred_train))
rmse_test = np.sqrt(mean_squared_error(y_test, pred_test))

print("-----Ridge regression-----")
print("train RMSE : ", round(rmse_train,3))
print("test RMSE : ", round(rmse_test,3))

>>> -----Ridge regression-----
    train RMSE :  4.754
    test RMSE :  4.825

알파를 10을 줬을 때 train과 test데이터의 RMSE값입니다.

 

마찬가지로 회귀계수를 시각화해보겠습니다.

 

plt.figure(figsize = (6, 3))

coef = pd.Series(model.coef_, index = X_train.columns).sort_values()
plt.bar(coef.index, coef.values)
plt.title("Ridge / alpha = 10")
plt.xticks(rotation = 90)

이번에도 마찬가지로 알파 값에 변화를 주고 RMSE값을 비교해보겠습니다.

 

alpha_list = [0, 0.1, 1, 10, 100]

for alpha in alpha_list:
    model = Ridge(alpha = alpha, random_state = 1234)
    model.fit(X_train, y_train)
    pred = model.predict(X_test)
    rmse = np.sqrt(mean_squared_error(y_test, pred))
    print("alpha = ", alpha, "일 때, RMSE = ", round(rmse,3))
    
>>> alpha =  0 일 때, RMSE =  4.934
    alpha =  0.1 일 때, RMSE =  4.932
    alpha =  1 일 때, RMSE =  4.917
    alpha =  10 일 때, RMSE =  4.825
    alpha =  100 일 때, RMSE =  4.93

알파가 10일 때 가장 낮은 RMSE값을 가지는 것을 볼 수 있습니다.

 

마찬가지로 각각의 알파 값에 대한 회귀계수를 시각화해보겠습니다.

 

fig, axs = plt.subplots(figsize = (18, 6), nrows = 1, ncols = 5)

for pos, alpha in enumerate(alpha_list):
    model = Ridge(alpha = alpha, random_state = 1234)
    model.fit(X_train, y_train)
    coef = pd.Series(model.coef_, index = X_train.columns).sort_values()
    sns.barplot(x = coef.values, y = coef.index, ax = axs[pos])
    axs[pos].set_title("alpha = " + str(alpha))
    axs[pos].set_xlim(-5, 4)
    
plt.show()

 

 

3. ElasticNet Regression

model = ElasticNet(alpha = 0.1, random_state = 1234)
model.fit(X_train, y_train)
pred_train = model.predict(X_train)
pred_test = model.predict(X_test)

rmse_train = np.sqrt(mean_squared_error(y_train, pred_train))
rmse_test = np.sqrt(mean_squared_error(y_test, pred_test))

print("-----ElasticNet regression-----")
print("train RMSE : ", round(rmse_train,3))
print("test RMSE : ", round(rmse_test,3))

>>> -----ElasticNet regression-----
    train RMSE :  4.821
    test RMSE :  4.782

알파가 0.1일 때 ElasticNet regression의 RMSE를 구해봤습니다.

 

 

k-fold cross validation으로 하이퍼 파라미터 찾기

cv = 5
alpha_list = [0.01, 0.05, 0.07, 0.1, 0.5, 0.75, 1, 3, 5, 7, 10]

k-fold cross validation을 통해 

 

모든 데이터를 최소 한번 test데이터로 사용하여

 

결과가 편향되는 것을 방지하여

 

최적의 하이퍼 파라미터 값을 찾아보겠습니다.

 

# find optimal Lasso model
model = LassoCV(alphas = alpha_list, cv = cv)
model.fit(X_train, y_train)
print("Lasso : alpha = ", model.alpha_)

>>> Lasso : alpha =  0.01

위에서 Lasso regression에서 RMSE값이

 

알파가 0.01에서 가장 작았던 것처럼

 

하이퍼 파라미터도 0.01로 나오는 것을 볼 수 있습니다.

 

# find optimal Ridge model
model = RidgeCV(alphas = alpha_list, cv = cv)
model.fit(X_train, y_train)
print("Ridge : alpha = ", model.alpha_)

>>> Ridge : alpha =  10.0

Ridge regression도 마찬가지로 알파가 10일 때

 

RMSE가 가장 작았었죠.

 

# find optimal ElasticNet model
model = ElasticNetCV(alphas = alpha_list, cv = cv)
model.fit(X_train, y_train)
print("ElasticNet : alpha = ", model.alpha_)

>>> ElasticNet : alpha =  0.01

ElasticNet regression은 여러 가지 알파 값일 때

 

돌려보지는 않았지만 알파 값이 0.01일 때

 

RMSE가 가장 작을 것이라고 유추할 수 있습니다.

 

여기까지 규제 회귀 모델에 대해

 

Python으로 실습해봤습니다.


Copyright

 

- 비어플 빅데이터 학회

'학회 세션 > 비어플' 카테고리의 다른 글

규제 회귀 모델  (0) 2022.04.02
[R] 로지스틱 회귀 & LDA  (0) 2022.03.26
[Classification] LDA(선형 판별분석)  (0) 2022.03.26
[Python] IMAGE(2D data) AUGMENTATION  (0) 2022.03.24
[R] 데이터 불균형 해소  (0) 2022.03.20