콘텐츠로 이동

Chapter 7: 첫 학습 - 붓꽃 품종 분류하기

한 줄 요약: fit()으로 학습시키고, predict()로 예측하고, accuracy로 평가하는 머신러닝의 기본 사이클을 완성해요!


🎯 이 장에서 배우는 것

  • [ ] scikit-learn으로 분류 모델을 학습시킬 수 있다
  • [ ] 학습된 모델로 새로운 데이터를 예측할 수 있다
  • [ ] 정확도(accuracy)의 의미를 이해하고 계산할 수 있다
  • [ ] train_test_split으로 데이터를 나누는 이유를 설명할 수 있다
  • [ ] 머신러닝의 전체 흐름(학습 → 예측 → 평가)을 직접 수행할 수 있다

💡 왜 이걸 배우나요?

드디어, 기계를 가르치는 순간!

지금까지 우리는 if문으로 규칙을 직접 작성했어요:

if 꽃잎_길이 > 2.5:
    품종 = "versicolor"

하지만 이 방식의 한계를 봤죠? - 규칙이 너무 많아지면 관리 불가능 - 새로운 패턴이 나타나면 규칙을 다시 작성해야 함 - 사람이 발견 못한 패턴은 놓침

이번 장에서 배우는 머신러닝은 완전히 다른 접근이에요:

기존 방식: "이런 조건이면 A야" → 규칙을 내가 만듦
머신러닝: "여기 데이터 있어, 알아서 패턴 찾아" → 규칙을 기계가 만듦

이걸 배우면 할 수 있는 것들

📧 스팸 메일 분류기    → "이 메일은 스팸일까, 정상일까?"
🏥 질병 예측 모델      → "이 환자는 당뇨병 위험이 있을까?"
🎬 영화 추천 시스템    → "이 사람은 어떤 장르를 좋아할까?"
🌸 오늘 우리가 만들 것 → "이 붓꽃은 어떤 품종일까?"

오늘 붓꽃 분류를 완성하면, 위의 모든 프로젝트에 같은 패턴을 적용할 수 있어요. 머신러닝의 기본 흐름은 다 똑같거든요!


📚 핵심 개념

개념 1: fit() - 학습시키기

비유로 시작: fit()은 마치 선생님이 학생에게 문제집을 풀게 하는 것과 같아요.

문제집 = 데이터
정답지 = 레이블(라벨)
학생 = 모델
공부 과정 = fit()

학생이 문제(데이터)와 정답(레이블)을 보면서 "아, 이런 유형은 이렇게 푸는구나" 패턴을 익히는 거예요.

정확한 정의: fit()은 모델이 주어진 데이터(X)와 정답(y)의 관계를 학습하는 과정이에요. 이 과정에서 모델 내부의 파라미터(가중치)가 조정돼요.

예시로 확인:

# X = 특성(feature) 데이터 - 꽃잎 길이, 너비 등
# y = 레이블(label) - 품종 이름

model.fit(X, y)  # "이 데이터로 공부해!"

쉽게 말하면: fit()은 "이 데이터를 보고 패턴을 배워라"라는 명령이에요.


개념 2: predict() - 예측하기

비유로 시작: predict()는 마치 시험을 보는 것과 같아요.

공부 끝난 학생 = 학습된 모델
새 시험 문제 = 처음 보는 데이터
학생의 답안 = predict() 결과

이번에는 정답지 없이, 문제만 주고 "알아서 맞혀봐"라고 하는 거죠.

정확한 정의: predict()는 학습이 끝난 모델에 새로운 데이터를 넣어서 예측값을 얻는 함수예요.

예시로 확인:

# 처음 보는 붓꽃 데이터
new_flower = [[5.0, 3.4, 1.5, 0.2]]

# 모델아, 이건 무슨 품종이야?
prediction = model.predict(new_flower)
print(prediction)  # ['setosa'] 라고 예측!

쉽게 말하면: predict()는 "그래서 이건 뭐야?"라고 물어보는 거예요.


개념 3: 정확도(Accuracy) - 얼마나 잘 맞췄나?

비유로 시작: 정확도는 마치 시험 점수와 같아요.

총 20문제 중 18개 맞춤 → 정확도 = 18/20 = 0.9 (90%)
총 50문제 중 47개 맞춤 → 정확도 = 47/50 = 0.94 (94%)

정확한 정의:

정확도(Accuracy) = 맞춘 개수 / 전체 개수

예시로 확인:

# 모델의 예측
predictions = ['setosa', 'versicolor', 'virginica', 'versicolor']

# 실제 정답
actual = ['setosa', 'versicolor', 'versicolor', 'versicolor']
#                                  ↑ 여기 틀림!

# 4개 중 3개 맞춤
accuracy = 3 / 4  # = 0.75 (75%)

쉽게 말하면: 정확도는 "100개 중 몇 개 맞췄어?"의 비율이에요.


개념 4: train_test_split - 왜 데이터를 나누나?

비유로 시작: 이건 마치 문제집과 모의고사를 분리하는 것과 같아요.

나쁜 공부법: 문제집으로 공부 → 같은 문제집으로 시험
              → "난 100점이야!" (사실은 외운 것)

좋은 공부법: 문제집으로 공부 → 처음 보는 모의고사로 시험
              → 진짜 실력 측정

왜 이게 중요할까?

학습에 사용한 데이터로 평가하면, 모델이 답을 외워버린 건지, 진짜 이해한 건지 알 수 없어요!

                     전체 데이터 (150개)
                    ↙                ↘
        학습용 (Train) 120개       테스트용 (Test) 30개
               ↓                          ↓
          fit()으로 학습            predict()로 예측 후
                                     정확도 측정

정확한 정의: train_test_split은 전체 데이터를 학습용(train)과 테스트용(test)으로 나누는 함수예요. 보통 70-80%를 학습에, 20-30%를 테스트에 사용해요.

쉽게 말하면: "컨닝 방지를 위해 시험 문제는 따로 빼둬요"


개념 5: 머신러닝의 전체 흐름

┌─────────────────────────────────────────────────────────────┐
│                    머신러닝 기본 흐름                        │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│   1. 데이터 준비          2. 데이터 분리                     │
│   ┌─────────────┐        ┌──────────────────┐               │
│   │ X (특성)    │   →    │ X_train, X_test  │               │
│   │ y (레이블)  │        │ y_train, y_test  │               │
│   └─────────────┘        └──────────────────┘               │
│                                 ↓                            │
│   3. 모델 선택 & 학습                                        │
│   ┌────────────────────────────┐                            │
│   │ model = KNeighbors...()    │                            │
│   │ model.fit(X_train, y_train)│  ← 학습용으로 공부!        │
│   └────────────────────────────┘                            │
│                    ↓                                         │
│   4. 예측                                                    │
│   ┌────────────────────────────┐                            │
│   │ predictions = model.predict│                            │
│   │              (X_test)      │  ← 테스트용으로 시험!      │
│   └────────────────────────────┘                            │
│                    ↓                                         │
│   5. 평가                                                    │
│   ┌────────────────────────────┐                            │
│   │ accuracy = 맞춘 개수 /     │                            │
│   │            전체 개수       │  ← 점수 확인!              │
│   └────────────────────────────┘                            │
│                                                              │
└─────────────────────────────────────────────────────────────┘

외워야 할 순서: 준비 → 분리 → 학습 → 예측 → 평가

이 패턴은 거의 모든 머신러닝 프로젝트에서 동일하게 사용돼요!


🔨 따라하기

Step 1: 필요한 도구 불러오기

목표: scikit-learn의 핵심 도구들을 import해요.

코드:

# === WHAT: 머신러닝에 필요한 도구들 가져오기 ===
# 이 코드는 사이킷런(scikit-learn)의 핵심 기능을 불러와요

# --- WHY: 각 도구는 정해진 역할이 있어요 ---
# datasets: 연습용 데이터셋 제공
# model_selection: 데이터 분리 도구
# neighbors: KNN 분류 알고리즘
# metrics: 성능 평가 도구

from sklearn import datasets  # HOW: 붓꽃 데이터 가져올 곳
from sklearn.model_selection import train_test_split  # HOW: 데이터 나누는 함수
from sklearn.neighbors import KNeighborsClassifier  # HOW: 분류 모델
from sklearn.metrics import accuracy_score  # HOW: 정확도 계산 함수

print("✅ 필요한 도구를 모두 불러왔어요!")

실행 결과:

✅ 필요한 도구를 모두 불러왔어요!

여기서 잠깐! 🤔

sklearn은 "사이킷런"이라고 읽어요.
scikit-learn의 줄임말이고, 머신러닝의 국민 라이브러리예요.

왜 KNeighborsClassifier를 쓸까?
→ K-최근접 이웃(K-Nearest Neighbors) 알고리즘
→ "비슷한 애들 중 다수결로 결정"하는 가장 직관적인 방법
→ 나중에 자세히 배우지만, 지금은 "그냥 분류해주는 도구"로 이해해도 OK!

Step 2: 데이터 불러오고 확인하기

목표: 붓꽃 데이터를 로드하고, 구조를 파악해요.

코드:

# === WHAT: 붓꽃 데이터셋 불러오기 ===
# sklearn에 내장된 유명한 연습용 데이터

# --- WHY: 머신러닝 입문에 가장 많이 쓰이는 데이터셋 ---
# 150개 샘플, 4개 특성, 3개 품종
# 크기가 작아서 빠르게 실험 가능

# HOW: load_iris() 함수로 데이터 가져오기
iris = datasets.load_iris()

# 데이터 구조 확인
print("📊 붓꽃 데이터셋 구조")
print("=" * 50)

# HOW: data는 특성(X), target은 레이블(y)
print(f"특성(X) 데이터 크기: {iris.data.shape}")
print(f"레이블(y) 데이터 크기: {iris.target.shape}")

print("\n📋 특성 이름:")
for i, name in enumerate(iris.feature_names):
    print(f"  {i}. {name}")

print("\n🌸 품종 이름:")
for i, name in enumerate(iris.target_names):
    print(f"  {i}. {name}")

실행 결과: ``` 📊 붓꽃 데이터셋 구조 ================================================== 특성(X) 데