08_ML(Machine_Learning)

02_KNN 이진분류

chuu_travel 2025. 4. 2. 17:42
728x90
KNN 이진분류

 

 

01. 생선 분류
  • 수산물 전문 물류 센터에서 신입 직원들이 생선 이름을 외우지 못해 작업의 효율성이 현저히 떨어지는 일이 잦음
  • 이 물류 센터에서는 주로 생선의 길이와 무게로 생선을 분류
  • 판매하는 생선은 도미, 잉어, 대구, 청돔, 농어, 민물꼬치고기, 빙어

 

02. 이진 분류(binary classification)
  • 분류(classification): 여러 개의 범주(클래스) 중 하나를 구별해 내는 것
  • 이진 분류: 2개의 범주 중 하나를 고류는 분류
    • 도미인가 빙어인가
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import LabelEncoder # 사이킷런의 전처리기 -> 카테고리값을 코드값으로
from sklearn.neighbors import KNeighborsClassifier # 이웃 알고리즘

 

 

03. 데이터 준비
df = pd.read_csv("./data/Fish.csv")
df.head()

 

df.shape # 보통 10만개정도의 데이터가 머신러닝에 쓰이지만 예제의 데이터는 159개
(159, 7)

 

df.dtypes
Species     object
Weight     float64
Length1    float64
Length2    float64
Length3    float64
Height     float64
Width      float64
dtype: object

 

 

df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 159 entries, 0 to 158
Data columns (total 7 columns):
 #   Column   Non-Null Count  Dtype  
---  ------   --------------  -----  
 0   Species  159 non-null    object 
 1   Weight   159 non-null    float64
 2   Length1  159 non-null    float64
 3   Length2  159 non-null    float64
 4   Length3  159 non-null    float64
 5   Height   159 non-null    float64
 6   Width    159 non-null    float64
dtypes: float64(6), object(1)
memory usage: 8.8+ KB

 

df["Species"].unique()
array(['Bream', 'Roach', 'Whitefish', 'Parkki', 'Perch', 'Pike', 'Smelt'],
      dtype=object)

 

# 이번 예제에서는 도미와 빙어에 대한 데이터 중 종, 무게, 길이 피처만 사용
df = df.loc[df["Species"].isin(["Bream", "Smelt"]), ["Species", "Weight", "Length2"]]

 

df.head()

 

df.shape
(49, 3)

 

plt.figure()
plt.scatter(data = df, x = "Length2", y = "Weight")
plt.show()

 

 

groups = df.groupby("Species")

plt.figure()

for name, group in groups:
    plt.scatter(group["Length2"], group["Weight"], label = name)

plt.legend()
plt.xlabel("Length")
plt.ylabel("Weight")
plt.show()

  • 도미의 길이가 길수록 무게가 무거워지는 경향이 있음
  • 빙어는 상대적으로 무게가 영향을 덜 받는 것처럼 보이지만 데이터의 분포가 일직선에 가까워 선형적임

 

04. 레이블 인코딩
  • 컴퓨터는 문자의 의미를 직접 이해하지 못함
  • 따라서 도미와 빙어를 숫자 0과 1로 표현
le = LabelEncoder()
df["label"] = le.fit_transform(df["Species"])
df.head()

 

df["Species"].value_counts()
Species
Bream    35
Smelt    14
Name: count, dtype: int64

 

df["label"].value_counts()
label
0    35
1    14
Name: count, dtype: int64

 

# 인코딩 클래스 확인
le.classes_
array(['Bream', 'Smelt'], dtype=object)

 

# 인코딩된 값을 다시 디코딩
le.inverse_transform(df["label"][:5])
array(['Bream', 'Bream', 'Bream', 'Bream', 'Bream'], dtype=object)

 

 

 

05. 모델 훈련

K-Nearest Neighbor

  • 기존 데이터 중 가장 유사한 k개의 데이터를 이용해서 새로운 데이터를 예측
  • 특징
    • 최고 인접 다수결
      • 기존 데이터 중 가장 유사한 k개의 데이터를 측정하여 분류
    • Lazy learning 기법
      • 새로운 입력 값이 들어온 후 분류 시작
      • 데이터셋을 저장만 하고 일반화된 모델을 능동적으로 만들지 않음
    • 단순 유연성
      • 모형이 단순하며 파라미터의 가정이 거의 없음
  • 장점
    • 학습이 간단
    • 훈련 데이터의 크기가 클수록 정확해짐
    • 모형이 단순하고 쉽게 구현할 수 있음
  • 단점
    • k값 선정에 따라 성능이 좌우됨(동률이 될 가능성 때문에 k값은 일반적으로 홀수로 설정)
    • 높은 자원 요구량
      • 데이터셋 전체를 메모리에 기억
    • 계산 복잡성
      • 모든 데이터와의 거리 측정 수행이 필요

 

# KNN 분류기 모델 객체 생성
knn = KNeighborsClassifier()
# 모델 훈련
knn.fit(df[["Length2", "Weight"]], df["label"])

 

 

knn.score(df[["Length2", "Weight"]], df["label"]) # score(예측값(평가를 수행할 데이터), 정답값)
1.0

 

 

  • 정확도
    • 정확한 답을 몇 개 맞혔는지를 백분율로 나타낸 값
    • 0 ~ 1사이의 값으로 출력
    • 정확도 = (정확히 맞힌 개수) / (전체 데이터 개수)
groups = df.groupby("Species")

plt.figure()

for name, group in groups:
    plt.scatter(group["Length2"], group["Weight"], label = name)

plt.scatter(30, 600, c = "g", marker = "^", label = "predict") # (30, 600)의 물고기가 어떤 물고기인지 예측

plt.legend()
plt.xlabel("Length")
plt.ylabel("Weight")
plt.show()

 

# 길이 30, 무게 600의 생선에 대한 예측
knn.predict([[30, 600]])
array([0])

 

# 레이블인코더로 예측값 디코딩
le.inverse_transform([0])
array(['Bream'], dtype=object)
  • 모든 데이터로 학습을 하면 정답을 잘 맞히는 것이 당연하기 때문에 일반화할 수 있는 좋은 모델인지를 평가할 평가지표가 없음
728x90

'08_ML(Machine_Learning)' 카테고리의 다른 글

06_KNN 심화  (0) 2025.04.04
05_KNN회귀  (0) 2025.04.04
04_KNN_타이타닉 분류  (0) 2025.04.02
03_데이터 전처리  (0) 2025.04.02
01. 머신러닝 기본 이론  (2) 2025.04.02