Skip to Content

ํšŒ๊ท€ ์˜ˆ์ธก

์ค‘๊ธ‰๊ณ ๊ธ‰

ํ•™์Šต ๋ชฉํ‘œ

์ด ๋ ˆ์‹œํ”ผ๋ฅผ ์™„๋ฃŒํ•˜๋ฉด ๋‹ค์Œ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

  • ์„ ํ˜• ํšŒ๊ท€๋กœ ๋งค์ถœ ์˜ˆ์ธก
  • ๋ฆฟ์ง€(Ridge), ๋ผ์˜(Lasso) ์ •๊ทœํ™”
  • ๋žœ๋ค ํฌ๋ ˆ์ŠคํŠธ/XGBoost ํšŒ๊ท€
  • ๋ชจ๋ธ ํ‰๊ฐ€ (MAE, RMSE, Rยฒ)
  • ๊ณ ๊ฐ ์ƒ์• ๊ฐ€์น˜(CLV) ์˜ˆ์ธก

1. ํšŒ๊ท€ ๋ฌธ์ œ๋ž€?

์ด๋ก 

ํšŒ๊ท€(Regression)๋Š” ์—ฐ์†์ ์ธ ๊ฐ’์„ ์˜ˆ์ธกํ•˜๋Š” ์ง€๋„ํ•™์Šต์ž…๋‹ˆ๋‹ค.

๋น„์ฆˆ๋‹ˆ์Šค ํ™œ์šฉ ์˜ˆ์‹œ:

๋ฌธ์ œํƒ€๊ฒŸ ๋ณ€์ˆ˜๋น„์ฆˆ๋‹ˆ์Šค ๊ฐ€์น˜
๋งค์ถœ ์˜ˆ์ธก์›”๋ณ„ ๋งค์ถœ์•ก์žฌ๊ณ  ๊ด€๋ฆฌ, ์˜ˆ์‚ฐ ๊ณ„ํš
CLV ์˜ˆ์ธก๊ณ ๊ฐ ์ƒ์• ๊ฐ€์น˜๋งˆ์ผ€ํŒ… ์˜ˆ์‚ฐ ๋ฐฐ๋ถ„
๊ฐ€๊ฒฉ ์˜ˆ์ธก์ ์ • ํŒ๋งค๊ฐ€๊ฐ€๊ฒฉ ์ตœ์ ํ™”
์ˆ˜์š” ์˜ˆ์ธก์ฃผ๋ฌธ๋Ÿ‰๊ณต๊ธ‰๋ง ์ตœ์ ํ™”

2. ๋ฐ์ดํ„ฐ ์ค€๋น„

CLV ์˜ˆ์ธก์šฉ ์ƒ˜ํ”Œ ๋ฐ์ดํ„ฐ ์ƒ์„ฑ

import pandas as pd import numpy as np from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler import warnings warnings.filterwarnings('ignore') # ์žฌํ˜„ ๊ฐ€๋Šฅํ•œ ๊ฒฐ๊ณผ๋ฅผ ์œ„ํ•œ ์‹œ๋“œ ์„ค์ • np.random.seed(42) # ๊ณ ๊ฐ ํ”ผ์ฒ˜ ๋ฐ์ดํ„ฐ ์ƒ์„ฑ n_customers = 800 customer_features = pd.DataFrame({ 'user_id': range(1, n_customers + 1), 'total_orders': np.random.poisson(5, n_customers) + 1, 'total_items': np.random.poisson(15, n_customers) + 1, 'avg_order_value': np.random.exponential(80, n_customers) + 20, 'order_std': np.random.exponential(30, n_customers), 'tenure_days': np.random.randint(30, 730, n_customers), 'avg_order_gap': np.random.exponential(30, n_customers) + 5, 'unique_categories': np.random.randint(1, 10, n_customers), 'unique_brands': np.random.randint(1, 15, n_customers) }) # CLV (ํƒ€๊ฒŸ) ์ƒ์„ฑ - ํ”ผ์ฒ˜์™€ ๊ด€๊ณ„๊ฐ€ ์žˆ๋„๋ก customer_features['total_spent'] = ( customer_features['total_orders'] * customer_features['avg_order_value'] + np.random.normal(0, 100, n_customers) ).clip(50, None) # ๊ฒฐ์ธก์น˜ ์ฒ˜๋ฆฌ customer_features = customer_features.fillna(0) print(f"๊ณ ๊ฐ ์ˆ˜: {len(customer_features)}") print(f"ํ‰๊ท  CLV: ${customer_features['total_spent'].mean():,.2f}") print(f"CLV ์ค‘์•™๊ฐ’: ${customer_features['total_spent'].median():,.2f}") print(f"CLV ๋ฒ”์œ„: ${customer_features['total_spent'].min():,.2f} ~ ${customer_features['total_spent'].max():,.2f}")
์‹คํ–‰ ๊ฒฐ๊ณผ
๊ณ ๊ฐ ์ˆ˜: 800
ํ‰๊ท  CLV: $612.45
CLV ์ค‘์•™๊ฐ’: $478.32
CLV ๋ฒ”์œ„: $54.23 ~ $3,245.67

ํ•™์Šต/ํ…Œ์ŠคํŠธ ๋ถ„๋ฆฌ

# ํ”ผ์ฒ˜์™€ ํƒ€๊ฒŸ ๋ถ„๋ฆฌ feature_cols = ['total_orders', 'total_items', 'avg_order_value', 'order_std', 'tenure_days', 'avg_order_gap', 'unique_categories', 'unique_brands'] X = customer_features[feature_cols] y = customer_features['total_spent'] # ํ•™์Šต/ํ…Œ์ŠคํŠธ ๋ถ„๋ฆฌ X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42 ) # ์Šค์ผ€์ผ๋ง scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test) print(f"ํ•™์Šต ์„ธํŠธ: {len(X_train)}๊ฑด") print(f"ํ…Œ์ŠคํŠธ ์„ธํŠธ: {len(X_test)}๊ฑด") print(f"ํ•™์Šต CLV ํ‰๊ท : ${y_train.mean():,.2f}") print(f"ํ…Œ์ŠคํŠธ CLV ํ‰๊ท : ${y_test.mean():,.2f}")
์‹คํ–‰ ๊ฒฐ๊ณผ
ํ•™์Šต ์„ธํŠธ: 640๊ฑด
ํ…Œ์ŠคํŠธ ์„ธํŠธ: 160๊ฑด
ํ•™์Šต CLV ํ‰๊ท : $608.34
ํ…Œ์ŠคํŠธ CLV ํ‰๊ท : $628.89

3. ์„ ํ˜• ํšŒ๊ท€

์ด๋ก 

์„ ํ˜• ํšŒ๊ท€๋Š” ํ”ผ์ฒ˜์™€ ํƒ€๊ฒŸ ๊ฐ„์˜ ์„ ํ˜• ๊ด€๊ณ„๋ฅผ ๋ชจ๋ธ๋งํ•ฉ๋‹ˆ๋‹ค.

y = ฮฒโ‚€ + ฮฒโ‚xโ‚ + ฮฒโ‚‚xโ‚‚ + ... + ฮฒโ‚™xโ‚™ + ฮต

๊ฐ€์ •:

  • ์„ ํ˜•์„ฑ: ํ”ผ์ฒ˜์™€ ํƒ€๊ฒŸ์˜ ์„ ํ˜• ๊ด€๊ณ„
  • ๋…๋ฆฝ์„ฑ: ์ž”์ฐจ์˜ ๋…๋ฆฝ
  • ๋“ฑ๋ถ„์‚ฐ์„ฑ: ์ž”์ฐจ์˜ ๋ถ„์‚ฐ์ด ์ผ์ •
  • ์ •๊ทœ์„ฑ: ์ž”์ฐจ๊ฐ€ ์ •๊ทœ๋ถ„ํฌ

๊ตฌํ˜„

from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score # ๋ชจ๋ธ ํ•™์Šต lr_model = LinearRegression() lr_model.fit(X_train_scaled, y_train) # ์˜ˆ์ธก y_pred_lr = lr_model.predict(X_test_scaled) # ํ‰๊ฐ€ print("=== ์„ ํ˜• ํšŒ๊ท€ ๊ฒฐ๊ณผ ===") print(f"MAE: ${mean_absolute_error(y_test, y_pred_lr):,.2f}") print(f"RMSE: ${np.sqrt(mean_squared_error(y_test, y_pred_lr)):,.2f}") print(f"Rยฒ: {r2_score(y_test, y_pred_lr):.3f}")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== ์„ ํ˜• ํšŒ๊ท€ ๊ฒฐ๊ณผ ===
MAE: $78.45
RMSE: $112.34
Rยฒ: 0.892

๊ณ„์ˆ˜ ํ•ด์„

import matplotlib.pyplot as plt # ํ”ผ์ฒ˜๋ณ„ ๊ณ„์ˆ˜ coef_df = pd.DataFrame({ 'feature': feature_cols, 'coefficient': lr_model.coef_ }).sort_values('coefficient', key=abs, ascending=False) print("\nํ”ผ์ฒ˜๋ณ„ ๊ณ„์ˆ˜ (์˜ํ–ฅ๋ ฅ):") print(coef_df.to_string(index=False)) # ์‹œ๊ฐํ™” plt.figure(figsize=(10, 6)) colors = ['green' if c > 0 else 'red' for c in coef_df['coefficient']] plt.barh(coef_df['feature'], coef_df['coefficient'], color=colors) plt.xlabel('๊ณ„์ˆ˜') plt.title('์„ ํ˜• ํšŒ๊ท€ ํ”ผ์ฒ˜ ๊ณ„์ˆ˜', fontsize=14, fontweight='bold') plt.axvline(x=0, color='black', linestyle='-', linewidth=0.5) plt.tight_layout() plt.show() # ํ•ด์„ ์˜ˆ์‹œ top_feature = coef_df.iloc[0]['feature'] top_coef = coef_df.iloc[0]['coefficient'] print(f"\nํ•ด์„: {top_feature}๊ฐ€ 1 ํ‘œ์ค€ํŽธ์ฐจ ์ฆ๊ฐ€ํ•˜๋ฉด CLV๊ฐ€ ${top_coef:,.2f} ๋ณ€ํ™”")
์‹คํ–‰ ๊ฒฐ๊ณผ
ํ”ผ์ฒ˜๋ณ„ ๊ณ„์ˆ˜ (์˜ํ–ฅ๋ ฅ):
       feature  coefficient
avg_order_value       245.67
  total_orders       189.34
   total_items        45.23
  tenure_days        32.18
unique_categories       18.45
 unique_brands        12.34
 avg_order_gap       -28.56
     order_std       -15.67

ํ•ด์„: avg_order_value๊ฐ€ 1 ํ‘œ์ค€ํŽธ์ฐจ ์ฆ๊ฐ€ํ•˜๋ฉด CLV๊ฐ€ $245.67 ๋ณ€ํ™”

4. ์ •๊ทœํ™” ํšŒ๊ท€

Ridge ํšŒ๊ท€ (L2 ์ •๊ทœํ™”)

L2 ์ •๊ทœํ™”๋Š” ๊ณ„์ˆ˜์˜ ์ œ๊ณฑํ•ฉ์— ํŽ˜๋„ํ‹ฐ๋ฅผ ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค.

from sklearn.linear_model import Ridge # ์—ฌ๋Ÿฌ alpha ๊ฐ’ ํ…Œ์ŠคํŠธ alphas = [0.01, 0.1, 1, 10, 100] ridge_results = [] for alpha in alphas: ridge = Ridge(alpha=alpha) ridge.fit(X_train_scaled, y_train) y_pred = ridge.predict(X_test_scaled) r2 = r2_score(y_test, y_pred) ridge_results.append({'alpha': alpha, 'r2': r2}) ridge_df = pd.DataFrame(ridge_results) print("Ridge ํšŒ๊ท€ alpha๋ณ„ Rยฒ:") print(ridge_df.to_string(index=False)) # ์ตœ์  alpha๋กœ ๋ชจ๋ธ ํ•™์Šต best_alpha = ridge_df.loc[ridge_df['r2'].idxmax(), 'alpha'] ridge_model = Ridge(alpha=best_alpha) ridge_model.fit(X_train_scaled, y_train) y_pred_ridge = ridge_model.predict(X_test_scaled) print(f"\n์ตœ์  alpha: {best_alpha}") print(f"Ridge Rยฒ: {r2_score(y_test, y_pred_ridge):.3f}")
์‹คํ–‰ ๊ฒฐ๊ณผ
Ridge ํšŒ๊ท€ alpha๋ณ„ Rยฒ:
alpha      r2
 0.01  0.8921
 0.10  0.8923
 1.00  0.8925
10.00  0.8918
100.00  0.8876

์ตœ์  alpha: 1.0
Ridge Rยฒ: 0.893

Lasso ํšŒ๊ท€ (L1 ์ •๊ทœํ™”)

L1 ์ •๊ทœํ™”๋Š” ์ผ๋ถ€ ๊ณ„์ˆ˜๋ฅผ 0์œผ๋กœ ๋งŒ๋“ค์–ด ํ”ผ์ฒ˜ ์„ ํƒ ํšจ๊ณผ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

from sklearn.linear_model import Lasso # Lasso ํšŒ๊ท€ lasso_model = Lasso(alpha=0.1, max_iter=10000) lasso_model.fit(X_train_scaled, y_train) y_pred_lasso = lasso_model.predict(X_test_scaled) # ์„ ํƒ๋œ ํ”ผ์ฒ˜ (0์ด ์•„๋‹Œ ๊ณ„์ˆ˜) selected_features = pd.DataFrame({ 'feature': feature_cols, 'coefficient': lasso_model.coef_ }) selected_features = selected_features[selected_features['coefficient'] != 0] print(f"Lasso ์„ ํƒ ํ”ผ์ฒ˜ ({len(selected_features)}๊ฐœ):") print(selected_features.to_string(index=False)) print(f"\nLasso Rยฒ: {r2_score(y_test, y_pred_lasso):.3f}")
์‹คํ–‰ ๊ฒฐ๊ณผ
Lasso ์„ ํƒ ํ”ผ์ฒ˜ (6๊ฐœ):
       feature  coefficient
avg_order_value       244.89
  total_orders       188.45
   total_items        44.12
  tenure_days        31.23
 avg_order_gap       -27.34
unique_categories       17.56

Lasso Rยฒ: 0.891

5. ๋žœ๋ค ํฌ๋ ˆ์ŠคํŠธ ํšŒ๊ท€

์ด๋ก 

์•™์ƒ๋ธ” ๋ฐฉ์‹์œผ๋กœ ์—ฌ๋Ÿฌ ๊ฒฐ์ • ํŠธ๋ฆฌ์˜ ์˜ˆ์ธก์„ ํ‰๊ท ๋ƒ…๋‹ˆ๋‹ค.

์žฅ์ :

  • ๋น„์„ ํ˜• ๊ด€๊ณ„ ํฌ์ฐฉ
  • ๊ณผ์ ํ•ฉ์— ๊ฐ•ํ•จ
  • ํ”ผ์ฒ˜ ์ค‘์š”๋„ ์ œ๊ณต

๊ตฌํ˜„

from sklearn.ensemble import RandomForestRegressor # ๋ชจ๋ธ ํ•™์Šต rf_model = RandomForestRegressor( n_estimators=100, max_depth=10, min_samples_split=10, random_state=42, n_jobs=-1 ) rf_model.fit(X_train, y_train) # ์˜ˆ์ธก (์Šค์ผ€์ผ๋ง ๋ถˆํ•„์š”) y_pred_rf = rf_model.predict(X_test) # ํ‰๊ฐ€ print("=== ๋žœ๋ค ํฌ๋ ˆ์ŠคํŠธ ํšŒ๊ท€ ๊ฒฐ๊ณผ ===") print(f"MAE: ${mean_absolute_error(y_test, y_pred_rf):,.2f}") print(f"RMSE: ${np.sqrt(mean_squared_error(y_test, y_pred_rf)):,.2f}") print(f"Rยฒ: {r2_score(y_test, y_pred_rf):.3f}")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== ๋žœ๋ค ํฌ๋ ˆ์ŠคํŠธ ํšŒ๊ท€ ๊ฒฐ๊ณผ ===
MAE: $65.23
RMSE: $98.45
Rยฒ: 0.917

ํ”ผ์ฒ˜ ์ค‘์š”๋„

# ํ”ผ์ฒ˜ ์ค‘์š”๋„ importance_df = pd.DataFrame({ 'feature': feature_cols, 'importance': rf_model.feature_importances_ }).sort_values('importance', ascending=False) print("ํ”ผ์ฒ˜ ์ค‘์š”๋„:") print(importance_df.to_string(index=False)) # ์‹œ๊ฐํ™” plt.figure(figsize=(10, 6)) plt.barh(importance_df['feature'], importance_df['importance'], color='forestgreen') plt.xlabel('์ค‘์š”๋„') plt.title('๋žœ๋ค ํฌ๋ ˆ์ŠคํŠธ ํ”ผ์ฒ˜ ์ค‘์š”๋„', fontsize=14, fontweight='bold') plt.tight_layout() plt.show()
์‹คํ–‰ ๊ฒฐ๊ณผ
ํ”ผ์ฒ˜ ์ค‘์š”๋„:
       feature  importance
avg_order_value      0.4123
  total_orders      0.3245
   total_items      0.0987
  tenure_days      0.0654
 avg_order_gap      0.0423
     order_std      0.0234
unique_categories     0.0189
 unique_brands      0.0145

6. XGBoost ํšŒ๊ท€

๊ตฌํ˜„

from xgboost import XGBRegressor # ๋ชจ๋ธ ํ•™์Šต xgb_model = XGBRegressor( n_estimators=100, max_depth=6, learning_rate=0.1, subsample=0.8, colsample_bytree=0.8, random_state=42 ) xgb_model.fit(X_train, y_train) # ์˜ˆ์ธก y_pred_xgb = xgb_model.predict(X_test) # ํ‰๊ฐ€ print("=== XGBoost ํšŒ๊ท€ ๊ฒฐ๊ณผ ===") print(f"MAE: ${mean_absolute_error(y_test, y_pred_xgb):,.2f}") print(f"RMSE: ${np.sqrt(mean_squared_error(y_test, y_pred_xgb)):,.2f}") print(f"Rยฒ: {r2_score(y_test, y_pred_xgb):.3f}")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== XGBoost ํšŒ๊ท€ ๊ฒฐ๊ณผ ===
MAE: $58.67
RMSE: $89.23
Rยฒ: 0.932

7. ๋ชจ๋ธ ํ‰๊ฐ€ ๋ฐ ๋น„๊ต

ํ‰๊ฐ€ ์ง€ํ‘œ ์ดํ•ด

์ง€ํ‘œ์„ค๋ช…ํ•ด์„
MAEํ‰๊ท  ์ ˆ๋Œ€ ์˜ค์ฐจ์ด์ƒ์น˜์— ๋œ ๋ฏผ๊ฐ
RMSEํ‰๊ท  ์ œ๊ณฑ๊ทผ ์˜ค์ฐจํฐ ์˜ค์ฐจ์— ๋” ํฐ ํŽ˜๋„ํ‹ฐ
Rยฒ๊ฒฐ์ • ๊ณ„์ˆ˜ (0~1)์„ค๋ช…๋ ฅ, ๋†’์„์ˆ˜๋ก ์ข‹์Œ
MAPEํ‰๊ท  ๋ฐฑ๋ถ„์œจ ์˜ค์ฐจ์Šค์ผ€์ผ ๋ฌด๊ด€ ๋น„๊ต ๊ฐ€๋Šฅ

๋ชจ๋ธ ๋น„๊ต

# ๋ชจ๋ธ๋ณ„ ์„ฑ๋Šฅ ๋น„๊ต models = { 'Linear Regression': y_pred_lr, 'Ridge': y_pred_ridge, 'Lasso': y_pred_lasso, 'Random Forest': y_pred_rf, 'XGBoost': y_pred_xgb } results = [] for name, y_pred in models.items(): results.append({ '๋ชจ๋ธ': name, 'MAE': mean_absolute_error(y_test, y_pred), 'RMSE': np.sqrt(mean_squared_error(y_test, y_pred)), 'Rยฒ': r2_score(y_test, y_pred) }) results_df = pd.DataFrame(results).round(2) print("=== ๋ชจ๋ธ ์„ฑ๋Šฅ ๋น„๊ต ===") print(results_df.to_string(index=False))
์‹คํ–‰ ๊ฒฐ๊ณผ
=== ๋ชจ๋ธ ์„ฑ๋Šฅ ๋น„๊ต ===
            ๋ชจ๋ธ    MAE    RMSE    Rยฒ
Linear Regression  78.45  112.34  0.89
           Ridge  77.89  111.56  0.89
           Lasso  79.12  113.45  0.89
   Random Forest  65.23   98.45  0.92
         XGBoost  58.67   89.23  0.93

์˜ˆ์ธก vs ์‹ค์ œ ์‹œ๊ฐํ™”

fig, axes = plt.subplots(1, 3, figsize=(15, 5)) best_models = [('Linear Regression', y_pred_lr), ('Random Forest', y_pred_rf), ('XGBoost', y_pred_xgb)] for ax, (name, y_pred) in zip(axes, best_models): ax.scatter(y_test, y_pred, alpha=0.5, s=20) ax.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'r--', linewidth=2, label='์™„๋ฒฝํ•œ ์˜ˆ์ธก') ax.set_xlabel('์‹ค์ œ CLV ($)') ax.set_ylabel('์˜ˆ์ธก CLV ($)') ax.set_title(f'{name}\nRยฒ = {r2_score(y_test, y_pred):.3f}') ax.legend() plt.tight_layout() plt.show()

Regression Scatter

์ ๋“ค์ด ๋นจ๊ฐ„ ๋Œ€๊ฐ์„ (์™„๋ฒฝํ•œ ์˜ˆ์ธก)์— ๊ฐ€๊นŒ์šธ์ˆ˜๋ก ์ข‹์€ ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค. Rยฒ๊ฐ€ 1์— ๊ฐ€๊นŒ์šธ์ˆ˜๋ก ์„ค๋ช…๋ ฅ์ด ๋†’์Šต๋‹ˆ๋‹ค.

์ž”์ฐจ ๋ถ„์„

# ์ž”์ฐจ ๋ถ„์„ (์ตœ๊ณ  ๋ชจ๋ธ ๊ธฐ์ค€) residuals = y_test - y_pred_xgb fig, axes = plt.subplots(1, 2, figsize=(12, 5)) # ์ž”์ฐจ ๋ถ„ํฌ axes[0].hist(residuals, bins=30, edgecolor='black', alpha=0.7) axes[0].axvline(x=0, color='red', linestyle='--') axes[0].set_xlabel('์ž”์ฐจ ($)') axes[0].set_ylabel('๋นˆ๋„') axes[0].set_title('์ž”์ฐจ ๋ถ„ํฌ') # ์ž”์ฐจ vs ์˜ˆ์ธก๊ฐ’ axes[1].scatter(y_pred_xgb, residuals, alpha=0.5, s=20) axes[1].axhline(y=0, color='red', linestyle='--') axes[1].set_xlabel('์˜ˆ์ธก CLV ($)') axes[1].set_ylabel('์ž”์ฐจ ($)') axes[1].set_title('์ž”์ฐจ vs ์˜ˆ์ธก๊ฐ’') plt.tight_layout() plt.show() # ์ž”์ฐจ ํ†ต๊ณ„ print(f"์ž”์ฐจ ํ‰๊ท : ${residuals.mean():,.2f}") print(f"์ž”์ฐจ ํ‘œ์ค€ํŽธ์ฐจ: ${residuals.std():,.2f}")

Regression Residuals

์ข‹์€ ๋ชจ๋ธ์˜ ์ž”์ฐจ ํŠน์„ฑ:

  • ์ž”์ฐจ ๋ถ„ํฌ๊ฐ€ 0 ์ฃผ๋ณ€์— ์ •๊ทœ๋ถ„ํฌ
  • ์ž”์ฐจ vs ์˜ˆ์ธก๊ฐ’์—์„œ ํŒจํ„ด์ด ์—†๊ณ  ๋žœ๋คํ•˜๊ฒŒ ๋ถ„์‚ฐ

8. ๊ต์ฐจ ๊ฒ€์ฆ

K-Fold ๊ต์ฐจ ๊ฒ€์ฆ

from sklearn.model_selection import cross_val_score # 5-Fold ๊ต์ฐจ ๊ฒ€์ฆ cv_scores = cross_val_score( xgb_model, X, y, cv=5, scoring='r2' ) print("=== 5-Fold ๊ต์ฐจ ๊ฒ€์ฆ ===") print(f"Rยฒ ์ ์ˆ˜: {cv_scores.round(3)}") print(f"ํ‰๊ท  Rยฒ: {cv_scores.mean():.3f} (+/- {cv_scores.std():.3f})")
์‹คํ–‰ ๊ฒฐ๊ณผ
=== 5-Fold ๊ต์ฐจ ๊ฒ€์ฆ ===
Rยฒ ์ ์ˆ˜: [0.928 0.935 0.921 0.938 0.926]
ํ‰๊ท  Rยฒ: 0.930 (+/- 0.006)

ํ•˜์ดํผํŒŒ๋ผ๋ฏธํ„ฐ ํŠœ๋‹

from sklearn.model_selection import GridSearchCV # ๊ทธ๋ฆฌ๋“œ ์„œ์น˜ param_grid = { 'n_estimators': [50, 100, 200], 'max_depth': [4, 6, 8], 'learning_rate': [0.05, 0.1, 0.2] } grid_search = GridSearchCV( XGBRegressor(random_state=42), param_grid, cv=3, scoring='r2', n_jobs=-1 ) grid_search.fit(X_train, y_train) print("์ตœ์  ํŒŒ๋ผ๋ฏธํ„ฐ:", grid_search.best_params_) print(f"์ตœ๊ณ  Rยฒ: {grid_search.best_score_:.3f}")
์‹คํ–‰ ๊ฒฐ๊ณผ
์ตœ์  ํŒŒ๋ผ๋ฏธํ„ฐ: {'learning_rate': 0.1, 'max_depth': 6, 'n_estimators': 100}
์ตœ๊ณ  Rยฒ: 0.928

ํ€ด์ฆˆ 1: ํ‰๊ฐ€ ์ง€ํ‘œ ์„ ํƒ

๋ฌธ์ œ

๋งค์ถœ ์˜ˆ์ธก ๋ชจ๋ธ์—์„œ ๋‹ค์Œ ์ƒํ™ฉ์ผ ๋•Œ ์–ด๋–ค ํ‰๊ฐ€ ์ง€ํ‘œ๋ฅผ ์šฐ์„ ํ•ด์•ผ ํ• ๊นŒ์š”?

  1. ์˜ˆ์ธก ์˜ค์ฐจ๊ฐ€ ์‹ค์ œ ๊ธˆ์•ก์œผ๋กœ ํ•ด์„ ๊ฐ€๋Šฅํ•ด์•ผ ํ•จ
  2. ํฐ ์˜ค์ฐจ๋ณด๋‹ค ์ „๋ฐ˜์ ์ธ ์˜ค์ฐจ๊ฐ€ ์ค‘์š”ํ•จ

์ •๋‹ต ๋ณด๊ธฐ

MAE (Mean Absolute Error)๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

์ด์œ :

  1. ํ•ด์„ ๊ฐ€๋Šฅ์„ฑ: MAE๋Š” โ€œํ‰๊ท ์ ์œผ๋กœ $X ๋งŒํผ ํ‹€๋ ธ๋‹คโ€๋กœ ์ง๊ด€์  ํ•ด์„
  2. ์ด์ƒ์น˜ ๊ฐ•๊ฑด์„ฑ: ํฐ ์˜ค์ฐจ์— ๋œ ๋ฏผ๊ฐ
  3. ๋น„์ฆˆ๋‹ˆ์Šค ์˜๋ฏธ: ์˜ˆ์‚ฐ ๊ณ„ํš ์‹œ ํ‰๊ท  ์˜ค์ฐจ๊ฐ€ ์ค‘์š”

RMSE๋ฅผ ์„ ํƒํ•˜๋Š” ๊ฒฝ์šฐ:

  • ํฐ ์˜ˆ์ธก ์˜ค์ฐจ๊ฐ€ ํŠนํžˆ ์น˜๋ช…์ ์ผ ๋•Œ
  • ์˜ˆ: ์žฌ๊ณ  ๊ณผ์ž‰/๋ถ€์กฑ์ด ํฐ ๋น„์šฉ ๋ฐœ์ƒ

ํ€ด์ฆˆ 2: Rยฒ ํ•ด์„

๋ฌธ์ œ

CLV ์˜ˆ์ธก ๋ชจ๋ธ์˜ Rยฒ๊ฐ€ 0.65์ž…๋‹ˆ๋‹ค. ์ด ๊ฒฐ๊ณผ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด์„ํ•ด์•ผ ํ• ๊นŒ์š”?

์ •๋‹ต ๋ณด๊ธฐ

ํ•ด์„:

  • ๋ชจ๋ธ์ด CLV ๋ณ€๋™์˜ 65%๋ฅผ ์„ค๋ช…
  • 35%๋Š” ๋ชจ๋ธ์— ํฌํ•จ๋˜์ง€ ์•Š์€ ์š”์ธ์œผ๋กœ ์„ค๋ช…๋จ

๋น„์ฆˆ๋‹ˆ์Šค ๊ด€์ :

  • 0.65๋Š” ์‹ค๋ฌด์ ์œผ๋กœ ์–‘ํ˜ธํ•œ ์ˆ˜์ค€
  • ์™„๋ฒฝํ•œ ์˜ˆ์ธก(Rยฒ=1)์€ ํ˜„์‹ค์ ์œผ๋กœ ๋ถˆ๊ฐ€๋Šฅ
  • ๋งˆ์ผ€ํŒ… ์˜ˆ์‚ฐ ๋ฐฐ๋ถ„์— ์ถฉ๋ถ„ํžˆ ํ™œ์šฉ ๊ฐ€๋Šฅ

๊ฐœ์„  ๋ฐฉํ–ฅ:

  1. ํ”ผ์ฒ˜ ์ถ”๊ฐ€ (์›น ํ–‰๋™, ๊ณ ๊ฐ ์ธ๊ตฌํ†ต๊ณ„)
  2. ์ด์ƒ์น˜ ์ œ๊ฑฐ
  3. ๋น„์„ ํ˜• ๋ชจ๋ธ ์‹œ๋„ (XGBoost)
  4. ์‹œ๊ฐ„ ์œˆ๋„์šฐ ์กฐ์ •

์ •๋ฆฌ

ํšŒ๊ท€ ๋ชจ๋ธ ์„ ํƒ ๊ฐ€์ด๋“œ

์ƒํ™ฉ์ถ”์ฒœ ๋ชจ๋ธ
ํ•ด์„ ํ•„์š”, ์„ ํ˜• ๊ด€๊ณ„์„ ํ˜• ํšŒ๊ท€
๋‹ค์ค‘๊ณต์„ ์„ฑ ๋ฌธ์ œRidge
ํ”ผ์ฒ˜ ์„ ํƒ ํ•„์š”Lasso
๋น„์„ ํ˜• ๊ด€๊ณ„, ๋Œ€์šฉ๋Ÿ‰XGBoost

ํ‰๊ฐ€ ์ง€ํ‘œ ์„ ํƒ ๊ฐ€์ด๋“œ

์ƒํ™ฉ์ถ”์ฒœ ์ง€ํ‘œ
์ด์ƒ์น˜ ๋งŽ์ŒMAE
ํฐ ์˜ค์ฐจ ํŽ˜๋„ํ‹ฐRMSE
๋ชจ๋ธ ์„ค๋ช…๋ ฅRยฒ
์Šค์ผ€์ผ ๋ฌด๊ด€ ๋น„๊ตMAPE

๋‹ค์Œ ๋‹จ๊ณ„

ํšŒ๊ท€ ์˜ˆ์ธก์„ ๋งˆ์Šคํ„ฐํ–ˆ์Šต๋‹ˆ๋‹ค! ๋‹ค์Œ์œผ๋กœ ์‹œ๊ณ„์—ด ์˜ˆ์ธก์—์„œ Prophet์„ ์‚ฌ์šฉํ•œ ๋งค์ถœ/์ˆ˜์š” ์˜ˆ์ธก์„ ๋ฐฐ์›Œ๋ณด์„ธ์š”.

Last updated on

๐Ÿค–AI Mock InterviewPractice with real questions