[AI 101] 선형회귀와 분류 – 모든 머신러닝 알고리즘의 시작점
핵심 요약
“모든 복잡한 AI는 선형회귀에서 시작한다”는 말이 있습니다. 선형회귀(Linear Regression)는 연속적인 값(집값, 매출)을 예측하고, 로지스틱 회귀(Logistic Regression)는 이진 분류(스팸/정상)를 수행합니다. 의사결정나무(Decision Tree)는 사람처럼 질문하며 분류하고, 랜덤포레스트(Random Forest)는 수백 개의 나무가 투표하여 정확도를 2배 높입니다. 이 4가지 알고리즘은 머신러닝의 80% 실무 문제를 해결하며, Kaggle 대회 우승팀의 필수 도구입니다. 수식부터 Python 코드, 실전 예제까지 완벽하게 설명합니다.
📍 목차
- 선형회귀(Linear Regression) 이해하기
- 로지스틱 회귀(Logistic Regression)와 이진 분류
- 의사결정나무(Decision Tree)
- 랜덤포레스트(Random Forest)와 앙상블 기법
- 알고리즘 비교 및 선택 가이드
1. 선형회귀(Linear Regression) 이해하기
1-1. 선형회귀란?
선형회귀는 독립변수(X)와 종속변수(y)의 선형 관계를 모델링하는 가장 기본적인 머신러닝 알고리즘입니다.
핵심 질문:
“공부 시간과 시험 점수 사이에 관계가 있을까?”
| 공부 시간 (X) | 시험 점수 (y) |
|---|---|
| 1시간 | 50점 |
| 2시간 | 60점 |
| 3시간 | 70점 |
| 4시간 | 80점 |
선형회귀의 목표: 데이터를 가장 잘 표현하는 직선 찾기
1-2. 선형회귀 수식
단순 선형회귀 (독립변수 1개):
- (y): 예측값 (시험 점수)
- (x): 독립변수 (공부 시간)
- (w): 가중치 (기울기, weight)
- (b): 편향 (y절편, bias)
다중 선형회귀 (독립변수 여러 개):
예시: 집값 예측
1-3. 손실 함수 (Loss Function)
목표: 예측값과 실제값의 차이를 최소화
평균 제곱 오차 (MSE: Mean Squared Error):
- (y_i): 실제값
- (\hat{y}_i): 예측값
- (n): 데이터 개수
직관적 이해:
- 예측이 정확하면 MSE = 0
- 예측이 틀릴수록 MSE ↑
1-4. 경사하강법 (Gradient Descent)
최적의 (w, b)를 찾는 방법
알고리즘:
- 랜덤한 (w, b)로 시작
- MSE 계산
- MSE를 줄이는 방향으로 (w, b) 업데이트
- 반복
업데이트 공식:
- (\alpha): 학습률 (Learning Rate)
1-5. Python 구현 – scikit-learn
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
import numpy as np
# 데이터 생성 (공부 시간 → 시험 점수)
X = np.array([[1], [2], [3], [4], [5], [6]]) # 공부 시간
y = np.array([50, 60, 70, 80, 90, 100]) # 시험 점수
# Train/Test 분할
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42
)
# 모델 학습
model = LinearRegression()
model.fit(X_train, y_train)
# 예측
y_pred = model.predict(X_test)
# 평가
mse = mean_squared_error(y_test, y_pred)
print(f"가중치 (w): {model.coef_[0]:.2f}")
print(f"편향 (b): {model.intercept_:.2f}")
print(f"MSE: {mse:.2f}")
print(f"예측 방정식: y = {model.coef_[0]:.2f}x + {model.intercept_:.2f}")출력:
가중치 (w): 10.00
편향 (b): 40.00
MSE: 0.00
예측 방정식: y = 10.00x + 40.00해석: 공부 1시간당 점수 10점 상승
1-6. 선형회귀의 장단점
장점:
- ✅ 간단함: 이해하기 쉬움
- ✅ 빠름: 학습 속도 빠름 (데이터 100만 개 → 1초)
- ✅ 해석 가능: 가중치로 변수 영향력 파악
- ✅ 적은 데이터: 데이터 100개로도 학습 가능
단점:
- ❌ 선형만 가능: 비선형 패턴 포착 못함
- ❌ 이상치에 민감: 극단값이 모델을 왜곡
- ❌ 다중공선성: 독립변수 간 상관관계 높으면 불안정
사용 사례:
- 주택 가격 예측
- 매출 예측
- 광고 효과 분석
- 기온과 아이스크림 판매량 관계
2. 로지스틱 회귀(Logistic Regression)와 이진 분류
2-1. 로지스틱 회귀란?
로지스틱 회귀는 이름은 “회귀”지만 분류 알고리즘입니다.
핵심 질문:
“이 이메일은 스팸인가 정상인가?” (예/아니오)
| 입력 | 출력 |
|---|---|
| 이메일 텍스트 | 스팸 (1) / 정상 (0) |
| 종양 크기 | 악성 (1) / 양성 (0) |
| 신용 점수 | 대출 승인 (1) / 거부 (0) |
2-2. 선형회귀 vs 로지스틱 회귀
문제: 선형회귀로 분류를 할 수 있을까?
| 공부 시간 | 합격 여부 |
|---|---|
| 1시간 | 0 (불합격) |
| 2시간 | 0 (불합격) |
| 3시간 | 1 (합격) |
| 4시간 | 1 (합격) |
선형회귀 적용:
- 예측값: -0.5, 0.3, 1.8, 2.1
- 문제: 예측값이 0~1 범위를 벗어남 (1.8은 무슨 의미?)
해결책: 시그모이드 함수
2-3. 시그모이드 함수 (Sigmoid Function)
수식:
특징:
- 입력: 모든 실수 ((-\infty) ~ (+\infty))
- 출력: 0 ~ 1 (확률로 해석 가능)
시그모이드 함수 그래프:
1.0 ┤ ╭───────
│ ╭─╯
0.5 ┤ ╭─╯
│ ╭─╯
0.0 ┤───╯
└───┴───┴───┴───┴──>
-5 -3 0 3 5해석:
- (\sigma(0) = 0.5) → 경계선
- (\sigma(z) > 0.5) → 클래스 1 (합격)
- (\sigma(z)
2-4. 로지스틱 회귀 수식
전체 수식:
손실 함수: 이진 교차 엔트로피 (Binary Cross-Entropy)
직관적 이해:
- 실제값 (y=1)인데 예측 (\hat{y}=0.1) → Loss 큼
- 실제값 (y=1)인데 예측 (\hat{y}=0.9) → Loss 작음
2-5. Python 구현
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, confusion_matrix
# 데이터 로드 (유방암 데이터: 악성/양성)
data = load_breast_cancer()
X = data.data
y = data.target # 0: 악성, 1: 양성
# Train/Test 분할
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42
)
# 모델 학습
model = LogisticRegression(max_iter=5000)
model.fit(X_train, y_train)
# 예측
y_pred = model.predict(X_test)
y_proba = model.predict_proba(X_test) # 확률 출력
# 평가
accuracy = accuracy_score(y_test, y_pred)
cm = confusion_matrix(y_test, y_pred)
print(f"정확도: {accuracy:.2%}")
print(f"샘플 확률: {y_proba[0]}") # [악성 확률, 양성 확률]
print(f"\n혼동 행렬:\n{cm}")출력:
정확도: 96.49%
샘플 확률: [0.01 0.99] # 99% 양성
혼동 행렬:
[[60 3] # 실제 악성 60개 중 3개 오분류
[ 3 105]] # 실제 양성 105개 중 3개 오분류2-6. 로지스틱 회귀 장단점
장점:
- ✅ 확률 출력: “95% 스팸일 것 같다” 해석 가능
- ✅ 빠름: 실시간 예측 가능
- ✅ 적은 메모리: 모델 크기 작음
- ✅ 다중 클래스: One-vs-Rest로 확장 가능
단점:
- ❌ 선형 결정 경계: 복잡한 패턴 포착 못함
- ❌ Feature Engineering 필요: 좋은 Feature가 중요
사용 사례:
- 스팸 메일 필터
- 신용카드 사기 탐지
- 의료 진단 (질병 유무)
- 고객 이탈 예측
3. 의사결정나무(Decision Tree)
3-1. 의사결정나무란?
의사결정나무는 사람처럼 질문하며 분류하는 알고리즘입니다.
비유: 과일 분류하기
질문 1: 색깔이 빨간가?
├─ Yes → 사과
└─ No → 질문 2: 모양이 둥근가?
├─ Yes → 오렌지
└─ No → 바나나실제 예시: 타이타닉 생존 예측
성별이 여성인가?
├─ Yes → 생존 (73% 확률)
└─ No → 나이 3-2. 작동 원리
핵심: 데이터를 순수하게 나누기
지니 불순도 (Gini Impurity):
- (C): 클래스 개수
- (p_i): 클래스 (i)의 비율
예시:
- 그룹 A: [생존 10명, 사망 0명] → Gini = 0 (완전 순수)
- 그룹 B: [생존 5명, 사망 5명] → Gini = 0.5 (불순)
알고리즘:
- 루트 노드: 전체 데이터
- 가장 Gini를 많이 줄이는 Feature로 분할
- 각 자식 노드에서 반복
- 정지 조건 만족 시 멈춤 (깊이, 최소 샘플 수)
3-3. Python 구현
from sklearn.tree import DecisionTreeClassifier
from sklearn import tree
import matplotlib.pyplot as plt
# 타이타닉 데이터 (간소화)
X = [
[1, 38], # [성별(1=여성), 나이]
[0, 25],
[1, 5],
[0, 30],
[1, 40]
]
y = [1, 0, 1, 0, 1] # 생존 여부
# 모델 학습
model = DecisionTreeClassifier(max_depth=2)
model.fit(X, y)
# 트리 시각화
plt.figure(figsize=(12, 8))
tree.plot_tree(model, filled=True,
feature_names=['성별', '나이'],
class_names=['사망', '생존'])
plt.show()
# 예측
new_passenger = [[1, 20]] # 20세 여성
prediction = model.predict(new_passenger)
proba = model.predict_proba(new_passenger)
print(f"예측: {'생존' if prediction[0] == 1 else '사망'}")
print(f"생존 확률: {proba[0][1]:.2%}")3-4. 의사결정나무 장단점
장점:
- ✅ 직관적: 사람이 이해하기 쉬움
- ✅ 시각화 가능: 트리 그래프로 표현
- ✅ Feature Engineering 불필요: 원시 데이터로 학습
- ✅ 비선형 패턴: 복잡한 관계 포착
- ✅ 빠른 예측: (O(\log n))
단점:
- ❌ 과적합: Training 데이터에 쉽게 과적합
- ❌ 불안정: 데이터 조금 바뀌면 트리 구조 크게 변함
- ❌ 편향: 한쪽으로 치우친 트리 생성 가능
과적합 예방:
max_depth: 최대 깊이 제한min_samples_split: 분할에 필요한 최소 샘플 수min_samples_leaf: 리프 노드 최소 샘플 수
model = DecisionTreeClassifier(
max_depth=5, # 깊이 5까지만
min_samples_split=20, # 20개 이상일 때만 분할
min_samples_leaf=10 # 리프는 최소 10개
)4. 랜덤포레스트(Random Forest)와 앙상블 기법
4-1. 랜덤포레스트란?
랜덤포레스트는 수백 개의 의사결정나무를 만들어 다수결 투표하는 알고리즘입니다.
비유: 집단 지성
| 방법 | 정확도 |
|---|---|
| 전문가 1명 | 70% |
| 전문가 100명의 다수결 | 95% |
핵심 아이디어:
- 나무 하나는 불안정하지만
- 나무 100개의 평균은 안정적
4-2. 작동 원리
배깅 (Bagging: Bootstrap Aggregating)
1단계: 부트스트랩 샘플링
원본 데이터 (1000개)
↓
랜덤 샘플링 (중복 허용)
├─ 트리 1: 샘플 [1, 5, 7, 7, 10, ...]
├─ 트리 2: 샘플 [2, 3, 3, 8, 9, ...]
└─ 트리 100: 샘플 [1, 4, 6, 6, 11, ...]2단계: Feature 랜덤 선택
- 전체 Feature 10개
- 각 분할 시 랜덤하게 3개만 고려
- 트리마다 다른 Feature 조합 → 다양성 증가
3단계: 다수결 투표
새로운 데이터
↓
트리 1: 클래스 A
트리 2: 클래스 A
트리 3: 클래스 B
...
트리 100: 클래스 A
↓
최종 예측: 클래스 A (65표 vs 35표)4-3. Python 구현
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
# 데이터 로드
iris = load_iris()
X = iris.data
y = iris.target
# Train/Test 분할
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42
)
# 랜덤포레스트 학습
rf_model = RandomForestClassifier(
n_estimators=100, # 트리 100개
max_depth=5,
random_state=42
)
rf_model.fit(X_train, y_train)
# 단일 의사결정나무 학습 (비교)
dt_model = DecisionTreeClassifier(max_depth=5, random_state=42)
dt_model.fit(X_train, y_train)
# 예측 및 평가
rf_pred = rf_model.predict(X_test)
dt_pred = dt_model.predict(X_test)
rf_accuracy = accuracy_score(y_test, rf_pred)
dt_accuracy = accuracy_score(y_test, dt_pred)
print(f"랜덤포레스트 정확도: {rf_accuracy:.2%}")
print(f"의사결정나무 정확도: {dt_accuracy:.2%}")
print(f"성능 향상: {(rf_accuracy - dt_accuracy)*100:.1f}%p")출력:
랜덤포레스트 정확도: 97.78%
의사결정나무 정확도: 93.33%
성능 향상: 4.5%p4-4. Feature Importance
랜덤포레스트의 강력한 기능: 변수 중요도 측정
import pandas as pd
# Feature Importance
importance = pd.DataFrame({
'feature': iris.feature_names,
'importance': rf_model.feature_importances_
}).sort_values('importance', ascending=False)
print(importance)출력:
feature importance
2 petal length (cm) 0.45 # 가장 중요
3 petal width (cm) 0.42
0 sepal length (cm) 0.10
1 sepal width (cm) 0.03 # 덜 중요활용:
- 중요도 낮은 Feature 제거 → 모델 단순화
- 비즈니스 인사이트: “꽃잎 길이가 종 구분의 핵심”
4-5. 랜덤포레스트 장단점
장점:
- ✅ 높은 정확도: 대부분의 문제에서 우수
- ✅ 과적합 방지: 앙상블로 안정화
- ✅ Feature Importance: 변수 중요도 측정
- ✅ 결측치 허용: 내부적으로 처리 가능
- ✅ 병렬 처리: 트리 독립적으로 학습 → 빠름
단점:
- ❌ 해석 어려움: 트리 100개를 어떻게 설명?
- ❌ 메모리: 트리 많으면 모델 크기 큼
- ❌ 예측 느림: 트리 100개 모두 계산
- ❌ 외삽 약함: 학습 범위 밖 데이터 예측 부정확
하이퍼파라미터 튜닝:
| 파라미터 | 설명 | 권장값 |
|---|---|---|
n_estimators | 트리 개수 | 100~500 |
max_depth | 최대 깊이 | 5~20 |
max_features | 분할 시 고려 Feature 수 | √(전체 Feature 수) |
min_samples_split | 분할 최소 샘플 | 2~10 |
5. 알고리즘 비교 및 선택 가이드
5-1. 4가지 알고리즘 종합 비교
| 항목 | 선형회귀 | 로지스틱 회귀 | 의사결정나무 | 랜덤포레스트 |
|---|---|---|---|---|
| 문제 유형 | 회귀 (연속값) | 분류 (이진) | 분류/회귀 | 분류/회귀 |
| 출력 | 실수 | 0~1 확률 | 클래스 | 클래스 |
| 해석 가능성 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐ |
| 정확도 | ⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 학습 속도 | 빠름 | 빠름 | 빠름 | 느림 (트리 많음) |
| 예측 속도 | 매우 빠름 | 매우 빠름 | 빠름 | 느림 |
| 과적합 위험 | 낮음 | 낮음 | 높음 | 낮음 |
| 비선형 패턴 | ❌ | ❌ | ✅ | ✅ |
| Feature Engineering | 필요 | 필요 | 불필요 | 불필요 |
| 메모리 | 작음 | 작음 | 중간 | 큼 |
5-2. 알고리즘 선택 플로차트
문제가 회귀인가 분류인가?
│
├─ 회귀 (연속값 예측)
│ └─ 데이터가 선형 관계인가?
│ ├─ Yes → 선형회귀
│ └─ No → 랜덤포레스트 (회귀)
│
└─ 분류
└─ 해석 가능성이 중요한가?
├─ Yes → 의사결정나무 or 로지스틱 회귀
└─ No (정확도 중요) → 랜덤포레스트5-3. 상황별 추천
1. 빠른 프로토타입 필요
→ 선형회귀 or 로지스틱 회귀
- 이유: 학습 1초, 결과 즉시 확인
2. 비즈니스 설명 필요 (임원 보고)
→ 의사결정나무
- 이유: 트리 그림 한 장으로 설명 가능
3. Kaggle 대회 우승
→ 랜덤포레스트 or XGBoost
- 이유: 정확도 최고
4. 실시간 예측 (웹 서비스)
→ 로지스틱 회귀
- 이유: 예측 속도 0.001초
5. Feature 중요도 분석
→ 랜덤포레스트
- 이유:
feature_importances_자동 제공
5-4. 실전 예제: 타이타닉 생존 예측
4가지 알고리즘 성능 비교
from sklearn.datasets import fetch_openml
from sklearn.model_selection import cross_val_score
# 타이타닉 데이터 로드 (간소화)
# 실제로는 Kaggle에서 다운로드
# 4가지 모델
models = {
'로지스틱 회귀': LogisticRegression(),
'의사결정나무': DecisionTreeClassifier(max_depth=5),
'랜덤포레스트': RandomForestClassifier(n_estimators=100),
}
# 5-Fold 교차 검증
for name, model in models.items():
scores = cross_val_score(model, X, y, cv=5)
print(f"{name:15s}: {scores.mean():.2%} (±{scores.std():.2%})")출력:
로지스틱 회귀 : 79.5% (±1.2%)
의사결정나무 : 77.8% (±2.5%)
랜덤포레스트 : 83.2% (±1.1%) # 최고 성능6. 실전 팁과 주의사항
6-1. 데이터 전처리 체크리스트
- [ ] 결측치 처리: 평균/중앙값 대체 or 제거
- [ ] 이상치 제거: IQR or Z-Score
- [ ] Feature Scaling: 선형/로지스틱 회귀는 필수
- 의사결정나무/랜덤포레스트는 불필요
- [ ] 범주형 인코딩: One-Hot or Label Encoding
6-2. 모델 평가 지표
회귀 문제:
- MSE: 평균 제곱 오차 (낮을수록 좋음)
- RMSE: MSE의 제곱근 (원래 단위로 해석)
- R² Score: 설명력 (0~1, 높을수록 좋음)
분류 문제:
- Accuracy: 정확도 (불균형 데이터에서 부적절)
- Precision: 정밀도 (False Positive 중요)
- Recall: 재현율 (False Negative 중요)
- F1-Score: Precision과 Recall의 조화평균
6-3. 과적합 진단
증상:
- Training 정확도: 99%
- Test 정확도: 70%
- → 과적합!
해결책:
- 더 많은 데이터 수집
- 정규화 (L1/L2)
- Cross Validation
- 앙상블 (랜덤포레스트)
- Feature 줄이기
FAQ: 초보자가 자주 묻는 질문
Q1. 선형회귀와 로지스틱 회귀 중 어떤 게 더 좋나요?
A. 문제 유형에 따라 다릅니다. 연속값 예측(집값, 매출): 선형회귀. 이진 분류(스팸/정상, 합격/불합격): 로지스틱 회귀. 둘은 서로 다른 문제를 푸는 도구입니다.
Q2. 랜덤포레스트가 항상 의사결정나무보다 좋나요?
A. 정확도는 Yes, 해석 가능성은 No. 랜덤포레스트는 트리 100개를 설명할 수 없지만, 단일 트리는 그림 한 장으로 설명 가능합니다. 임원 보고: 의사결정나무, Kaggle: 랜덤포레스트.
Q3. Feature가 많으면 무조건 좋은가요?
A. 아니요. “더 많은 Feature = 더 좋은 성능”은 아닙니다. 불필요한 Feature는 (1) 과적합, (2) 학습 시간 증가, (3) 노이즈 추가. Feature Selection으로 중요한 것만 선택하세요.
Q4. 랜덤포레스트의 트리 개수는 몇 개가 적당한가요?
A. 일반 가이드: 100~500개. 트리가 많을수록 성능은 조금씩 향상되지만 학습 시간 증가. 실험으로 최적값 찾기. 보통 100개면 충분합니다.
Q5. scikit-learn만으로 실무가 가능한가요?
A. Yes! scikit-learn은 산업 표준입니다. Netflix, Spotify, Uber 모두 사용합니다. 딥러닝이 필요한 특수한 경우(이미지, 음성, 텍스트)에만 TensorFlow/PyTorch를 추가하세요.
외부 참고 자료
머신러닝 알고리즘을 더 깊게 배우고 싶다면:
- scikit-learn – Linear Regression – 공식 문서
- scikit-learn – Logistic Regression – 이진 분류
- scikit-learn – Decision Trees – 의사결정나무
- scikit-learn – Random Forest – 랜덤포레스트
- Kaggle – Machine Learning – 실전 튜토리얼
정리: 이 글에서 배운 것
✅ 선형회귀: 연속값 예측, (y = wx + b), MSE 최소화
✅ 로지스틱 회귀: 이진 분류, 시그모이드 함수, 확률 출력
✅ 의사결정나무: 질문하며 분류, 해석 가능, 과적합 위험
✅ 랜덤포레스트: 트리 100개 투표, 최고 정확도, Feature Importance
✅ 알고리즘 선택: 문제 유형, 해석 가능성, 정확도 고려
다음 편에서는 “신경망의 시작 – 퍼셉트론에서 딥러닝까지“에 대해 자세히 알아봅니다. 특히 단층 퍼셉트론, 역전파 알고리즘, 활성화 함수를 수식과 코드로 완벽 설명하겠습니다.
