Notice
Recent Posts
Recent Comments
Link
«   2025/08   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
Tags
more
Archives
Today
Total
관리 메뉴

kang's study

6일차 ② : 다중회귀_규제 본문

[학습 공간]/[혼공머신러닝]

6일차 ② : 다중회귀_규제

보끔밥0302 2022. 3. 2. 01:33

다중회귀 (multiple regression)

 

② 규제
In [40]:
import pandas as pd
df = pd.read_csv('https://bit.ly/perch_csv_data') # Data.frame형태
perch_full = df.to_numpy() # 넘파이 배열
perch_weight = np.array(
    [5.9, 32.0, 40.0, 51.5, 70.0, 100.0, 78.0, 80.0, 85.0, 85.0, 
     110.0, 115.0, 125.0, 130.0, 120.0, 120.0, 130.0, 135.0, 110.0, 
     130.0, 150.0, 145.0, 150.0, 170.0, 225.0, 145.0, 188.0, 180.0, 
     197.0, 218.0, 300.0, 260.0, 265.0, 250.0, 250.0, 300.0, 320.0, 
     514.0, 556.0, 840.0, 685.0, 700.0, 700.0, 690.0, 900.0, 650.0, 
     820.0, 850.0, 900.0, 1015.0, 820.0, 1100.0, 1000.0, 1100.0, 
     1000.0, 1000.0]
     )
In [41]:
from sklearn.model_selection import train_test_split

train_input, test_input, train_target, test_target = train_test_split(perch_full, perch_weight, random_state=42)
In [42]:
from sklearn.preprocessing import PolynomialFeatures
# 5제곱까지 특성
poly = PolynomialFeatures(degree=5, include_bias=False)
poly.fit(train_input)
train_poly = poly.transform(train_input)
test_poly = poly.transform(test_input)
In [43]:
from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(train_poly, train_target)
print(lr.score(train_poly, train_target))
print(lr.score(test_poly, test_target))
 
0.9999999999938143
-144.40744532797535
 

규제(regularization)

훈련 세트를 너무 과도하게 학습하지 못하도록 훼방 넣기 (과대적합 방지)
선형 회귀 모델의 경우 특성에 곱해지는 계수의 크기를 작게 한다.

In [44]:
# 특성의 스케일이 정규화되지 않아 곱해지는 계수 값의 차이가 남
# 규제를 적용하기 전 정규화 필요
from sklearn.preprocessing import StandardScaler # 정규화

ss = StandardScaler()
ss.fit(train_poly)

train_scaled = ss.transform(train_poly)
test_scaled = ss.transform(test_poly)
 

모델에 규제를 가하는 방법에 따라 릿지(ridge)와 라쏘(lasso)가 있다.

 

릿지회귀 (가중치가 높으면 벌칙을 줌)

가중치의 제곱을 사용함 (L2규제)

In [45]:
from sklearn.linear_model import Ridge

# alpha = 1 분석자가 정해줘야함 (하이퍼 파라미터) 클수록 규제가 강함
ridge = Ridge()
ridge.fit(train_scaled, train_target)
print(ridge.score(train_scaled, train_target))
 
0.9896101671037343
In [46]:
print(ridge.score(test_scaled, test_target))
 
0.979069397761539
 

적절한 규제 강도 찾기

alpha 매개변수로 규제의 강도를 조절한다.
alpha 값이 크면 규제 강도가 세진다 ( 계수 값을 더 줄이고 과속적합을 유도 )

In [47]:
import matplotlib.pyplot as plt

train_score = []
test_score = []
In [48]:
alpha_list = [0.001, 0.01, 0.1, 1, 10, 100] # 보통 초기에 10의 배수로 간격을 정함
for alpha in alpha_list:
    # 릿지 모델을 만듭니다
    ridge = Ridge(alpha=alpha)
    # 릿지 모델을 훈련합니다
    ridge.fit(train_scaled, train_target)
    # 훈련 점수와 테스트 점수를 저장합니다
    train_score.append(ridge.score(train_scaled, train_target))
    test_score.append(ridge.score(test_scaled, test_target))
In [49]:
plt.plot(np.log10(alpha_list), train_score, 'b') # 상용로그로 동일한 간격으로 바꿈
plt.plot(np.log10(alpha_list), test_score, 'r')
plt.xlabel('alpha')
plt.ylabel('R^2')
plt.show()
 
 

적절한 alpha 값은 두 그래프가 가장 가깝고 테스트 세트의 점수가 가장 높아야 한다.
-1 즉 0.1

In [50]:
# 최종 훈련
ridge = Ridge(alpha=0.1)
ridge.fit(train_scaled, train_target)

print(ridge.score(train_scaled, train_target))
print(ridge.score(test_scaled, test_target))
 
0.9903815817570368
0.9827976465386954
 

라쏘 회귀 (가중치의 절대값으로 벌칙)

다른 모형은 L1규제

In [51]:
from sklearn.linear_model import Lasso

lasso = Lasso()
lasso.fit(train_scaled, train_target)
print(lasso.score(train_scaled, train_target))
 
0.989789897208096
In [52]:
print(lasso.score(test_scaled, test_target))
 
0.9800593698421884
In [53]:
train_score = []
test_score = []
alpha_list = [0.001, 0.01, 0.1, 1, 10, 100]
for alpha in alpha_list:
    # 라쏘 모델을 만듭니다
    lasso = Lasso(alpha=alpha, max_iter=10000)
    # 라쏘 모델을 훈련합니다
    lasso.fit(train_scaled, train_target)
    # 훈련 점수와 테스트 점수를 저장합니다
    train_score.append(lasso.score(train_scaled, train_target))
    test_score.append(lasso.score(test_scaled, test_target))
 
C:\Users\kang\anaconda3\lib\site-packages\sklearn\linear_model\_coordinate_descent.py:529: ConvergenceWarning: Objective did not converge. You might want to increase the number of iterations. Duality gap: 18778.697957792032, tolerance: 518.2793833333334
  model = cd_fast.enet_coordinate_descent(
C:\Users\kang\anaconda3\lib\site-packages\sklearn\linear_model\_coordinate_descent.py:529: ConvergenceWarning: Objective did not converge. You might want to increase the number of iterations. Duality gap: 12972.821345401393, tolerance: 518.2793833333334
  model = cd_fast.enet_coordinate_descent(
In [54]:
plt.plot(np.log10(alpha_list), train_score)
plt.plot(np.log10(alpha_list), test_score)
plt.xlabel('alpha')
plt.ylabel('R^2')
plt.show()
 
In [55]:
lasso = Lasso(alpha=10)
lasso.fit(train_scaled, train_target)

print(lasso.score(train_scaled, train_target))
print(lasso.score(test_scaled, test_target))
 
0.9888067471131867
0.9824470598706695
In [56]:
print(np.sum(lasso.coef_ == 0)) # TRUE의 개수 (가중치가 0으로 특성이 사용되지 않음)
 
40
 

특성을 많이 추가하면 선형 회귀는 매우 강력한 성능을 낸다.
하지만 특성이 너무 많으면 과대적합 문제가 발생하므로 선형 회귀 모델을 제약하기 위한 도구가 필요함을 알아보았다.

출처 : 박해선, 『혼자공부하는머신러닝+딥러닝』, 한빛미디어(2021), p159-170

Comments