한 문장 요약!
✔️ 독립변수(X)와 종속변수(Y) 간의 관계를 활용해 연속형 결과(소수 포함 다양한 숫자)를 예측하는 것
(연속적이지 않은 것 -> 정수만 있는 것)
- 종속변수(Y) : 예측하고자 하는 변수
- 독립변수(X) : 종속변수 외 모든 변수
회귀 분석이란?
종속변수와 하나 이상의 독립변수 간의 관계를 추정 -> 연속형 종속변수를 예측하는 통계/머신러닝 기법
예) "공부한 시간(x)에 따라 시험점수(y)가 어떻게 변하는가?"를 예측
- 지도학습
- 분류(Classification) : 결과값이 이산형(클래스 라벨)
- 회귀(Regression) : 결과값이 연속형(숫자 값)
- 사용이유
1. 미래 값 예측 : 판매량, 주가, 온도 등 예측
2. 인과 관계 해석(통계 관점) : 특정 독립변수가 종속변수에 미치는 영향력 해석
3. 데이터 기반 의사결정 : 추세(trend)파악, 자원 분배 등
회귀 -> 시간에 따라 변하는 데이터들을 다루는 곳에서 굉장히 많이 사용
사례 -> 경제(주식가격, 판매량), 건강(혈압, 콜레스테롤 수치 예측), 제조(불량률, 생산량 예측) // 불량여부는 '분류'임!
선형 회귀
독립변수(X)와 종속변수(Y)가 선형적(일차 방정식 형태)으로 관계를 맺음, 직선관계, 단순한 관계


선형 회귀 모델 학습 과정
1. 가중치(회귀계수) 초기화
2. 손실함수(Loss Function) 설정 : 오차, 손실 -> MSE(Mean Squared Error) 사용
3. 최적화 : 수학적 방법(최소자승법), 경사하강법(Gradient Descent) 등으로 가중치 업데이트
-> 오차가 가장 작은 베타 값을 찾으면 방정식 결정. X값 넣으면 Y값 예측!!
예시.

실제로는 독립변수가 1개 보다는 더 많음.
✍️ 장단점 : 해석이 간단하고 구현이 쉬움. but, 선형성이 아닐 경우 예측력 저하
선형회귀 코드
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)

# 3. 선형회귀 (LinearRegression) 모델
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("[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))
* MSE, R2, 평균비율 오차 : 평가 지표 | * 가중치, 절편 : 머신러닝 모델을 해석할 때 사용

- 첫번째 독립변수는 크지 않은 값 -> 중요하지 않은 변수
- 931 값은 매우 중요한 값
- MSE : '0'에 가까울수록 좋은 것
- R2 : 1에 가까워지면 좋은 것
- 평균 비율 오차 : 실제 값대비 예측값이 전체적으로 몇퍼센트 정도 나타났는지. '0'에 가까울수록 좋다.
( * 예측값 > 실제값 : (-)값 | 예측값 < 실제값 : (+)값 )
# 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))

방정식에서 B(베타)값을 찾는 과정이었음.
다항 회귀 (Polynomial Regression)
✔️ 비선형적인 관계를 다항식 형태로 모델링 : 2차 다항식, n차 다항식
예시.
- 제조 : 온도와 반응율 관계가 곡선 형태인 경우
- 건강 : 나이와 특정 지표(근육량 등)가 곡선 형태인 경우
주의.
- 고차항을 무작정 늘리면, 과적합(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)

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

# 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))
* Pipeline : 여러개의 머신러닝을 차례대로 돌리거나, 전처리 후 머신러닝을 하는 등 여러가지 처리순서를 하나로 묶어서 처리하게 끔하는 sklearn의 기능

회귀모델 평가 방법
✔️ MSE (Mean Squared Error)

- 예측값과 실제값의 차이를 제곱하여 평균
- 오차가 클수록 제곱에 의해 더 큰 벌점 -> 큰 오차에 민감
- "평균 제곱 오차", 회귀 모델 평가에 매우 자주 사용
✔️ MAE (Mean Absolute Error)

- 예측값과 실제값의 차이를 절댓값으로 측정한 후 평균
- 예측이 평균적으로 실제에서 얼마나 벗어났는지 직관적으로 표현
✔️ RMSE (Root Mean Squared Error)

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

- 0에서 1 사이의 값 (음수가 될 수도)
- 1 에 가까울수록 학습된 모델이 데이터를 잘 설명! (0은 그 반대로 해석)
- (-) 값이 나오면 전처리부터 잘못된 것은 없는지 전면적 검토 필요!
고급 회귀 기법
선형 회귀에 규제항을 추가하여 과적합을 방지
Lasso & Ridge Regression
✔️ 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)

# 3. Ridge 회귀
# alpha=1.0 (규제 세기) 는 필요에 따라 조정 가능
ridge_reg = Ridge(alpha=1.0, random_state=42)
ridge_reg.fit(X_train, y_train)
* 알파 값(위 공식에서 람다값, 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 : 얼마나 반복할 것인지 설정 (릿지, 라쏘 둘다 가능)

# 예측
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))

총 정리
1. 회귀 모델은 연속형 결과 변수를 예측하는 데 사용
2. 선형 회귀는 가장 기본적 형태지만, 데이터 패턴이 비선형일 경우 다항 회귀 등 고려
3. 규제 기법을 활용한 모델(라쏘, 릿지)을 가중치를 규체하여 과적합을 방지
4. 앙상블 기법을 사용하는 경우 복잡한 비선형 패턴을 더 잘 포착할 수 있음
5. 모델의 성능 평가는 MAE, RMSE, R^2 등 다양한 지표를 통해 진행
'머신러닝' 카테고리의 다른 글
| [ML] 머신러닝 5강 - 무엇인지 맞추고 싶으면 분류! (1) | 2025.11.18 |
|---|---|
| [ML] 3강 - 머신러닝을 위한 전처리 실습 (0) | 2025.11.17 |
| [ML] 2강 - 머신러닝을 위한 전처리 이론 (1) | 2025.11.17 |