Machine Learning & DeepLearning

머신러닝 회귀(Regression)

gellygelly 2022. 5. 2. 23:35

※ 이 글은 <파이썬 머신러닝 완벽 가이드(위키북스)> 책을 공부한 내용&개인적으로 공부한 내용을 정리한 글입니다! 

 

회귀(Regression)

머신러닝에서 회귀란, 주어진 피처와 결정 값 데이터 기반에서 학습을 통해 최적의 회귀 계수를 찾아내는 것을 의미한다. 

 

※ 같은 지도학습 유형인 분류와의 차이점

  • 분류: 예측값이 카테고리와 같은 이산형 클래스 값
  • 회귀: 연속형 숫자 값

 

회귀의 유형

독립변수 개수 회귀 계수의 결합
1개: 단일 회귀 선형: 선형 회귀
여러 개: 다중 회귀 비선형: 비선형 회귀
    선형 회귀는 실제 값과 예측값의 차이(오류의 제곱 값)를 최소화하는 직선형 회귀선을 최적화하는 방식이다. 선형 회귀의 유형은 아래와 같이 나눠진다.

<선형 회귀의 유형> 

  • 일반 선형 회귀
  • 릿지(Ridge)
  • 라쏘(Lasso)
  • 엘라스틱넷(ElasticNet)
  • 로지스틱 회귀(Logistic Regression)

단순 선형 회귀(Simple Linear Regression)

단순 선형 회귀는 독립변수 1개, 종속변수 1개인 선형 회귀이다. 

 

단순 선형 회귀 <출처: 위키피디아>

### 선형 회귀 ### 
from sklearn.linear_model import LinearRegression

lr = LinearRegression()
lr.fit(X_train, y_train)
lr_pred = lr.predict(X_test)

 

다항 회귀(Polynomial Regression)

회귀과 독립변수의 단항식이 아닌 2차, 3차 방정식과 같은 다항식으로만 표현되는 회귀이다.

 

주의할 점은 다항 회귀는 비선형 회귀가 아니라는 점이다.

선형 회귀와 다항 회귀

※그래프 출처: https://serokell.io/blog/polynomial-regression-analysis

 

Introduction to Polynomial Regression Analysis

What is polynomial regression? When should you use it? In this article, we’ll give you all the answers.

serokell.io

 

회귀에서 선형/비선형의 구분은 독립 변수의 선형/비선형 여부와는 관계없이 회귀 계수가 선형/비선형인지 여부로 결정된다. 

 

아래와 같은 수식으로 회귀 방정식이 정리된다면, 선형 회귀이다. 

선형회귀 수식

### 다항 회귀 ###
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import Pipeline
import numpy as np

def polynomial_func(X):
	y = 1 + 2*X[:, 0] + 3*X[:, 0]**2 + 4*X[:, 1]**3
    
    return y
    
# Pipeline 객체로 Ploynomial 변환과 LinearRegression 연결
model = Pipeline([('poly', PolynomialFeatures(degree=3)), ('linear', LinearRegression())])

X = np.arange(4).reshape(2,2)
y = polynomial_func(X)

model.fit(X, y)

print('Polynomial 회귀 계수\n', np.round(model.named_steps['linear'].coef_, 2))

# model.predict(X_test) test 데이터셋 지정

 

<다중 회귀 VS 다항 회귀>

 

  • 다중 회귀: 독립 변수의 개수가 2개 이상인 회귀
  • 다항 회귀: 독립 변수의 차수가 2차 이상인 회귀

어디선 다중 회귀분석 이러고 어디선 다항 회귀 이래서 다중 회귀랑 다항 회귀랑 뭔 차이여.. 같은 건가? 하고 헷갈렸는데 아래 게시물을 보고 이해됐다!! 완전 정리 잘 되어있어서 감동!!!!!

 

https://herjh0405.tistory.com/70

 

[ML] 다중 회귀 VS 다항 회귀 (Multiple VS Polynomial regression)

 우리는 머신러닝 기법을 사용할 때 회귀 관련 모델을 사용하긴 한다. 가장 기본적인 선형 회귀(Linear Regression) 모델을 많이 사용할 텐데, 데이터의 분포가 직선이 아니라 곡선 형태를 띠고 있을

herjh0405.tistory.com


규제 선형 모델

다항 회귀에서 다항식의 차수가 낮으면 데이터에 비해 지나치게 단순화된 과소 적합 모델이, 너무 크면 지나치게 학습 데이터에만 맞춰진 복잡하고 회귀 계수가 매우 큰 과대 적합 모델이 생성된다.

 

회귀 모델에서 중요한 것은 데이터에 대해 적합하면서도 회귀 계수가 기하급수적으로 커지는 것을 제어하는 것이다. 회귀 계수의 크기를 제어하기 위해서는 비용(Cost) 함수의 목표가 아래와 같이 (RSS(W)+alpha∗‖w‖_2^2) 값을 최소화할 수 있는 방향으로 튜닝 파라미터 alpha를 제어해야 한다. 

비용 함수의 목표

 

위와 같이 비용 함수에 alpha 값으로 페널티를 부여해 회귀 계수 값의 크기를 감소시켜 과적합을 개선하는 방식을 규제(Regularization)라고 한다. 

 

1) L2 규제 : 릿지 회귀(Ridge Regression)

  • L2 규제: alpha∗‖w‖_2^2와 같이 W의 제곱에 대해 페널티를 부여하는 방식이다. L2 규제는 상대적으로 큰 회귀 계수 값의 예측 영향도를 감소시키기 위해 회귀 계수 값을 더 작게 만드는 규제이다. 

 

from sklearn.linear_model import Ridge
from sklearn.model_selection import cross_val_score
import numpy as np

# alpha=10으로 설정해 릿지 회귀 수행
ridge = Ridge(alpha=10)
neg_mse_scores = cross_val_score(ridge, X_data, y_target, scoring='neg_mean_squared_error', cv=5) # 교차 검증 score
rmse_scores = np.sqrt(-1 * neg_mse_scores) # neg_mse_scores 값이 음수이므로 -1 곱함
avg_rmse = np.mean(rmse_scores)

ridge.fit(X_data, y_target)

위 코드에서 rmse_score를 구할 때, neg_mse_scores 값이 음수이므로 -1을 곱했다고 했는데 해당 값이 음수인 이유는 sklearn에서는 평가 지표 값이 높을수록 성능이 뛰어나다고 판단하는데, 회귀의 경우 평가 지표의 값이 작아야 성능이 좋기 때문에 음수 값으로 변경되어 나오는 것이다.

 

따라서, rmse를 구할 때에는 다시 -1을 곱해준 후 구하면 된다. 

 

2) L1 규제 : 라쏘 회귀(Lasso Regression)

  • L1 규제: alpha∗‖w‖_1 과 같이 W의 절댓값에 대해 페널티를 부여하는 방식이다. L1 규제는 예측 영향력이 작은 피처의 회귀 계수를 0으로 만들어 회귀 예측 시 해당 피처가 선택되지 않게 하는 규제이다. 
from sklearn.linear_model import Lasso
from sklearn.model_selection import cross_val_score
import numpy as np

# alpha=10으로 설정해 라쏘 회귀 수행
lasso = Lasso(alpha=10)
neg_mse_scores = cross_val_score(lasso, X_data, y_target, scoring='neg_mean_squared_error', cv=5) # 교차 검증 score
rmse_scores = np.sqrt(-1 * neg_mse_scores)
avg_rmse = np.mean(rmse_scores)

lasso.fit(X_data, y_target)

 

3) L1 규제+L2 규제 : 엘라스틱넷(ElasticNet)

엘라스틱넷은 라쏘 회귀가 중요한 피처만을 선택하고 다른 피처들의 회귀 계수를 모두 0으로 만드는 성향 때문에 alpha 값에 따라 회귀 계수의 값이 급격히 변동될 수 있다는 점을 완화하기 위해 L2 규제를 라쏘 회귀에 추가한 것이다. 

 

엘라스틱넷 회귀는 L1+L2 규제를 모두 결합한 것 때문에 수행시간이 상대적으로 오래 걸린다는 단점이 있다. 

 

엘라스틱넷 비용 함수의 목표는 아래 수식과 같다.

from sklearn.linear_model import ElasticNet
from sklearn.model_selection import cross_val_score
import numpy as np

# 엘라스틱넷 회귀 수행
en = ElasticNet(alpha=10, l1_ratio=0.7)
neg_mse_scores = cross_val_score(en, X_data, y_target, scoring='neg_mean_squared_error', cv=5) # 교차 검증 score
rmse_scores = np.sqrt(-1 * neg_mse_scores)
avg_rmse = np.mean(rmse_scores)

en.fit(X_data, y_target)

로지스틱 회귀(Logistic Regression)

로지스틱 회귀는 선형 회귀 방식을 분류에 적용한 알고리즘이다. 로지스틱 회귀는 학습을 통해 선형 함수의 회귀 최적선을 찾는 것이 아닌, 시그모이드(Sigmoid) 함수 최적선을 찾고 해당 함수의 반환 값을 확률로 간주해 이 확률에 따라 분류를 결정한다. 

 

시그모이드 함수

 

from sklearn.linear_model import LogisticRegression

# 로지스틱 회귀
lr = LogisticRegression()
lr.fit(X_train, y_train)
pred = lr.predict(X_test)

회귀 트리

회귀 트리는 비선형 회귀의 일종으로, 회귀를 위한 트리를 생성하고 리프 노드에 속한 데이터 값의 평균값을 구해 회귀 예측값을 계산한다. 

데이터 세트의 X 피처를 결정 트리 기반으로 분할 <파이썬 머신러닝 완벽 가이드 336p 그림>

 

트리 분할 완료 후 리프 노드에 소속된 값의 평균값을 구해 최종적으로 리프 노드 결정값으로 할당 <파이썬 머신러닝 완벽 가이드 336p 그림>

결정 트리, 랜덤 포레스트, GBM, XGBoost, LightGBM 등의 트리 기반 알고리즘은 분류 뿐 아니라 회귀도 가능하다. 

from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import cross_val_score
import numpy as np


# 랜덤 포레스트 회귀 트리
rf = RandomForestRegressor(n_estimators=1000)
neg_mse_scores = cross_val_score(rf, X_data, y_target, scoring='neg_mean_squared_error', cv=5) # 교차 검증 score
rmse_scores = np.sqrt(-1 * neg_mse_scores)
avg_rmse = np.mean(rmse_scores)

rf.fit(X_data, y_target)
pred = rf.predict(X_test)