728x90
반응형

1. k-최근접 이웃 회귀

회귀/ k-최근접 회귀/ 결정계수/ 과대적합과 과소적합

 

지도 학습 알고리즘

  • 분류: 샘플 -> 몇 개의 클래스 중 하나로 분류하는 문제
  • 회귀(regression): 임의의 어떤 숫자를 예측하는 문제
    • ex. 내년도 경제 성장률 예측, 배달 도착할 시간 예측
    • 정해진 클래스 X 임의의 수치 출력
    • 두 변수 사이의 상관관계를 분석하는 방법

k-최근접 이웃 분류

  1. 예측하려는 샘플에 가장 가까운 샘플 k개 선택
  2. 샘플들의 클래스 확인 -> 다수 클래스를 새로운 샘플의 클래스로 예측

k-최근접 이웃 회귀

  1. 예측하려는 샘플에 가장 가까운 이웃 샘플 k개 선택
  2. 이웃한 샘플의 타깃은 어떤 클래스 X 임의의 수치 O
  3. 이웃 샘플의 수치 사용 -> 새로운 샘플 x의 타깃 예측

=> 가장 가까운 이웃 샘플을 찾고 이 샘플들의 타깃값을 평균하여 예측으로 삼음


데이터 준비


      
# https://gist.github.com/rickiepark/2cd82455e985001542047d7d55d50630
import numpy as np
perch_length = np.array([8.4, 13.7, 15.0, 16.2, 17.4, 18.0, 18.7, 19.0, 19.6, 20.0, 21.0,
21.0, 21.0, 21.3, 22.0, 22.0, 22.0, 22.0, 22.0, 22.5, 22.5, 22.7,
23.0, 23.5, 24.0, 24.0, 24.6, 25.0, 25.6, 26.5, 27.3, 27.5, 27.5,
27.5, 28.0, 28.7, 30.0, 32.8, 34.5, 35.0, 36.5, 36.0, 37.0, 37.0,
39.0, 39.0, 39.0, 40.0, 40.0, 40.0, 40.0, 42.0, 43.0, 43.0, 43.5,
44.0])
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])

 

산점도 

하나의 특성 사용 -> 특성 데이터: x축/ 타깃 데이터: y축


      
import matplotlib.pyplot as plt
plt.scatter(perch_length, perch_weight)
plt.xlabel('length')
plt.ylabel('weight')
plt.show()

=> 농어 길이 ↑ -> 무게 

 

훈련 세트와 테스트 세트로 나누기


      
from sklearn.model_selection import train_test_split
train_input, test_input, train_target, test_target = train_test_split(perch_length, perch_weight, random_state=42)

 

2차원 배열로 변환

  • 사이킷런에 사용할 훈련 세트 -> 2차원 배열이어야 함
  • perch_length: 1차원 배열 => train_input, test_input: 1차원 배열
  • 1차원 배열의 크기 -> 원소가 1개인 튜플로 나타냄
    • ex. [1, 2, 3]의 크기: (3, )
    • -> 2차원 배열: 열 추가 => 크기: (3, 1)

      
# 2차원 배열 만들기 예시
test_array = np.array([1, 2, 3, 4])
print(test_array.shape) # (4, )
test_array = test_array.reshape(2, 2)
print(test_array.shape) # (2, 2)

      
train_input = train_input.reshape(-1, 1)
test_input = train_input.reshape(-1, 1)
print(train_input.shape, test_input.shape) # (42, 1) (14, 1)

결정계수(coefficient of determination) (R2)(R^2)

KNeighborsRegressor

  • k-최근접 이웃 회귀 모델 만드는 사이킷런 클래스
  • n_neighbors 매개변수로 이웃의 개수 지정 (기본값: 5)

분류) 정확도 = 테스트 세트에 있는 샘플을 정확하게 분류한 개수의 비율 = 정답을 맞힌 개수의 배율

회귀) 예측하는 값, 타깃 모두 임의의 수치 -> 정확한 숫자 맞힐 수 X  => 결정계수로 평가

R2=1(타깃예측)2(타깃평균)2=(yiy^i)2(yiyˉ)2 R^2 = 1 - \frac{\sum (타깃 - 예측)^2}{\sum (타깃 - 평균)^2} = \frac{\sum (y_i - \hat{y}_i)^2}{\sum (y_i - \bar{y})^2}

  • 타깃의 평균 정도 예측(분자와 분모 비슷) -> 0에 가까운 값
  • 예측이 타깃에 가까워짐(분자가 0에 가까워짐) -> 1에 가까운 값

      
from sklearn.neighbors import KNeighborsRegressor
knr = KNeighborsRegressor()
# k-최근접 이웃 회귀 모델 훈련
knr.fit(train_input, train_target)
# 테스트 세트 R^2 점수
print(knr.score(test_input, test_target)) # 0.992809~

 

mean_absolute_error

  • 회귀 모델의 평균 절댓값 오차 계산
  • 첫 번째 매개변수: 타깃/ 두 번째 매개변수: 예측값

mean_squared_error()

  • 평균 제곱 오차
  • 타깃과 예측을 뺀 값을 제곱한 다음 전체 샘플에 대한 평균값 반환

      
from sklearn.metrics import mean_absolute_error
# 테스트 세트에 대한 예측 만듦
test_prediction = knr.predict(test_input)
# 테스트 세트에 대한 평균 절댓값 오차 계산
mae = mean_absolute_error(test_target, test_prediction)
print(mae) # 19.157142~ = 예측이 평균적으로 19g 정도 타깃값과 다름

과대적합 vs 과소적합

훈련 세트 vs 테스트 세트 -> 훈련 세트 > 테스트 세트

=> 훈련 세트에서 모델을 훈련했기 때문

  • 과대적합(overfitting)
    • 훈련 세트가 너무 높은 경우
    • 훈련 세트에만 잘 맞는 모델 -> 실전에 투입해 새로운 샘플에 대한 예측 만들 때 잘 동작 X
  • 과소적합(underfitting)
    • 훈련 세트 < 테스트 세트 or 두 점수 모두 낮은 경우
    • 모델이 너무 단순 -> 훈련 세트에 적절히 훈련 X
    • 훈련 세트와 테스트 세트의 크기 매우 작음

훈련 세트 점수(0.98048~) < 테스트 세트 점수(0.992809~) -> 과소적합

=> (해결) 모델 더 복잡하게 만듦 => 이웃의 개수 k

  • k ↓ -> 훈련 세트에 있는 국지적인 패턴에 민감
  • k ↑ -> 데이터 전반에 있는 일반적인 패턴 따름

      
# 훈련 세트 R^2 점수
print(knr.score(train_input, train_target)) #0.969882~
# 이웃의 개수: 5 -> 3
knr.n_neighbors = 3
# 모델 다시 훈련
knr.fit(train_input, train_target)
# 훈련 세트 R^2 점수
print(knr.score(train_input, train_target)) #0.98048~
# 테스트 세트 R^2 점수
print(knr.score(test_input, test_target)) # 0.974645~

[문제해결 과정]회귀 문제 다루기

회귀: 임의의 수치를 예측하는 문제

 

k-최근접 이웃 회귀 모델

  • 가까운 k개의 이웃 찾음
  • 이웃 샘플의 타깃값을 평균하여 샘플의 예측값으로 사용
  • 회귀 모델의 점수로 R2R^2(결정계수) 반환, 1에 가까울수록 좋음
    • 정량적인 평가 방법: 절댓값 오차
  • 모델 훈련 후 훈련 세트, 테스트 세트 평가 점수
    1. 과대적합: 테스트 세트 점수 너무 낮음 
    2. -> 모델 덜 복잡하게 만들기: k 값 늘리기
    3. 과소적합: 테스트 세트 점수 너무 높음 or 두 점수 모두 낮음
    4. -> 모델 더 복잡하게 만들기: k 값 줄이기

2. 선형 회귀

선형 회귀/ 계수 또는 가중치/ 모델 파라미터/ 다항 회귀

k-최근접 이웃의 한계

길이 50cm인 농어 무게 예측: 1.033kg But, 실제는 훨씬 더 많이 나감


      
print(knr.predict([[50]])) # [1033.3333~]

 

산점도

훈련 세트, 50cm 농어, 농어의 최근접 이웃

 

kneighbors()

가장 가까운 이웃까지의 거리와 이웃 샘플의 인덱스 


      
import matplotlib.pyplot as plt
# 50cm 농어의 이웃 구함
distnaces, indexexs = knr.kneighbors([[50]])
# 훈련 세트의 산점도 그림
plt.scatter(train_input, train_target)
# 훈련 세트 중 이웃 샘플만 다시 그리기
plt.scatter(train_input[indexes], tarin_target[indexes], marker='D')
# 50cm 농어의 데이터
plt.scatter(50, 1033, marker='^')
plt.xlabel('length')
plt.ylabel('weight')
plt.show()

=> 길이 ↑ -> 농어 무게 ↑

But, 50cm 농어에서 가장 가까운 것은 45cm 근방 -> k-최근접 이웃 알고리즘: 샘플들의 무게 평균


      
print(np.mean(train_target[indexes])) # 1033.333333~

 

=> k-최근접 이웃 회귀: 가장 가까운 샘플 찾아 타깃 예측

=> 새로운 샘플이 훈련 세트 범위 벗어나면 이상한 값 예측할 수 있음

ex. 길이가 100cm인 농어의 무게: 1.033g으로 예측


      
print(knr.predict([[100]])) # 1033.333333~

 

산점도


      
# 100cm 농어의 이웃을 구함
distances, indexes = knr.kneighbors([[100]])
# 훈련 세트의 산점도
plt.scatter(train_input, train_target)
# 훈련 세트 중 이웃 샘플만 다시 그림
plt.scatter(train_input[indexes], train_target[indexes], market='D')
# 100cm 농어 데이터
plt.scatter(100, 1033, market='^')
plt.xlabel('length')
plt.ylabel('weight')
plt.show()

=> 농어가 커도 무게 늘어나지 X

-> k-최근접 이웃 사용해 문제 해결 -> 가장 큰 농어가 포함되도록 훈련 세트 다시 만들어야 함


선형 회귀(linear regression)

  • 특성과 타깃 사이의 관계를 가장 잘 나타내는 선형 방정식을 찾음
    • 특성이 한 개 -> 직선 방정식
  • 특성과 타깃 사이의 관계 -> 선형 방정식의 계수 or 가중치에 저장
    • 가중치는 기울기와 절편을 모두 의미하는 경우 ↑

  1. 모든 농어의 무게를 하나로 예측
    • IF. 훈련 세트의 평균에 가깝다면 R2R^2는 0에 가까운 값이 됨
  2. 길이 ↓ 농어의 무게 ↑/ 길이 ↑ 농어의 무게 ↓ => R2R^2 음수가 될 수 있음

LinearRegression

  • 사이킷런의 선형 회귀 클래스
  • fit_intercept 매개변수 False로 지정 -> 절편 학습 X (기본값: True)
  • 학습된 모델의 coef_ 속성: 특성에 대한 계수를 포함한 배열 
    • 배열의 크기 = 특성의 개수
  • intercept_ 속성: 절편이 저장되어 있음

      
from sklearn.linear_model import LinearRegression
lr = LinearRegression()
# 선형 회귀 모델을 훈련
lr.fit(train_input, train_target)
# 50cm 농어에 대해 예측
print(lr.predict([[50]]) # [1241.838603223]

y=ax+b(x:농어의길이,y:농어의무게) y = a * x + b (x: 농어의 길이, y: 농어의 무게)


      
print(lr.coef_, lr.intercept_) # [39.01714496] -709.0186449535477

기울기 = 계수(coefficient) = 가중치(weight)

 

모델 파라미터(model parameter)

  • 머신러닝 알고리즘이 찾은 값
  • 머신러닝 모델이 특성에서 학습한 파라미터
  • ex. coef_, intercept_ 
  • 모델 기반 학습: 머신러닝 알고리즘의 훈련 과정은 최적의 모델 파라미터를 찾는 것 
    • 사례 기반 학습: 훈련 세트를 저장하는 것
      • 모델 파라미터 X 
      • ex. k-최근접 이웃 알고리즘

산점도 + 직선

농어의 길이 15 ~ 50까지 직선

기울기, 절편 -> (15, 15*39-709)와 (50, 50*39-709) 두 점 이음


      
# 훈련 세트의 산점도
plt.scatter(train_input, train_target)
# 15 ~ 50까지 1차 방정식 그래프 그림
plt.plot([15, 50], [15*lr.coef_+lr.intercept_, 50*lr.coef_+lr.intercept_])
# 50cm 농어 데이터
plt.scatter(50, 1241.8, marker='^')
plt.xlabel('length')
plt.ylbael('weight')
plt.show()


      
# 훈련 세트
print(lr.score(train_input, train_target)) # 0.939846~
# 테스트 세트
print(lr.score(test_input, test_target)) # 0.82475031~

다항 회귀(polynomial regression)

  • 다항식(polynomial) 사용 -> 특성과 타깃 사이의 관계를 나타냄
  • 비선형일 수 있지만, 선형 회귀로 표현할 수 있음

농어의 무게가 0g 이하로 내려가는 것은 현실에서 있을 수 X

-> 최적의 직선이 아닌 최적의 곡선 찾기

=> 길이를 제곱한 항이 훈련 세트에 추가 되어야 함

column_stack()

훈련 세트, 테스트 세트 모두 열 2개로 늘이기


      
train_poly = np.column_stack((train_input ** 2, train_input))
test_poly = np.column_stack((test_input ** 2, test_input))
print(train_poly.shape, test_poly.shape) # (42, 2) (14, 2)

 

train_poly

선형 회귀 모델 다시 훈련


      
train_poly = np.column_stack((train_input ** 2, train_input))
test_poly = np.column_stack((test_input ** 2, test_input))
print(train_poly.shape, test_poly.shape) # (42, 2) (14, 2)

 

=> 2차 방정식 그래프 찾기 위해 훈련 세트에 제곱 항 추가 But, 타깃값 그대로 사용


      
lr = LinearRegression()
lr.fit(train_poly, train_target)
print(lr.predict([[50**2, 50]])) # [1573.98423528]

      
print(lr.coef_, lr.intercept_) # [ 1.01433211 -21.55792498] 116.0502107827827

무게=1.01221.6길이+116.05 무게 = 1.01 * 길이^2 - 21.6 * 길이 + 116.05

 

산점도

짧은 직선 이어 그려서 곡선처럼 표현


      
# 구간별 직선을 그리기 위해 15 ~ 49까지 정수 배열을 만듦
point = np.arrage(15, 50)
# 훈련 세트의 산점도 그림
plt.scatter(train_input, train_target)
# 15 ~ 49까지 2차 방정식 그래프 그림
plt.plot(point, 1.01*point**2 - 21.6*point + 116.05)
# 50cm 농어 데이터
plt.scatter(50, 1574, marker='^')
plt.xlable('length')
plt.ylable('weight')
plt.show()


      
print(lr.score(train_poly, train_target)) # 0.970680~
print(lr.score(test_poly, test_target)) # 0.977593~

 

=> 훈련 세트와 테스트 세트에 대한 점수 크게 높아짐

But, 여전히 테스트 세트의 점수가 조금 더 높음 = 과소 적합

-> 조금 더 복잡한 모델 필요


[문제해결 과정] 선형 회귀로 훈련 세트 범위 밖의 샘플 예측

k-최근접 이웃 회귀 사용해서 농어의 무게 예측

-> (-) 훈련 세트 범위 밖의 샘플을 예측할 수 X

아무리 멀리 떨어져 있더라도 무조건 가장 가까운 샘플의 타깃을 평균하여 예측

=> (해결) 선형 회귀

  • 훈련 세트에 잘 맞는 직선의 방정식 사용
    • 최적의 기울기와 절편 구한다
    • coef_, intercept_ 속성
  • 사이킷런의 LinearRegression 클래스 사용
  • (-) 모델이 단순 -> 농어의 무게 음수일 경우 O

=> (해결) 다항 회귀

  • 농어의 길이 제곱 -> 훈련 세트에 추가 -> 선형 회귀 모델 다시 훈련
  • 2차 방정식의 그래프 형태를 학습, 훈련 세트가 분포된 형태 잘 표현
  • 훈련 세트, 테스트 세트의 성능이 훨씬 ↑
  • (-) 훈련 세트의 성능 < 테스트 세트의 성능 = 과소적합 경향 남아 있음

=> (해결) 조금 더 복잡한 모델 만듦


3. 특성 공학과 규제

다중 회귀/ 특성 공학/ 릿지/ 라쏘/ 하이퍼파라미터

다중 회귀(multiple regression)

  • 여러 개의 특성을 사용하는 회귀 모델
  • 특성 ↑ 강력한 성능 발휘

  1. 특성 1개 -> 직선
  2. 특성 2개 -> 평면 학습
    • 타깃값과 함께 3차원 공간 형성
    • 타깃=a특성1+b특성2+절편 타깃 = a * 특성1 + b * 특성2 + 절편

=> 3차원 공간 이상 그리거나 상상 X

선형 회귀 단순한 직선 or 평면으로 생각 -> 성능 무조건 낮다? (X)

특성 ↑ 고차원 -> 선형 회귀) 매우 복잡한 모델 표현 O

 

농어의 길이 + 높이, 두께 데이터 추가

-> 3개의 특성 각각 제곱하여 추가, 새로운 특성 만들어서 추가(농어 길이 * 농어 높이)

 

특성 공학(feature engineering)

기존의 특성을 사용해 새로운 특성을 뽑아내는 능력


데이터 준비

csv 파일 -> 판다스 데이터 프레임: pd.read_csv() -> 넘파일 배열: to_numpy()

 

read_csv()

  • csv 파일을 로컬 컴퓨터나 인터넷에서 읽어 판다스 데이터프레임으로 변환하는 함수
  • sep: csv 파일의 구분자 지정 (기본값: 콤마(,))
  • header: 데이터프레임의 열 이름으로 사용할 csv 파일의 행 번호 지정 (기본값: 첫 번째 행 -> 열 이름으로 사용)
  • skiprows: 파일에서 읽기 전에 건너뛸 행의 개수 지정
  • nrows: 파일에서 읽을 행의 개수 지정

      
import pandas as pd
df = pd.read_csv('https://bit.ly/perch_csv_data')
perch_full = df.to_numpy()
print(perch_full)
# [[8.4 2.11 1.41]
# [13.7 3.53 2. ]
# [15. 3.82 2.43]
# ...
# [44. 12.49 7.6 ]]

      
# https://bit.ly/perch_data
import numpy as np
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])
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)

사이킷런의 변환기(transformer)

특성을 만들거나 전처리하기 위한 다양한 클래스 제공

LinearRegression 같은 사이킷런의 모델 클래스는 추정기(estimator)라고도 부름


      
from sklearn.preprocessing import PolynomialFeatures
poly = PolynomialFeatures()
poly.fit([[2, 3]])
print(poly.transform([[2, 3]]) # [[1. 2. 3. 4. 6. 9.]]

 

=> 변환기는 입력 데이터를 변환하는 데 타깃 데이터 필요 X

-> 모델 클래스와 다르게 fit() 메서드에 입력 데이터만 전달

무게=a길이+b높이+c두께+d1 무게 = a * 길이 + b * 높이 + c * 두께 + d * 1

 

선형 방정식의 절편: 항상 값이 1인 특성과 곱해지는 계수

-> 특성: 길이, 높이, 두께, 1

But, 선형 모델: 자동으로 절편 추가

 

PolynomialFeatures

  • 주어진 특성을 조합하여 새로운 특성을 만듦
  • degree: 최고 차수 지정 (기본값: 2)
  • interactoin_only=True: 거듭제곱 항 제외, 특성 간의 곱셈 항만 추가 (기본값: False)
  • include_bias=False: 절편을 위한 특성 추가 X (기본값: True)  

      
# 절편을 위한 항 제거, 특성의 제곱과 특성끼리 곱한 항만 추가
# include_bias=False 지정하지 않아도 자동으로 특성에 추가된 절편 항 무시
poly = PolynomialFeatures(include_bias=False)
poly.fit([[2, 3]])
print(poly.transform([[2, 3]]) # [[2. 3. 4. 6. 9.]]

      
poly = PolynomialFeatures(include_bias=False)
poly.fit(train_input)
train_poly = poly_transform(train_input)
print(train_poly.shape) # (42, 9)

      
# 9개의 특성이 각각 어떤 조합으로 만들어졌는지 알려줌
poly.get_feature_names_out()
# ['x0', 'x1', 'x2', 'x0^2', 'x0 x1', 'x0 x2', 'x1^2', 'x1 x2', 'x2^2']
# x0: 첫 번째 특성 의미, x0^2: 첫 번째 특성의 제곱, x0 x1: 첫 번째 특성과 두 번째 특성 곱

 

테스트 세트 변환


      
test_poly = poly.transform(test_input)

다중 회귀 모델 훈련하기

~= 선형 회귀 모델 훈련

= 여러 개의 특성을 사용하여 선형 회귀 수행


      
from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(train_poly, train_target)
print(lr.score(train_poly, train_target)) # 0.99031834~
print(lr.score(test_poly, test_target)) # 0.97145599~

 

=> 과소적합 문제 해결

-> 특성 더 많이 추가하면? ex. 3제곱, 4제곱 항 추가

=> PolynomialFeatures 클래스의 degree 매개변수 사용 -> 필요한 고차항의 최대 차수 지정


      
poly = PolynomialFeatures(degree=5, include_bias=False) # 5제곱
poly.fit(train_input)
train_poly = poly.transform(train_input)
test_poly = poly.transform(test_input)
print(train.poly.shape) # (42, 55)

 

=> 만들어진 특성의 개수: 55개

train_poly 배열의 열의 개수 = 특성의 개수


      
lr.fit(train_poly, train_target)
print(lr.score(train_poly, train_target)) # 0.999999999~
print(lr.score(test_poly, test_target)) # -144.40579~

 

=> 테스트 세트에 대한 점수가 음수 

=> 특성 개수 -> 선형 모델 강력해짐 = 훈련 세트에 대해 거의 완벽하게 학습

But, 훈련 세트에 너무 과대적합 


규제(regularization)

  • 머신러닝 모델이 훈련 세트를 너무 과도하게 학습하지 못하도록 훼방하는 것
  • 모델이 훈련 세트에 과대적합되지 않도록 만드는 것
    • 선형 회귀 모델) 특성에 곱해지는 계수(or 기울기)의 크기 작게 만드는 것

특성의 스케일 정규화 X -> 곱해지는 계수 값의 차이 => 공정하게 제어 X 


      
from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
ss.fit(train_poly)
train_scaled = ss.transform(train_poly)
test_scaled = ss.transform(test_poly)

 

선형 회귀 모델 + 규제 -> sklearn.linear_model

  • 릿지 (조금 더 선호)
    • 계수를 제곱한 값을 기준으로 규제 적용
    • 계수의 크기 줄임
  • 라쏘
    • 계수가 절댓값을 기준으로 규제 적용
    • 계수의 크기 줄임, 0으로 만들 수 있음

릿지 회귀 

  • 규제가 있는 선형 회귀 모델 중 하나
  • 선형 모델의 계수 작게 만들어 과대적합 완화
  • 효과가 좋아 널리 사용하는 규제 방법

Ridge

  • 규제가 있는 회귀 알고리즘인 릿지 회귀 모델 훈련
  • alpha 매개변수: 규제의 강도 조절
    • alpha 값 ↑ -> 규제 ↑ (기본값: 1)
  • solver 매개변수: 최적의 모델 찾기 위한 방법 지정 (기본값: auto)
  • random_state: solver가 sag나 saga일 때 넘파이 난수 시드값 지정
    • sag: 확률적 평균 경사 하강법 알고리즘/ 특성과 샘플 수 ↑ -> 성능 빠르고 좋음
    • saga: sag의 개선 버전

      
from sklearn.linear_model import Ridge
ridge = Ridge()
ridge.fit(train_scaled, train_target)
print(ridge.score(train_scaled, train_target)) # 0.989610~
print(ridge.score(test_scaled, test_target)) # 0.97906939~

 

alpha 값 ↑ -> 규제 강도 ↑ => 계수 값 ↓, 조금 더 과소적합되도록 유도

 

적절한 alpha 값 찾는 방법: alpha 값에 대한 R2R^2의 그래프 그려 보는 것

훈련 세트와 테스트 점수가 가장 가까운 지점 -> 최적의 alpha 값


      
import matplotlib.pyplot as plt
train_score = []
test_score = []
alpha_list = [0.001, 0.01, 0.1, 1, 10, 100]
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))

      
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()

=> 훈련 세트와 테스트 세트의 점수 차이가 큼

L: 훈련 세트에 잘 맞고, 테스트 세트에 과대적합/ R: 훈련 세트와 테스트 세트 점수 모두 과소적합

=> 적합한 alpha 값: -1 (101=0.110^{-1}=0.1)


      
ridge = Ridge(alpha=0.1)
ridge.fit(train_scaled, train_target)
print(ridge.score(train_scaled, train_target)) # 0.9903815~
print(ridge.score(test_scaled, test_target)) # 0.9827976~

라쏘 회귀

  • 또 다른 규제가 있는 선형 회귀 모델
  • 릿지와 달리 계수 값을 아예 0으로 만들 수 있음

Lasso

  • 규제가 있는 회귀 알고리즘인 라쏘 회귀 모델 훈련
  • 최적의 모델 찾기 위해 좌표축을 따라 최적화 수행(좌표 하강법)
  • alpha와 random_state 매개변수 = Ridge 클래스
  • max_iter: 알고리즘의 수행 반복 횟수 지정 (기본값: 1000)

      
from sklearn.linear_model import Lasso
lasso = Lasso()
lasso.fit(train_scaled, train_target)
print(lasso.score(train_scaled, train_target)) # 0.989789~
print(lasso.score(test_scaled, test_target)) # 0.980059~

      
train_score = []
test_score = []
alpha_test = [0.001, 0.01, 0.1, 1, 10, 100]
for alpha in alpha_list:
# 라쏘 모델 만듦
lasso = Lasso()
# 라쏘 모델 훈련
lasso.fit(train_scaled, train_target)
# 훈련 점수와 테스트 점수 저장
train_score.append(lasso.score(train_scaled, train_target))
test_score.append(lasso.score(test_scaled, test_target))

      
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()

L: 과대적합/ R: 훈련 세트와 테스트 세트의 점수가 좁혀짐

=> 최적의 alpha 값: 1 (101=1010^{1}=10)


      
lasso = Lasso()
lasso.fit(train_scaled, train_target)
print(lasso.score(train_scaled, train_target)) # 0.9888067~
print(lasso.score(test_scaled, test_target)) # 0.9824470~

 

계수 0으로 만들기


      
print(np.sum(lasso.coef_ == 0)) # 40

[문제해결 과정] 모델의 과대적합을 제어하기

선형 회귀 알고리즘 -> 농어의 무게를 예측하는 모델 훈련

But, 훈련 세트에 과소적합

 

(해결)

  • 농어의 길이 + 높이, 두께 사용 => 다중 회귀 모델 훈련
  • 다항 특성 ↑ 추가
    • -> 선형 회귀 성능 ↑ But, 과할 경우 제약하기 위한 도구 필요(릿지, 라쏘)
    • 최적의 alpha 값 찾아 릿지와 라쏘 모델의 규제 양 조절

=> 훈련 세트에서 거의 완벽에 가까운 점수 얻는 모델 훈련


출처

 

GitHub - rickiepark/hg-mldl: <혼자 공부하는 머신러닝+딥러닝>의 코드 저장소입니다.

<혼자 공부하는 머신러닝+딥러닝>의 코드 저장소입니다. Contribute to rickiepark/hg-mldl development by creating an account on GitHub.

github.com

728x90
반응형
김앩옹