Sparta/Theory

[250930] 머신러닝 03 - 회귀

junecho 2025. 9. 30. 21:12

✅ 회귀 분석                                                             

종속변수(Y)와 하나 이상의 독립변수(X) 간의 관계를 추정하여, 연속형 종속변수를 예측하는 통계/머신러닝 기법

 

ex) “공부한 시간(X)에 따라 시험 점수(Y)가 어떻게 변하는가?” 를 예측

 

🔸 개요                                                                                                                          

  • 지도학습에서의 분류와 회귀의 차이
    • 분류 (Classification) : 결과값이 이산형(클래스 라벨)
    • 회귀 (Regression) : 결과값이 연속형(숫자 값)
    • 사람의 지능적인 작업을 기계가 수행하도록 만드는 광범위한 개념
  • 회귀 모델을 사용하는 이유
    • 1️⃣ 미래 값 예측 : 실수값 예측에 사용 ex) 매량, 주가, 온도 등…
    • 2️⃣ 인과 관계 해석 (통계 관점) : 특정 독립변수가 종속변수에 미치는 영향력을 해석하기 위해
    • 3️⃣ 데이터 기반 의사결정 : 추세 파악, 자원 배분 등

 

  • 회귀 모델 대표적 활용 사례
    • 경제 - 주식 가격 예측, 판매량 예측
    • 건강 - 혈압, 콜레스테롤 수치 예측
    • 제조업 - 불량률, 생산량 예측

 

🔸 선형 회귀 (Linear Regression)                                                                            

독립변수(X)와 종속변수(Y)가 선형적(일차 방정식 형태)으로 관계를 맺고 있다고 가정

 

❓ 선형적 관계

: 변수가 증가하면, 다른 변수도 일정한 비율로 증가/감소 하는 관계

ex) 키가 커지면 몸무게도 증가하는 경향 / 공부 시간을 늘리면 시험 점수가 오르는 경향

  • 장점 : 해석 간단, 구현 쉬움
  • 단점 : 데이터가 선형성이 아닐 경우 예측력이 떨어짐
  • 독립변수 한 개인 상황에서는 직선이 나오는데, 독립변수가 많으면 평면이 나오게 됨

회귀식

  • β0 : 절편(intercept) = 편향
  • βi : 각 독립변수의 회귀계수(coefficient) = x의 계수 = 가중치 = 파라미터 = 베타

⇒ 독립변수가 많아질수록 항이 늘어난다

 

선형 회귀 모델 학습 과정

1️⃣ 가중치 (회귀계수) 초기화 ⇒ 베타값을 처음엔 모르니까 아무 값이나 해서 정해둠

2️⃣ 손실함수(Loss Function) 설정 : 주로 MSE(Mean Squared Error) 사용

     ❓ 손실함수 : 얼마나 오차가 나는지, 손실이 나는지 평가 해주는 지표

                           ⇒ 좋은 베타값은 오차가 적게 나오는 베타값

3️⃣ 최적화 : 수학적인 방법(최소자승법), 경사하강법(Gradient Descent) 등을 통해 가중치 업데이트

4️⃣ 학습 완료 후 : β0, β1, …를 얻어서 새로운 입력 값에 대한 예측 수행

 

  • 예시
    • 데이터
      • X = 공부 시간, Y = 시험 점수
      • (1시간, 40점), (2시간, 50점), (3시간, 60점), (4시간, 70점) …
    • 모델

              1시간 공부 → 40점, 2시간 공부 → 50점 …

 

 

🔎 선형회귀 코드                                                                                                                            

import numpy as np
import pandas as pd
from sklearn.datasets import load_diabetes
from sklearn.linear_model import LinearRegression, SGDRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score

# 1. 데이터 로드
diabetes = load_diabetes()
X = diabetes.data       # X : 특성(독립변수)
y = diabetes.target     # y : 타겟(종속변수)

print(X.shape)
print(y.shape

📌 train_test_split()

# 2. 학습/테스트 데이터 분리
# 80% 학습용, 20% 테스트용으로 데이터 분할 (재현성을 위한 random_state=42)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42)

print(X_train.shape)
print(y_train.shape)
print(X_test.shape)
print(y_test.shape)

: 전체 데이터셋을 학습용 세트와 테스트용 세트로 분할하는 데 사용

📌 LinearRegression()

# 3. 선형회귀 (LinearRegression) 모델
lin_reg = LinearRegression()
lin_reg.fit(X_train, y_train)

 

  • : 종속 변수(대상)와 하나 이상의 독립 변수(특징) 간의 선형 관계를 구하는 것을 목표로 함
  • fit() : 모델을 학습하기 위해 객체에 호출되는 메서드

📌 predict()

# 예측
y_pred_lin = lin_reg.predict(X_test)

# 성능 측정
mse_lin = mean_squared_error(y_test, y_pred_lin)
r2_lin = r2_score(y_test, y_pred_lin)

# 평균 비율 오차 - 실제값 대비 예측값이 몇 % 오차가 났는지
def MPE(y_true, y_pred):
    return np.mean((y_true - y_pred) / y_true) * 100

print("[LinearRegression 결과]")
print("가중치(coefficient):", lin_reg.coef_)
print("절편(intercept):", lin_reg.intercept_)
print("MSE:", mse_lin)
print("R2 점수:", r2_lin)
print("평균 비율 오차 : ", MPE(y_test, y_pred_lin))

  • predict() : 테스트 세트에 대한 예측 수행
  • mean_squared_error(x, y) : MSE 오차를 계산하는 어떤 지표. x, y 두 개의 값의 오차 계산
  • r2_score(x, y) : 얼마나 예측이 잘 되어져 있는지 점수로 나타내는 값

10열이 있었기 때문에 가중치는 10개가 나옴.

절편은 베타값을 처음에는 모르니까 임의로 지정해주는 상수값

📌 SGDRegressor()

# 4. SGDRegressor 모델
sgd_reg = SGDRegressor(max_iter=6000, tol=1e-3, random_state=42)
sgd_reg.fit(X_train, y_train)

  • : 확률적 경사하강법
# 예측
y_pred_sgd = sgd_reg.predict(X_test)

# 성능 측정
mse_sgd = mean_squared_error(y_test, y_pred_sgd)
r2_sgd = r2_score(y_test, y_pred_sgd)

# 평균 비율 오차
def MPE(y_true, y_pred):
    return np.mean((y_true - y_pred) / y_true) * 100

print("[SGDRegressor 결과]")
print("가중치(coefficient):", sgd_reg.coef_)
print("절편(intercept):", sgd_reg.intercept_)
print("MSE:", mse_sgd)
print("R2 점수:", r2_sgd)
print("평균 비율 오차 : ", MPE(y_test, y_pred_sgd))

 

  • 예측 후, MSE와 R2 점수를 통해 모델 성능 확인

 

 

🔸 다항 회귀 (Polynomial Regression)                                                                    

비선형적인 관계를 다항식(polynomial) 형태로 모델링

  • ex) 2차 다항식
  • 선형 회귀와 다른 점 : 단순 선형항(X) 뿐만 아니라 $X^2, X^3$,... 같은 고차항을 추가해 비선형 패턴을 학습할 수 있다
  • 적용 예시
    • 제조 공정에서 온도와 반응률 관계가 곡선 형태인 경우
    • 건강 데이터에서 나이와 특정 지표(근육량 등)가 단순 선형보다 곡선 형태로 나타나는 경우
  • 주의점
    • 고차항을 무작정 늘리면 훈련 데이터에는 과도하게 맞춰져 과적합(overfitting) 문제가 발생
    • 모델 복잡도와 일반화 성능 간의 균형을 맞춰야 함

 

🔎 다항회귀 코드                                                                                                                           

import numpy as np
import pandas as pd
from sklearn.datasets import make_friedman1
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.pipeline import Pipeline

# 1) 비선형 데이터 생성 (make_friedman1)
# n_samples: 샘플 개수, n_features: 특성 개수, noise: 잡음 크기
X, y = make_friedman1(n_samples=1000, n_features=5, noise=1.0, random_state=42)
print(X.shape)
print(y.shape)

 

# 2) 학습/테스트 분리
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42
)

print(X_train.shape)
print(y_train.shape)
print(X_test.shape)
print(y_test.shape)

 

📌 LinearRegression()

# 3) 단순 선형회귀 모델 (비교용)
lin_reg = LinearRegression()
lin_reg.fit(X_train, y_train)
y_pred_lin = lin_reg.predict(X_test)

mse_lin = mean_squared_error(y_test, y_pred_lin)
r2_lin = r2_score(y_test, y_pred_lin)

# 평균 비율 오차
def MPE(y_true, y_pred):
    return np.mean((y_true - y_pred) / y_true) * 100

print("[단순 선형회귀 결과]")
print("MSE:", mse_lin)
print("R2:", r2_lin)
print("평균 비율 오차 : ", MPE(y_test, y_pred_lin))
print()

⇒ 비선형을 고려하지 않고, LinearRegression만 적용했을 때의 성능을 MSE, R^2, MPE로 측정

 

📌 PolynomialFeatures()

# 4) Polynomial Regression (2차 예시)
poly_model = Pipeline([
    ("poly", PolynomialFeatures(degree=2, include_bias=False)),
    ("lin_reg", LinearRegression())
])
poly_model.fit(X_train, y_train)
y_pred_poly = poly_model.predict(X_test)

mse_poly = mean_squared_error(y_test, y_pred_poly)
r2_poly = r2_score(y_test, y_pred_poly)

# 평균 비율 오차
def MPE(y_true, y_pred):
    return np.mean((y_true - y_pred) / y_true) * 100

print("[다항회귀(2차) 결과]")
print("MSE:", mse_poly)
print("R2:", r2_poly)
print("평균 비율 오차 : ", MPE(y_test, y_pred_poly))

 

  • PolynomialFeatures(degree=2)로 2차 항까지 고려하도록 변한 후, 다시 선형회귀를 적용하는 파이프라인을 구성
  • 비선형 패턴을 어느 정도 학습할 수 있으므로, 단순 선형회귀보다 더 좋은 성능이 기대됨 (물론 과적합 위험도 존재
  • 결과 비교
    • MSE, R^2 등을 비교하여 단순 선형회귀 대비 다항회귀가 Friedman1 데이터셋에서 어떤 차이를 보이는지 확인 가능
    • 만약 더 높은 차수(예: 3차, 4차)를 적용하거나, 다른 비선형 모델(예: 랜덤 포레스트, SVM 회귀 등)을 사용하면 성능이 달라질 수 있음

 

🔸 회귀 모델 평가 방법                                                                                               

🔎 MSE (Mean Squared Error)                                                                                                     

  • 예측값과 실제값의 차이를 제곱하여 평균
  • 오차가 클수록 제곱에 의해 더 큰 벌점이 매겨지므로, 큰 오차에 특히 민감
  • 평균 제곱 오차라고도 하며, 회귀 모델 평가에서 매우 자주 사용됨

 

🔎 MAE (Mean Absolute Error)                                                                                                     

  • 예측값과 실제값의 차이를 절댓값으로 측정한 후 평균
  • 예측이 평균적으로 실제값에서 얼마나 벗어났는지 직관적으로 표현

 

🔎 RMSE (Root Mean Squared Error)                                                                                        

  • MAE와 달리 제곱을 통해 큰 오차에 가중치를 더 주는 특징
  • 오차가 클수록 패널티가 커지므로, 큰 오차가 중요한 문제에서 자주 사용

 

🔎 R² (결정 계수)                                                                                                                              

  • yˉ: 종속변수의 평균
  • 값의 범위
    • 0 ~ 1 (음수가 될 수도 있음)
  • 해석
    • 1에 가까울수록 학습된 모델이 데이터를 잘 설명한다고 볼 수 있음
    • 0이라면 모델이 종속변수를 전혀 설명하지 못한다는 의미

 

🔸 고급 회귀 기법 - Ridge & Lasso Regression                                                     

선형 회귀에 규제(Regularization) 항을 추가하여 과적합을 방지 

🔎 Ridge(릿지) 회귀                                                                                                                       

  • 가중치 제곱합(L2 Norm)을 패널티로 추가
  • 효과 : 가중치가 너무 커지지 않도록 방지 (가중치 값을 부드럽게 줄임)

 

🔎 Lasso(라쏘) 회귀                                                                                                                       

  • 가중치 절댓값합(L1 Norm)을 패널티로 추가
  • 효과 : 가중치를 0으로 만들어 변수 선택(Feature Selection) 효과

 

🔎 릿지회귀 & 라쏘회귀 코드                                                                                                       

import numpy as np
import pandas as pd
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.linear_model import Ridge, Lasso
from sklearn.metrics import mean_squared_error, r2_score

# 1. 데이터 로드
housing = fetch_california_housing()
X = housing.data
y = housing.target

print(X.shape)
print(y.shape)

 

# 2. 학습/테스트 데이터 분리
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

print(X_train.shape)
print(y_train.shape)
print(X_test.shape)
print(y_test.shape)

 

📌 Ridge()

# 3. Ridge 회귀
# alpha=1.0 (규제 세기) 는 필요에 따라 조정 가능
ridge_reg = Ridge(alpha=1.0, random_state=42)
ridge_reg.fit(X_train, y_train)

  • L2 규제항을 포함하는 Ridge 모델
  • alpha가 클수록 규제 강도가 세어져, 모델 가중치(계수)들의 크기를 더욱 제약
  • 학습 후, 예측 결과에 대해 MSER^2 점수를 계산

 

# 예측
y_pred_ridge = ridge_reg.predict(X_test)

# 성능 평가
mse_ridge = mean_squared_error(y_test, y_pred_ridge)
r2_ridge = r2_score(y_test, y_pred_ridge)

# 평균 비율 오차
def MPE(y_true, y_pred):
    return np.mean((y_true - y_pred) / y_true) * 100

print("[Ridge 회귀 결과]")
print("  가중치(coefficient):", ridge_reg.coef_)
print("  절편(intercept):", ridge_reg.intercept_)
print("  MSE:", mse_ridge)
print("  R^2 점수:", r2_ridge)
print("평균 비율 오차 : ", MPE(y_test, y_pred_ridge))
print()

 

📌 Lasso()

# 4. Lasso 회귀
# alpha=0.1 정도로 조금 낮춰 볼 수도 있음 (기본값 1.0)
# alpha가 너무 크면 가중치가 0이 되어 과소적합 위험이 있습니다.
lasso_reg = Lasso(alpha=0.1, random_state=42, max_iter=10000)
lasso_reg.fit(X_train, y_train)

  • L1 규제항을 사용하는 Lasso 모델
  • alpha가 클수록 일부 가중치가 정확히 0으로 수렴(특성 선택 효과)
  • 마찬가지로 MSE, R^2를 통해 성능을 평가

 

# 예측
y_pred_lasso = lasso_reg.predict(X_test)

# 성능 평가
mse_lasso = mean_squared_error(y_test, y_pred_lasso)
r2_lasso = r2_score(y_test, y_pred_lasso)

# 평균 비율 오차
def MPE(y_true, y_pred):
    return np.mean((y_true - y_pred) / y_true) * 100

print("[Lasso 회귀 결과]")
print("  가중치(coefficient):", lasso_reg.coef_)
print("  절편(intercept):", lasso_reg.intercept_)
print("  MSE:", mse_lasso)
print("  R^2 점수:", r2_lasso)
print("평균 비율 오차 : ", MPE(y_test, y_pred_lasso))

 

 

 

💥 정리 / Q&A                                                            

🔎 정리                                                                                                                                              

  • 회귀 모델은 연속형 결과 변수를 예측하는 데 사용
  • 선형 회귀는 가장 기본적인 형태지만, 데이터의 패턴이 비선형일 경우 다항 회귀 등을 고려
  • 규제(Regularization) 기법을 활용한 모델(Lasso, Ridge)은 가중치를 규제하여 과적합을 방지
  • 앙상블 기법(Gradient Boosting, XGBoost 등)을 사용하는 경우 복잡한 비선형 패턴을 더 잘 포착할 수 있다 (추후 배울 내용)
  • 모델의 성능 평가는 MAE, RMSE, R² 등 다양한 지표를 통해 진행

🔎 Q&A                                                                                                                                             

📚 Q1: 선형 회귀와 다항 회귀 중 어느 것을 선택해야 하나요?

A1: 데이터의 분포와 잔차(오차) 패턴을 확인하여, 단순 선형 모델로 설명이 어렵다면 다항 회귀를 고려합니다. 먼저, 선형회귀와 다항회귀 모두를 진행해보고 나서 판단해보는 방법도 있습니다.

 

📚 Q2: Lasso와 Ridge 중 어느 규제 기법을 써야 하나요?

A2: Lasso는 변수 선택(가중치를 0으로 만들어 불필요한 변수 제거)에 유리하며, Ridge는 모든 가중치를 부드럽게 줄여 모델 안정성을 높이는 데 유리합니다. 분석 목적과 데이터 특성에 따라 선택하거나, Elastic Net처럼 두 기법을 혼합하는 방법도 있습니다.

 

📚 Q3: 앙상블 기법은 항상 선형 회귀보다 좋은가요?

A3: 대부분의 경우 앙상블 기법이 예측 성능이 높지만, 데이터의 규모나 특징, 문제의 복잡도에 따라 다릅니다. 또한 하이퍼파라미터 튜닝이 까다롭고 계산 비용이 큰 단점도 있으므로 상황에 맞춰 선택합니다.

 

📚 Q4: 회귀 모델에서 독립변수가 많아질수록 항상 성능이 좋아지나요?

A4: 독립변수가 많아지면 모델이 복잡해져 과적합될 가능성이 커집니다. 변수 선택 기법(Feature Selection)이나 규제(Regularization)를 통해 불필요한 변수를 제거하고, 교차검증으로 모델 일반화 성능을 평가해야 합니다.

 

📚 Q5: 회귀 모델을 만들 때 어떤 지표(R², MAE, RMSE)를 우선적으로 봐야 하나요?

A5: 문제의 특성에 따라 달라집니다. 예측 오차의 크기가 중요하면 RMSE나 MAE, 모델이 데이터를 얼마나 잘 설명하는지 보려면 R²를 사용합니다. 여러 지표를 종합적으로 살펴보는 것이 바람직합니다.

 

'Sparta > Theory' 카테고리의 다른 글

[251002] 통계검정 실습 01 - t-test  (0) 2025.10.02
[251001] 머신러닝 04 - 분류  (0) 2025.10.01
[250929] 머신러닝 02  (0) 2025.09.29
[250929] 머신러닝 01  (0) 2025.09.29
[250925] 스파르타코딩 본캠프 38일차  (0) 2025.09.25