Post

머신러닝 2: 혼공머신 3장

3장: 회귀 알고리즘과 모델 규제

k-최근접 이웃 회귀

  • 정해진 클래스가 없고 오히려 임의의 수치를 반환
  • 예시:
    • 내년도 경제 성장률을 예측
    • 배달 도착하는 시간 예측
k최근접 이웃 분류k-최근접 이웃 회귀
샘플을 몇 개의 클래스 중 하나로 분류임의의 어떤 숫자를 예측
샘플에 가장 가까운 샘플 k개의 새로운 샘플을 다수 클래스로 예측샘플에 가장 가까운 샘플 k개의 수치의 평균을 구하여 새로운 샘플의 타깃값이 그 평균으로 예측

photo 1

데이터 준비

배열 크기 변환

  • 사이킷런에 사용할 훈련 세트는 2차원 배열이어야 해서 어떤 배열은 2차원 아닌 배열인 경우 2차원으로 나타내야 한다.
    • 즉:

      photo 2

    • 넘파이 reshape() 메서드를 이용하여 어떤 배열의 크기를 바꿀 수 있다.

      1
      2
      3
      4
      5
      
        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)를 출력
      
      • reshape(-1, 1)를 이용하여 크기를 자동으로 지정할 수 있다
        • -1는 나머지 원소 개수로 모두 채우라는 의미
        • 1는 2번째 크기를 1로 지정함
          1
          2
          3
          
            train_input = train_input.reshape(-1, 1)
            test_input = test_input.reshape(-1, 1)
            print(train_input.shape, test_input.shape) # (42, 1) (14, 1)를 출력 
          

결정계수 ($\mathsf{R}^2$)

  • 사이킷런에서 KNeighborsClassifier와 비슷한 k-최근접 이웃 회귀 알고리즘을 구현하는 KNeighborsRegressor라는 클래스가 있다.
1
2
3
4
5
6
7
8
		from sklearn.neighbors import KNeighborsRegressor

		knr = KNeighborsRegressor()

		# k-최근접 이웃 회귀 모델을 훈련한다
		knr.fit(train_input, train_target)

		print(knr.score(test_input, test_target)) # 0.9928....를 출력

knr.score()가 출력된 점수는 졍정계수(coefficient of determination(또는 $\mathsf{R}^2$))라고 부른다. 계산 방식은 아래와 같다.

\[R^2 = 1 - \frac{(타깃 - 예측)^2}{(타깃 - 평균)^2}\]
  • 만약 타깃의 평균 정도를 예측하는 수준이라면 $\mathsf{R}^2$는 0에 가까워지고 타깃이 예측에 아주 가까워지면 1에 가까운 값이 됩니다.

정확도처럼 $\mathsf{R}^2$가 직감적으로 얼마나 좋은지 이해하기는 어려워 타깃과 예측한 값 사이의 차이를 구해 보면 어느 정도 예측이 벗어났는지 가늠하기 좋다.

  • 사이킷런의 sklearn.metrics 패키지가 제공하는 mean_absolute_error는 타깃과 예측의 절대값 오차를 평균하여 반환한다.
1
2
3
4
5
6
7
8
from sklearn.metrics import mean_absolute_error

# 테스트 세트에 대한 예측을 만든다
test_prediction = knr.predict(test_input)

# 테스트 세트에 대한 평균 절댓값 오차를 계산한다
mae = mean_absolute_error(test_target, test_prediction)
print(mae) # 19.157..... 출력

과대적합 vs. 과소적합

모델을 훈련 세트에 훈련하여 훈련 세트에 잘 맞는 모델이 만들어지므로 $\mathsf{R}^2$ 점수가 보통은 훈련 세트에서 테스트 세트에서보다 더 좋은 점수가 나온다.

과대적합 (overfitting)과소적합 (underfitting)
훈련 세트에서 점수가 굉장히 좋았지만 테스트 세트에서 점수가 굉장히 나쁘다훈련 세트보다 테스트 세트의 점수가 높거나 두 점수가 모두 너무 낮다
훈련 세트에만 잘 맞는 모델모델이 너무 단순하여 훈련 세트에 적절히 훈련되지 않는다
해결: 덜 복잡한 모델을 만들어야 한다해결: 더 복잡한 모델을 만들어야 한다

k-최근접 이웃 알고리즘으로 더(아니면 덜) 복잡하는 모델을 만드는 법:

과대적합을 해결과소적합을 해결
개수 k를 늘리기개수 k를 줄이기

개수 k를 높아지면 데이터 전반에 있는 일반적인 패턴을 따를 것이고 개수 k를 줄이면 훈련 세트에 있는 국지적인 패턴을 민감해질 것이다.

1
2
# 이웃의 개수를 3으로 설정한다
knr.n_neighbors = 3

선형 회귀

  • 짐작할 수 있듯이 특성이 하나인 경우 어떤 직선을 학습하는 알고리즘이다.
  • 널리 사용되는 대표적인 회귀 알고리즘이다.

    photo 3

사이킷런은 sklearn.linear_model 패키지 아래에 LinearRegression 클래스로 선형 회귀 알고리즘을 구현할 수 있다.

  • 사이킷런의 모델 클래스들은 훈련, 평가, 예측하는 메서드 이름이 모두 동일한다.
1
2
3
4
5
6
7
8
from sklearn.linear_model import LinearRegression
lr = LinearRegression()

# 선형 회귀 모델을 훈련한다
lr.fit(train_input, train_target)

# 50cm 농어에 대해 예측한다
print(lr.predict([[50]]))

수학적으로 선형 회귀의 직선이 아래와 같이 표현할 수 있다. \(y=ax+b\)

여기서는 x는 특성이고 y는 타깃이다. 따라서 LinearRegression 클래스가 어떤 데이터에 가장 잘 맞는 a와 b를 찾고 coef_와 intercept_ 라는 속성을 이용하여 확인할 수 있다.

1
print(lr.coef_, lr.intercept_) # a, b의 값 출력

다항 회귀

  • 다항식을 이용하여 특성과 타깃 사이의 관계를 나타낸다
    • 비선형일 수 있는데 선형 회귀로도 표현할 수 있다

2차 다항 회귀 예시

1차 선형 회귀 비슷하는데 위에 방정식 대신에 아래의 2차 방정식으로 계산하여 예측한다. \(y = ax^2 + bx + c\) 그래프를 그려보면 아래 그래프를 나타난다.

photo 4

혼공머신 교재에 있는 데이터가 1차원이므로 2차원으로 변환해야 한다. column_stack() 함수를 이용하여 1차원 데이터가 2차원으로 변환 할 수 있다

1
2
3
4
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) 출력

특성 공학과 규제

다중 회귀란?

  • 여러 개의 특성을 사용한 선형 회귀

    photo 5

  • 즉, $y = ax_0 + bx_1 + c$

특성 공학이란?

  • 기존의 특성을 이용하여 새로운 특성을 뽑아내는 과정

데이터 준비

판다스

  • 데이터 분석 라이브러리
  • 데이터프레임: 판다스의 핵심 데이터 구조
    • to_numpy() 메서드를 이용하여 넘파이 배열로 쉽게 바꿀 수도 있다
  • read_csv() 함수를 이용하여 csv 파일을 쉽게 읽을 수 있다
1
2
3
4
import pandas as pd
df = pd.read_csv('https://bit.ly/perch_csv')
perch_full = df.to_numpy()
print(perch_full) # 넘파이 배열 출력

사이킷런의 변환하기

  • 변환기: 특성을 만들거나 전처리하기 위한 클래스
1
2
3
4
5
6
from sklearn.preprocessing import PolynomialFeatures # 사이킷런 제공하는 변환기들이 중 하나

poly = PolynomialFeatures()
poly.fit([[2, 3]]) # 새롭게 만들 특성 조합을 찾는다
print(poly.transform([[2, 3]])) # 셀제로 데이터를 변환한다
# [[1. 2. 3. 4. 6. 9.]] 출력

PolynomialFeatures 클래스는 기본적으로 각 특성을 제곱한 항을 추가하고 특성끼리 서로 곱한 항을 추가한다

  • 위의 예시의 경우, 2와 3을 각기 제곱한 4와 9가 추가되었다
  • 2와 3을 곱한 6이 추가되었다
  • $y = ax_0 + bx_1 + c*1$이므로 1이 추가되었다
    • include_bias=False가 지정하면 1이 추가되지 않는다
      • 사이킷런 모델은 자동으로 특성에 추가된 절편 항을 무시하므로 지정하지 않아도 됨
  • get_feature_names() 메서드를 이용하여 특성이 각각 어떤 입력의 조합으로 만들어졌는지 알아볼 수 있다
  • 테스트 세트를 변환:

    1
    
      test_poly = poly.transform(test_input)
    
  • degree 매개변수를 이용하여 필요한 고차항의 최개 차수를 지정할 수 있다

    1
    
      poly = PolynomialFeatures(degree=5, include_bias=False)
    

규제

  • 머신러닝 모델이 훈련 세트에 과대적합되지 않도록 만드는 것
  • 선형 회귀 모델의 경우 특성에 곱해지는 계수(또는 기울기)의 크기를 작게 만드는 일

photo 6

규제를 적용하기 전에 먼저 정규화를 해야 한다.

  • 사이킷런에서 제공하는 StandardScaler 클래스를 이용하여 정규화를 할 수 있다.
    • 변환기의 하나이다
    1
    2
    3
    4
    5
    6
    
      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)
      • 계수의 절댓값을 기준으로 규제를 적용
      • 아예 0으로 만들 수도 있으므로 선호하지 않는다.
  • 이 두 모델을 사용할 때 alpha 매개변수로 규제의 양을 임의로 조절할 수 있다.
    • alpha 값이 크면 규제 강도가 세져 계수 값을 더 줄이고 과소적합이 발생 가능
    • alpha 값이 작으면 계수를 줄이는 역할이 줄어들고 과대적합을 극복하지 못 할 수 있다

적절한 alpha 값을 찾는 법:

  • alpha에 대한 $\mathsf{R}^2$ 값의 그래프를 그려 본다
    • 훈련 세트와 테스트 세트의 점수가 가장 가까운 지점이 최적의 alpha 값이 된다 photo 7

위의 그래프를 보면 적절한 alpha 값은 두 그래프가 가장 가깝고 테스트 세트의 점수가 가장 높은 -1(즉 $\mathsf{10^-1=0.01}$)이다.

참고문헌: 혼자 공부하는 머신러닝 + 딥러닝

This post is licensed under CC BY 4.0 by the author.

Trending Tags