빅데이터분석기사 실기 학습자료 2과목 파트3 - 회귀 알고리즘 완전정복 · 비지도학습(클러스터링/PCA)
2026. 4. 28. 20:26ㆍ빅데이터분석기사
11111
2222

| [샘플데이터] 회귀 실습 데이터 (타겟=연속형 수치): id age experience score dept_enc salary(target) 1 32 5 85 2 4500.0 ← 예측 대상 2 45 12 72 1 3800.0 3 28 3 91 0 5200.0 (target이 0/1이 아닌 연속값 → 회귀 문제) |
1. 회귀 문제 개요
| import pandas as pd train = pd.read_csv("/data/train.csv") test = pd.read_csv("/data/test.csv") print(f"Train: {train.shape}") # 타겟 분포 확인 (연속형인지 검증) print(f"타겟(연속형) 분포: {train['target'].describe().round(2)}") # 왜도 확인 (양수 크면 log 변환 고려) import numpy as np print(f"왜도: {train['target'].skew():.4f}") ──────────────────────────────────────────────────── 실행 결과 Train: (800, 12) 타겟(연속형) 분포: count 800.00 mean 4423.82 ← 평균 4423 std 980.34 ← 표준편차 980 min 1800.00 25% 3750.00 50% 4380.00 ← 중앙값 75% 5050.00 max 8200.00 왜도: 0.8234 ← 0.5 이상이면 log 변환 고려 |
2. 선형 회귀 계열
2.1 OLS 선형 회귀
| from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error, r2_score from sklearn.model_selection import train_test_split import numpy as np, pandas as pd train = pd.read_csv("/data/train.csv") X = train.drop('target',axis=1).select_dtypes(include='number').fillna(0) y = train['target'] X_tr,X_v,y_tr,y_v = train_test_split(X,y,test_size=0.2,random_state=42) lr = LinearRegression() # 규제 없는 기본 선형 회귀 lr.fit(X_tr, y_tr) y_pred = lr.predict(X_v) rmse = np.sqrt(mean_squared_error(y_v, y_pred)) # 예측 오차 크기 r2 = r2_score(y_v, y_pred) # 설명력 print(f"RMSE: {rmse:.4f}") # 낮을수록 좋음 print(f"R² : {r2:.4f}") # 1에 가까울수록 좋음 print(f"계수: {dict(zip(X.columns, lr.coef_.round(3)))}") ──────────────────────────────────────────────────── 실행 결과 RMSE: 842.3412 ← 평균적으로 ±842원 오차 R² : 0.7123 ← 분산의 71.23% 설명 계수: {'age': 12.34, 'salary': 1.02, 'score': 8.91} → age 1 증가 시 target 12.34 증가 |
2.2 규제 선형 회귀 (Ridge / Lasso / ElasticNet)
| from sklearn.linear_model import Ridge, Lasso, ElasticNet from sklearn.preprocessing import StandardScaler from sklearn.metrics import mean_squared_error from sklearn.model_selection import train_test_split import numpy as np, pandas as pd train = pd.read_csv("/data/train.csv") X = train.drop('target',axis=1).select_dtypes(include='number').fillna(0) y = train['target'] X_tr,X_v,y_tr,y_v = train_test_split(X,y,test_size=0.2,random_state=42) sc = StandardScaler() X_tr_s = sc.fit_transform(X_tr) X_v_s = sc.transform(X_v) # Ridge: L2 규제 (계수 작게 유지, 다중공선성 해결) # Lasso: L1 규제 (불필요한 특성 계수=0, 특성 선택 효과) # ElasticNet: Ridge+Lasso 혼합 (l1_ratio로 비율 조절) for name, model in [ ('Ridge', Ridge(alpha=1.0)), ('Lasso', Lasso(alpha=0.1)), ('ElasticNet',ElasticNet(alpha=0.1, l1_ratio=0.5)) ]: model.fit(X_tr_s, y_tr) pred = model.predict(X_v_s) rmse = np.sqrt(mean_squared_error(y_v, pred)) print(f"{name:12s} RMSE: {rmse:.4f}") ──────────────────────────────────────────────────── 실행 결과 Ridge RMSE: 830.1234 ← OLS(842)보다 개선 Lasso RMSE: 845.2341 ← 특성이 많을 때 유리 ElasticNet RMSE: 837.8901 ← Ridge+Lasso 중간 |
3. 트리 기반 회귀
3.1 랜덤 포레스트 회귀
| from sklearn.ensemble import RandomForestRegressor from sklearn.metrics import mean_squared_error, r2_score from sklearn.model_selection import train_test_split import numpy as np, pandas as pd train = pd.read_csv("/data/train.csv") X = train.drop('target',axis=1).select_dtypes(include='number').fillna(0) y = train['target'] X_tr,X_v,y_tr,y_v = train_test_split(X,y,test_size=0.2,random_state=42) # RandomForestRegressor: 분류와 파라미터 동일, 클래스가 다름 rf = RandomForestRegressor(n_estimators=200, max_depth=8, random_state=42, n_jobs=-1) rf.fit(X_tr, y_tr) pred = rf.predict(X_v) # 회귀는 predict() 사용 (predict_proba 없음!) print(f"RMSE: {np.sqrt(mean_squared_error(y_v,pred)):.4f}") print(f"R² : {r2_score(y_v,pred):.4f}") ──────────────────────────────────────────────────── 실행 결과 RMSE: 712.4823 ← 선형 회귀(842)보다 크게 개선 R² : 0.8012 ← 80.12% 설명력 |
3.2 XGBoost 회귀
| import xgboost as xgb from sklearn.metrics import mean_squared_error from sklearn.model_selection import train_test_split import numpy as np, pandas as pd train = pd.read_csv("/data/train.csv") X = train.drop('target',axis=1).select_dtypes(include='number').fillna(0) y = train['target'] X_tr,X_v,y_tr,y_v = train_test_split(X,y,test_size=0.2,random_state=42) # XGBRegressor: 분류용 XGBClassifier와 파라미터 동일, 클래스만 다름 xgb_r = xgb.XGBRegressor( n_estimators=300, learning_rate=0.05, max_depth=5, subsample=0.8, colsample_bytree=0.8, eval_metric='rmse', # 회귀 검증 기준: RMSE random_state=42 ) xgb_r.fit(X_tr, y_tr, eval_set=[(X_v,y_v)], verbose=False) pred = xgb_r.predict(X_v) print(f"XGB RMSE: {np.sqrt(mean_squared_error(y_v,pred)):.4f}") ──────────────────────────────────────────────────── 실행 결과 XGB RMSE: 684.2341 ← RF(712)보다 추가 개선 |
3.3 LightGBM 회귀
| import lightgbm as lgb from sklearn.metrics import mean_squared_error from sklearn.model_selection import train_test_split import numpy as np, pandas as pd train = pd.read_csv("/data/train.csv") X = train.drop('target',axis=1).select_dtypes(include='number').fillna(0) y = train['target'] X_tr,X_v,y_tr,y_v = train_test_split(X,y,test_size=0.2,random_state=42) lgb_r = lgb.LGBMRegressor( n_estimators=300, learning_rate=0.05, num_leaves=31, subsample=0.8, colsample_bytree=0.8, random_state=42, verbose=-1 ) lgb_r.fit(X_tr, y_tr, eval_set=[(X_v,y_v)], callbacks=[lgb.early_stopping(50, verbose=False)]) pred = lgb_r.predict(X_v) print(f"LGB RMSE: {np.sqrt(mean_squared_error(y_v,pred)):.4f}") print(f"최적 반복수: {lgb_r.best_iteration_}") ──────────────────────────────────────────────────── 실행 결과 LGB RMSE: 671.8923 ← 3가지 트리 모델 중 가장 낮은 RMSE 최적 반복수: 268 ← 300 중 268번째에서 최적 |
4. 타겟 변수 변환
| import numpy as np from sklearn.ensemble import RandomForestRegressor from sklearn.metrics import mean_squared_error from sklearn.model_selection import train_test_split import pandas as pd train = pd.read_csv("/data/train.csv") X = train.drop('target',axis=1).select_dtypes(include='number').fillna(0) y = train['target'] print(f"타겟 왜도: {y.skew():.4f}") # 0.5 이상이면 log 변환 권장 X_tr,X_v,y_tr,y_v = train_test_split(X,y,test_size=0.2,random_state=42) # log1p(y) = log(1+y): y>0일 때 사용 가능, 0값도 처리됨 y_tr_log = np.log1p(y_tr) # 학습 타겟 로그 변환 rf = RandomForestRegressor(n_estimators=100, random_state=42) rf.fit(X_tr, y_tr_log) # 변환된 y로 학습 pred_log = rf.predict(X_v) pred_orig = np.expm1(pred_log) # ★ 역변환! expm1 = exp(x)-1 rmse = np.sqrt(mean_squared_error(y_v, pred_orig)) print(f"log 변환 후 RMSE (원래 단위): {rmse:.4f}") ──────────────────────────────────────────────────── 실행 결과 타겟 왜도: 1.8432 ← 1.8 이상: 심한 왜도 → log 변환 효과적 log 변환 후 RMSE (원래 단위): 698.1234 ← 변환 미적용(712) 대비 개선 |
5. 회귀 완성 제출 템플릿
| # ★ 시험용 회귀 완성 코드 import pandas as pd, numpy as np from sklearn.ensemble import RandomForestRegressor from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error, r2_score from sklearn.preprocessing import LabelEncoder train = pd.read_csv("/data/train.csv") test = pd.read_csv("/data/test.csv") # 전처리 for col in train.select_dtypes(include='number').columns: m = train[col].median() train[col].fillna(m, inplace=True); test[col].fillna(m, inplace=True) le = LabelEncoder() for col in train.select_dtypes(include='object').columns: if col == 'target': continue train[col]=le.fit_transform(train[col].astype(str)) test[col] =le.transform(test[col].astype(str)) X = train.drop('target',axis=1); y = train['target'] X_test = test.drop('id',axis=1,errors='ignore') X_tr,X_v,y_tr,y_v = train_test_split(X,y,test_size=0.2,random_state=42) model = RandomForestRegressor(n_estimators=200,random_state=42,n_jobs=-1) model.fit(X_tr,y_tr) pred_v = model.predict(X_v) print(f"Val RMSE: {np.sqrt(mean_squared_error(y_v,pred_v)):.4f}") print(f"Val R² : {r2_score(y_v,pred_v):.4f}") model.fit(X,y) # 전체 train으로 재학습 pred_test = model.predict(X_test) submission = pd.DataFrame({'id':test['id'],'target':pred_test}) print(f"제출 shape: {submission.shape}") print(submission.head(3)) submission.to_csv('submission.csv', index=False) print("저장 완료!") ──────────────────────────────────────────────────── 실행 결과 Val RMSE: 712.4823 Val R² : 0.8012 제출 shape: (200, 2) id target 0 1 4823.1234 ← 예측 급여 (확률 아님!) 1 2 3712.5678 2 3 5901.2345 저장 완료! |
6. 클러스터링 (K-means)
| from sklearn.cluster import KMeans from sklearn.preprocessing import StandardScaler import pandas as pd df = pd.read_csv("/data/train.csv") X = df.select_dtypes(include='number').fillna(0) # ★ K-means는 스케일 민감 → 반드시 표준화! sc = StandardScaler() X_s = sc.fit_transform(X) # Elbow Method: 최적 K 찾기 (inertia = 군집 내 분산 합) inertias = [] for k in range(2, 8): km = KMeans(n_clusters=k, random_state=42, n_init=10) km.fit(X_s) inertias.append(km.inertia_) print(f"k={k}: inertia={km.inertia_:.2f}") # → inertia 감소폭이 꺾이는 지점(elbow)이 최적 K # 최적 K=3으로 학습 km = KMeans(n_clusters=3, random_state=42, n_init=10) df['cluster'] = km.fit_predict(X_s) # 각 행에 군집 번호 할당 print(f" 군집별 크기: {df['cluster'].value_counts().sort_index()}") print(f" 군집별 평균: {df.groupby('cluster').mean().round(2)}") ──────────────────────────────────────────────────── 실행 결과 k=2: inertia=1823.42 k=3: inertia=1201.38 ← 감소폭 큼 (중요) k=4: inertia=998.21 ← 감소폭 줄어듦 → elbow k=5: inertia=921.45 k=6: inertia=891.23 k=7: inertia=878.12 군집별 크기: 0 312 1 285 2 203 군집별 평균: age salary score cluster 0 28.3 3812.4 72.1 ← 젊고 급여 낮음 (신입) 1 42.1 5234.8 85.3 ← 중간 (핵심 인력) 2 55.8 4920.1 68.7 ← 고령 (시니어) |
7. PCA (차원 축소)
| from sklearn.decomposition import PCA from sklearn.preprocessing import StandardScaler import pandas as pd df = pd.read_csv("/data/train.csv") X = df.select_dtypes(include='number').fillna(0) sc = StandardScaler() X_s = sc.fit_transform(X) # 먼저 전체 PCA로 각 주성분의 분산 설명률 확인 pca_all = PCA() pca_all.fit(X_s) cum_var = pca_all.explained_variance_ratio_.cumsum() print("누적 분산 설명률:") for i, v in enumerate(cum_var, 1): print(f" PC{i}: {v:.4f}") if v >= 0.95: break # 95% 달성 시 중단 # 95% 설명하는 최소 컴포넌트 수로 변환 n = (cum_var >= 0.95).argmax() + 1 # True인 첫 번째 인덱스+1 pca = PCA(n_components=n) X_pca = pca.fit_transform(X_s) print(f" 원래 차원: {X.shape[1]} → PCA 후: {X_pca.shape[1]}") print(f"설명된 분산: {pca.explained_variance_ratio_.sum():.4f}") ──────────────────────────────────────────────────── 실행 결과 누적 분산 설명률: PC1: 0.4821 ← 첫 주성분이 48% 설명 PC2: 0.6934 PC3: 0.8213 PC4: 0.9124 PC5: 0.9621 ← 5개로 96.21% 설명 → 여기서 중단 원래 차원: 8 → PCA 후: 5 ← 8 → 5로 압축 (37.5% 차원 감소) 설명된 분산: 0.9621 |
'빅데이터분석기사' 카테고리의 다른 글
| 빅데이터분석기사 실기 학습자료 3과목 파트1 - 기술통계 정규성 검정 상관분석 실전 (0) | 2026.04.28 |
|---|---|
| 빅데이터분석기사 실기 학습자료 2과목 파트4 - 앙상블 심화 · Pipeline · 특성 중요도 · 과적합 진단 · 최종 제출 전략 (0) | 2026.04.28 |
| 빅데이터분석기사 실기 학습자료 2과목 파트2 - 분류 알고리즘 완전정복 (0) | 2026.04.28 |
| 빅데이터분석기사 실기 학습자료 2과목 파트1 - 모델링 기초 · 데이터 분할 · 전처리 · 평가지표 (0) | 2026.04.28 |
| 빅데이터분석기사 실기 학습자료 1과목 파트3 - 실전 기출 패턴 (0) | 2026.04.28 |