이거어어어어는... 돌리는건 하나 돌렸습니다. 그럼 왜함? 그 옵튜나인가 뭔가 하는 거 써보려고 했음.
Optuna
파이썬 라이브러리인데, 하이퍼파라미터 튜닝할때 쓴다. 모델 학습 전 사용자가 직접 설정하는 외부 구성 변수를 하이퍼파라미터라고 하는데, 이걸 사람이 수동으로 일일이 조정해가면서 어느 조건에서 내 모델을 뽕을 잘 뽑을지를 고민...하면서 일일이 하다 보면 할 것도 많고 파라미터 하나하나 일일이 손대가면서 찾기도 힘들잖아요? 그 노가다를 알아서 해주는게 옵튜나입니다.
모델 바이 모델이라 함수에 집어넣는 게 다른데, 아무튼 이거 이거 이거 해줘 하면 지 알아서 음 이렇군 하면서 오케이 가릿 이걸로 진행시켜 한다. 모델에 따라서는 시간이 좀 걸리기도 합니다.
안하면 섭한 전처리
자녀 수 범주화
# 자녀 수는 모르겠고 유무로 범주화할거임. ㅇㅋ? ㅇㅇㅋ.
cost['have_child'] = cost['children'].apply(lambda x: 0 if x == 0 else 1) # 자녀수가 0이면 0, 0보다 크면 1
# 유자녀가 1입니다
심플하게 유자녀 무자녀로 범주화했다.
일부 칼럼 퇴근시키기
cost.drop('region', axis = 1, inplace = True)
cost.drop('children', axis = 1, inplace = True)
자녀 칼럼: 범주화했으니까 퇴근해도 됨/지역 칼럼: 학습에 도움 안 될 것 같아서 퇴근
스케일뤄어어어어
scaler = StandardScaler()
cost[['age','bmi']] = scaler.fit_transform(cost[['age','bmi']])
이정도면 다들 저거 뭔지 아시죠?
매핑
# 흡연여부
cost['smoker'] = cost['smoker'].map({'yes': 1, 'no': 0})
cost['sex'] = cost['sex'].map({'male': 1, 'female': 0})
아니 성별은 원핫인코더 쓰려고 했더니 에러토하데… ㅡㅡ
옵튜나 써보기
# 1. 독립변수(X)와 종속변수(y) 분리
X = cost.drop('charges', axis=1)
y = np.log1p(cost['charges']) # 아까 말씀드린 로그 변환!
# 2. 데이터 분할 (보통 8:2나 7.5:2.5로 나눕니다)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
print(f"학습 데이터 개수: {len(X_train)}")
print(f"테스트 데이터 개수: {len(X_test)}")
근데 우리 이거 쓰기 전에 학습용 테스트용 나눠야되는건 아시죠?
def objective(trial):
param = {
'n_estimators': trial.suggest_int('n_estimators', 500, 2000),
'max_depth': trial.suggest_int('max_depth', 3, 9),
'learning_rate': trial.suggest_float('learning_rate', 0.01, 0.1),
'subsample': trial.suggest_float('subsample', 0.6, 1.0),
'colsample_bytree': trial.suggest_float('colsample_bytree', 0.6, 1.0),
'random_state': 42
}
model = XGBRegressor(**param)
model.fit(X_train, y_train)
preds = model.predict(X_test)
rmse = np.sqrt(mean_squared_error(y_test, preds))
return rmse
# 최적화 시작
study = optuna.create_study(direction='minimize')
study.optimize(objective, n_trials=50) # 50번 정도만 돌려봐도 감이 옵니다.
print(f"최고의 파라미터: {study.best_params}")
이렇게 범위를 정해주면... 그 범위 뭐가 뭔지 모르겠으면 에미나이나 지피티, 클로드한테 나 이 모델 돌릴건데 옵튜나 짜줘 하시면 됩니다... 아무튼. 저렇게 주고 맞춰주십쇼 하면 옵튜나가 아 ㅇㅋㅇㅋ 해봅시다! 하면서 뭔가 돌아가요.
최고의 파라미터: {'n_estimators': 815, 'max_depth': 3, 'learning_rate': 0.017046309566345508, 'subsample': 0.9510680208670862, 'colsample_bytree': 0.8874051559739393}
그리고 다 돌아가면 이렇게 돌리면 이렇게 나온다! 하고 알려줍니다. 회귀 돌릴때 옵튜나 쓰면 최상의 파라미터랑 그걸로 돌렸을때 R^2도 같이 나옴.
학습
model = XGBRegressor(**study.best_params)
model.fit(X_train, y_train)
하아니 그럼 저 파라미터를 다 복붙해야 하나요? 아니, 그런 귀찮은 짓을 할 필요가 없어요. 우리는 저 파라미터를 변수에 할당해뒀으니까 그거 앞에 애스터리스크 두개 붙여서 모델에 넣으십쇼.
# 1. 예측 수행 (로그 상태)
y_pred_log = model.predict(X_test)
# 2. 역변환 (로그 -> 원래 달러 단위)
y_pred = np.expm1(y_pred_log)
y_actual = np.expm1(y_test)
# 3. 성능 지표 확인
print(f"R² Score (결정계수): {r2_score(y_actual, y_pred):.4f}")
print(f"MAE (평균 절대 오차): ${mean_absolute_error(y_actual, y_pred):.2f}")
print(f"MSE (평균 제곱 오차): ${mean_squared_error(y_actual, y_pred):.2f}")
print(f"RMSE (제곱근 평균 제곱 오차): ${np.sqrt(mean_squared_error(y_actual, y_pred)):.2f}")
R² Score (결정계수): 0.8768
MAE (평균 절대 오차): $1999.14
MSE (평균 제곱 오차): $19125564.44
RMSE (제곱근 평균 제곱 오차): $4373.28
?? 근데 내 예상보다 더 잘나왔어 이거...
'Coding > EDA' 카테고리의 다른 글
| clinVar EDA를 Polars로 해보자-Pathogenic EDA (0) | 2026.04.14 |
|---|---|
| clinVar EDA를 Polars로 해보자 (0) | 2026.04.13 |
| Red Wine Quality (0) | 2026.03.13 |
| Palmer Archipelago (Antarctica) penguin data (0) | 2026.03.11 |
| Google Play Store – Most Downloaded Android Apps (0) | 2026.03.02 |