소스 뷰어
k- 최근접 이웃 분류기¶
- 최근접 이웃 알고리즘은 기존에 가지고 있는 데이터들을 일정한 규칙에 의해 분류된 상태에서 새로운 입력이 들어왔을 때 입력 데이터의 종류를 예측하는 분류 알고리즘이다
- 이 방법은 기존의 학습된 여러 클래스의 샘플들을 각각 좌표로 표시하여 두고, 새로운 미지의 샘플이 입력될 대, 학습 클래스의 샘플들과 새 샘플의 거리가 가장 가까운 (nearest)클래스로 분류한다. 여기서 가갖 가까운 거리는 미지의 샘플화 학습 클래스 샘플 간의 유사도가 가장 높은 것을 의미한다. 이 거리 측정 방법은 샘플의 형태와 종류에 다라서 다양한데, 대포적으로 유클리드 거리(euclidean distance), 해밍 거리(hamming distance)차분 절대값 등을 이용한다.
- 최 근접 이웃 방법 중 가장 많이 사용하는 것은 학습된 클래스들에서 여러 개(k개)의 가가운 이웃을 선출하고 이를 이용하여 미지의 샘플을 분류하는 방법이다. 즉 미지의 샘플과 가까운 이웃으로 선출된 여러 개의 클래스 샘플 중 가장 많은 수를 가진 클래스로 미지의 샘플을 분류하는 방법이다. 이러한 분류 과정을 k-최근접 이웃(K-NN; K-Nearest Neighbors)라고 한다
- k-NN을 사용하기 위해서는 미리 정답을 알고 있는 데이터들이 있어야 한다. 그리고 해당 데이터에 대한 정답을 의미하는 레이브롤 지정해야 한다. 이 과정을 보통 학습 데이터 새성이라고 하낟.
- OpenCV에서 기계학습과 관련된 함수들은 대부분 cv2.ml 모듈에 구현되어 있다. KNN 도 ml 모듈의 KNeares_create() 함수로 Knn 객체를 생성한다. 학습을 위해서는 knn객체 내부 메서드인 train() 함수를 사용한다.
import numpy as np, cv2
def draw_points(image, group, color):
for p in group:
pt = tuple(p.astype(int))
cv2.circle(image, pt, 3, color, cv2.FILLED)
nsample = 50
traindata = np.zeros((nsample*2, 2), np.float32) # 학습 데이터 행렬
label = np.zeros((nsample*2, 1), np.float32) # 레이블
cv2.randn(traindata[:nsample], 150, 30)
cv2.randn(traindata[nsample:], 250, 60)
label[:nsample], label[nsample:] = 0 , 1
K = 7
knn = cv2.ml.KNearest_create() # kNN 클래스로 객체 생성
knn.train(traindata, cv2.ml.ROW_SAMPLE, label) # 학습 수행
points = [(x, y) for y in range(400) for x in range(400) ]
ret, resp, neig, dist = knn.findNearest(np.array(points, np.float32), K) # 분류 수행
colors = [(0, 180, 0) if p==1 else (0, 0, 180) for p in resp]
image = np.reshape(colors, (400,400,3)).astype("uint8")
draw_points(image, traindata[:nsample], color=(0, 0, 255))
draw_points(image, traindata[nsample:], color=(0, 255, 0))
cv2.imshow("sample K="+ str(K), image)
cv2.waitKey(0)