Security_RNRF

머신러닝 기초1 - kNN 이해하기 본문

Project/AI

머신러닝 기초1 - kNN 이해하기

RNRF 2020. 12. 22. 02:18

머신러닝은 컴퓨터나 기계로 하여금 주어진 데이터를 바탕으로 새로운 질문에 대해 예측하는 것을 목적으로 한다.

머신러닝 방법은 크게 지도학습(supervised learning)과 비지도학습(nonsupervised learning)으로 구분할 수 있다.

지도학습은 학습을 위해 주어진 데이터에 어떤 조건을 만족하는 경우, 그에 대한 정답을 미리 제시해둔다. 결국 어떤 규칙에 의한 "룰 기반으로 학습"을 시킨다고 보면 된다.

비지도학습은 학습을 위해 주어진 데이터에 정답을 제시하지 않고 컴퓨터 스스로 알아서 정답을 찾아내는 방법이라 보면 된다. 예를 들어, 승용차, 화물차, 버스 등에 대한 모양을 학습시킨 후, 다양한 차종이 섞여 있는 이미지에서 승용차, 화물차, 버스를 구분하라고 하면 이는 비학습지도가 되는것이다.

kNN은 k-Nearest Neighbours의 약자이며, 지도학습(supervised learning)에 활용되는 가장 단순한 종류의 알고리즘이다. 아래 그림을 보자.

지도학습 예시

이 그림에는 파란색 사각형과 빨간색 삼각형이 흩어져 있다. 파란색 사각형, 빨간색 삼각형은 각각 동일한 특성을 가진 특정 그룹이라고 가정해본다. 예를 들어, 강아지 그룹을 파란색 사각형으로, 고양이 그룹을 빨간색 삼각형으로 말이다.

위 그림에서 파란색 사각형들과 빨간색 삼각형들은 2차원 평면에 불규칙적으로 분포되어 있다. 따라서 파란색 사각형과 빨간색 삼각형은 2가지 특성으로 구분되는 그룹이다. 여기서 말하는 특성이란, 강아지로 분류할 수 있는 특성과 고양이로 분류할 수 있는 특성이 그 예가 될 것이다. 만약 3가지 특성으로 구분되는 것이라면 3차원 공간에 표현해야할 것이다. 이와 같은 공간을 특성 공간(feature space)이라 부른다.

이제 새로운 멤버 초록색 원으로 표현되는 녀석이 하나 등장 했다고 가정한다. 새로운 멤 버는 파란색 사각형 또는 빨간색 삼각형 중 하나가 되야한다. 이 경우 새로운 멤버는 파란색 사각형일까? 아니면 빨간색 삼각형일까요? 이를 분류할 수 있는 한 가지 방법은 새로운 멤버와 가장 가깝게 위치하는 멤버가 속해 있는 그 룹으로 분류하는 것이다. 위 그림의 경우 새로운 멤버는 빨간색 삼각형과 가장 가까이 있으므로, 이 멤버를 빨간색 삼각 형 그룹으로 분류하면 된다. 이와 같이 가장 가까이 존재하는 멤버와 같은 그룹으로 분류하 는 방법을 Nearest Neighbour 라고 한다. 그런데 이 방법에는 약간 문제가 있어 보인다. 위 그림에서 보면 빨간색 삼각형보다 파란색 사각형이 더 많이 분포하고 있고, 특히 새로운 멤 버 근처에 제일 가깝게 있는 녀석은 빨간색 삼각형이지만 조금만 범위를 넓혀 보면 파란색 사 각형이 더 많다. 실선으로 그려진 원으로 범위를 확대하면 파란색 사각형과 빨간색 삼각형 개수가 동일하다. 점선으로 그려진 원으로 범위를 더 확대해보면 파란색 사각형이 빨간색 삼각형보다 더 많이 존재한다. 다시 말하면, 새로운 멤버인 초록색 원과 4번째까지 가까운 멤버들의 분포를 보고 판단하면 파란색 사각형으로 분류할지 빨간색 삼각형으로 분류할지 판단할 수 없다. 조금 더 범위를 확대해서 7번째까지 가까운 멤버들의 분포를 보고 판단하면 초록색 원은 파란색 사각형으로 분류해야 한다. 이와 같이 주어진 개수만큼 가까운 멤버들과 비교하여 판단하는 방법을 k-Nearest Neighbour s 알고리즘이라 부른다. 여기서 주어지는 멤버 개수를 k로 표현한 것이다. k=4이면 파란색 사각형과 빨간색 삼각형 의 개수가 같은 범위이며, k=7이면 파란색 사각형이 더 많은 범위이다. 또 한 가지 고려해야 할 사항은 초록색 원과 거리가 제각각인 멤버들과 동일한 가중치를 두게 되면 이 역시 문제가 된다. 가까운 멤버에는 가중치를 높게, 멀리 떨어져 있는 멤버에는 가중 치를 낮게 해야 바람직하다. 이런 방식의 kNN을 수정된 kNN이라 합니다.

import cv2
import numpy as np
import matplotlib.pyplot as plt

def makeTraindata():
    traindata = np.random.randint(0, 100, (25, 2)).astype(np.float32)
    resp = np.random.randint(0, 2, (25, 1)).astype(np.float32)
    return traindata, resp

def knn():
    traindata, resp = makeTraindata()
    
    red = traindata[resp.ravel()==0]
    blue = traindata[resp.ravel()==1]
    plt.scatter(red[:,0], red[:,1], 80, 'r', '^')
    plt.scatter(blue[:,0], blue[:,1], 80, 'b', 's')
    
    newcomer = np.random.randint(0, 100, (1, 2)).astype(np.float32)
    plt.scatter(newcomer[:,0], newcomer[:,1], 80, 'g', 'o')
    plt.show()
    
    knn = cv2.ml.KNearest_create()
    knn.train(traindata, cv2.ml.ROW_SAMPLE, resp)
    ret, results, neighbours, dist = knn.findNearest(newcomer, 3)
    
    print(results, neighbours)
    
    return

knn()

이 코드는 0~100 범위에서 2차원 좌표로 된 25개의 멤버를 랜덤하게 생성하고, 각 멤버들을 랜덤하게 클래스0(빨간색 삼각형으로 표시), 클래스1(파란색 사각형으로 표시)로 구분한다. 그런 후 새로운 멤버를 랜덤하게 생성하고 kNN 방법으로 k=3(빨간색, 파란색, 초록색)일 때 이 멤버가 어느 클래스에 속하는지 알아보는 것이다.

코드 결과

코드를 실행해보니 위 그림과 같이 파란색 사각형(클래스1)과 빨간색 삼각형(클래스0)이 분포하였고, 새로 등장한 초록색 원이 오른쪽 약간 위쪽에 나타난다.

코드 실행 결과는, [[1 .]] [[1. 1. 1.]] 로 나오는데, [[1. ]]은 초록색 원이 클래스1(파란색)에 속하며, [[1. 1. 1.]]은 초록색 원 주위에 가까운 이웃 멤버는 클래스0(빨간색) 멤버가 1개([[1. 1. 1.]]에 0이 1개), 클래스1(파란색) 멤버가 2개 있다라는 의미이다.

Comments