Image Classification

 

우리가 Image classification을 수행한다고 생각해보자. 어떻게 해야 할까?

 

우선 이미지를 입력 받아야 할 것이다.

 

고양이 사진을 예로 들자.

 

우리 Image classification 시스템에는 미리 정해놓은 카레고리 집합이 존재한다.

 

개, 고양이, 자동차 등이 있을 수 있다.

 

이제 우리 알고리즘은 입력된 고양이 사진을 어떤 카테고리에 속할 지 정하는 일을 해야한다.

 

인간은 시각 인식 테스크에 고도화되어 있기에 매우 쉬워 보일수도 있지만

 

컴퓨터(기계) 입장에서는 매우 어려운 작업일 수 밖에 없다.

 

 

컬러 Image는 보통 3개의 채널을 가지고 있다

 

컴퓨터가 고양이 사진을 볼 때는 고양이라고 판단하지 못한다. 단지 해상도 크기의 숫자 집합으로 밖에 보이지 않는다.

 

거대한 숫자 집합에 불과하다.

 

각 픽셀은 red, green, blue 채널의 3개의 숫자로 표현된다. 

 

이 거대한 숫자 집합에서 '고양이' 라는 것을 인식하기는 상당히 어려운 일이다.

 

이러한 것을 '의미론적 차이(semantic gap)이라고 한다.

 

위 사진이 고양이라는 사실과 컴퓨터가 보는 픽셀 값과는 큰 차이가 있다.

 

 

Viewpoint Variation

 

고양이 사진에 작은 변화만 주더라도 픽셀 값들은 대부분 변하게 된다.

 

고양이를 촬영하는 카메라를 조금만 옆으로 옮겨도 모든 픽셀값들은 달라지게 된다.

 

하지만 달라진 픽셀 값에도 여전히 고양이라는 사실은 변하지 않는다.

 

우리가 만들려는 알고리즘은 이러한 변화에 강인해야 한다.

 

 

Illumination

 

바라보는 방향 뿐만 아니라 외부 조명 또한 문제가 될 수 있다.

 

장면에 따라 조명이 천차만별로 달라지게 된다.

 

어두운 곳에든 밝은 곳이든 고양이라는 사실이 변하지 않는다.

 

이러한 조명 변화에도 강인한 알고리즘을 설계해야 한다.

 

 

Deformation

 

고양이를 객체라고 표현하면 객체의 변형이 다양할 수 있다.

 

다양한 자세에도 불구하고 고양이는 고양이다.

 

이 또한 강인해야 한다.

 

 

Occlusion

 

가려지는 것도 문제가 될 수 있다. 사람은 고양이의 일부만 보아도 고양이라는 사실을 바로 알 수 있다.

 

가려져도 고양이는 고양이인 것이다.

 

우리의 알고리즘은 이러한 가림에도 강인해야 한다. 아주 어려운 문제일 수 있다.

 

 

Background Clutter

 

고양이가 배경과 비슷해도 문제가 발생한다.

 

사람은 금방 눈치챌 수 있지만 기계는 그렇지 못하다.

 

이러한 문제도 다뤄야만 한다.

 

 

Intraclass Variation

 

하나의 클래스 내에서도 다양성이 존재한다.

 

'고양이'라는 개념으로 모든 고양이의 다양한 모습들을 내포해야 한다.

 

고양이에 따라 다양한 생김새, 크기, 색, 나이 등이 전부 다르다.

 

알고리즘은 이러한 다양성도 강인해야 한다. 이러한 문제들은 매우 어렵다.

 

앞서 말한 여러 문제들을 전부 다룰 수 있는 알고리즘이며, 고양이뿐만 아니라 다양한 객체를 인식해야 한다면

 

이는 아주 어려운 문제일 것이다.

 

하지만 일부 제한된 상황을 가정한다며, 잘 동작할뿐만 아니라

 

수행 속도도 몇 ms 걸리지 않는 인간과 비슷한 수준의 알고리즘이 존재할 수 있다.

 

 

Image Classifier

 

Image Classifier API 코드를 작성한다고 가정해보자.

 

위의 그림처럼 python 메서드를 작성해보지 않을까 싶다.

 

이미지를 입력받고 어떤 마법같은 일을 수행하면 해당 이미지의 알맞은 클래스를 반환하는 것이다.

 

하지만 이를 구현하기 위한 적절한 코드가 딱히 없을 것이다.

 

만약, 우리가 '숫자 정렬'이나 'convex hull 계산' 등의 문제를 풀어야 한다면,

 

우리는 알고리즘을 하나씩 작성하면서 필요한 모든 과정을 나열할 수 있을 것이다.

 

하지만 image classification의 경우, 그런 직관적이고 명시적인 알고리즘이 존재하지 않는다.

 

우리는 위의 함수를 만들려고 할때 이러한 문제를 맞이하게 된다.

 

 

Find Edge?

 

기계학습이 등장하기 전에는 객체 인식을 하기위해 룰 기반의 코드를 만들어왔다.

 

예를들어 고양이는 두 개의 귀와 하나의 코가 있다는 것을 알고 있고,

 

Hubel과 Wiesel 연구에서 edge가 중요하다는 것도 알고 있다.

 

그렇다면 이미지의 edge를 계산하는것을 시도해볼만 하다.

 

그리고 다양한 corner와 edge들을 각 카테고리로 분류한다.

 

가령 세 개의 선이 만나는 점을 corner라고 했을 때, 귀는 여기에 corner 한개, 저기에 corner 한개 등등

 

이런식으로 고양이를 인식하기 위해 '명시적인 규칙 집합'을 써내려 가는 방법이다.

 

하지만 이러한 방법은 잘 동작하지 않는다.  이러한 알고리즘은 위에 나열했던 문제들에 강인하지 못하다.

 

또 다른 문제는 고양이가 아닌 강아지를 인식한다고 했을 때 또 다른 규칙에 대해 작성해야 한다.

 

다른 객체들에 대해서도 마찬가지로 재작성해야한다.

 

이러한 방법은 확장성이 전혀 없는 방법들이다.

 

이 세상에 존재하는 다양한 객체들에게 유연하게 적용할 수 있는 확장성이 있는 알고리즘을 만들어야 한다.

 

 

Data-Driven Approach

 

이러한 알고리즘을 가능하게 하는 하나의 insight는 '데이터 중심 접근방법(data-driven approach)이다.

 

고양이는 무엇이다, 강아지는 무엇이다, 자동차는 무엇이다, 이렇게 직접 어떤 규칙을 설계하는 것 대신에

 

인터넷에서 많은 양의 고양이, 강아지, 자동차 데이터를 수집한다.

 

이러한 방대한 데이터를 수집하려면 상당히 많은 시간과 노력이 필요하지만,

 

요즘은 손쉽게 사용할 수 있는 고퀄리티의 데이터셋들이 많이 있다.

 

이러한 데이터셋을 이용해서 machine learning classifier를 학습시킬 수 있다.

 

ML 알고리즘은 어떤 식으로든 데이터를 잘 요약해서 다양한 객체들을 인식할 수 있는 모델을 만들어낸다.

 

그리고 만들어진 모델로 새로운 이미지를 테스트하면 고양이인지 강아지인지 등 객체를 잘 인식할 수 있다.

 

이러한 관점으로 보면 만들려는 API는 위의 그림처럼 변할 수 있다.

 

하나는 train 함수이다. 입력은 이미지와 해당 레이블이고 출력은 학습 모델이 된다.

 

또 다른 하나는 predict 함수이다. 입력이 학습 모델과 테스트 이미지이고 출력은 예측 레이블이 된다.

 

이는 machine learning의 key insight이다. 이러한 key insight는 지난 10-20년간 아주 잘 동작했다.

 

data-driven approach는 deep learning 뿐만아니라 아주 일반적인 개념이다.

 

심플한 classifier를 한번 살펴보자.

 

 

Nearest Neighbor

 

NN 알고리즘은 아주 심플하다.

 

train 단계에서는 모든 학습 데이터를 기억하는 일만 한다.

 

predict 단계에서는 새로운 이미지가 입력되면

 

새로운 이미지와 기존의 학습 데이터를 비교해서

 

가장 유사한 학습 이미지의 레이블로 출력한다. 아주 심플하다.

 

좀 더 구체적으로 살펴보기 위해 CIFAR-10 데이터셋을 살펴보자.

 

 

CIFAR10 Dataset

 

CIFAR-10은 ML에서 자주 쓰이는 테스트용 데이터셋이다.

 

비행기, 자동차, 새, 고양이 등 총 10가지 클래스가 있다.

 

10가지 각 카테고리가 있고 총 50,000장의 학습용 이미지가 있다.

 

50,000장의 학습용 이미지는 각 카테고리에 균일하게 분포되어 있다.

 

10,000장의 테스트 이미지도 존재한다.

 

위 그림의 오른쪽에서 맨 왼쪽 열은 테스트 이미지이다.

 

그의 오른쪽 방향으로는 학습 이미지들 중 테스트 이미지와 유사한 순서대로 정렬된 이미지이다.

 

테스트 이미지와 학습 이미지를 비교해보면, 눈으로 보기에는 상당히 비슷해보인다.

 

참고로 이미지는 32x32로 상당히 작다.

 

두 번째 행의 이미지는 흰색 강아지이다. 그리고 그 오른쪽으로 가장 가까운 이미지도 강아지를 나타낸다.

 

하지만, 두번째, 세번째 등 그 오른쪽들을 보면 사슴이나 말과 같아 보이는 이미지들도 존재한다.

 

강아지는 아니지만 이미지 중간에 흰색 객체가 있는 등의 눈으로 보기에도 비슷한 경향을 보인다. 

 

이렇든 NN 알고리즘은 학습 데이터셋에서 가장 가까운 샘플을 찾게 된다.

 

이렇게 찾은 샘플의 레이블 또한 알 수 있다.

 

왜냐하면 찾은 샘플 데이터는 학습 데이터이기 때문에 레이블을 미리 알고 있다.

 

NN 알고리즘이 잘 동작하지 않을 것 같지만, 그럼에도 불구하고 해볼만한 좋은 예제라고 할 수 있다.

 

 

Distance Metric to Compare Images

 

여기에서 중요한 점은 이미지가 쌍으로 존재할 때 어떻게 비교할 것인가 이다.

 

테스트 이미지 하나를 모든 학습 데이터와 비교할 때 여러가지 비교 방법들이 있다.

 

정확하게 말하면 '어떤 비교 함수를 사용할지'에 달려있다.

 

위의 그림에서는 L1 distance를 사용했다. Manhattan distance라고도 한다.

 

이미지를 pixel-wise로 비교한다. 예를 들어 4x4 테스트 이미지에서

 

학습 이미지의 같은 자리의 픽셀을 서로 빼고 절대값을 계산한다.

 

이렇게 픽셀 간 차이를 계산하고 모든 픽셀의 수행 결과를 모두 더한다.

 

image classification 문제에서 이러한 방법은 별로일 것 같지만 연습삼아 해보는것이 좋다.

 

위의 예제에서는 두 이미지간의 차이는 '456' 을 나타낸다.

 

 

Nearest Neighbor Classifier

 

NN classifier를 구현한 python 코드는 짧고 간결하다.

 

numpy에서 제공하는 vectorized operations를 이용했기 때문이다.

 

train 함수의 경우 위에 언급한대로 단지 학습 데이터를 기억하는 일만 한다.

 

predict 함수에서는 테스트 이미지를 입력받고 L1 distance로 비교한다.

 

학습 데이터들중에 테스트 이미지와 가장 유사한 이미지를 찾는다.

 

이 간단한 classifier에 대한 몇 가지 궁금증이 생길 수 있다.

 

첫번째, 학습 데이터셋의 이미지가 총 N개라면 train/predict(test) 함수의 속도는 어떻게 될까?

 

일단 train time은 상수시간 O(1)이다. 데이터만 기억하면 되기 때문이다.

 

포인터를 잘 이용해서 복사를 하게 되면, 데이터 크기에 관계없이 상수시간으로 끝낼 수 있다.

 

하지만 test time은 N개의 학습 데이터 전부를 테스트 이미지와 비교해야만 한다. 상당히 느린 작업이다.

 

이는 우리가 기대하는 것과 다르다 (train time < test time)

 

우리는 train time은 조금 느려도 되지만 test time은 빠르길 원한다.

 

예를들어 어떤 classifier를 학습시키고 있다고 생각해보면

 

좀 더 좋은 성능을 얻기 위해 train time에 많은 시간을 쏟을 수 있다.

 

classifier는 test time 관점에서 생각해보면 

 

이 모델이 휴대폰이나, 브라우저 등 low power device에서 동작해야 할 수도 있다.

 

이러한 상황에서는 classifier가 test time에서 빠른 성능을 보장할 수 있어야 한다.

 

이런 관점에서 NN 알고리즘은 정반대의 경우이다.

 

CNN과 같은 parametric model들은 NN과 정반대이다.

 

train time은 엄청 오래 걸릴지 모르나 test time은 엄청 빠르다.

 

 

Decision Region

 

그렇다면 NN 알고리즘을 실제로 적용해 본다면 어떻게 생겼을까?

 

위의 그림은 NN 알고리즘의 'decision regions'을 나타낸다.

 

2차원 평면 상의 각 점은 학습 데이터이다. 점의 색은 클래스 레이블(카테고리)이다.

 

위의 예제에서는 클래스가 5개이다.

 

차원 평면 내의 모든 좌표에서 각 좌표가 어떤 학습 데이터와 가장 가까운지 계산한다.

 

그리고 각 좌표를 해당 클래스로 분류한다.

 

하지만 이 classifier는 그다지 좋지 않다.

 

예를들어 가운데를 보면, 대부분 초록색 점들인데 중간에 노란 점이 껴있다.

 

NN 알고리즘은 '가장 가까운 이웃' 만을 보기 때문에, 녹색 무리 한 가운데 노란색 영역이 생겨 버린다.

 

사실은 노란색이 아닌 초록색 영역이여만 한다.

 

이와 비슷하게 근처에 초록색 영역이 파란색 영역을 침범하고 있다.

 

이는 잡음(noise)이거나 가짜(spurious)일 수 있다.

 

이러한 문제들이 발생하기 때문에 NN의 좀 더 일반화된 버전인 k-NN 알고리즘이 탄생했다.

 

 

K-Nearest Neigbors

 

단순하게 가장 가까운 이웃만 찾는것이 아닌 distance metric을 이용해서 가까운 이웃을 K개 만큼 찾고,

 

이웃끼리 투표하는 방법이다. 그리고 가장 많은 표를 획득한 레이블로 예측한다.

 

투표 방법들도 거리별 가중치를 고려한다거나 다양하게 존재하지만

 

가장 잘 동작하면서 쉬운 방법은 득표수만 고려하는 방법이다.

 

위의 세개의 예제는 동일한 데이터를 사용한 K-NN 분류기들이다.

 

각각 K=1, 3, 5에서의 결과이다.

 

K=3을 보면 초록색 영역에서 자리 잡았단 노란색 영역이 깔끔하게 사라진 것을 볼 수 있다.

 

왼쪽의 빨강/파랑 사이의 뾰족한 경계들도 점차 부드러워지는 것을 볼 수 있다. 다수결의 힘이라고 볼 수 있다.

 

K=5를 보면 파란/빨간 영역의 경계가 부드럽고 좋아졌다.

 

대체 NN 분류기를 사용하면 K는 적어도 1보다는 큰 값을 사용한다.

 

왜냐하면 K가 1보다 커야 decision region가 더 부드러워지고 더 좋은 결과를 보이기 때문이다.

 

 

Result by using K-NN

 

이미지 분류를 다루는 문제에서 K-NN을 사용하는 전략은 그다지 좋은 방법이 아니다.

 

cifar-10에서 K-NN을 사용한 결과이며, 잘 분류된 것은 초록색, 아닌것은 빨간색으로 표기하였다.

 

성능이 별로 좋지 않다.

 

K값을 높이면 어떻게 될까? 가장 가까운 이웃 뿐만 아니라 top3, top5 혹은 모든 행(row)을 사용하면 어떻게 될까?

 

더 많은 이웃들이 투표에 참여하면 각종 잡음에 조금 더 강인해질 것으로 추측할 수 있다.

 

 

K-Nearest Neighbors: Distance Metric

 

K-NN을 사용할 때 결정해야 할 사항이 한 가지 있다. 서로 다른 점들을 어떻게 비교할 것인가이다.

 

지금까지는 L1 distance를 사용했다. 픽셀 간 차이의 절대값의 합이다.

 

하지만 L2 distance, Euclidean distance를 사용할수도 있다. 픽셀간 차의 제곱의 합의 루트를 거리로 이용하는 방법이다.

 

어떤 거리 척도(distance metirc)을 선택할 지는 흥미로운 주제이다.

 

왜냐하면 서로 다른 척도에서는 해당 공간의 근본적인 기하학적 구조 자체가 서로 다르기 때문이다.

 

 

L1/L2 distance in K-NN

 

어떤 거리 척도를 사용하는지에 따라 실제 기하학적으로 어떻게 변하는지 위의 그림을 통행 알 수 있다.

 

모두 동일한 데이터를 사용했다. 단지 왼쪽은 L1 distacne, 오른쪽은 L2 distance를 사용했다.

 

결과를 보면 거리 척도에 따라 결정 경계의 모양 자체가 달라짐을 알 수 있다.

 

 

Hyperparameters

 

어떻게 하면 주어진 문제와 데이터에 꼭 맞는 모델을 찾을 수 있을까?

 

K-NN에서 K와 거리척도를 '하이퍼파라미터'라고 한다.

 

하이퍼파라미터는 train time에 학습하는 것이 아니기 때문에 학습 전 사전에 반드시 선택해야 한다.

 

데이터로 직접 학습시킬 방법이 없다.

 

(음 하이퍼파라미터도 학습을 통해 최적을 구하는 논문이 있는것으로 알고 있다,

근데 요즘 논문이나 코드들을 보면 아직까지 메뉴얼하게 정하는거 보면 딱히 효율이 없는거 같기도)

 

하이퍼파라미터를 정하는 일은 문제 의존적(problem-dependent)이다.

 

가장 간단한 방법은 데이터에 맞게 다양한 하이퍼파라미터 값을 시도해 보고 가장 좋은 값을 찾는 것이다.

 

단지 여러가지 시도를 해보고 좋은 것을 선택하는 것이다.

 

하지만 하이퍼파라미터 값들을 실험해 보는 작업도 다양하다.

 

'다양한 하이퍼파라미터를 시도해 보는 것'과

 

'그 중 최고를 선택하는 것'은 어떻게 할까?

 

 

Setting Hyperparameters

 

가장 먼저 떠올릴 수 있는 아이디어는 매우 단순하다.

 

'학습 데이터의 정확도와 성능'을 최대화하는 하이퍼파라미터를 선택하는 것이다.

 

이 방법은 정말 끔직한 방법이다. 절대로 이렇게 해서는 안된다.

 

예를 들어 NN 분류기에서 K=1일때 학습 데이터를 가장 완벽하게 분류한다.

 

학습 데이터의 정확도와 성능 측면에서 K=1일때가 최고이기 때문이다.

 

하지만 앞서 보았듯이 실제 K를 더 큰 값으로 선택하는 것이 학습 데이터에서는 몇 개 잘못 분류 할 수 있겠지만,

 

학습 데이터에 없던 테스트 데이터에 대해서는 더 좋은 성능을 보일 수 있다.

 

궁극적으로 기계학습에서는 학습 데이터를 얼마나 잘 분류하는지는 중요하지 않다.

 

우리가 학습시킨 분류기가 한번도 본 적 없는 데이터를 얼마나 잘 예측하는지가 중요하다.

 

그렇기 때문에 학습 데이터에 대해서만 정확도와 성능을 신경쓰는 것은 최악이다.

 

또 다르게는, 전체 데이터셋 중 학습 데이터를 쪼개서 일부를 테스트 데이터로 사용하는 것이다.

 

학습 데이터로 다양한 하이퍼파라미터 값들을 학습을 시키고

 

테스트 데이터로 적용시킨 다음, 하이퍼파라미터를 선택하는 방법이다.

 

이 방법이 좀 더 합리적인 방법 같지만, 이 또한 쓰면 안되는 방법이다.

 

기계학습은 궁긍적으로 한번도 보지 못했던 데이터에서 잘 동작해야한다.

 

하지만 학습시킨 모델 중 테스트 데이터에만 가장 잘 맞는 모델을 선택한다면

 

이는 그저 가지고 있는 테스트셋에서만 잘 동작하는 하이퍼파라미터를 고른 것일수 있다.

 

좀 더 일반적인 방법은 데이터를 세 개로 나누는 것이다.

 

데이터의 대부분을 트레이닝셋, 일부는 밸리데이션셋, 일부는 테스트셋으로 나눈다.

 

그리고 다양한 하이퍼파라미터를 트레이닝셋으로 학습시킨다.

 

그리고 벨리데이션셋으로 검증한다. 그리고 벨리데이션에서 가자 좋았던 하이퍼파라미터를 선택한다.

 

최종적으로 개발/디버깅 등 모든 일을 마친 후에 밸리데이션셋에서 가장 좋았던 분류기를 가지고

 

테스트셋에서는 오직 한번만 수행한다.

 

이 마지막 수치가 논문과 보고서 등에 삽입되는 것이다.

 

실제로 벨리데이션 데이터와 테스트 데이터를 엄격하게 나눠놓는 것은 상당히 중요하다.

 

 

Cross-Validation

 

또 다른 하이퍼파라미터 선택 전략은 교차 검증(cross-validation)이다.

 

이 방법은 작은 데이터셋일 경우 많이 사용하고, deep learning에서는 많이 사용하지는 않는다.

 

교차 검증은 우선 테스트 데이터를 정해 놓는다. 이는 마지막에만 사용된다.

 

그리고 나머지 데이터를 트레이닝/벨리데이션으로 딱 나눠놓는 대신에

 

위의 그림처럼 트레이닝 데이터를 여러 부분으로 나눈다.

 

이런 식으로 번갈아가면서 벨리데이션셋을 지정해준다.

 

위의 그림은 5-Fold cross-validation을 사용하고 있다.

 

처음 4개의 fold에서 하이퍼파라미터를 학습시키고 남은 한 fold에서 알고리즘을 평가한다.

 

그리고 1, 2, 3, 5 fold에서 다시 학습시키고, 4 fold로 평가한다. 이런식으로 계속 순환한다.

 

이를 방식을 통해 최적의 하이퍼파라미터를 확인할 수 있다.

 

이런 방식이 거의 표준이긴 하지만 실제로 deep learning과 같은 큰 모델에서 학습시킬 때는

 

학습 자체가 계산량이 많기 때문에 실제로는 잘 쓰지 않는다.

 

(coco dataset으로 cross-validation한다고 생각하면 끔직하다)

 

 

Example of 5-fold cross-validation

 

위의 그래프는 5-fold 교차 검증을 수행한 결과이다. x축은 K-NN의 K이다. y축은 분류 정확도이다.

 

각 K마다 5번의 교차 검증을 통해 알고리즘이 얼마나 잘 동작하는지 보여준다.

 

'테스트셋이 알고리즘 성능 향상에 미치는 영향'을 알아보려면 K-fold 교차검증이 도움이 될 수 있다.

 

여러 validation fold 별 성능의 분산(variance)을 고려할 수 있다.

 

분산을 같이 계산하게 되면, 어떤 하이퍼파라미터가 가장 좋은지 뿐만 아니라, 그 성능의 분산도 알 수 있다.

 

하이퍼 파라미터에 따라 모델의 정확도와 성능을 평가할 수 있다.

 

그리고 벨리데이션셋의 성능이 최대인 하이퍼파라미터를 선택하게 된다.

 

위의 그림에서는 K=7인 경우에 가장 좋은 성능을 나타낸다.

 

 

k-Nearest Neighbor on images never used

 

하지만 실제로 입력이 이미지인 경우에는 k-NN 분류기는 잘 사용하지 않는다.

 

앞서 말한 문제들 때문이다.

 

한가지는 너무 느리기 때문이다.

 

또 하나는 L1/L2 거리척도가 이미지들간의 거리를 측정하기에는 적절하지 않다는 점이다.

 

이 벡터간의 거리 측정 관련 함수들은 이미지들 간의 '지각적 유사성'을 측정하는 척도로는 적절하지 않다.

 

위의 그림을 보면 원본 이미지와 세개의 왜곡된 이미지를 볼 수 있다.

 

눈과 입을 가리거나, 픽셀을 이동시키거나, 파란색 색조를 추가한 것이다.

 

이 왜곡된 이미지들과 원본과의 L2 distance를 측정해보면 모두 동일하게 계산된다.

 

이는 L2 distance가 이미지들간의 '지각적 유사도'를 측정하기에는 적합하지 않다는 의미가 된다.

 

 

Curse of Dimensionality

 

k-NN의 또 다른 문제 중 하나는 '차원의 저주'이다.

 

k-NN은 학습 데이터를 이용하여 공간을 분할했다.

 

이는 k-NN이 잘 동작하라면 전체 공간을 조밀하게 커버할 만큼의 충분한 학습 데이터 샘플이 필요하다는 것을 의미한다.

 

그렇지 않다면 이웃이 엄청 멀 수도 있으며, 그렇게 된다면 테스트 이미지를 제대로 분류할 수 없을 것이다.

 

공간을 조밀하게 구성하려면 충분한 양의 학습 데이터가 필요하고

 

그 양은 차원이 증가함에 따라 기하급수적으로 증가한다.

 

이는 아주 좋지 않은 현상이다. 기하급수적으로 증가하는 것은 언제나 옳지 못하다.

 

위의 그림에서 각 점은 학습 데이터 샘플을 의미한다. 점 하나하나가 학습 샘플이다.

 

각 점의 색은 학습 샘플이 속한 카테고리를 나타낸다.

 

맨 왼쪽 1차원 공간을 조밀하게 덮으려면 학습 샘플 4개면 충분하다.

 

2차원 공간을 다 덮으려면 16개가 필요하다. 1차원의 4배이다.

 

이렇게 3, 4, 5차원 같이 고차원을 고려해보면 각 공간을 조밀하게 덮기 위한 필요한 학습 샘플 수는

 

차원이 늘어남에 따라 기하급수적으로 증가하게 된다.

 

Linear Classifier

linear classifier는 간단한 알고리즘이다. 아주 중요하고 NN과 CNN의 기반이 되는 알고리즘이다.

 

어떤 사람들은 NN를 레고 블럭에 비유한다.

 

NN을 설계할 때 다양한 컴포넌트를 사용할 수 있다.

 

이 컴포넌트들을 모아서 CNN이라는 거대한 타워를 지을 수 있다.

 

앞으로 보게 될 다양한 종류의 딥러닝 알고리즘들의 가장 기본이 되는 블록 중 하나가 바로 linear classifier이다.

 

그렇기 때문에 linear classifier가 어떻게 동작하는지 정확히 이해하는것이 아주 중요하다.

 

왜냐하면 linear classifier가 결국은 전체 NN을 아우르게 될 것이기 때문이다.

 

Image Captioning

위의 그림은 NN의 구조적인 특성을 설명하는 image captioning 예시이다.

 

image captioning에서는 입력이 이미지이고, 출력이 이미지를 설명하는 문장이 된다.

 

이미지를 인식하기 위해 CNN을 사용한다.

 

그리고 언어를 인식하기 위해 RNN을 사용한다.

 

이렇게 두 개(CNN+RNN)을 레고 블록처럼 붙이고 한번에 학습시킨다. 그렇게 되면 이런 어려운 문제도 해결할 수 있다.

 

여기서 중요한 점은 NN이 레고 블록과 같다는 것이고 linear classifier가 기본 블록이 된다는 것이다.

 

CIFAR-10

cifar-10을 다시 상기시켜보자.

 

50,000장의 학습 데이터, 10,000장의 테스트 데이터가 있고,

 

각 이미지는 32x32 픽셀을 가진 3채널 컬러 이미지이다.

 

Parametric Approach: Linear Classifier

linear classifier에서는 k-NN과는 조금 다른 접근 방법을 이용한다.

 

linear classifier는 'parametric model'의 가장 단순한 형태이다.

 

parametric model은 두 개의 요소가 있다.

 

위의 그림을 보면 입력으로 고양이 이미지가 있다.

 

이 입력 이미지를 보통 'X'로 표현한다.

 

파라미터, 즉 가중치는 문헌에 따라 다르지만 'W'라고도 하고 세타(theta)라고도 한다.

 

이제 어떤 함수 F를 만들어야 하는데, 이 함수는 입력을 X와 W로 하고, 10개의 숫자를 출력으로하는 함수이다.

 

10개의 숫자는 cifar-10의 각 카테고리별 스코어가 된다.

 

예를 들어, '고양이'의 스코어가 높다는 건 입력 X가 '고양이'일 확률이 크다는 것을 의미한다.

 

앞의 k-NN은 이러한 파라미터가 없었다.

 

단순히 전체 학습 데이터셋을 기억하고, 모든 학습 데이터셋을 predict에 사용했다.

 

하지만 parametric approach에서는 학습 데이터셋의 정보를 요약한다.

 

그리고 그 요약된 정보를 파라미터 W에 저장한다.

 

이런 방식을 사용하면 predict(test) time에 더 이상의 학습 데이터가 필요하지 않게된다.

 

test time에서 파라미터 W만 있으면 된다.

 

이 방법은 휴대폰과 같은 low power 디바이스에서 모델을 동작시켜야할때 매우 효율적이다.

 

그렇기 때문에 딥러닝은 바로 이 함수 F의 구조를 적절하게 설계하는 일이라고 볼 수 있다.

 

어떤 식으로 가중치 W와 데이터를 조합할지 여러가지 복잡한 방법으로 고려해볼 수 있는데,

 

이 과정들이 모두 다양한 NN 아키텍처를 설계하는 과정이 된다.

 

가중치 W와 데이터 X를 조합하는 가장 쉬운 방법은 단순히 둘을 곱하는 것이다.

 

이 방법이 바로 linear classification이다.

 

f(x,W) = Wx로 아주 간단한 식이다.

 

입력 이미지는 32x32x3 이다. 이 값을 길게 펴서 column 벡터로 만들면 3,072차원 벡터가 된다.

 

이 3,072차원 column 벡터를 입력으로 10개의 카테고리에 대한 스코어가 출력되야 한다.

 

따라서 파라미터 W는 10x3,072 행렬이 되야한다.

 

X와 W를 곱하면 10개의 카테고리 스코어를 의미하는 10x1 크기의 column 벡터를 얻을 수 있다.

 

'bias' 텀이 있을수도 있다. 바이어스 텀도 10x1 column 벡터이다. 바이어스는 입력에 연결되지 않는다.

 

바이어스느 '데이터와 무관하게' 특정 클래스에 '우선권'을 부여한다.

 

예를 들면 고양이 데이터가 강아지 데이터보다 훨씬 더 많거나 하는

 

데이터의 불균형한 상황에서 

 

고양이 클래스에 해당하는 바이어스가 더 커지도록 학습된다.

 

Example with an Image

입력을 2x2 이미지라고 가정해보자.

 

linear classifier는 2x2 이미지를 입력으로 받고, 이를 column 벡터로 길게 펼친다.

 

위의 예제에서는 고양이, 강아지, 배 이렇게 3개의 클래스만 있다고 가정했을때,

 

가중치 W의 행렬은 4x3 행렬이 된다.

 

추가적으로 3차원 바이어스 벡터가 있다. (1.1, 3.2, -1.2) 

 

바이어스는 데이터와 독립적으로 각 카테고리와 연결된다.

 

고양이 스코어는 입력 이미지의 픽셀 값들과 가중치 W 행렬을 내적(inner product)한 값에 바이어스 텀을 더한 것이다.

 

이러한 관점에서 linear classification은 템플릿 매칭과 거의 유사하다.

 

가중치 행렬 W의 각 행은 각 이미지에 대한 템플릿으로 볼 수 있으며,

 

해당 row 벡터와 이미지의 column 벡터간의 내적을 계산한다.

 

여기서 내적이란 결국 클래스간 템플릿의 유사도를 측정하는 것과 비슷하다.

 

바이어스는 데이터 독립적으로 각 클래스에 scaling offset을 더해주는 것이다.

 

Interpreting a Linear Classifier

템플릿 매칭 관점에서 linear classification을 해석해보자.

 

가중치 행렬 W의 하나의 행을 뽑아서 이를 이미지로 시각화 시켜보면

 

linear classifier가 이미지 데이터를 인식하기 위해 어떤 일을 하는지 짐작할 수 있다.

 

위의 그림은 linear classifier가 cifar-10 이미지를 학습하고

 

가중치 행렬 W의 각 행 벡터를 시각화시킨 그림이다.

 

맨 왼쪽 이미지는 비행이 클래스에 대한 템플릿 이미지이다.

 

하늘과 같이 푸른끼가 많고 가운데에는 어떤 객체가 있는것 같다.

 

이 이미지를 해석해보자면 linear classifier가 비행기를 분류할 때 푸른색인것들을 찾고 있다고 볼 수 있다.

 

이러한 특징들이 비행기를 더 잘 찾을 수 있다고, 가중치 W가 학습했다고 볼 수 있다.

 

하지만 linear classifier의 문제 중 하나는 각 클래스에 대해서 단 하나의 템플릿만을 학습한다는 것이다.

 

한 클래스 내에서 다양한 특징들이 존재할 수 있지만, 이 모든 것들을 평균화 시키기 때문에

 

다양한 모습들이 있더라도 각 카테고리를 인식하기 위한 템플릿은 하나 밖에 없다.

 

말을 분류하는 템플릿을 보면 또 다른 문제를 볼 수 있다.

 

바닥은 초원같이 초록빛을 띄고 있다. 보통 말이 풀밭에 있으니 템플릿이 배경을 초록빛으로 학습한 것이다.

 

그런데 잘 보면 왼쪽, 오른쪽 각각 말 머리가 두 개인것을 볼 수 있다.

 

머리가 두 개인 말은 존재하지 않는다.

 

하지만 linear classifier는 템플릿이 하나밖에 허용되지 않으므로 위의 그림이 최선인 것이다.

 

그래도 NN와 같은 복잡한 모델이라면 조금 더 정확도를 높힐 수 있을 것이다.

 

클래스당 하나의 템플릿만을 학습할 수 있다는 것과 같은 제약조건이 없을 경우라면 말이다.

 

Interpreting a Linear Classifier

linear classifier를 또 다른 관점에서 해석할 수 있다.

 

이미지를 고차원 공간의 한 점으로 보는 것이다.

 

linear classifier는 각 클래스를 구분하는 선형 결정 경계를 그어주는 역할을 한다.

 

맨 왼쪽 비행기의 예를 보자.

 

linear classifier는 파란색 선을 학습해서 비행기와 다른 클래스를 구분할 수 있다.

 

임의의 값으로 초기화된 가중치 W가 데이터를 잘 분류하려고 학습되는 모습을 보면 아주 재밌다.

 

하지만 이미지가 고차원 공간의 하나의 점이라는 관점에서 해석해보면

 

linear classifier가 직면할 수 있는 문제가 있다.

 

Hard cases for a linear classifier

linear classifier를 망칠 수 있는 예제를 만드는 것은 간단하다.

 

맨 왼쪽 그림을 보면,

 

파란색 카테고리는 0보다 큰 픽셀의 개수가 홀수인 경우이다. ([3, -1]이면 0보다 큰 수 : 3 (1개, 홀수) -> 파랑)

 

빨간색 카테고리는 0보다 큰 픽셀의 개수가 짝수인 경우이다.

 

좌표 평면에 이와 같은 규칙으로 그리면 두 개의 사분면은 파란색,

 

또 다른 두 개 사분면은 빨간색 클래스를 볼 수 있다.

 

이 데이터들을 선 하나로 분류할 수 있는 방법은 없다.

 

linear classifier로 풀기 힘든 문제이다.

 

픽셀의 수를 세는 것이 아닌, 사람의 수가 홀수/짝수인지 분류하는 문제도 동일하게 적용된다.

 

linear classifier로 풀기 어려운 또 하나의 문제는 맨 오른쪽 그림의 multimodal 문제이다.

 

위의 말 머리 두개의 예시처럼 왼쪽 머리가 하나의 파란색 원처럼 될 수 있고,

 

오른쪽 머리가 또 하나의 파란색 원처럼 될 수 있다.

 

이러한 경우에도 선을 하나만 그어서는 클래스를 분류할 수 없다.

 

multimodal data라면 한 클래스가 다양한 공간에 분포할 수 있으며,

 

이러한 문제는 linear classifier로는 풀 수 없다.

 

Example Class Scores for 3 Images for some W

지금까지 linear classifier 수식을 살펴보았다.

 

linear classifier가 단순히 행렬과 벡터의 곱의 형태라는 것을 알 수 있었다.

 

템플릿 매칭 관점에서 해석해보면 각 카테고리에 대해 하나의 템플릿을 학습한다는 것을 알 수 있었다.

 

그리고 가중치 행렬 W를 학습시키면 새로운 테스트 데이터에도 스코어를 계산할 수 있다.

 

우리는 아직 가중치 행렬 W를 어떻게 학습하는지 배우지 않았다.

 

단지 linear classifier가 어떻게 구성되어 있고, 어떻게 동작하는지 간단하게 살펴보았다.

+ Recent posts