본문 바로가기

공부 일지 #29 | 머신러닝 경험해보기: KNN 알고리즘

@studying:)2025. 9. 5. 16:19

학습 날짜: 2025.09.03


Scikit-learn으로 머신러닝 시작하기

# ML Library(Scikit-learn) import
import sklearn

print(sklearn.__version__) # 버전 확인 1.6.1

1. 데이터 준비

  • Iris(붓꽃) 데이터로 실습
  • Iris는 꽃잎, 꽃받침 모양에 따라서 여러가지 품종으로 분류
    • 꽃잎(Petal)의 길이와 넓이: Petal Length, Petal Width
    • 꽃받침(Sepal)의 길이와 넓이: Sepal Length, Sepal Width
    • 품종: Setosa, Versicolor, Virginica

1.1. 데이터 불러오기

import pandas as pd  # 데이터 분석과 DataFrame 처리를 위한 라이브러리
from sklearn.datasets import load_iris # Iris 데이터셋 불러오는 함수

# Iris 데이터 불러오기
iris = load_iris()

# Iris 데이터 열이름 확인
iris.keys()
'''
출력값
dict_keys(['data', 'target', 'frame', 'target_names', 'DESCR', 'feature_names', 'filename', 'data_module'])
'''

# y값 확인
iris['target'] # y 값 'setosa' = 0, 'versicolor' = 1, 'virginica' =2
df = pd.DataFrame(data = iris['data'])
df.head() # 열 이름이 0,1,2,3 으로 나옴
'''
	0	1	2	3
0	5.1	3.5	1.4	0.2
1	4.9	3.0	1.4	0.2
2	4.7	3.2	1.3	0.2
3	4.6	3.1	1.5	0.2
4	5.0	3.6	1.4	0.2
'''

df = pd.DataFrame(data = iris['data'], columns=iris['feature_names'])
df.head() # 열 이름이 feature_names로 나옴
'''
	sepal length (cm)	sepal width (cm)	petal length (cm)	petal width (cm)
0	5.1	3.5	1.4	0.2
1	4.9	3.0	1.4	0.2
2	4.7	3.2	1.3	0.2
3	4.6	3.1	1.5	0.2
4	5.0	3.6	1.4	0.2
'''

1.2. 데이터 분할

# hold-out dataset1
from sklearn.model_selection import train_test_split # 데이터셋 분할 라이브러리

# 클래스의 비율로 계층적 랜덤 샘플링을 해줌, default은 50, 50
cols = iris['feature_names']
x_train, x_test, y_train, y_test = train_test_split(df[cols], df['target'], test_size = 0.3, random_state=11)
x_train.shape, x_test.shape, y_train.shape, y_test.shape

'''
출력값
((105, 4), (45, 4), (105,), (45,))
'''

 

2. 학습 알고리즘 선택

K 최근접 이웃(KNN) 알고리즘

  • 분류와 회귀문제를 모두 다룰 수 있음
    • 분류: 다수결로 예측
    • 회귀: 평균값으로 결과 예측
  • 데이터 간의 거리는 어떻게 측정하는가?
    • 유클리디안 거리: 두 점의 거리
    • 맨해튼 거리: 격자무늬 선을 따른 두 점의 거리
    • 거리 기반 알고리즘은 이상값의 영향을 많이 받음
    • default = minkowski, 1 = 맨해턴 2 = 유클리디안
  • KNN은 거리 계산이 핵심이라, 데이터의 스케일(단위)이 서로 다른 경우 별도의 정규화 필요!
  • 적절한 k값의 크기는 어떻게 설정할 것 인가?
    • k = 1을 사용하지 않음 why? 100% 과적합이 일어나기 때문
    • k가 너무 작으면 과대 적합, 너무 크면 과소적합이 일어남
  • 하이퍼 파라미터
    • 학습 시작 전에 모델러에 의해 결정되는 값
    • 모델의 성능에 영향을 주기에 최적의 값을 찾아야 함
    • ex) 거리계산 방식, k값
  • 장점:
    • 이상치(Anomaly) 탐색할 때도 사용 가
    • 비모수라 비선형적인 특징을 가진 데이터 분류에도 좋음
  • 단점: 거리를 다 계산해야 해서 오래 걸림
from sklearn.neighbors import KNeighborsClassifier # KNN 알고리즘 사용
'''
새로운 데이터가 주어졌을 때, 가장 가까운 K개의 이웃 데이터를 찾는 알고리즘
이웃데이터 다수결 값에 의해 class 값이 정해짐
'''

knn_model = KNeighborsClassifier(n_neighbors=5) # n_neighbors = K값, default 5개

knn_model # 깡통 모델(주황색)

 

3. 학습 데이터를 통한 모델 학습

knn_model.fit(x_train, y_train) # 학습 모델(하늘색)

 

4. 테스트 데이터를 통한 모델 검증

y_pred = knn_model.predict(x_test) # 테스트 테이터 적용

score = knn_model.score(x_test, y_test) #acc
score # 0.98 거의 다 맞춤!

5. 여러 k 값을 사용해 모델 학습 및 검증해보기

'''
k값을 [3, 5, 7, 9, 11, 13, 15, 17, 19] 로 설정하여
각각 학습하고 정확도 확인해보기
'''

# 모델 학습 함수 생성
def make_model_knn(k):
  knn_model = KNeighborsClassifier(n_neighbors=k)
  knn_model.fit(x_train, y_train) #학습

  return knn_model

# k 값 리스트 만들기
k_seq = range(3, 20, 2)

# 모델을 각각 만들고, 정확도는 리스트에 담기
train_acc = []
test_acc = []

for k in k_seq:
  model = make_model_knn(k)
  y_pred = model.predict(x_test)

  train_score = model.score(x_train, y_train)
  test_score = model.score(x_test, y_test)

  train_acc.append(train_score)
  test_acc.append(test_score)

k값에 따른 정확도를 그래프로 그리기

import matplotlib.pyplot as plt
import seaborn as sns

plt.figure(figsize=(8, 5))
plt.plot(list(k_seq), train_acc, "b--", label = "Train ACC")
plt.plot(list(k_seq), test_acc, "r", label = "Test ACC")

plt.title('IRIS KNN')
plt.xlabel('K')
plt.ylabel('Score')
plt.show()

'''
6~7 정도가 좋아보임
'''

k = 7 일 때, 모델 정확도 확인하기

k = 7
model = make_model_knn(k)
y_pred = model.predict(x_test)

test_score = model.score(x_test, y_test)

print(f"k: {k} - score:{test_score}")
'''
k: 7 - score:0.9777777777777777
'''
studying:)
@studying:) :: what i studied

studying:) 님의 학습 여정을 기록하는 블로그입니다.

목차