본 글에서는 "K최근접이웃모델(KNN) - 분류분석의 기초"에 대한 내용을 다룰 것이다. 차례와 사용 툴 및 라이브러리는 아래와 같다.
[차례]
첫 번째, K최근접이웃 모델(KNN)의 개념
두 번째, KNN의 작동 원리
세 번째, KNN의 파라메터
네 번째, KNN의 특징
다섯 번째, 예제: 생선구분하기 - K최근접이웃모델(분류)
[순서]
- 데이터 불러오기
- 데이터 전처리
- 데이터 분포 확인
- 데이터 통합
- 독립변수 및 종속변수 생성 - KNN 분류모델 구축
- 모델 훈련(학습)
- 모델 성능 평가
- 훈련 데이터 세트의 정확도 확인 - 모델 예측 및 결과 시각화
- 임의 데이터의 전달을 통한 종속변수 예측
- 산점도 그래프 생성 - 하이퍼파라메터 튜닝
- (과대적합 해소를 위한) 하이퍼파라메터(이웃의 갯수) 조정
- 모델 생성 ~ 모델 예측 재수행 - 최종 모델 검증
[사용 툴]
- Jupyter notebook(웹 기반 대화형 코딩 환경)
[사용 라이브러리 및 모듈]
- 시각화 라이브러리 및 모듈: matplotlib의 pyplot 모듈
- 머신러닝 라이브러리 및 모델: scikit-learn
sklearn.neighbors.KNeighborsClassifier : KNN 분류모델 생성
· K최근접이웃 모델(KNN)의 개념
K최근접이웃 모델(KNN)은 지도 학습 기반의 방법으로, 분류 및 회귀 문제에 모두 효과적인 해결책을 제공한다. 이 모델은 주어진 데이터셋으로부터 학습하여, 새로운 데이터의 결과를 예측할 때 그 주변에 위치한 가장 가까운 이웃 데이터들의 정보를 활용하여 결정을 내리는 방식을 취한다. KNN은 분류 문제에서는 가까운 이웃들을 기반으로 새로운 데이터의 결과를 예측하고, 회귀 문제에서는 이웃들의 수치 값을 평균 내어 연속적인 값을 예측한다.
· KNN의 작동 원리
KNN 분류(Classification)
분류에서 주어진 입력값에 대해 예측하고자 하는 대상의 모델(클래스)을 결정할 때, 그 대상과 가장 가까운 몇 개의 이웃을 찾아 그 이웃들이 속한 모델 중 가장 많이 나타나는 모델을 다수결 원칙에 따라 기준으로 결정한다. KNN 분류 모델에서는 '가장 가까운 이웃의 개수'를 의미하는 K값이 매우 중요한데, 이 값은 모델이 얼마나 많은 이웃을 고려할지를 결정한다. 기본적으로 K값은 5로 설정되어 있다.
KNN 회귀(Regression)
회귀에서 주어진 입력값에 대한 연속적인 수치 예측을 생성하는 데 사용된다. KNN 회귀 알고리즘에서는 예측하고자 하는 데이터와 가장 가까운 이웃들을 찾고, 이 이웃들의 수치적인 값들의 평균이나 중앙값을 사용하여 예측값을 결정한다. 이렇게 함으로써, KNN은 주어진 데이터에 대해 연속적인 값을 예측할 수 있다.
· KNN의 파라메터
K값: K는 가장 가까운 이웃의 수를 나타내며, 이 값에 따라 모델의 복잡도가 결정된다. K가 너무 낮으면 예측이 이웃의 임의의 변동에 지나치게 민감해질 수 있고, K가 너무 크면 예측이 너무 단순화되어 정확도가 떨어질 수 있기 때문이다. 따라서 적절한 K값을 찾는 게 중요하다.
· KNN의 특징
- 간단하고 이해하기 쉬움: KNN은 매우 직관적인 모델이기 때문에 머신러닝 입문자에게 적합하다. 복잡한 가정이 필요 없고, 모델의 파라미터가 많지 않다.
- 비교용 모델로 적합: 특히 초기 분석 단계에서 다른 복잡한 모델과 성능을 비교하기 위한 기준점으로 사용하기 좋다.
- 실제 사용에는 한계: KNN은 게으른 학습 방식을 취하기 때문에, 매 예측마다 전체 데이터를 대상으로 가장 가까운 이웃을 찾아야 한다. 이는 데이터가 크면 클수록 계산 복잡도가 증가하며, 실시간 예측이 필요한 시스템에는 부적합할 수 있다.
- 표준화/정규화의 중요성: KNN은 거리 기반 모델로, 모든 특성들이 동일한 스케일을 갖도록 데이터를 표준화하거나 정규화하는 것이 매우 중요하다.
예제: 생선구분하기 - K최근접이웃모델(분류)
1. 데이터 불러오기
1.1 도미 데이터 불러오기
# - 도미 길이(cm)
bream_length = [25.4, 26.3, 26.5, 29.0, 29.0, 29.7, 29.7, 30.0,
30.0, 30.7, 31.0, 31.0, 31.5, 32.0, 32.0, 32.0,
33.0, 33.0, 33.5, 33.5, 34.0, 34.0, 34.5, 35.0,
35.0, 35.0, 35.0, 36.0, 36.0, 37.0, 38.5, 38.5,
39.5, 41.0, 41.0]
# - 도미 무게(g)
bream_weight = [242.0, 290.0, 340.0, 363.0, 430.0, 450.0, 500.0,
390.0, 450.0, 500.0, 475.0, 500.0, 500.0, 340.0,
600.0, 600.0, 700.0, 700.0, 610.0, 650.0, 575.0,
685.0, 620.0, 680.0, 700.0, 725.0, 720.0, 714.0,
850.0, 1000.0, 920.0, 955.0, 925.0, 975.0, 950.0]
1.2 빙어 데이터 불러오기
# - 빙어 길이(cm)
smelt_length = [9.8, 10.5, 10.6, 11.0, 11.2, 11.3, 11.8,
11.8, 12.0, 12.2, 12.4, 13.0, 14.3, 15.0]
# - 빙어 무게(g)
smelt_weight = [6.7, 7.5, 7.0, 9.7, 9.8, 8.7, 10.0,
9.9, 9.8, 12.2, 13.4, 12.2, 19.7, 19.9]
2. 데이터 전처리
2.1 도미 데이터 분포 확인
import matplotlib.pyplot as plt
# 산점도 그래프 생성
plt.scatter(bream_length, bream_weight)
plt.xlabel("length")
plt.ylabel("weight")
plt.show()
2.1.1 해석
- 도미 데이터에서 도미의 길이가 증가함에 따라 무게 또한 비례하여 증가함을 보인다.
- 분포의 방향은 x가 커질수록 y가 커지는 '양(+)의 상관관계'를 나타낸다.
- 이와 같은 양의 상관관계는 '우상향 분포'로, 선형적인 관계를 보인다.
모델을 분석하는 입장에서 이러한 선형적인 관계는 '선형 형태'를 나타낸다고 하며, 이 선형 형태에 대한 분석은 '회귀분석'을 사용하여 모델링하고 분석한다.
2.1.2 참고 - 모델구분
- 선형 관계를 보이는 데이터에 대해서는 '회귀분석'을 사용하여 변수 간의 관계를 모델링한다.
- 만약 도미와 같은 생선을 다른 생선 종류와 구분해야 할 경우에는 '분류분석'을 사용한다.
- 분류 모델은 주어진 입력(ex. 길이와 무게)에 대해 생선의 종류(ex. 도미)를 예측하는 데 사용된다.
- 이 경우, 우리가 알고 있는 정보는 생선의 길이와 무게, 그리고 그에 해당하는 생선의 종류이다.
요약하자면, 데이터의 선형적인 관계를 분석하기 위해서는 '회귀분석'을, 생선의 종류를 구분하는 문제에는 '분류분석'을 사용하며, 이 두 분석 방법은 각각 길이와 무게와 같은 수치 데이터와 생선의 종류와 같은 범주형 데이터에 기반한다.
2.2 도미&빙어 데이터 분포 확인하기
# 산점도 그래프 생성
plt.scatter(bream_length, bream_weight, c="red", label="bream")
plt.scatter(smelt_length, smelt_weight, c="blue", label="smelt")
plt.xlabel("length")
plt.ylabel("weigth")
plt.legend()
plt.show()
2.2.1 해석
- 도미와 빙어 두 종류의 생선 데이터 모두 길이와 무게 간에 '양의 상관관계'를 보이며, 이는 '우상향 분포'를 나타낸다.
- 도미 데이터의 경우, 길이가 증가함에 따라 무게가 상대적으로 큰 비율로 증가하고 있음을 의미하는 가파른 경사를 보인다.
- 반면 빙어 데이터는 길이가 증가해도 무게의 증가율이 완만함을 나타내는 완만한 경사를 보인다.
2.3 데이터 통합
도미와 빙어에 대한 각각의 데이터를 하나의 데이터(길이, 무게)로 통합한다.
# - 길이(length)
length = bream_length + smelt_length
print(f"length : {length} / count : {len(length)}")
# - 무개(weight)
weight = bream_weight + smelt_weight
print(f"weight : {weight} / count : {len(weight)}")
2.4 독립변수 생성
머신러닝은 독립변수로 '2차원 데이터'를 사용한다. 따라서, zip 함수를 사용해 독립변수로 사용할 '길이'와 '무게'를 묶어 2차원 형태로 반환한다.
# 독립변수 : 길이&무게
fish_data = [ [l, w] for l, w in zip(length, weight) ]
print(f"fish_data : {fish_data} / count : {len(fish_data)}")
2.5 종속변수 생성
머신러닝은 종속변수로 '1차원 데이터'를 사용한다. 단, 독립변수와 데이터의 개수가 일치해야 한다. 데이터의 형태는 주로 정수형을 사용하며, 범주 값의 개수에 따라 '0 ~ n'의 값을 사용한다. 일반적으로는 찾고자 하는 값을 '1'로 지정하지만, 어떠한 값을 사용하여도 무방하다.
- 이진분류: '0' 또는 '1'의 값 사용
- 다중분류: '0 ~ n'의 값 사용
# 종속변수 : 생선의 이름
fish_target = [1]*35 + [0]*14
print(f"fish_target : {fish_target} / count : {len(fish_target)}")
3. 모델 구축
3.1 라이브러리 호출하기
sklearn 라이브러리에서 KNN 분류모델 생성을 위한 KNeighborsClassifier 모듈을 호출한다.
from sklearn.neighbors import KNeighborsClassifier
3.2 KNN 분류모델 생성하기
KNeighborsClassifier 함수를 사용하여 KNN 분류모델 생성하는 함수
kn = KNeighborsClassifier()
kn
4. 모델 훈련(학습)
KNN 모델은 '학습'이라는 개념보다는 '기억'하는 방식에 더 가깝다. fit 함수를 호출할 때, KNN 모델은 주어진 독립변수(특성 데이터)와 종속변수(레이블 또는 타겟 데이터)를 메모리에 저장한다. 이는 모델이 훈련 데이터를 '기억'하는 과정이다. 그리고 새로운 데이터 포인트가 주어졌을 때, 모델은 기억해둔 훈련 데이터 중에서 독립변수(특성) 사이의 거리를 기반으로 가장 가까운 K개의 데이터 포인트(이웃)을 찾는다. 이렇게 찾아진 이웃들의 종속변수(레이블 또는 타겟)을 바탕으로 새로운 데이터 포인트의 종속변수를 예측한다.
분류 문제에서는 이웃들의 종속변수 중 가장 많이 나타난 클래스를 예측값으로 선택한다. 따라서 KNN 모델은 독립변수와 종속변수를 모두 '기억'하며, 이를 바탕으로 새로운 데이터에 대한 예측을 수행한다.
kn.fit(fish_data, fish_target)
5. 모델 성능 평가
5.1 훈련 데이터 세트의 정확도 확인
훈련 데이터의 독립변수와 종속변수에 score 함수를 적용하여 KNN 분류모델(kn)에 대한 훈련 정확도를 학인한다. score 함수의 첫 번째 인자로는 모델을 평가하기 위한 훈련 데이터의 독립변수를 입력하며, 두 번째 인자로는 훈련 데이터의 실제 정답인 종속변수를 입력한다. 모델의 예측을 이 정답과 비교하여 성능을 평가한다.
kn.score(fish_data, fish_target)
# 1.0 출력
5.1.1 해석
- 분류에서의 정확도는 '0(0%) ~ 1(100%)' 사이의 값이 나타난다.
- 정확도를 확인했을 때, '1.0'의 정확도는 과대적합을 의미한다.
5.1.2 참고
- '과대적합'이란 모델이 훈련 데이터에 과도하게 적합하여, 아직 훈련되지 않은 새로운 데이터에 대해 제대로 예측하지 못하는 상태를 의미한다.
6. 모델 예측 및 결과 시각화
학습된 모델을 통해 임의의 입력 값에 대한 출력 값을 예측하고, 이를 기존의 훈련 데이터와 함께 산점도 그래프에 표시함으로써, 모델이 어떻게 데이터를 해석하고 예측하는지를 직접적으로 확인할 수 있다. 이는 모델의 성능을 평가하고, 필요한 경우 모델을 수정하거나 개선하는 데 도움이 된다.
6.1 임의 데이터로 예측하기
predict 함수를 사용하여 모델에 학습된 패턴을 바탕으로 새로운 데이터의 결과를 예측한다. 예측을 진행할 때, 모델에는 '문제' 즉, 새로운 데이터의 독립변수만 제공된다. 여기서 독립변수는 모델이 예측을 수행하기 위해 필요한 입력 데이터를 의미한다. 임의의 입력 데이터는 훈련 데이터의 종속변수와 동일한 형태(예를 들어 단위, 스케일 등)로 사용해야 한다.
kn.predict([[30, 600]])
# array([1]) 출력
6.2 산점도 그래프 생성
plt.scatter(bream_length, bream_weight, c="red", label="bream")
plt.scatter(smelt_length, smelt_weight, c="blue", label="smelt")
plt.scatter(30, 600, marker="^", c="green", label="pred")
plt.xlabel("length")
plt.ylabel("weigth")
plt.legend()
plt.show()
6.2.1 해석
- 임의의 예측 데이터가 전체 데이터 분포 중, 도미의 위치에 놓여있는 것으로 보아 모델이 해당 예측 데이터를 '도미'로 분류했음을 나타낸다.
7. 하이퍼파라메터 튜닝
하이퍼파라메터 튜닝은 모델의 성능을 향상하기 위한 방법으로, 모델이 학습하기 전에 설정하는 매개변수들, 즉 하이퍼파라메터의 값(이웃의 갯수)을 조정하는 과정이다. KNN 모델에서 하이퍼파라메터를 조정하고자 하면, 일반적으로 모델의 복잡도와 성능이 바뀌므로 모델 생성부터 다시 시작해야 한다.
튜닝이 필요한 상황은 다음과 같다.
- 모델 성능 개선: 모델이 훈련 데이터에 대해 높은 성능을 보이지만, 검증 데이터나 테스트 데이터에 대해서는 만족스러운 결과를 보이지 않을 때
- 과대적합 조정: 모델이 훈련 데이터에 너무 잘 맞춰져 있어서, 새로운 데이터에 대한 예측 성능이 떨어질 때
- 과소적합 해결: 모델이 너무 간단하여 훈련 데이터의 패턴을 충분히 학습하지 못하고, 결과적으로 낮은 성능을 보일 때
7.1 (과대적합 해소를 위한) 하이퍼파라메터(이웃의 갯수) 조정
하이퍼파라메터 속성인 'n_neighbors'를 통해, 하이퍼파라메터(이웃의 개수) 조정
kn20 = KNeighborsClassifier(n_neighbors=20)
kn20
7.2 모델 학습(훈련)
kn20.fit(fish_data, fish_target)
7.3 훈련 데이터 세트의 정확도 확인
정확도 결과가 0.95 & 기준 이상일 경우, 일반적으로는 '매우 좋은 성능을 보이는 모델'로 판단된다.
kn20.score(fish_data, fish_target)
7.4 임의 데이터로 예측하기
kn20.predict([[30, 600]])
7.5 모델의 성능이 가장 좋은 시점 확인하기
훈련 정확도가 '1'(과대적합) 미만이면서 가장 좋은 훈련 정확도를 보이는 시점을 확인한다. 이웃의 갯수는 '다수결 원칙'에 용이한 홀수(3 이상)로 지정한다.
kn = KNeighborsClassifier()
kn.fit(fish_data, fish_target)
# 정확도가 가장 높을 때, 이웃의 갯수를 담을 변수
nCnt = 0
# 정확도가 가장 높을 때, 값을 담을 변수
nScore = 0
# 학습 데이터의 갯수만큼 이웃의 갯수를 지정하여, 정확도 확인
for n in range(3, len(fish_data), 2) :
kn.n_neighbors = n
score = kn.score(fish_data, fish_target)
# '1' 미만이면서 가장 높은 정확도인 경우
if score < 1 :
if nScore < score :
nScore = score
nCnt = n
print(f"nCnt = {nCnt} / nScore = {nScore}")
7.5.1 해석
- KNN 분류모델의 성능을 최적화 하기 위한 하이퍼파라메터 튜닝결과, 이웃의 갯수를 '19'로 조정하였을 때 가장 좋은 성능을 발휘하는 것으로 확인됨
8. 최종 모델 검증
kn.n_neighbors = nCnt
kn.score(fish_data, fish_target)
8.1 임의 데이터를 통해 예측하기
kn.predict([[10, 30]])
8.1.1 해석
- 최종 예측 값이 '0'으로 출력된 것을 보아, 길이와 무게가 각각 10, 30인 생선은 빙어로 판단됨
이번 글에서는 K최근접이웃모델 중, KNN 분류모델에 대해 알아보았다. 다음 글에서는 KNN 회귀모델에 대해 살펴보도록 하겠다.
2023.12.22 - [[파이썬]/머신러닝] - [머신러닝] K최근접이웃모델(KNN) - 회귀분석의 기초(+ 예제)
(머신러닝의 기초 및 학습방법 과정에 대해 궁금하신 분은 아래의 링크를 참고하시길 바란다.)
2023.12.20 - [[파이썬]/머신러닝] - [머신러닝] 머신러닝이란? (Machine Learning, 기계학습)
[머신러닝] 머신러닝이란? (Machine Learning, 기계학습)
본 글에서는 머신러닝이 무엇인지 대해 알아보고자 한다. 차례는 아래와 같다. [차례] 첫 번째, 머신러닝이란? 두 번째, 머신러닝을 사용하는 이유는? 세 번째, 머신러닝의 종류(주도학습 - 회귀,
sungmin93.tistory.com
'[파이썬] > 머신러닝' 카테고리의 다른 글
[머신러닝] 릿지·라쏘모델의 성능비교와 알파값 조정 (0) | 2023.12.25 |
---|---|
[머신러닝] 특성공학을 활용한 다중회귀모델 성능 향상(+예제, 해석, 개념) (0) | 2023.12.24 |
[머신러닝] 선형회귀와 다항회귀 모델링의 이론과 실제 적용 방법(+예제) (1) | 2023.12.23 |
[머신러닝] K최근접이웃모델(KNN) - 회귀분석의 기초(+ 예제) (0) | 2023.12.22 |
[머신러닝] 머신러닝이란? (Machine Learning, 기계학습) (1) | 2023.12.20 |