- 규제 선형 회귀 개요
- 최초 목표는 RSS(오차)를 최소화하는 것이었지만, 그러다보니 회귀 계수가 커져서 과대적합이라는 문 제를 만나게 되었다.
- 그래서 RSS와 더불어 회귀 계수 크기를 밸런스있게 제어하는 것이 필요하게 되었다.
- -> 비용 함수의 목표가 밸런스 조절(RSS값 최소화, 회계 계수 값 제어)이 됨
- 릿지는 데이터에서 영향력이 큰 수치를 다른 데이터들과 비슷하게 만들어주어 영향력을 낮춰주고
- 리쏘는 데이터에서 영향력이 미미한 수치를 다른데이터와 비슷하게 올려주는 회귀이다.
- 평균 제곱근 오차(Root Mean Square Error; RMSE
- rmse는 낮을 수록 좋다 -> 이뜻은 다른 데이터들과의 오차가 적다는 뜻을 의미한다.
- 릿지와 리쏘는 둘다 목표는 수치를 비슷하게 만들어주는 것에 있기 때문이다.
01_릿지¶
릿지 회귀로 보스톤 집값 예측¶
In [14]:
from sklearn.linear_model import Ridge
from sklearn.model_selection import cross_val_score
from sklearn.datasets import load_boston
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
boston =load_boston()
bostondf=pd.DataFrame(boston.data, columns=boston.feature_names)
bostondf['PRICE']= boston.target
y_target =bostondf['PRICE']
X_data=bostondf.drop(['PRICE'],axis=1,inplace=False)
#랏지 클래스
ridge= Ridge(alpha=10)
neg_mse_scores = cross_val_score(ridge, X_data,y_target,scoring='neg_mean_squared_error',cv=5)
rmse_scores = np.sqrt(-1* neg_mse_scores)
avg_rmse = np.mean(rmse_scores)
print('5 fold 의 개별 negtivate mse scores:',np.round(neg_mse_scores,3))
print('5 fold 의 개별 rmse scors: ', np.round(rmse_scores,3))
print('5 fold의 평균 rmse:{0:.3f}'.format(avg_rmse))
5 fold 의 개별 negtivate mse scores: [-11.422 -24.294 -28.144 -74.599 -28.517]
5 fold 의 개별 rmse scors: [3.38 4.929 5.305 8.637 5.34 ]
5 fold의 평균 rmse:5.518
C:\Users\82105\anaconda3\lib\site-packages\sklearn\utils\deprecation.py:87: FutureWarning: Function load_boston is deprecated; `load_boston` is deprecated in 1.0 and will be removed in 1.2.
The Boston housing prices dataset has an ethical problem. You can refer to
the documentation of this function for further details.
The scikit-learn maintainers therefore strongly discourage the use of this
dataset unless the purpose of the code is to study and educate about
ethical issues in data science and machine learning.
In this special case, you can fetch the dataset from the original
source::
import pandas as pd
import numpy as np
data_url = "http://lib.stat.cmu.edu/datasets/boston"
raw_df = pd.read_csv(data_url, sep="\s+", skiprows=22, header=None)
data = np.hstack([raw_df.values[::2, :], raw_df.values[1::2, :2]])
target = raw_df.values[1::2, 2]
Alternative datasets include the California housing dataset (i.e.
:func:`~sklearn.datasets.fetch_california_housing`) and the Ames housing
dataset. You can load the datasets as follows::
from sklearn.datasets import fetch_california_housing
housing = fetch_california_housing()
for the California housing dataset and::
from sklearn.datasets import fetch_openml
housing = fetch_openml(name="house_prices", as_frame=True)
for the Ames housing dataset.
warnings.warn(msg, category=FutureWarning)
alphas = [0 , 0.1 , 1, 10 ,100]으로 변경하면서 RMSE값 측정
- 알파값이 증가할수록 모델 성능이 향상되고 있다.
In [12]:
# ridge에 사용될 alpha 파라미터의 값들을 정의
alphas = [0 , 0.1 , 1, 10 ,100]
# alphas list 값을 iteration하면서 alpha에 따른 평균 rmse를 구함
for alpha in alphas:
ridge = Ridge(alpha =alpha)
#cross_val_score을 이용해 5fold평균 rmse 계산
neg_mse_scores = cross_val_score(ridge, X_data, y_target, scoring='neg_mean_squared_error',cv=5)
avg_rmse= np.mean(np.sqrt(-1 * neg_mse_scores))
print('alpha {0}일때 5 fold 의 평균 rmse:{1:.3f}]'.format(alpha,avg_rmse))
alpha 0일때 5 fold 의 평균 rmse:5.829]
alpha 0.1일때 5 fold 의 평균 rmse:5.788]
alpha 1일때 5 fold 의 평균 rmse:5.653]
alpha 10일때 5 fold 의 평균 rmse:5.518]
alpha 100일때 5 fold 의 평균 rmse:5.330]
알파값이 증가할수록 실제 회귀계수 값이 작아지는 것을 확인하기¶
In [15]:
alphas = [0 , 0.1 , 1, 10 ,100]
# 각 alpha에 따른 회귀 계수 값을 시각화하기 위해 5개의 열로 된 맷플롯립 축 생성
fig , axs = plt.subplots(figsize=(18,6) , nrows=1 , ncols=5)
# 각 alpha에 따른 회귀 계수 값을 데이터로 저장하기 위한 DataFrame 생성
coeff_df = pd.DataFrame()
# alphas 리스트 값을 차례로 입력해 회귀 계수 값 시각화 및 데이터 저장. pos는 axis의 위치 지정
for pos , alpha in enumerate(alphas) :
ridge = Ridge(alpha = alpha)
ridge.fit(X_data , y_target)
# alpha에 따른 피처별 회귀 계수를 Series로 변환하고 이를 DataFrame의 컬럼으로 추가.
coeff = pd.Series(data=ridge.coef_ , index=X_data.columns )
colname='alpha:'+str(alpha)
coeff_df[colname] = coeff
# 막대 그래프로 각 alpha 값에서의 회귀 계수를 시각화. 회귀 계수값이 높은 순으로 표현
coeff = coeff.sort_values(ascending=False)
axs[pos].set_title(colname)
axs[pos].set_xlim(-3,6)
sns.barplot(x=coeff.values , y=coeff.index, ax=axs[pos])
# for 문 바깥에서 맷플롯립의 show 호출 및 alpha에 따른 피처별 회귀 계수를 DataFrame으로 표시
plt.show()
- NOX가 많이 작아져서 다른 회귀 계수와 스케일이 비슷해짐
알파값이 증가할수록 실제 회귀계수 값이 작아지는 것을 확인하기¶
In [16]:
ridge_alphas = [0 , 0.1 , 1, 10 ,100]
sort_colnm ='alpha:'+str(ridge_alphas[0])
coeff_df.sort_values(by=sort_colnm, ascending=False)
Out[16]:
alpha:0 | alpha:0.1 | alpha:1 | alpha:10 | alpha:100 | |
---|---|---|---|---|---|
RM | 3.809865 | 3.818233 | 3.854000 | 3.702272 | 2.334536 |
CHAS | 2.686734 | 2.670019 | 2.552393 | 1.952021 | 0.638335 |
RAD | 0.306049 | 0.303515 | 0.290142 | 0.279596 | 0.315358 |
ZN | 0.046420 | 0.046572 | 0.047443 | 0.049579 | 0.054496 |
INDUS | 0.020559 | 0.015999 | -0.008805 | -0.042962 | -0.052826 |
B | 0.009312 | 0.009368 | 0.009673 | 0.010037 | 0.009393 |
AGE | 0.000692 | -0.000269 | -0.005415 | -0.010707 | 0.001212 |
TAX | -0.012335 | -0.012421 | -0.012912 | -0.013993 | -0.015856 |
CRIM | -0.108011 | -0.107474 | -0.104595 | -0.101435 | -0.102202 |
LSTAT | -0.524758 | -0.525966 | -0.533343 | -0.559366 | -0.660764 |
PTRATIO | -0.952747 | -0.940759 | -0.876074 | -0.797945 | -0.829218 |
DIS | -1.475567 | -1.459626 | -1.372654 | -1.248808 | -1.153390 |
NOX | -17.766611 | -16.684645 | -10.777015 | -2.371619 | -0.262847 |
- 릿지 회귀에서 알파값이 증가할수록 NOX값의 감소하여서 다른 회귀 계수 값들과 스케일이 비슷해졌다. 이로 인해 기존 회귀 모델의 성능이 개선되었다.
02_라쏘¶
In [ ]:
L2 규제 vs L1 규제
L2의 경우에는 가중치의 값을 이용합니다. 어느 정도 튀는 값에 대해 대응할 수 있다는 소리죠. 따라서, 이상치나 노이즈가
있는 데이터에 대한 학습을 진행할 때 사용하면 좋습니다. 특히 선형 모델의 일반화에 좋습니다.
-> L2규제는 회귀 계수 값의 증감을 관리한다.
L1의 경우에는 가중치의 크기에 상관없이 상수값을 뺍니다. 이는 대체적으로 불필요한 가중치의 수치를
0으로 만들도록 하는 방향으로 적용됩니다.
즉, 중요한 가중치만을 취하기 때문에 sparse feature에 대한 모델을 구성하는데
In [21]:
from sklearn.linear_model import Lasso, ElasticNet
# alpha값에 따른 회귀 모델의 폴드 평균 RMSE를 출력하고 회귀 계수값들을 DataFrame으로 반환
def get_linear_reg_eval(model_name, params=None, X_data_n=None, y_target_n=None,
verbose=True, return_coeff=True):
coeff_df = pd.DataFrame()
if verbose : print('####### ', model_name , '#######')
for param in params:
if model_name =='Ridge': model = Ridge(alpha=param)
elif model_name =='Lasso': model = Lasso(alpha=param)
elif model_name =='ElasticNet': model = ElasticNet(alpha=param, l1_ratio=0.7)
neg_mse_scores = cross_val_score(model, X_data_n,
y_target_n, scoring="neg_mean_squared_error", cv = 5)
avg_rmse = np.mean(np.sqrt(-1 * neg_mse_scores))
print('alpha {0}일 때 5 폴드 세트의 평균 RMSE: {1:.3f} '.format(param, avg_rmse))
# cross_val_score는 evaluation metric만 반환하므로 모델을 다시 학습하여 회귀 계수 추출
model.fit(X_data_n , y_target_n)
if return_coeff:
# alpha에 따른 피처별 회귀 계수를 Series로 변환하고 이를 DataFrame의 컬럼으로 추가.
coeff = pd.Series(data=model.coef_ , index=X_data_n.columns )
colname='alpha:'+str(param)
coeff_df[colname] = coeff
return coeff_df
# end of get_linear_regre_eval
In [22]:
# 라쏘에 사용될 alpha 파라미터의 값들을 정의하고 get_linear_reg_eval()함수 추출
lasso_alphas =[0.07, 0.1, 0.5, 1 ,3]
coeff_lasso_df= get_linear_reg_eval('Lasso',params = lasso_alphas, X_data_n = X_data, y_target_n=y_target)
####### Lasso #######
alpha 0.07일 때 5 폴드 세트의 평균 RMSE: 5.612
alpha 0.1일 때 5 폴드 세트의 평균 RMSE: 5.615
alpha 0.5일 때 5 폴드 세트의 평균 RMSE: 5.669
alpha 1일 때 5 폴드 세트의 평균 RMSE: 5.776
alpha 3일 때 5 폴드 세트의 평균 RMSE: 6.189
In [ ]:
03_엘라스틱넷 회귀¶
In [ ]:
In [ ]:
'머신러닝 > 회귀' 카테고리의 다른 글
05-1_실습_UCIDATASET_콘크리트_회귀실습 (0) | 2022.10.25 |
---|---|
05_회귀 실습_자전거 대여 수요 예측_ 캐글 (0) | 2022.10.25 |
04_데이터 전처리(정규화,로그변환, 스케일러, 원-핫 인코딩 ) (0) | 2022.10.25 |
2_다항 선형 회귀 (0) | 2022.10.25 |
1_다중 선형 회귀 (0) | 2022.10.25 |