머신러닝 두 번째: 예측과 분류
댓글 불러오는 중…
댓글 불러오는 중…
첫 번째 여정에서 파이썬 ML 생태계 기초를 다졌다면, 이번엔 실제 예측과 분류 모델을 직접 만들어보는 시간이었다. 선형 회귀부터 로지스틱 회귀까지, 데이터로부터 패턴을 찾아 미래를 예측하는 법을 학습했다.
선형 회귀는 이번 파트에서 가장 먼저 손으로 돌려본 예측 모델이었다. 독립변수와 종속변수 간의 선형 관계를 찾아 미래 값을 예측한다. 이론은 단순한데, 실제로 써보면 생각보다 많은 것을 잡아낸다.
1import numpy as np
2import pandas as pd
3from sklearn.linear_model import LinearRegression
4from sklearn.model_selection import train_test_split
5from sklearn.metrics import mean_squared_error, r2_score
6
7# 데이터 준비
8X = np.random.rand(100, 1) * 10
9y = 2 * X + 1 + np.random.randn(100, 1) * 0.5
10
11# 모델 학습
12model = LinearRegression()
13model.fit(X, y)
14
15# 예측
16y_pred = model.predict(X)
17print(f"계수: {model.coef_[0][0]:.2f}")
18print(f"절편: {model.intercept_[0]:.2f}")실제 문제에서는 여러 변수가 복합적으로 작용한다. 여기서 중요한 건 어떤 변수가 얼마나 영향을 미치는지 계수로 확인할 수 있다는 점이다.
1# 다중 변수 데이터
2X_multi = np.random.rand(100, 3) * 10
3y_multi = 2*X_multi[:, 0] + 1.5*X_multi[:, 1] - 0.5*X_multi[:, 2] + np.random.randn(100) * 0.5
4
5# 다중 선형 회귀
6model_multi = LinearRegression()
7model_multi.fit(X_multi, y_multi)
8
9# 변수 중요도 확인
10for i, coef in enumerate(model_multi.coef_):
11 print(f"변수 {i+1} 계수: {coef:.2f}")로지스틱 회귀는 연속적인 확률을 이진 분류로 변환하는 도구다. 이름에 '회귀'가 붙어 있어서 처음엔 회귀 문제인 줄 알았는데, 사실 분류 알고리즘이다.
1from sklearn.linear_model import LogisticRegression
2from sklearn.metrics import classification_report, confusion_matrix
3
4# 이진 분류 데이터 생성
5X_binary = np.random.randn(200, 2)
6y_binary = (X_binary[:, 0] + X_binary[:, 1] > 0).astype(int)
7
8# 로지스틱 회귀 모델
9logistic_model = LogisticRegression()
10logistic_model.fit(X_binary, y_binary)
11
12# 예측 및 평가
13y_pred_binary = logistic_model.predict(X_binary)
14print(classification_report(y_binary, y_pred_binary))세 개 이상의 클래스를 분류할 때는 다중 클래스 로지스틱 회귀를 사용한다.
1from sklearn.datasets import make_classification
2from sklearn.multiclass import OneVsRestClassifier
3
4# 다중 클래스 데이터
5X_multi_class, y_multi_class = make_classification(
6 n_samples=300, n_features=4, n_classes=3, n_clusters_per_class=1
7)
8
9# 다중 클래스 로지스틱 회귀
10multi_logistic = LogisticRegression(multi_class='ovr')
11multi_logistic.fit(X_multi_class, y_multi_class)
12
13# 예측
14y_pred_multi = multi_logistic.predict(X_multi_class)
15print(classification_report(y_multi_class, y_pred_multi))한 번 쪼갠 train/test 결과만 믿기 어려워서, K-Fold로 점수 분산부터 확인했다. 단 한 번의 split을 믿는 것보다 훨씬 신뢰도가 높았다.
1from sklearn.model_selection import cross_val_score, KFold
2
3# K-Fold 교차 검증
4kfold = KFold(n_splits=5, shuffle=True, random_state=42)
5scores = cross_val_score(logistic_model, X_binary, y_binary, cv=kfold)
6
7print(f"교차 검증 점수: {scores.mean():.3f} (+/- {scores.std() * 2:.3f})")GridSearchCV로 최적의 하이퍼파라미터를 탐색한다. 이게 왜 중요하냐면, 같은 모델이라도 파라미터에 따라 성능 차이가 꽤 크게 난다.
1from sklearn.model_selection import GridSearchCV
2
3# 하이퍼파라미터 그리드
4param_grid = {
5 'C': [0.1, 1, 10, 100],
6 'penalty': ['l1', 'l2'],
7 'solver': ['liblinear', 'saga']
8}
9
10# 그리드 서치
11grid_search = GridSearchCV(
12 LogisticRegression(), param_grid, cv=5, scoring='accuracy'
13)
14grid_search.fit(X_binary, y_binary)
15
16print(f"최적 파라미터: {grid_search.best_params_}")
17print(f"최고 점수: {grid_search.best_score_:.3f}")실제 데이터로 주택 가격을 예측해봤다. 데이터를 직접 만들고 모델을 학습시키는 전 과정을 해보니 각 단계가 왜 필요한지 체감됐다.
1import pandas as pd
2from sklearn.preprocessing import StandardScaler
3from sklearn.ensemble import RandomForestRegressor
4
5# 주택 가격 데이터 (예시)
6data = pd.DataFrame({
7 'area': np.random.rand(1000) * 200 + 50,
8 'bedrooms': np.random.randint(1, 6, 1000),
9 'bathrooms': np.random.randint(1, 4, 1000),
10 'age': np.random.randint(0, 50, 1000)
11})
12
13# 가격 생성 (실제로는 더 복잡한 관계)
14data['price'] = (
15 data['area'] * 100 +
16 data['bedrooms'] * 50000 +
17 data['bathrooms'] * 30000 -
18 data['age'] * 2000 +
19 np.random.randn(1000) * 10000
20)
21
22# 특성과 타겟 분리
23X_house = data[['area', 'bedrooms', 'bathrooms', 'age']]
24y_house = data['price']
25
26# 데이터 분할
27X_train, X_test, y_train, y_test = train_test_split(
28 X_house, y_house, test_size=0.2, random_state=42
29)
30
31# 스케일링
32scaler = StandardScaler()
33X_train_scaled = scaler.fit_transform(X_train)
34X_test_scaled = scaler.transform(X_test)
35
36# 랜덤 포레스트 모델
37rf_model = RandomForestRegressor(n_estimators=100, random_state=42)
38rf_model.fit(X_train_scaled, y_train)
39
40# 예측 및 평가
41y_pred_house = rf_model.predict(X_test_scaled)
42mse = mean_squared_error(y_test, y_pred_house)
43r2 = r2_score(y_test, y_pred_house)
44
45print(f"평균 제곱 오차: {mse:.2f}")
46print(f"R² 점수: {r2:.3f}")GridSearchCV로 하이퍼파라미터 뒤지다가 데이터 스케일링 안 하면 로지스틱 회귀가 이렇게 불안정하구나를 처음으로 실감했다.
흥미로웠던 건, Random Forest가 선형 회귀보다 주택 가격 예측에서 성능이 좋은 이유를 계수만 보고는 설명이 안 되는데, 특성 중요도(feature importance)로 면적이 제일 중요하다를 뽑아내니 납득이 됐다. 해석 가능성이 실제로 유용하다는 걸 코드로 확인한 순간이었다. 나름 보람 있었다.
앙상블 쪽(Random Forest, XGBoost)으로 이어가려고 한다. 딥러닝은 그다음.