본문으로 건너뛰기

012 첫 번째 회귀 모델 만들기

키워드: 회귀, 첫 번째 모델

개요

이번에는 FLAML로 첫 번째 회귀 모델을 만들어 봅니다. 당뇨병 진행도를 예측하는 모델을 구현하며, 분류와 다른 회귀 문제의 특성을 이해합니다.

실습 환경

  • Python 버전: 3.11 권장
  • 필요 패키지: flaml[automl], pandas, scikit-learn, matplotlib
pip install flaml[automl] pandas scikit-learn matplotlib

프로젝트 개요

목표

환자의 건강 지표를 기반으로 1년 후 당뇨병 진행도(연속값)를 예측

데이터세트

  • 이름: Diabetes Dataset
  • 샘플 수: 442개
  • 특성 수: 10개 (나이, 성별, BMI, 혈압 등)
  • 타겟: 당뇨병 진행도 (연속값, 25~346)

Step 1: 라이브러리 임포트

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

from flaml import AutoML
from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split
from sklearn.metrics import (
mean_squared_error,
mean_absolute_error,
r2_score
)

import warnings
warnings.filterwarnings('ignore')

print("라이브러리 로드 완료!")

Step 2: 데이터 로드 및 탐색

# 012 데이터 로드
data = load_diabetes()

# 012 DataFrame으로 변환
df = pd.DataFrame(data.data, columns=data.feature_names)
df['target'] = data.target

# 012 기본 정보
print("="*60)
print("데이터 기본 정보")
print("="*60)
print(f"데이터 크기: {df.shape}")

print(f"\n컬럼 목록:")
for i, col in enumerate(df.columns, 1):
print(f" {i:2d}. {col}")

# 012 기초 통계량
print(f"\n기초 통계량:")
print(df.describe())

실행 결과

============================================================
데이터 기본 정보
============================================================
데이터 크기: (442, 11)

컬럼 목록:
1. age
2. sex
3. bmi
4. bp
5. s1
6. s2
7. s3
8. s4
9. s5
10. s6
11. target

타겟 분포 확인

# 012 타겟 분포 시각화
plt.figure(figsize=(10, 4))

plt.subplot(1, 2, 1)
plt.hist(df['target'], bins=30, edgecolor='black')
plt.xlabel('당뇨병 진행도')
plt.ylabel('빈도')
plt.title('타겟 분포')

plt.subplot(1, 2, 2)
plt.boxplot(df['target'])
plt.ylabel('당뇨병 진행도')
plt.title('타겟 박스플롯')

plt.tight_layout()
plt.savefig('target_distribution.png', dpi=100)
plt.show()

print(f"\n타겟 통계:")
print(f" 평균: {df['target'].mean():.2f}")
print(f" 표준편차: {df['target'].std():.2f}")
print(f" 최소: {df['target'].min():.2f}")
print(f" 최대: {df['target'].max():.2f}")

실행 결과

타겟 통계:
평균: 152.13
표준편차: 77.09
최소: 25.00
최대: 346.00

Step 3: 데이터 전처리

# 012 특성(X)과 타겟(y) 분리
X = df.drop('target', axis=1)
y = df['target']

# 012 결측치 확인
print("결측치 확인:")
print(f" 총 결측치: {X.isnull().sum().sum()}")

# 012 데이터 분할
X_train, X_test, y_train, y_test = train_test_split(
X, y,
test_size=0.2,
random_state=42
)

print(f"\n데이터 분할 완료:")
print(f" 학습 데이터: {X_train.shape[0]}개")
print(f" 테스트 데이터: {X_test.shape[0]}개")

Step 4: FLAML AutoML 실행

# 012 AutoML 객체 생성
automl = AutoML()

# 012 설정
settings = {
"task": "regression", # 회귀 태스크
"time_budget": 60,
"metric": "r2", # R² 점수 최적화
"estimator_list": ["lgbm", "xgboost", "rf", "extra_tree"],
"seed": 42,
"verbose": 1
}

print("="*60)
print("FLAML AutoML 학습 시작 (회귀)")
print("="*60)
print(f"시간 예산: {settings['time_budget']}초")
print(f"최적화 지표: {settings['metric']}")
print()

# 012 학습 실행
automl.fit(X_train, y_train, **settings)

실행 결과

============================================================
FLAML AutoML 학습 시작 (회귀)
============================================================
시간 예산: 60초
최적화 지표: r2

[flaml.automl.logger: INFO] Iteration 1, current learner lgbm
[flaml.automl.logger: INFO] at 0.2s, best lgbm's error=0.4892, ...
...
[flaml.automl.logger: INFO] Best ML model: lgbm

Step 5: 학습 결과 확인

print("="*60)
print("학습 결과")
print("="*60)

# 012 최적 모델
print(f"최적 모델: {automl.best_estimator}")

# 012 최적 하이퍼파라미터
print(f"\n최적 하이퍼파라미터:")
for key, value in automl.best_config.items():
print(f" {key}: {value}")

# 012 검증 점수
print(f"\n검증 R²: {1 - automl.best_loss:.4f}")

Step 6: 테스트 세트 평가

# 012 예측
y_pred = automl.predict(X_test)

print("="*60)
print("테스트 세트 평가")
print("="*60)

# 012 평가 지표 계산
r2 = r2_score(y_test, y_pred)
mse = mean_squared_error(y_test, y_pred)
rmse = np.sqrt(mse)
mae = mean_absolute_error(y_test, y_pred)

print(f"R² Score: {r2:.4f}")
print(f"MSE: {mse:.2f}")
print(f"RMSE: {rmse:.2f}")
print(f"MAE: {mae:.2f}")

# 012 해석
print(f"\n해석:")
print(f" - 모델이 타겟 변동의 {r2*100:.1f}%를 설명합니다.")
print(f" - 평균적으로 {mae:.1f} 정도의 오차가 발생합니다.")

실행 결과

============================================================
테스트 세트 평가
============================================================
R² Score: 0.4526
MSE: 2934.67
RMSE: 54.17
MAE: 44.32

해석:
- 모델이 타겟 변동의 45.3%를 설명합니다.
- 평균적으로 44.3 정도의 오차가 발생합니다.

Step 7: 결과 시각화

예측값 vs 실제값

plt.figure(figsize=(10, 5))

# 012 산점도
plt.subplot(1, 2, 1)
plt.scatter(y_test, y_pred, alpha=0.6, edgecolors='black', linewidth=0.5)
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()],
'r--', lw=2, label='Perfect Prediction')
plt.xlabel('실제값')
plt.ylabel('예측값')
plt.title(f'예측값 vs 실제값 (R²={r2:.4f})')
plt.legend()

# 012 잔차 분포
plt.subplot(1, 2, 2)
residuals = y_test - y_pred
plt.hist(residuals, bins=20, edgecolor='black')
plt.xlabel('잔차 (실제 - 예측)')
plt.ylabel('빈도')
plt.title('잔차 분포')
plt.axvline(x=0, color='r', linestyle='--')

plt.tight_layout()
plt.savefig('regression_results.png', dpi=100)
plt.show()

잔차 분석

# 012 잔차 통계
print("잔차 분석:")
print(f" 평균: {residuals.mean():.2f} (0에 가까워야 좋음)")
print(f" 표준편차: {residuals.std():.2f}")
print(f" 최소: {residuals.min():.2f}")
print(f" 최대: {residuals.max():.2f}")

Step 8: 다른 지표로 최적화

# 012 MAE로 최적화
print("\n" + "="*60)
print("MAE로 최적화 비교")
print("="*60)

automl_mae = AutoML()
automl_mae.fit(
X_train, y_train,
task="regression",
time_budget=60,
metric="mae", # MAE 최적화
seed=42,
verbose=0
)

y_pred_mae = automl_mae.predict(X_test)

print(f"MAE 최적화 결과:")
print(f" R²: {r2_score(y_test, y_pred_mae):.4f}")
print(f" MAE: {mean_absolute_error(y_test, y_pred_mae):.2f}")

print(f"\nR² 최적화 결과:")
print(f" R²: {r2_score(y_test, y_pred):.4f}")
print(f" MAE: {mean_absolute_error(y_test, y_pred):.2f}")

Step 9: 모델 저장

import pickle

# 012 모델 저장
model_path = 'diabetes_regressor.pkl'
with open(model_path, 'wb') as f:
pickle.dump(automl, f)

print(f"모델 저장 완료: {model_path}")

전체 코드 (복사용)

"""
FLAML 첫 번째 회귀 모델 - 당뇨병 진행도 예측
"""
import pandas as pd
import numpy as np
from flaml import AutoML
from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score, mean_squared_error, mean_absolute_error
import pickle

# 1. 데이터 로드
X, y = load_diabetes(return_X_y=True)

# 2. 데이터 분할
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)

# 3. FLAML 학습
automl = AutoML()
automl.fit(
X_train, y_train,
task="regression",
time_budget=60,
metric="r2",
seed=42
)

# 4. 평가
y_pred = automl.predict(X_test)
print(f"최적 모델: {automl.best_estimator}")
print(f"R² Score: {r2_score(y_test, y_pred):.4f}")
print(f"RMSE: {np.sqrt(mean_squared_error(y_test, y_pred)):.2f}")
print(f"MAE: {mean_absolute_error(y_test, y_pred):.2f}")

# 5. 저장
with open('model.pkl', 'wb') as f:
pickle.dump(automl, f)

분류 vs 회귀 비교

항목분류회귀
타겟범주형 (클래스)연속형 (숫자)
task"classification""regression"
주요 metricaccuracy, roc_auc, f1r2, mse, mae
평가 방법혼동 행렬, ROC 곡선잔차 분석, 산점도
예측 메서드predict(), predict_proba()predict()

정리

  • 당뇨병 데이터세트로 회귀 모델을 만들었습니다.
  • task="regression"metric="r2"를 설정했습니다.
  • R², MSE, RMSE, MAE 등 다양한 지표로 평가했습니다.
  • 잔차 분석으로 모델의 예측 패턴을 확인했습니다.
  • 최적화 지표에 따라 결과가 달라질 수 있음을 확인했습니다.

다음 글 예고

다음 글에서는 학습 결과 확인하기 - best_estimator에 대해 알아보겠습니다. FLAML 학습 후 결과를 확인하는 다양한 방법을 다룹니다.


FLAML AutoML 마스터 시리즈 #012