programming/파이썬으로 배우는 통계학

사이킷런을 활용한 머신러닝(linear_model) - 릿지 회귀와 라소회귀 최적의 정규화 강도 결정_[파이썬/머신러닝]

Jofresh 2023. 5. 29. 23:39
728x90
반응형

 

이전 포스팅과 연결되는 부분이 많아서 이전 포스팅을 태그 걸었습니다.

이번 포스팅에서는 머신러닝 실전을 해보겠습니다. 

 

[파이썬/통계] 통계학과 머신러닝 - 이론적인 부분들 (라소회귀, 리지회귀)

머신러닝 기본 머신러닝은 컴퓨터에 학습능력을 부여하는 것을 목적으로 한 연구 분야입니다. 학습은 데이터를 기반으로 행해져 데이터가 가지는 규칙성을 분명히 합니다. 규칙성을 분명히 함

jofresh.tistory.com

 

사이킷런

사이킷런은 파이썬에서 머신러닝을 적용하는 데 자주 사용되는 패키지입니다. sklearn이라고 줄여서 부르기도 합니다.

pip install sklearn

위 코드를 통해서 설치해주면됩니다. 리지회귀/라소회귀 외에도 뉴럴네트워크나 서포트 벡터머신등 여러 방법에 사용할 수 있습니다.

 

필요한 라이브러리 임포트

# 수치 계산에 사용하는 라이브러리
import numpy as np
import pandas as pd
import scipy as sp
from scipy import stats

# 그래프를 그리는 라이브러리
from matplotlib import pyplot as plt
import seaborn as sns
sns.set()

# 통계 모델을 추정하는 라이브러리(워크닝이 나올 수도 있습니다)
import statsmodels.formula.api as smf
import statsmodels.api as sm

# 기계 학습법을 적용하기 위한 라이브러리
from sklearn import linear_model

# 표시 자릿수 지정
%precision 3
# 그래프를 jupyter Notebook 내에 표시하도록 하기 위한 지정
%matplotlib inline

# 파일로부터의 데이터 가져오기
X = pd.read_csv("7-3-1-large-data.csv")
X.head(3)

- 파일 가져오는 코드도 위에 추가했습니다.

7-3-1-large-data.csv
0.10MB

 

 

- 샘플데이터는 x_1부터 x_100까지 100개 열이 있는 복잡한 데이터입니다. 현재는 종속변수는 없지만, 나중에 만들겠습니다.

 

표준화

먼저 데이터를 표준화합니다. 표준화는 각각의 변수에서 평균값을 빼고 표준편차로 나누는 작업입니다. 이렇게 하면 평균이 0, 표준편차가 1이 됩니다.

 

우선 X에 대해 평균값을 계산합니다. axis = 0으로 지정하여 열단위로 평균값을 한번에 계산합니다.

 

위와 같이 하면 단순하게 표준화 할 수 있습니다.

평균값이 0이 되었는지 확인합니다.

표준편차가 1이 되었는지 확인합니다.

 

둘 다 잘 되었습니다.

 

시뮬레이션으로 종속변수 만들기

위 데이터에는 종속변수가 없습니다. 올바른 계수를 알고 있는 상황에서 이를 제대로 추정할 수 있는지 체크하겠습니다.

올바른 계수를 5라고 설정하여 종속변수를 만듭니다. 정규분포에 따른 노이즈가 들어 있는걸로 하겠습니다.

위 코드는 응답 변수 y를 생성하는데 사용되는 코드입니다. 코드를 살펴보면 다음과 같은 작업이 수행됩니다:

np.random.seed(1): 난수 생성기의 시드를 1로 설정하여 난수 생성 과정을 재현 가능하게 합니다.
noise = sp.stats.norm.rvs(loc=0, scale=1, size=X.shape[0]): 평균이 0이고 표준편차가 1인 정규 분포를 따르는 난수를 생성합니다. 이 난수는 노이즈로 사용될 것입니다. X의 행의 개수와 같은 크기의 난수를 생성합니다.
y = X.X_1 * 5 + noise: X의 첫 번째 열(X_1)에 5를 곱한 값에 noise를 더하여 응답 변수 y를 생성합니다. 이렇게 생성된 y는 X_1의 값에 선형적인 변형을 가한 뒤에 노이즈가 추가된 형태입니다.

 

이 코드는 선형 회귀 모델에서 사용될 수 있는 가상의 데이터를 생성하는데 사용될 수 있습니다. X는 입력 변수를 나타내며, X_1은 첫 번째 열을 의미합니다. y는 예측하려는 응답 변수를 나타냅니다. 노이즈를 추가함으로써 실제 데이터에 존재하는 잡음 요소를 모델에 반영할 수 있습니다.

종속변수와 X_1의 관계를 그래프로 그려보았습니다.

종속변수는 제가 만든 가상의 데이터지만, 정교하게 만들어져 있어서 0에 가까운 데이터가 대부분을 차지하고 있고, 그런 와중에 가끔 큰 값이 나오고 있습니다.

 

일반적인 최소제곱법 적용하기

일반적인 최소제곱법을 이용해서 파라미터 추정을 하겠습니다. 독립변수가 많아서 formula를 작성하는 것이 번거로우므로 아래와 같이 독립변수와 종속변수를 지정해서 모델링합니다.

위 코드는 StatsModels 라이브러리를 사용하여 선형 회귀 모델을 적합시키고 모델의 계수를 추정하는 코드입니다. 코드를 살펴보면 다음과 같은 작업이 수행됩니다:

sm.OLS(endog=y, exog=X): OLS(Ordinary Least Squares/최소제곱법) 클래스를 사용하여 선형 회귀 모델을 생성합니다. endog는 종속 변수(y)를 나타내며, exog는 설명 변수(X)를 나타냅니다.
.fit(): 생성된 선형 회귀 모델을 적합시킵니다. 이 과정에서 최적의 계수를 추정하게 됩니다.
lm_statsmodels.params: 추정된 모델의 계수를 확인합니다. params 속성을 통해 계수 값을 확인할 수 있습니다.
.head(3): 계수 값 중 상위 3개를 출력합니다.

 

이를 통해 모델이 추정한 X 변수들의 계수 값을 확인할 수 있습니다.

 

이 결과를 보면 꽤 이상한 값으로 추정되었다는 것을 알 수 있습니다.

 

sklearn(사이킷런)을 이용한 선형회귀

정규화를 이용한 모델을 사용해보기 전에 사이킷런 사용법에 조금 익숙해지기 위해 사이킷런을 사용해서 일반적인 최소제곱법을 이용한 정규선형모델을 추정해보겠습니다. 

 

사이킷런에서는 먼저 모델의 구조를 지정한 후 fit함수의 파라미터로 데이터를 지정합니다.

추정된 계수는 coef_변수에 저장됩니다. 계수의 절댓값이 크게 추정되는 것에 주목해주세요.

 

릿지 회귀 - 벌칙항의 영향

일반적인 최소제곱법(OLS)로는 잘 되지 않는 것을 알 수 있었으므로 정규화를 사용합니다. 우선 리지 회귀를 이용하겠습니다. 정규화에 있어서 중요한 것은 정규화의 강도 알파의 결정입니다. 정규화의 강도 알파가 주는 영향부터 알아보도록 하겠습니다. 우선 알파를 50개 만듭니다.

[0.01 0.011 0.013 0.015 0.017 0.019 0.021 0.024 0.028 0.031 0.036 0.04 0.046 0.052 0.059 0.067 0.076 0.086 0.098 0.111 0.126 0.144 0.163 0.185 0.21 0.239 0.271 0.307 0.349 0.396 0.45 0.511 0.58 0.658 0.747 0.848 0.963 1.093 1.241 1.409 1.6 1.816 2.062 2.341 2.658 3.017 3.425 3.889 4.415 5.012]

위 코드는 일련의 알파 값을 생성하는데 사용되는 코드입니다. 코드를 살펴보면 다음과 같은 작업이 수행됩니다:

n_alphas = 50: 생성할 알파 값의 개수를 50으로 설정합니다. 이는 로지스틱 공간에서 생성할 알파 값의 수입니다.
ridge_alphas = np.logspace(-2, 0.7, n_alphas): np.logspace 함수를 사용하여 로그 스케일로 알파 값을 생성합니다. np.logspace 함수는 지정된 범위에서 로그 스케일로 동일 간격의 값들을 생성하는 함수입니다. 여기서는 범위가 -2부터 0.7까지이며, n_alphas 개의 값들을 생성합니다. 이렇게 생성된 알파 값들은 ridge regression(릿지 회귀)에서 정칙화(regularization) 파라미터로 사용될 수 있습니다.

 

알파 값은 릿지 회귀에서 사용되는 정칙화 파라미터로, 모델의 복잡도를 제어하는 역할을 합니다. 작은 알파 값은 모델을 덜 제약하고, 큰 알파 값은 모델을 더 제약합니다. np.logspace 함수를 사용하여 로그 스케일로 알파 값을 생성함으로써, 작은 값과 큰 값 사이에 동일한 간격으로 알파 값을 분포시킬 수 있습니다. 이렇게 생성된 알파 값들을 사용하여 릿지 회귀 모델의 여러 가지 복잡도를 탐색하고, 적절한 알파 값을 선택하는 데 활용할 수 있습니다.

 

np.log10 함수를 사용하여 주어진 값들의 로그10 값을 계산합니다. 로그10을 적용하면 각 알파 값의 로그10 변환된 값들을 반환합니다.

 

50개의 알파를 바꿔가면서 50번 릿지 회귀로 추정합니다. 릿지 회귀 추정에는 lenear_model.ridge 함수를 사용합니다. 파라미터로 알파와 '절편은 추정하지 않는다'는 옵션을 지정합니다.

추정된 계수를 numpy 배열로 변환합니다.

결과는 50행 100열의 배열입니다. 행 수는 알파의 개수입니다. 100열은 독립변수의 개수입니다.

이제 plt.plot(log_alphas, ridge_coefs[::,0]으로 그래프를 그리면 가로축에 알파, 세로축에 계수의 값을 표시한 그래프를 그립니다. 이를 100번 반복할 필요 없이 plt.plot 함수에 2차원 배열을 넘기면 자동으로 그래프를 여러개 그립니다.

 

결과를 보기 쉽게 하기 위해 가로축을 -log10알파로 변환한 뒤 그래프를 그립니다. 이런 그래프를 solution-path라고 합니다.

 

가로축이 -log10알파이므로 왼쪽으로 갈수록 알파가 크고, 정규화의 강도가 강하다는 데 주의하세요. 왼쪽으로 갈수록 계수의 절대치가 작게 추정되는 경향이 있고, 오른쪽으로 갈수록 벌칙이 완화되므로 계수의 절대치가 크게 추정되기 쉬워집니다.

여기서 주로 봐야 할 것은 X_1의 계수지만 -log10알파 값인 0 부근에서는 다른 계수보다 절댓값이 꽤 크게 추정되는 것 같습니다. 하지만 계숫값은 알파에 의해 크게 바뀝니다.

 

릿지 회귀 - 최적의 정규화 강도 결정

알파의 크기를 결정하는 작업을 하겠습니다. 교차검증법을 이용하여 예측 정확도를 평가해서 정확도가 가장 좋은 알파를 채택하여 모델을 재구축합니다. 이러한 과정에 사용된느 함수는 이미 준비되어 있습니다. RindgeCV함수를 이용합니다. cv= 10이라고 지정하고 10-fold-CV를 사용해서 예측 정확도를 평가합니다.

 

-log10알파 = 0.237 지점을 좀 전의 solution-path에서 보면 X_1 이외의 독립변수의 계수의 절댓값이 0에 가까운 것으로 나타납니다.

적합한 알파는 아래와 같습니다.

추정된 계수는 아래와 같습니다.

독립변수 X_1의 계수가 4.463이 된것을 보면 정답과 상당히 가까운 값이 된것으로 나타납니다. 릿지 회귀의 성과입니다. 여기서 다른 독립변수의 계수를 보면 나름대로 작은 값으로 되어 있지만 영향이 아예 없다고는 할 수 없습니다.

 

라소 회귀 - 벌칙항의 영향

지금부터는 정규화에 라소 회귀를 이용하겠습니다. solution-path가 릿지 회귀와 어떻게 다른지 확인해볼께요.

릿지 회귀와 마찬가지로 몇 번이고 정직하게 모델을 추정해도 되지만 lasso-path라는 편리한 함수가 있으므로 그것을 사용하겠습니다. 파라미터로 데이터를 지정하는 것만으로도 알파를 다양하게 변화시킨 결과를 출력합니다.

릿지 회귀와 마찬가지로 solution-path를 그립니다. lasso_coefs의 순서가 릿지 회귀때와 달라서 행렬을 전치시키거나 배열의 첨자가 달라지지만 코드는 거의 동일합니다.

 

라소 회귀 - 최적의 정규화 강도 결정

교차검증법을 이용해서 알파를 결정합니다.

최적의 알파는 아래와 같습니다.

추정된 계수 목록은 아래와 같습니다. 대부분 계수가 0이 되었습니다. X_1의 계수가 5가 되었으므로 올바르게 모델링했다고 볼 수 있습니다.

 

 

라소회귀, 릿지회귀에 대해서 복습하고 싶다면 아래 포스팅을 확인해주세요 :)

 

[파이썬/통계] 통계학과 머신러닝 - 이론적인 부분들 (라소회귀, 리지회귀)

머신러닝 기본 머신러닝은 컴퓨터에 학습능력을 부여하는 것을 목적으로 한 연구 분야입니다. 학습은 데이터를 기반으로 행해져 데이터가 가지는 규칙성을 분명히 합니다. 규칙성을 분명히 함

jofresh.tistory.com

 

728x90
반응형