Post

머신러닝 데이터분리, 평가척도, 알고리즘 - 실전 머신러닝의 핵심

머신러닝 데이터분리, 평가척도, 알고리즘 - 실전 머신러닝의 핵심

머신러닝 데이터분리, 평가척도, 알고리즘 - 실전 머신러닝의 핵심

개요

실전 머신러닝의 핵심 요소들을 학습합니다:

  • 데이터 분리: 훈련/테스트 데이터 분할과 계층적 샘플링
  • 평가 척도: 회귀와 분류 문제의 성능 평가 지표
  • 핵심 알고리즘: 선형회귀, 결정트리, KNN, 로지스틱회귀
  • 실무 적용: 각 알고리즘의 특성과 활용 시나리오

1. 데이터 분리 (데이터셋 분할)

1-1. 기본 데이터 분리

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression, LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
import warnings
warnings.filterwarnings('ignore')

print("=== 데이터 분리 기본 ===")

# 샘플 데이터 생성
x_data = np.array([
    [1, 1], [2, 2], [3, 4], [4, 5], [5, 5],
    [6, 5], [7, 9], [8, 10], [9, 12], [10, 2],
    [11, 10], [12, 4]
])
y_data = np.array([3, 5, 7, 10, 12, 7, 13, 13, 12, 13, 12, 6])

print(f"전체 데이터 크기: {x_data.shape}")
print(f"레이블 크기: {y_data.shape}")

# 기본 데이터 분할 (70% 훈련, 30% 테스트)
x_train, x_test, y_train, y_test = train_test_split(
    x_data, y_data, 
    test_size=0.3, 
    random_state=777
)

print(f"훈련 데이터 크기: {x_train.shape}")
print(f"테스트 데이터 크기: {x_test.shape}")
print(f"훈련 레이블 크기: {y_train.shape}")
print(f"테스트 레이블 크기: {y_test.shape}")

1-2. 계층적 샘플링 (Stratified Sampling)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
print("=== 계층적 샘플링 ===")

# 분류 문제용 데이터
x_data_class = np.array([
    [2, 1], [3, 2], [3, 4], [5, 5], [7, 5], [2, 5],
    [8, 9], [9, 10], [6, 12], [9, 2], [6, 10], [2, 4]
])
y_data_class = np.array([0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0])

# 계층적 샘플링 적용
x_train, x_test, y_train, y_test = train_test_split(
    x_data_class, y_data_class, 
    test_size=0.3, 
    random_state=777,
    stratify=y_data_class  # 클래스 비율 유지
)

print(f"원본 클래스 분포: {np.bincount(y_data_class)}")
print(f"훈련 클래스 분포: {np.bincount(y_train)}")
print(f"테스트 클래스 분포: {np.bincount(y_test)}")

2. 평가 척도

2-1. 회귀 평가 지표

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score, mean_squared_log_error

print("=== 회귀 평가 지표 ===")

# 회귀 모델 학습
model = LinearRegression()
model.fit(x_train, y_train)
y_predict = model.predict(x_test)

# 1. R² (결정계수)
r2 = r2_score(y_test, y_predict)
print(f"R² Score: {r2:.4f}")

# 2. MSE (평균 제곱 오차)
mse = mean_squared_error(y_test, y_predict)
print(f"MSE: {mse:.4f}")

# 3. RMSE (평균 제곱근 오차)
rmse = mean_squared_error(y_test, y_predict, squared=False)
print(f"RMSE: {rmse:.4f}")

# 4. MAE (평균 절대 오차)
mae = mean_absolute_error(y_test, y_predict)
print(f"MAE: {mae:.4f}")

# 5. MSLE (평균 제곱 로그 오차)
msle = mean_squared_log_error(y_test, y_predict)
print(f"MSLE: {msle:.4f}")

# 통합 평가 함수
def evaluate_regression(y_test, y_predict):
    """회귀 모델 통합 평가"""
    mse = mean_squared_error(y_test, y_predict, squared=True)
    rmse = mean_squared_error(y_test, y_predict, squared=False)
    mae = mean_absolute_error(y_test, y_predict)
    r2 = r2_score(y_test, y_predict)
    
    print(f"MSE: {mse:.3f}, RMSE: {rmse:.3f}, MAE: {mae:.3f}, R²: {r2:.3f}")

print("\n통합 평가:")
evaluate_regression(y_test, y_predict)

2-2. 분류 평가 지표

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, confusion_matrix, classification_report

print("=== 분류 평가 지표 ===")

# 분류 모델 학습
x_train_class, x_test_class, y_train_class, y_test_class = train_test_split(
    x_data_class, y_data_class, 
    test_size=0.3, 
    random_state=777,
    stratify=y_data_class
)

model = LogisticRegression()
model.fit(x_train_class, y_train_class)
y_predict_class = model.predict(x_test_class)

# 1. 정확도 (Accuracy)
accuracy = accuracy_score(y_test_class, y_predict_class)
print(f"정확도: {accuracy:.4f}")

# 2. 정밀도 (Precision)
precision = precision_score(y_test_class, y_predict_class)
print(f"정밀도: {precision:.4f}")

# 3. 재현율 (Recall)
recall = recall_score(y_test_class, y_predict_class)
print(f"재현율: {recall:.4f}")

# 4. F1 Score
f1 = f1_score(y_test_class, y_predict_class)
print(f"F1 Score: {f1:.4f}")

# 5. 혼동 행렬 (Confusion Matrix)
cm = confusion_matrix(y_test_class, y_predict_class)
print(f"\n혼동 행렬:")
print(cm)

# 6. 분류 보고서
print(f"\n분류 보고서:")
print(classification_report(y_test_class, y_predict_class, target_names=['Fail', 'Pass']))

2-3. 평가 지표 해석

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
print("=== 평가 지표 해석 ===")

print("회귀 평가 지표:")
print("- R²: 1에 가까울수록 좋음 (설명력)")
print("- MSE, RMSE, MAE: 작을수록 좋음 (오차)")
print("- MSLE: 로그 스케일에서의 오차")

print("\n분류 평가 지표:")
print("- 정확도: 전체 예측 중 맞춘 비율")
print("- 정밀도: 양성 예측 중 실제 양성 비율")
print("- 재현율: 실제 양성 중 예측한 양성 비율")
print("- F1 Score: 정밀도와 재현율의 조화평균")

print("\n혼동 행렬:")
print("- TN (True Negative): 정답 (0,0)")
print("- TP (True Positive): 정답 (1,1)")
print("- FP (False Positive): 오답 (0,1)")
print("- FN (False Negative): 오답 (1,0)")

3. 핵심 알고리즘

3-1. 선형 회귀 (Linear Regression)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
print("=== 선형 회귀 ===")

# 회귀 데이터 준비
x_data_reg = np.array([
    [1, 1], [2, 2], [3, 4], [4, 5], [5, 5],
    [6, 5], [7, 9], [8, 10], [9, 12], [10, 2],
    [11, 10], [12, 4]
])
y_data_reg = np.array([3, 5, 7, 10, 12, 7, 13, 13, 12, 13, 12, 6])

# 데이터 분할
x_train, x_test, y_train, y_test = train_test_split(
    x_data_reg, y_data_reg, 
    test_size=0.3, 
    random_state=777
)

# 모델 생성 및 학습
model = LinearRegression()
model.fit(x_train, y_train)

# 모델 평가
train_score = model.score(x_train, y_train)
test_score = model.score(x_test, y_test)

print(f"훈련 데이터 R²: {train_score:.4f}")
print(f"테스트 데이터 R²: {test_score:.4f}")

# 회귀 계수 확인
print(f"회귀 계수: {model.coef_}")
print(f"절편: {model.intercept_:.4f}")

# 예측
x_new = np.array([[4, 6]])
y_predict = model.predict(x_new)
print(f"새로운 데이터 예측값: {y_predict[0]:.4f}")

# 상세 평가
y_predict_test = model.predict(x_test)
evaluate_regression(y_test, y_predict_test)

3-2. 결정트리 (Decision Tree)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
from sklearn.datasets import load_iris
from sklearn.tree import plot_tree
import matplotlib.pyplot as plt

print("=== 결정트리 ===")

# Iris 데이터셋 사용
iris_data = load_iris()
x_train, x_test, y_train, y_test = train_test_split(
    iris_data.data, iris_data.target, 
    test_size=0.2, 
    random_state=11
)

# 다양한 하이퍼파라미터 설정
models = {
    'max_depth=3': DecisionTreeClassifier(random_state=156, max_depth=3),
    'min_samples_leaf=5': DecisionTreeClassifier(random_state=156, min_samples_leaf=5),
    'combined': DecisionTreeClassifier(random_state=111, min_samples_leaf=2, max_depth=4)
}

print("결정트리 하이퍼파라미터 비교:")
for name, model in models.items():
    model.fit(x_train, y_train)
    train_score = model.score(x_train, y_train)
    test_score = model.score(x_test, y_test)
    print(f"{name}: 훈련={train_score:.4f}, 테스트={test_score:.4f}")

# 최적 모델 선택 및 시각화
best_model = DecisionTreeClassifier(random_state=156, max_depth=3)
best_model.fit(x_train, y_train)

plt.figure(figsize=(15, 10))
plot_tree(best_model, filled=True, feature_names=iris_data.feature_names)
plt.title('Decision Tree Visualization')
plt.show()

print("\n결정트리 특징:")
print("- 장점: 해석이 직관적, 피처 스케일링 불필요")
print("- 단점: 과적합 위험, 하이퍼파라미터 튜닝 필요")

3-3. K-최근접 이웃 (K-Nearest Neighbors)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
print("=== K-최근접 이웃 (KNN) ===")

# 분류 데이터 준비
x_data_knn = np.array([
    [2, 1], [3, 2], [3, 4], [5, 5], [7, 5], [2, 5],
    [8, 9], [9, 10], [6, 12], [9, 2], [6, 10], [2, 4]
])
y_data_knn = np.array([0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0])

# 데이터 분할
x_train, x_test, y_train, y_test = train_test_split(
    x_data_knn, y_data_knn, 
    test_size=0.3, 
    random_state=777, 
    stratify=y_data_knn
)

# 다양한 K 값 테스트
k_values = [3, 5, 7, 9]
labels = ['fail', 'pass']

print("K 값에 따른 성능 비교:")
for k in k_values:
    model = KNeighborsClassifier(n_neighbors=k)
    model.fit(x_train, y_train)
    train_score = model.score(x_train, y_train)
    test_score = model.score(x_test, y_test)
    print(f"K={k}: 훈련={train_score:.4f}, 테스트={test_score:.4f}")

# 최적 K 값으로 예측
best_k = 7
model = KNeighborsClassifier(n_neighbors=best_k)
model.fit(x_train, y_train)

# 예측 및 확률
x_new = np.array([[4, 6]])
y_predict = model.predict(x_new)
y_proba = model.predict_proba(x_new)

predicted_label = labels[y_predict[0]]
confidence = y_proba[0][y_predict[0]]

print(f"\n예측 결과: {predicted_label}")
print(f"신뢰도: {confidence:.4f}")

print("\nKNN 특징:")
print("- 장점: 간단하고 직관적, 비모수적 방법")
print("- 단점: 계산 비용 높음, 차원의 저주")

3-4. 로지스틱 회귀 (Logistic Regression)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
print("=== 로지스틱 회귀 ===")

# 분류 데이터 준비 (낮잠시간, 공부시간)
x_data_log = np.array([
    [2, 1], [3, 2], [3, 4], [5, 5], [7, 5], [2, 5],
    [8, 9], [9, 10], [6, 12], [9, 2], [6, 10], [2, 4]
])
y_data_log = np.array([0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0])

# 데이터 분할
x_train, x_test, y_train, y_test = train_test_split(
    x_data_log, y_data_log, 
    test_size=0.3, 
    random_state=777, 
    stratify=y_data_log
)

# 모델 생성 및 학습
model = LogisticRegression()
model.fit(x_train, y_train)

# 모델 평가
train_score = model.score(x_train, y_train)
test_score = model.score(x_test, y_test)

print(f"훈련 정확도: {train_score:.4f}")
print(f"테스트 정확도: {test_score:.4f}")

# 예측 및 확률
x_new = np.array([[4, 6]])
y_predict = model.predict(x_new)
y_proba = model.predict_proba(x_new)

predicted_label = labels[y_predict[0]]
confidence = y_proba[0][y_predict[0]]

print(f"\n예측 결과: {predicted_label}")
print(f"신뢰도: {confidence:.4f}")
print(f"확률 분포: {y_proba[0]}")

# 상세 평가
y_predict_test = model.predict(x_test)
print(f"\n상세 평가:")
print(classification_report(y_test, y_predict_test, target_names=['Fail', 'Pass']))

print("\n로지스틱 회귀 특징:")
print("- 시그모이드 함수 사용")
print("- 확률 기반 분류")
print("- 선형 결정 경계")
print("- 해석 가능한 계수")

4. 알고리즘 비교 및 선택

4-1. 알고리즘 성능 비교

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
print("=== 알고리즘 성능 비교 ===")

# 동일한 데이터로 모든 알고리즘 테스트
from sklearn.datasets import make_classification

# 샘플 데이터 생성
X, y = make_classification(n_samples=1000, n_features=4, n_classes=2, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 알고리즘 정의
algorithms = {
    'Logistic Regression': LogisticRegression(),
    'Decision Tree': DecisionTreeClassifier(random_state=42),
    'KNN': KNeighborsClassifier(n_neighbors=5)
}

# 성능 비교
results = {}
for name, model in algorithms.items():
    model.fit(X_train, y_train)
    train_score = model.score(X_train, y_train)
    test_score = model.score(X_test, y_test)
    results[name] = {'train': train_score, 'test': test_score}

# 결과 출력
print("알고리즘별 성능 비교:")
for name, scores in results.items():
    print(f"{name}:")
    print(f"  훈련 정확도: {scores['train']:.4f}")
    print(f"  테스트 정확도: {scores['test']:.4f}")
    print(f"  과적합 정도: {scores['train'] - scores['test']:.4f}")
    print()

4-2. 알고리즘 선택 가이드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
print("=== 알고리즘 선택 가이드 ===")

print("1. 선형 회귀 (Linear Regression)")
print("   - 사용 시기: 연속형 타겟 변수, 선형 관계")
print("   - 장점: 해석 가능, 빠른 학습")
print("   - 단점: 비선형 관계 처리 어려움")

print("\n2. 로지스틱 회귀 (Logistic Regression)")
print("   - 사용 시기: 이진 분류, 확률 예측 필요")
print("   - 장점: 해석 가능, 확률 출력")
print("   - 단점: 선형 관계 가정")

print("\n3. 결정트리 (Decision Tree)")
print("   - 사용 시기: 해석 가능성 중요, 비선형 관계")
print("   - 장점: 직관적, 피처 스케일링 불필요")
print("   - 단점: 과적합 위험")

print("\n4. K-최근접 이웃 (KNN)")
print("   - 사용 시기: 지역적 패턴, 비모수적 방법")
print("   - 장점: 간단, 직관적")
print("   - 단점: 계산 비용, 차원의 저주")

4-3. 실무 적용 시나리오

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
print("=== 실무 적용 시나리오 ===")

print("1. 금융 분야")
print("   - 신용 평가: 로지스틱 회귀 (해석 가능성)")
print("   - 주가 예측: 선형 회귀 (시계열 특성)")
print("   - 이상 거래 탐지: 결정트리 (규칙 기반)")

print("\n2. 의료 분야")
print("   - 질병 진단: 로지스틱 회귀 (확률 출력)")
print("   - 약물 효과 예측: 선형 회귀")
print("   - 환자 분류: KNN (유사 사례 기반)")

print("\n3. 마케팅 분야")
print("   - 고객 세분화: 결정트리 (해석 가능)")
print("   - 구매 예측: 로지스틱 회귀")
print("   - 추천 시스템: KNN (유사 고객)")

print("\n4. 제조업")
print("   - 품질 예측: 선형 회귀")
print("   - 불량품 분류: 결정트리")
print("   - 유지보수 예측: 로지스틱 회귀")

5. 모델 성능 개선 전략

5-1. 하이퍼파라미터 튜닝

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from sklearn.model_selection import GridSearchCV

print("=== 하이퍼파라미터 튜닝 ===")

# 결정트리 하이퍼파라미터 튜닝
param_grid = {
    'max_depth': [3, 5, 7, 10],
    'min_samples_leaf': [1, 2, 4, 8],
    'min_samples_split': [2, 5, 10]
}

grid_search = GridSearchCV(
    DecisionTreeClassifier(random_state=42),
    param_grid,
    cv=5,
    scoring='accuracy',
    n_jobs=-1
)

grid_search.fit(X_train, y_train)

print(f"최적 파라미터: {grid_search.best_params_}")
print(f"최적 점수: {grid_search.best_score_:.4f}")

# 최적 모델로 예측
best_model = grid_search.best_estimator_
test_score = best_model.score(X_test, y_test)
print(f"테스트 점수: {test_score:.4f}")

5-2. 교차 검증

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from sklearn.model_selection import cross_val_score

print("=== 교차 검증 ===")

# 5-fold 교차 검증
cv_scores = cross_val_score(
    LogisticRegression(),
    X_train, y_train,
    cv=5,
    scoring='accuracy'
)

print(f"교차 검증 점수: {cv_scores}")
print(f"평균 점수: {cv_scores.mean():.4f}")
print(f"표준편차: {cv_scores.std():.4f}")

마무리

머신러닝의 핵심 요소들을 종합적으로 학습했습니다:

핵심 학습 내용

  • 데이터 분리: 훈련/테스트 분할과 계층적 샘플링의 중요성
  • 평가 척도: 회귀와 분류 문제의 적절한 성능 지표
  • 핵심 알고리즘: 선형회귀, 결정트리, KNN, 로지스틱회귀의 특성
  • 실무 적용: 각 알고리즘의 장단점과 활용 시나리오

실무 적용

  • 알고리즘 선택: 문제 유형과 요구사항에 따른 적절한 알고리즘 선택
  • 성능 평가: 다양한 평가 지표를 통한 종합적 성능 분석
  • 하이퍼파라미터 튜닝: 체계적인 모델 최적화
  • 교차 검증: 안정적인 성능 평가

이러한 기초 알고리즘들을 바탕으로 더 복잡한 앙상블 방법과 딥러닝 모델로 발전시킬 수 있습니다.

This post is licensed under CC BY 4.0 by the author.