본문 바로가기
머신러닝

[실무에 쓰는 머신러닝 기초] 4. 분류

by 쿙이콩 2025. 7. 2.
728x90
반응형

4-1. 무엇인지 맞추고 싶어? 분류! 

☑️ 1. 분류 모델 개요

✔️ 지도학습 입력 데이터(특징, feature)와 정답(label)이 주어졌을 때, 모델이 정답을 예측하도록 학습하는 방식

  • 회귀 결과값 연속형 (숫자 값)
  • 분류 결과값 이산형 (클래스 라벨)

✔️ 분류 Classification

  • 목적 데이터가 어느 범주(클래스)에 속하는지 예측 = 이진 분류
    ex) 스팸 메일 분류(스팸/정상) , 질병 여부(양성/음성) , 제조 공정 품질(불량/정상) 등
  • 활용 알고리즘 Logistic Regression, SVM

✔️ 주요 분류 모델  로지스틱 회귀 / SVM / K-NN / Naive Bayes / MLP(신경망) 또는 딥러닝

 

✔️ 모델 평가 방법 

  • 손실함수 Binary Cross Entropy) / Cross Entropy / Hinge Loss
  • 혼동행렬 Confusion Matrix TP / FN / FP / TN
  • Precision(정밀도), Recall(재현율), F1-score(조화평균)
  • ROC곡선과 AUC

 

 


☑️ 2. 주요 분류 모델

①  로지스틱 회귀 Logistic Regression

이름에 '회귀' 들어갔지만 분류 모델임😂

 

✔️  선형 회귀처럼 입력값의 선형 결합을 취하지만

✔️  결과를 0~1 사이의 확률로 변환하기 위해 로지스틱 함수(시그모이드 함수)를 사용

✔️  (장점) 계산 빠름, 구현 간단, 결과 해석 용이 (회귀 계수로 각 변수의 영향도 해석 가능)

✔️  (단점) 복잡한 비선형 패턴 학습에 한계 존재

결과를 0~1 사이의 확률로 변환하기 위해  로지스틱 함수(시그모이드 함수)

 ①  로지스틱 회귀 코드

더보기

Logistic Regression

학습 데이터(X_train, y_train)를 이용해 로지스틱 회귀 모델을 학습

max_iter(최대 반복 횟수) 기본값(100)에서 조금 늘려 200으로 설정

 

accuracy_score로 정확도(Accuracy) 계산

classification_report 클래스별 정밀도(precision), 재현율(recall), F1 점수, 지원된 샘플 수(support) 등을 확인

target_names=iris.target_names 각 클래스의 이름(‘setosa’, ‘versicolor’, ‘virginica’)으로 보고서를 보기 쉽게 표시

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report

--------------------
★ 1. 데이터 로드
--------------------
iris = load_iris()
X = iris.data       특징(feature) 데이터 결과 (150, 4) = 150개 샘플, 4개 특성(피쳐)
y = iris.target     타깃(target)  데이터 결과 (150,) = 150개의 레이블(클래스)

--------------------
★ 2. 데이터 분할 (train : test = 8 : 2)
stratify=y : 클래스 비율을 train, test가 유사하게끔 맞춤
--------------------
X_train, X_test, y_train, y_test = train_test_split(X, y,
                                                    test_size=0.2,
                                                    random_state=42,
                                                    stratify=y)
--------------------
★ 3. Logistic Regression
--------------------
logistic_model = LogisticRegression(max_iter=200)  
logistic_model.fit(X_train, y_train)

--------------------
★ 4. 예측
--------------------
y_pred_logistic = logistic_model.predict(X_test)

--------------------
★ 5. 성능 평가
--------------------
print("=== Logistic Regression ===")
print("Accuracy:", accuracy_score(y_test, y_pred_logistic))
print(classification_report(y_test, y_pred_logistic, target_names=iris.target_names))

💡  ①  로지스틱 회귀 코드 - 해석 

✔️ 데이터 정보

- - - 특징 데이터 (150, 4) = 150개 샘플, 4개의 특성(피처)

- - - 타깃 데이터 (150,) = 150개 레이블(클래스)

✔️ 정확도 accuracy_score  0.9667

- - - 테스트 데이터의 97%를 정확하게 분류했다 = 매우 높은 성능

✔️ 클래스별 정밀도 (precision), 재현율(recall), F1-score

- - - setosa : 모든 샘플을 100% 정확하게 예측 (셋 다 모두 1.00)

- - - versicolor

- - - - - precision = 1.00 : versicolor로 예측한 것 중 실제로도 모두 versicolor

- - - - - recall = 0.90 : 실제 versicolor 중 90%만 맞춤 (1개는 다른 클래스로 분류)

- - - virginica

- - - - - precision =  0.91: virginica로 예측한 것 중 91%만 실제 virginica

- - - - - recall = 1.00: 실제 virginica는 모두 맞춤

✔️ 전체 성능 요약

- - - accuracy = 0.97 

- - - macro avg = 0.97 클래스별 지표의 단순 평균 (클래스 불균형에 영향 없음)

- - - weighted avg = 0.97 클래스별 샘플 수를 가중치로 한 평균 (클래스 불균형 반영)

 

 ② SVM Support Vector Machine

✔️  데이터를 가장 잘 (안전 여유공간 크게) 구분하는 경계를 찾는 알고리즘

✔️  ex) 두 부류(고양이 vs 개)를 잘 구분해주는 경계 찾음 = 두 부류가 최대한 멀리 떨어지도록(안전 여유공간이 넓도록) 찾는 방식

✔️  (장점) 차원 높은 데이터에서도 좋은 성능 / 결정 경계를 명확하게 찾는 경우, 예측 성능 우수

- - - - - 결정경계란? → SVM이 찾은 최적의 분류선(또는 초평면) ex) 한쪽 편을 '고양이'로, 다른 한편을 '개'로 구분해주는 기준선

✔️  (단점) 파라미터(C, 커널 종류 등)를 적절히 찾아야 하므로 튜닝 비용이 큼 / 대규모 데이터 세트에 대해 학습 속도가 느릴 수도

  SVM Support Vector Machine 코드

더보기

SVM

- SVC() 기본적으로 커널(kernel)을 ‘rbf’로 사용

- 다른 하이퍼파라미터(C, gamma 등)를 조정해서 성능 개선을 시도할 수 있음

accuracy_score 정확도(Accuracy) 계산

classification_report 클래스별 정밀도(precision), 재현율(recall), F1 점수, 지원된 샘플 수(support) 등을 확인

target_names=iris.target_names 각 클래스의 이름(‘setosa’, ‘versicolor’, ‘virginica’)으로 보고서를 보기 쉽게 표시

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score, classification_report

--------------------
1. 데이터 로드
--------------------
iris = load_iris()
X = iris.data       특징(feature) 데이터
y = iris.target     타깃(target) 데이터
print(X.shape)
print(y.shape)

--------------------
2. 데이터 분할 (train : test = 8 : 2)
--------------------
X_train, X_test, y_train, y_test = train_test_split(X, y,
                                                    test_size=0.2,
                                                    random_state=42,
                                                    stratify=y)
--------------------
3. SVM(Support Vector Machine)
C, gamma 등의 하이퍼파라미터를 설정해서 더 최적화 가능
--------------------
svm_model = SVC()
svm_model.fit(X_train, y_train)

--------------------
4. 예측
--------------------
y_pred_svm = svm_model.predict(X_test)

--------------------
5. 성능 평가
Accuracy(정확도)와 정밀 평가(classification_report)를 이용해 비교
--------------------
print("=== SVM ===")
print("Accuracy:", accuracy_score(y_test, y_pred_svm))
print(classification_report(y_test, y_pred_svm, target_names=iris.target_names))

💡   SVM Support Vector Machine 해석 

✔️ 데이터 정보

- - - 입력 데이터 (150, 4) = 150개 샘플, 4개의 특성(꽃받침 길이/너비, 꽃잎 길이/너비)

- - - 타깃 데이터 (150,) = 150개 레이블(클래스) (0: setosa, 1: versicolor, 2: virginica)

✔️ 정확도 accuracy_score  0.9667

- - - 테스트 데이터 30개 중 29개를 정확하게 분류함

- - - 테스트 데이터의 97%를 정확하게 분류했다 = 매우 높은 성능 

✔️ 클래스별 정밀도 (precision), 재현율(recall), F1-score

- - - setosa : 모든 샘플을 100% 정확하게 예측 (셋 다 모두 1.00)

- - - - - precision = 1.00 : setosa로 예측한 것 중 모두 실제 setosa

- - - - - recall = 1.00 :  실제 setosa를 모두 맞춤

- - - - - F1-score 1.00: 완벽한 분류

- - - versicolor

- - - - - precision = 1.00 : versicolor로 예측한 것 중 모두 실제 versicolor

- - - - - recall = 0.90 : 실제 versicolor 중 90%만 맞춤 (1개는 다른 클래스로 분류)

- - - - - F1-score 0.95 : 높은 성능

- - - virginica

- - - - - precision =  0.91: virginica로 예측한 것 중 91%만 실제 virginica

- - - - - recall = 1.00: 실제 virginica는 모두 맞춤

- - - - - F1-score 0.95 : 높은 성능

✔️ 전체 성능 요약

- - - accuracy = 0.97 

- - - macro avg = 0.97 클래스별 지표의 단순 평균 (클래스 불균형에 영향 없음)

- - - weighted avg = 0.97 클래스별 샘플 수를 가중치로 한 평균 (클래스 불균형 반영)

 

기타 : 추가로 알면 좋은 모델

K-NN (K-최근접 이웃) 나이브 베이즈 (Naive Bayes) 신경망(MLP) 또는 딥러닝 모델
간단하지만 대규모 데이터에서 계산량 큼 통계적 가정(독립성)에 기반하므로 계산이 빠름, 스팸 필터 등에서 자주 사용 복잡도는 높지만 대규모 데이터에서 강점

 


☑️ 3. 분류 모델 산업별 적용 사례

금융 Fin Tech 헬스케어 마케팅 제조업
사기 거래 탐지
(Fraud Detection)

거래 패턴이 정상 고객과 다른 이상 패턴을 보이는지 분류 모델로 판단

대출 상환 가능성 예측
대출 신청 고객의 과거 신용 기록, 소득, 직업, 기타 특성 등 종합해 상환이 가능한지 여부 분류

적용 모델
로지스틱 회귀, 랜덤 포레스트, XGBoost, 딥러닝 등
질병 진단
양성(Positive)/음성(Negative) 여부 분류
ex) 암 진단, 당뇨병 예측 등

임상 데이터
(혈액 검사 수치, 환자 진료 기록)와 의료 영상을 기반으로 머신러닝 모델을 훈련

적용 모델
로지스틱 회귀, SVM, 최근에는 딥러닝도 활발히 연구

고객 이탈 예측
고객이 서비스를 해지할 가능성이 있는지 분류

캠페인 반응 예측
이메일 또는 광고 캠페인에 대한 반응(열람/미열람, 구매/미구매) 여부 예측

적용 모델
로지스틱 회귀, 랜덤 포레스트, 나이브 베이즈 등


불량 검출
공정에서 생산된 부품이 불량인지 아닌지 분류

장비 이상 탐지
센서 데이터(온도, 진동, 압력 등)를 기반으로 이상 여부 분류

적용 모델
랜덤 포레스트, SVM, 앙상블 모델, 딥러닝이 주로 활용


 


☑️ 4. 모델 평가 방법

데이터가 불균형할 경우(ex : 사기 거래 탐지, 질병 예측 등) Accuracy(정확도)만으로는 모델을 평가하기 어려움

→ Precision, Recall, F1-score, ROC-AUC 등 지표를 함께 봐야 함

현업 목표에 따라 어떤 지표를 중시할지 결정(ex : 암 진단은 Recall 중요, 스팸 필터는 Precision 중요 등)

 

💡  ①  손실함수 Cross Entropy / Hinge Loss

Binary Cross Entropy / Cross Entropy Hinge Loss
  • Binary Cross Entropy 2진 분류에서 자주 사용
  • 일반적으로 다중 분류에서 Cross Entropy를 사용
  • 예측 확률이 실제 레이블과 얼마나 차이가 있는지 측정
  • SVM(Support Vector Machine)에서 많이 사용
  • 마진을 고려하여 오분류된 샘플에 페널티를 부여

💡  ②  혼동행렬 Confusion Matrix

실제 클래스와 예측 클래스의 관계를 행렬 형태로 나타낸 것

  예측 P 예측 N  
실제 P
TP
실제로 양성인 데이터를
모델이 양성이라고 맞게 예측한 수
FN = TYPE 2 ERROR
실제로 양성인 데이터를
모델이 음성이라고 잘못 예측
▶ 재현율 = 민감도 TP / (TP+FN)
실제 양성 중
모델이 양성이라고 맞게 예측한 비율
실제 N  FP = TYPE 1 ERROR
실제로 음성인 데이터를
모델이 양성이라고 잘못 예측
TN
실제로 음성인 데이터를
모델이 음성이라고 맞게 예측한 수
 
   
정밀도 TP / (TP+FP)

모델이 양성이라고 예측한 것 중
실제 양성인 비율
FPR 정확도 TP+TN / 4개 합
전체 예측 중
맞게 예측한 비율
  F1-score 정밀도(Precision)와 재현율(Recall)의 조화평균
정밀도와 재현율을 모두 고려한 종합적인 성능 지표. 두 값이 모두 높을 때 F1-score도 높아짐
F1-score = 2 * ( Pre x Rec ) / ( Pre + Rec )

 

💡  ③ ROC 곡선과 AUC ( area under the curve )

 

✔️ ROC 곡선

- 임계값(Threshold)을 변화시키며, TPR(True Positive Rate)과 FPR(False Positive Rate)의 변화를 시각화한 곡선

  • TPR(True Positive Rate) = 재현율 = 민감도
    0~1 사이의 값을 가지며 1에 가까울 수록 좋음
  • FPR(False Positive Rate)
    실제 음성(Negative) 샘플 중 모델이 양성이라고 잘못 예측한 비율
    0~1 사이의 값을 가지며 0에 가까울 수록 좋음
  • TPR과 FPR은 트레이드 오프 관계

- 이 지표도 클래스 불균형 상황에서 사용

- 임계값을 조정해서 생기는 성능 변화 전체를 보여주기 때문에 단순히 성능 하나만 얘기하는 위의 지표들과는 다름

 

✔️ AUC ROC 곡선 아래 면적. 1에 가까울수록 모델이 우수

💡  ③ ROC 곡선과 AUC - 코드

더보기

ROC-AUC 계산을 위한 예측 확률

ROC 곡선과 AUC는 분류 결과 자체(0/1)보다 ‘양성 클래스(1)일 확률’ 이 필요

predict_proba 각 클래스(0, 1)에 속할 확률을 예측해주는 메소드

 

ROC 곡선 계산

분류 임계값(threshold)을 다양하게 바꿔가며 FPR, TPR을 계산해줍니다.

fpr 거짓 양성 비율 = FP / (FP + TN)

tpr 참 양성 비율(재현율) = TP / (TP + FN)

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_curve, roc_auc_score

--------------------
1. 데이터 로드 (유방암 데이터셋: 이진 분류)
--------------------
data = load_breast_cancer()
X = data.data
y = data.target

--------------------
2. 학습/테스트 데이터 분할
--------------------
X_train, X_test, y_train, y_test = train_test_split(X, y, 
                                                    test_size=0.2, 
                                                    random_state=42,
                                                    stratify=y)
--------------------
3. 모델 생성 및 학습
--------------------
model = LogisticRegression(max_iter=500)  반복횟수를 충분히 늘려줌
model.fit(X_train, y_train)

--------------------
4. 예측(특히 ROC-AUC 계산을 위해 확률값이 필요하므로 predict_proba 사용)
--------------------
y_proba = model.predict_proba(X_test)[:, 1]  
predict_proba의 결과 shape는 (샘플 수, 클래스 수)
여기서는 양성 클래스(1)에 대한 확률만 사용

--------------------
5. ROC 곡선 계산
--------------------
fpr, tpr, thresholds = roc_curve(y_test, y_proba)
. fpr: False Positive Rate
. tpr: True Positive Rate (재현율과 동일)
. thresholds: 임계값(이 값을 기준으로 양성/음성 분류가 달라짐)

--------------------
6. AUC 계산
--------------------
auc_score = roc_auc_score(y_test, y_proba)

--------------------
7. ROC 곡선 시각화
--------------------
plt.figure()
plt.plot(fpr, tpr, label=f'Logistic (AUC = {auc_score:.3f})')
plt.plot([0, 1], [0, 1], linestyle='--')  랜덤 분류선
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC Curve')
plt.legend()
plt.show()

print("ROC-AUC Score:", auc_score)

 

 


☑️ 5. 분류 실습

 

Wine 데이터셋을 로드하세요.

학습용/테스트용 데이터를 적절한 비율로 분할하세요.

Logistic Regression, SVM 모델을 생성하고, 모델을 학습시키세요.

적절히 하이퍼파라미터(예: max_iter 등)를 설정해볼 것

테스트 데이터를 이용해 예측을 수행하고, 다음을 구하세요.

정확도(Accuracy)

분류 보고서(Classification Report)

혼동행렬(Confusion_matrix) → 선택사항

ROC, AUC  

참고!) sklearn의 confusion matrix는 아래와 같은 형태로 나온다는 점을 참고하세요!

import pandas as pd
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix, roc_auc_score, roc_curve
from sklearn.preprocessing import label_binarize
import matplotlib.pyplot as plt
--------------------
1. 데이터 로드 및 DataFrame 변환
--------------------
wine = load_wine()
X = wine.data
y = wine.target

df = pd.DataFrame(X, columns=wine.feature_names)
df['target'] = y

--------------------
2. 학습/테스트 데이터 분할 (80% 학습, 20% 테스트, 클래스 비율 유지)
--------------------
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)

--------------------
3. 모델 생성 및 학습
--------------------
logistic_model = LogisticRegression(max_iter=500, random_state=42)
logistic_model.fit(X_train, y_train)

svm_model = SVC(probability=True, random_state=42)
svm_model.fit(X_train, y_train)

--------------------
4. 예측
--------------------
y_pred_logistic = logistic_model.predict(X_test)
y_pred_svm = svm_model.predict(X_test)

--------------------
5. 성능 평가
--------------------
acc_logistic = accuracy_score(y_test, y_pred_logistic)
acc_svm = accuracy_score(y_test, y_pred_svm)

report_logistic = classification_report(y_test, y_pred_logistic, target_names=wine.target_names)
report_svm = classification_report(y_test, y_pred_svm, target_names=wine.target_names)

cm_logistic = confusion_matrix(y_test, y_pred_logistic)
cm_svm = confusion_matrix(y_test, y_pred_svm)

--------------------
6. ROC, AUC 계산 (다중 클래스 One-vs-Rest)
--------------------
y_test_bin = label_binarize(y_test, classes=[0,1,2])

y_score_logistic = logistic_model.predict_proba(X_test)
y_score_svm = svm_model.predict_proba(X_test)

fpr_logistic, tpr_logistic, roc_auc_logistic = {}, {}, {}
fpr_svm, tpr_svm, roc_auc_svm = {}, {}, {}

for i in range(3):
    fpr_logistic[i], tpr_logistic[i], _ = roc_curve(y_test_bin[:, i], y_score_logistic[:, i])
    roc_auc_logistic[i] = roc_auc_score(y_test_bin[:, i], y_score_logistic[:, i])
    fpr_svm[i], tpr_svm[i], _ = roc_curve(y_test_bin[:, i], y_score_svm[:, i])
    roc_auc_svm[i] = roc_auc_score(y_test_bin[:, i], y_score_svm[:, i])

--------------------
7. 결과 출력
--------------------
print("=== Logistic Regression ===")
print("Accuracy:", acc_logistic)
print("Classification Report:\n", report_logistic)
print("Confusion Matrix:\n", cm_logistic)
print("ROC AUC per class:", roc_auc_logistic)
print()
print("=== SVM ===")
print("Accuracy:", acc_svm)
print("Classification Report:\n", report_svm)
print("Confusion Matrix:\n", cm_svm)
print("ROC AUC per class:", roc_auc_svm)

728x90
반응형