회귀 모델은 연속형 결과 변수를 예측하는 데 사용한다.
선형 회귀는 가장 기본적인 형태지만, 데이터의 패턴이 비선형일 경우 다항 회귀 등을 고려해야 한다.
규제(Regularization) 기법을 활용한 모델(Lasso, Ridge)은 가중치를 규제하여 과적합을 방지한다.
앙상블 기법(Gradient Boosting, XGBoost 등)을 사용하는 경우 복잡한 비선형 패턴을 더 잘 포착할 수 있다 (추후 배울 내용)
모델의 성능 평가는 MAE, RMSE, R² 등 다양한 지표를 통해 진행한다.
종속변수(Y)와 하나 이상의 독립변수(X) 간의 관계를 추정하여, 연속형 종속변수를 예측하는 통계/머신러닝 기법
지도학습 분류 vs 회귀
분류(Classification)
결과값이 이산형(클래스 라벨)
클래스 라벨 = 분류할 대상의 '정답값' 이름
값이 셀 수 있는 형태로 서로 구분 가능한 값 = 이산형
회귀(Regression)의 차이
결과값이 연속형(숫자 값)
독립변수(X)와 종속변수(Y)가 선형적(일차 방정식 형태)으로 관계를 맺고 있다고 가정

1️⃣ 가중치(회귀계수) 초기화
2️⃣ 손실함수(Loss Function) 설정
: 주로 MSE(Mean Squared Error) 사용, 오차/손실이 얼마나 나는지 알려주는 지표
3️⃣ 최적화
: 수학적인 방법(최소자승법), 경사하강법(Gradient Descent, 대입 + 경험적 시도) 등을 통해 가중치를 업데이트
4️⃣ 학습 완료 후
: β0, β1,…를 얻어서 새로운 입력 값에 대한 예측 수행
장단점
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
y = diabetes.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)
train_test_split(X, y, test_size=0.2, train_size=None, shuffle=True, random_state=None, stratify=None)
매개변수: 의미
X: 입력 데이터 (특성들) → 보통 DataFrame이나 ndarray
y: 정답값 (레이블, 클래스 등)
test_size: 테스트셋 비율 or 개수 (ex. 0.2 → 20%, 200 → 200개)
train_size: (선택) 훈련셋 비율. test_size 안 쓰고 이거 쓸 수도 있음
shuffle: 데이터를 섞을지 여부 (True 기본값, 안 섞고 싶으면 False)
random_state: 데이터 섞는 기준 seed 값 → 결과 재현하고 싶을 때 사용
stratify: 계층 샘플링. 분류 문제에서 클래스 비율 맞추고 싶을 때 → y 넣어주면 됨
# 3. 선형회귀 (LinearRegression) 모델
lin_reg = LinearRegression()
lin_reg.fit(X_train, y_train)
# 예측
y_pred_lin = lin_reg.predict(X_test)
# 성능 측정, MSE
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))
fit은 학습하라는 뜻
모델이름.예측(데이터)
변수가 클수록 가중치가 커짐!(중요하지않을수록 0)
MSE는 오차값이기 때문에 작을수록(0일수록) 좋음
# 4. SGDRegressor 모델
sgd_reg = SGDRegressor(max_iter=6000, tol=1e-3, random_state=42)
sgd_reg.fit(X_train, y_train)
max_iter: 경험을 몇 번 할것인지(시도 횟수)
tol: 오차 허용범위(오차가 저정도 숫자가 되면 멈추게 함)
# 예측
y_pred_sgd = sgd_reg.predict(X_test)
# 성능 측정 MSE
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))
데이터(컬럼의 개수)가 많은경우 경사하강법이 효과적임 (시간적인 측면)
r2_score: 정답값(실제값), 예측값(모델값) 넣으면 자동으로 계산해줌
1에 가까울수록 예측이 맞다
비선형적인 관계를 다항식(polynomial) 형태로 모델링
ex) 2차 다항식

선형 회귀와 다른 점은, 단순 선형항()뿐만 아니라 ,... 같은 고차항을 추가해 비선형 패턴을 학습할 수 있다는 것
주의점
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)
# 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()

make_friedman1)n_samples=1000으로 1000개의 샘플을, n_features=5로 5개의 특성을 생성.noise=1.0으로 타겟 값에 약간의 랜덤 잡음을 추rk.# 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
MSE와 MAE의 장점 다 가져가려고 노력
제곱을 통해 큰 오차에 가중치를 더 주는 특징
오차가 클수록 패널티가 커지므로, 큰 오차가 중요한 문제에서 자주 사용

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

제곱을 절댓값으로 한 것 뿐.
가중치를 0으로 만드는걸 잘함(절댓값의 특징)
덜 필요한 독립변수 앞에 붙어 변수선택 효과를 줌(알아서 덜필요한 변수를 없앰)
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)
# 3. Ridge 회귀
# alpha=1.0 (규제 세기) 는 필요에 따라 조정 가능
ridge_reg = Ridge(alpha=1.0, random_state=42)
ridge_reg.fit(X_train, y_train)
alpha: 0~1, 규제를 얼마나 세게 줄 것인지 정함
# 예측
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()

낮은 가중치 확인 가능
# 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)
max_iter=10000로 반복을 얼마나 할 지 정할 수 있음
# 예측
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))

0에 가까운 가중치를 확인할 수 있음
= 3,4번째 독립변수는 회귀예측에 전혀 도움되지 않는다.
alpha가 클수록 규제 강도가 세어져, 모델 가중치(계수)들의 크기를 더욱 제약합니다.alpha가 클수록 일부 가중치가 정확히 0으로 수렴(특성 선택 효과).📚 회귀 모델을 만들 때 어떤 지표(R², MAE, RMSE)를 우선적으로 봐야 하나요?
문제의 특성에 따라 달라진다.
예측 오차의 크기가 중요하면 RMSE나 MAE,
모델이 데이터를 얼마나 잘 설명하는지 보려면 R²를 사용.
여러 지표를 종합적으로 살펴보는 것이 바람직