ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [cs231n] 2강 이미지 분류 (3/4, K-최근접 이웃/ K-Nearest Neighbors)
    AI 2021. 1. 5. 19:59

    손가락처럼 튀어 나온 이런 것들이 이 알고리즘을 일반화하고 싶은 동기를 유발합니다. 그래서 나온 것이 K-최근접 이웃 알고리즘이죠. 하나의 최근접 이웃을 찾기 보다는, 약간 더 멋진 걸 하는데, 거리 메트릭에 따라 K개의 최근접 이웃을 찾아서 투표를 합니다. 이웃중에서요. 그 다음에 가장 많은 표를 가진 이웃이 예측값이 됩니다. 이걸 좀 더 복잡하게 하는 방법도 생각할 수 있죠. 거리에 웨이트를 주는 것 등을 생각할 수 있는데, 가장 간단한게 꽤 잘 됩니다. 그냥 최다 득표를 선택하면 됩니다.

    여기 앞에서 본 것과 같은 점들의 집합이 있는데 K가 1인 분류기와, K가 3일때, K가 5일때가 있습니다. 3일때를 보면, 녹색 안에 있는 이상한 노란 점이 그 주변 영역을 노란색으로 만들지 않습니다. 가운데 녹색 덩어리는 전부 다 녹색으로 구분되죠. 빨강과 파란색의 길게 튀어나온 부분들이 부드럽게 없어지기 시작합니다. 이 다수 득표 알고리즘 때문이죠. 5가되면 파랑과 빨강사이의 결정 경계 (decision boundary)가 매우 부드러워지고 좋아집니다. 그래서 일반적으로 최근접 이웃 분류기를 쓸 땐, 1보다 큰 어떤 K값을 대개의 경우 사용하고 싶을 겁니다. 그래야 결정 경계가 부드러워지고 결과가 좋아집니다.

    컴퓨터 비전을 생각할 때, 여러 개의 다른 관점으로 왔다 갔다해 보는 것이 유용한 데, 하나는 평면에서 높은 차원의 점입니다.

    다른 하나는 구체적인 이미지를 보는 겁니다. 이미지의 픽셀들을 고차원 벡터로 생각할 수 있기 때문이죠. 이 두 가지 관점사이에서 왔다 갔다하는 것이 좋아 보입니다.

    K-최근접 이웃을 가지고, 이미지로 돌아가보면 이게 별로 안 좋은 걸 알게 됩니다. 위 그림에서 빨강이랑 녹색으로 칠한 걸 보면 최근접 이웃에 따라 맞았는지 틀렸는지 나타내고 있는데, 별로 안 좋죠. 만약 더 큰 K를 쓰면, 이건 사실상 top 3나 5 혹은 전체 열 중에서 투표하는 것과 연관될 겁니다. 그럼 이런 노이즈가 있고 이런 식으로 최근접을 도출하는데 있어서, 그게 더 견고하죠.

    K-최근접 이웃으로 작업할 때, 다른 선택해야 할 것은 우리가 어떻게 K-최근접 이웃을 비교하는지를 결정하는 겁니다. 지금까지 예는, L1 거리를 얘기했는데, 픽셀의 차이를 절대값으로 더하는 거립니다. 다른 선택중 흔히 쓰는 것은 L2 혹은 유클리드 거리입니다. 제곱의 합에 제곱근을 구한 거리입니다. 다른 거리 미터법을 선택하는건 매우 재밌는 주제인데, 다른 거리 미터법을 쓴다는 건 다른 가정을 한다는 겁니다. 근간에 깔려 있는 기하학 혹은 위상 공간에서 예상하는 가정이 다르다는 겁니다. 위 그림에서 왼쪽 그림은 사실 L1 거리 원인데, L1 거리에 따르면 원점을 중심으로 한 사각형 모양입니다. 그 사각형 위의 각점은 원점으로부터 같은 거립니다.

    한편, L2, 유클리드에선 이 원이 우리에게 익숙한 원이죠. 

    재밌는 점은 이 두 미터법에서, 특히 L1 거리는 여러분의 좌표 시스템 선택에 의존적이란 겁니다. 만약, 좌표 프레임을 회전하면 L1 거리 점들간의 거리는 변화됩니다. L2에서 좌표 프레임을 변경하는 건 상관이 없습니다. 좌표 프레임이 어떻게 회전하든 거리가 같습니다.

    만약 입력 피쳐 (feature)의 벡터의 각 항목이, 여러분의 작업에 중요한 의미를 가진다면, L1이 자연스럽게 맞는 것일 수 있고, 만약 공간에서의 포괄적인 벡터라면, 혹은 어떤 벡터의 각 항목의 의미를 모른다면, L2가 좀 더 자연스럽죠. 

    다른 거리 미터법을 사용해서, K-최근접 이웃을 일반화할 수 있는데, 벡터나 이미지만이 아니라 매우 다양한 타입의 데이타로 말이죠. 예를 들어, 텍스트 조각을 분류하고 싶다고 하면, K-최근접 이웃을 사용하기 위해서 해야 할 건, 거리 함수를 정의하는 겁니다. 두 단락이나 두 문장 사이의 거리에 대해서요. 단지 다른 거리 미터법을 지정하는 것만으로 이 알고리즘을 매우 일반적으로 만들어서 근본적으로 모든 데이타 타입에 적용할 수 있게 됩니다. 

    이게 단순한 알고리즘이지만, 새로운 문제를 볼 때, 일반적으로 제일 처음 해볼 수 있는 것입니다. 

    우리가 다른 미터법을 고르면, 기하학적으로 어떤 일이 벌어지는 지 생각해 보는 것도 재밌죠. 같은 점 집합들을 보고 있는데, 왼쪽은 L1 맨하탄 거리, 오른쪽은 익숙한 L2, 유클리드 거리를 사용합니다. 이 결정 경계 모양이 이 두 미터법에 따라 약간 변하는걸 볼 수 있죠. L1을 보면, 좌표축을 따라 그어지는 경향을 볼 수 있습니다. L1은 좌표축에 의존적이기 때무이죠, L2는 좌표축을 상관하지 않는 것 같고, 경계가 자연스럽게 그려지고 있네요.

    이 예는 웹 데모에서 가져온 건데, 이 K-최근접 이웃을 여러분 스스로 가지고 놀 수 있습니다. 꽤 재밌고, K를 바꿈에 따라, 거리 미터법을 바꿈에 따라 어떻게 경계가 바뀌는지에 대한 직관을 만들어 줍니다. 

    vision.stanford.edu/teaching/cs231n-demos/knn/

     

    http://vision.stanford.edu/teaching/cs231n-demos/knn/

     

    vision.stanford.edu

     

    케이값을 얘기했고, 다른 미터법도 얘기했습니다. 여러분의 문제와 데이타에 대해서 이것들을 어떻게 선택해야 할까요? K, 거리 미터법 이런 것들 우리는 하이퍼파라미터라고 합니다. 왜냐면 이런 것은 학습으로부터 꼭 배울 수 있다고 할 수 없고, 여러분이 알고리즘에 대해 선택하는 겁니다. 이걸 데이타로부터 직접 배울 방법이 없습니다. 그럼 여러분은 실제로 이걸 어떻게 설정해야 할까요?

    이것들은 문제에 따라 매우 다르다라고 알려져 있습니다. 대부분의 사람들이 사용하는 간단한 방법은 문제에 대해서 여러 하이퍼파라미터 값을 시도해 보고 뭐가 제일 잘 되는지 찾는 겁니다.

    여러 하이퍼파라미터들을 시도해 보고 뭐가 최선인지 본다는 것은 어떻게 한다는 의미일까요?

    생각해 볼 수 있는 첫번째 대답은 여러분 데이터에 대해서 최고의 정확도 혹은 성능을 내는 것을 선택하는거죠.

    이건 사실 진짜 나쁜 아이디어입니다. 절대 하지 마세요. 최근접 이웃의 구체적인 예를 보면, K를 1로 하면 학습 데이터를 완벽하게 분류합니다. 이 전략으로 K를 항상 1로 하면, 앞선 예에서 봤듯이, 실제 예서는 K가 더 큰 값을 가질 수록, 잘못 분류할 수 있지만, 학습 셋에 없는 점에 대해선, 사실은 더 나은 성능을 내죠. 궁극적으로 머신러닝에서는 학습 데이타를 맞추는 것은 신경쓰지 않습니다. 우리는 우리의 분류기 혹은 메소드가 데이타 학습 후에 보지 않았던 데이타에 대해 어떻게 동작하는지에 관심이 있습니다. 이건 매우 안 좋은 아이디어이니 하지 마세요.

    다른 아이디어는 전체 데이타 셋을 훈련 셋과 테스트 셋으로 나누는 겁니다. 그래서 학습 데이타에 대해서 여러 하이퍼파라미터 값으로 알고리즘 학습을 시도하고, 그 다음 학습된 분류기를 테스트 데이터에 적용하고, 테스트 데이타에서 가장 잘 동작한 걸 하이퍼 파라미터 셋으로 선택하죠.

    이게 더 합리적인 전략같죠. 근데 사실, 이것도 끔찍한 아이디어니까 하지 마세요. 테스트 셋에서 요점은 우리의 메소드가 야생에서 오는 보지 않은 데이타에 대해서 어떻게 수행할지 어떤 추측을 제공하는 것인데요. 이 전략을 쓴다는 건, 많은 알고리즘을 많은 하이퍼파라미터로 훈련한다는 것인데, 그 후 테스트 데이타에서 잘 되는 걸 최선의 하이퍼파라미터를 고르는 것이 새로운, 보지 않은 데이터에서 잘 된다는 걸 나타내진 않습니다. 이건 나쁜 아이디어고 이걸 쓰면 곤란해 집니다.

    훨씬 더 많이 사용되는 건, 3개의 셋으로 나누는 겁니다. 데이타의 대부분을 훈련 셋에 넣고, 검증 셋과 테스트 셋을 만드는 거죠. 우리가 전형적으로 하는 방법은, 많은 다양한 하이퍼파라미터를 옵션으로 알고리즘을 훈련셋으로 훈련하고, 검증 셋으로 평가하고, 검증 셋에서 제일 잘되는 하이퍼파라미터 셋을 고르는 겁니다.

    모든 개발과 디버깅을 한 후, 검증 셋에서 제일 잘 되는 분류기를 테스트 셋에서 돌립니다. 이 숫자가 논문과 리포트에 들어가는 거죠. 이 결과가 여러분의 알고리즘이 보지 않은 데이타에 대해서 어떻게 동작할 지를 얘기해 줍니다.

    여러분이 엄격하게 검증 데이타와 테스트 데이타를 나눈다는 건 정말 중요한 것입니다. 예를 들어, 우리가 연구 논문을 쓴다면, 우리는 테스트 셋을 제일 마지막에만 건드립니다. 테스트 셋은 마감시한 직전 주 정도에만 쓰죠. 우리가 남을 속이는 게 아니며 불공정한 숫자를 리포팅하는 게 아니란 것을 확실히 하기 위해서요.

    테스트 데이타를 제어한다는 것은 엄청나게 중요합니다.

    하이퍼 파라미터를 정하는 또 다른 전략은 교차 검증이라는 겁니다. 이건 작은 데이타셋에 더 흔히 사용되는데, 딥러닝에는 별로 사용하지 않습니다. 데이타 셋 중에 마지막 부분을 테스트 셋으로 하고 나머지를 하나의 검증 셋과 훈련 셋 파티션으로 하기 보다는, 여러개로 나누는 겁니다. 이런식으로, 어떤 부분이 검증 셋이 될지 고르는 것을 반복합니다.

    이 예에서는 5 폴드 교차 검증을 사용하는데, 처음에는 하나의 하이퍼파라미터 셋에 대해서 첫 4개의 폴드로 훈련하고, 성능을 폴드 5로 평가하고, 그다음 1, 2, 3, 5로 훈련하고, 폴드4로 평가합니다. 모든 다른 폴드에 대해서도 반복하죠. 이런 식으로 할 때, 어떤 하이퍼파라미터가 더 견고하게 동작하는지에 대해 더 자신감을 갖게 되죠. 요. 골드 스탠다드 (gold standard)인데요. 실제로 딥 러닝에서는, 큰 모델을 훈련할 때, 훈련하는데 드는 컴퓨팅이 비싸기 때문에, 이게 실제로는 많이 안 씁니다.

    이런 교차 검증을 거치게 되면, 위 그림과 같은 그래프를 얻게 됩니다. X 축은, 어떤 문제에 대한 K-최근접 이웃 분류기의 K값이죠. Y 축은 어떤 데이타 셋에서 여러 케이 값에 대해 우리 분류기의 정확도가 뭔지 보여줍니다. 이 경우, 우리는 데이타에 대해서 5 폴드 교차 검증을 했는데, 각 K 값에 대해 우리는 이 알고리즘이 얼마나 잘했는지에 대해 다른 다섯 가지 예를 가지고 있습니다. 다시 질문으로 돌아가면, 여러분의 알고리즘을 위해서 어떤 테스트 셋이 더 좋은지 나쁜지 알기 위해서, K 폴드 교차 검증을 사용하는 것은 그걸 정량화 시키는 걸 도와주는 방법이죠. 그 점에서, 우리는 이 알고리즘의 변화를 보게 됩니다. 이 알고리즘이 어떤 검증 폴드에서 어떻게 작동하는지를 이 결과로 알게 되죠. 최선은 아니지만, 성능의 분포가 어떤 지도 포함해서요. 머신 러닝 모델을 훈련할 때마다, 하이퍼파라미터에 따른 함수로서의 정확도 혹은 성능이 얼마가 나왔는지 보여 주는 이런 플롯을 그리는 것으로 끝나게 될 겁니다. 결국엔 검증 셋에서 제일 잘 동작하는 모델을 선택하거나, 하이퍼파라미터 셋을 선택할 거구요. 여기서는 K가 7일 때, 이 문제에 대해서 제일 잘 동작하네요.

    K-최근접 이웃 분류기는 이미지에 대해서는 거의 사용되지 않고, 사실 문제가 많다는 걸 얘기습니다.

    테스트시 너무 느리다는 문제가 있죠. 우리가 원하는 것은 테스트 시가 더 빠른 것인데요. 다른 하나는 유클리드 거리 혹은 L1 거리 같은 것이 이미지간 거리를 측정하기에 좋은 게 아니라는 거죠. 이 일종의 벡터 거리 함수는 이미지들에 있어서 사람의 인식의 유사성과 일치하지 않습니다. 여러분이 이미지 차이를 인식하는 것과 다릅니다. 이 예에서, 어떤 여자 이미지가 있는데요, 3개의 왜곡된 이미지가 있습니다. 입을 막은 이미지, 몇 픽셀을 아래로 내린 이미지, 파란색 색조를 띄도록 만든 이미지인데요. 원본과 박스를 그린 이미지의 유클리드 거리를 계산해 보면, 원본과 이동한 것, 원본과 색조가 변한 것, 이 모든 것은 같은 L2 거리를 가집니다. 아마도 좋지 않겠죠. 이것으로 이미지 간의 이런 인식적 차이를 잡아내는 데 L2 거리는 좋은 결과를 내지 못한 다는 걸 알 수 있습니다.

    다른 문제는 K-최근접 이웃 분류기에 대한 차원의 저주라는 것과 관련있습니다. K-최근접 이웃에서 가졌던 이 관점을 다시 생각해 보면, 이것은 학습 데이타 주변으로 페인트를 떨어뜨려서 공간을 분리하는데 사용합니다. 무슨 의미냐면, 우리가 K-최근접 이웃 분류기가 잘 동작하길 바란다면, 우리는 이 공간을 꽤 촘촘하게 커버하는 학습 예제가 필요합니다. 그렇지 않으면, 최근접 이웃이 꽤 멀 거고, 테스팅 포인트와 유사하지 않을 수가 있습니다. 공간을 밀도 높게 커버한다는 것은 많은 훈련 예제가 필요하다는 건데, 문제의 차원은 지수로 증가합니다. 이건 정말 안 좋죠. 지수로 증가하는 건 항상 안 좋아요. 이 높은 차원에서는 이 공간을 밀도 높게 커버하는 충분한 이미지를 절대 얻을 수 없을 겁니다. K-최근접 이웃을 사용할 때 기억해야 할 점이죠.

    정리하면, 이미지 분류 아이디어를 소개하기 위해 K-최근접 이웃을 사용했는데요. 우리는 이미지와 레이블로 된 훈련 셋이 있고, 그걸 사용해서 테스트 셋에서 이 레이블을 예측하기 위해 사용했습니다.

    댓글

Designed by Tistory.