저번 시간의 컴퓨터 비전, 그 역사, 수업의 전반적인 내용 소개 시간에 이어서 이번 시간에는 image classification에 대해서, 그리고 앞으로 배우게 될 알고리즘들이 실생활에서 어떻게 적용되는지 심도있게 살펴보도록 하겠다. 초반 강의들에서는 주로 큰 개념들을 다루고, 나머지 강의들에서는 조금 더 깊은 내용들과 다양한 알고리즘들의 세부 매커니즘을 위주로 다룰 것이다.
앞으로 신경망 모델을 구현하기 위해서 python과 numpy를 많이 사용하게 될텐데 관련 튜토리얼은
http://cs231n.github/io/python-numpy-tutorial/ 에서 찾아볼 수 있다. Numpy는 vectorized 연산을 효율적으로 할 수 있게 도와주고 방대한 양의 계산을 코드 몇 줄로 간단히 가능하게 해주고, 대부분의 수치 계산, 기계학습같은 것들이 vectorized 연산을 수행하기 때문에 잘 다루는 것이 중요하다.
딥러닝 모델은 많은 양의 데이터들을 다뤄야하기 때문에 구글 클라우드 등의 도움을 얻는 것도 좋다.
http://cs231n.github.io/gce-tutorial/
CS231n은 image classification을 주로 다룬다. Image Classification은 우선 입력 이미지를 받고, 시스템에서 사람이 미리 정해놓은 카테고리 집합에서 어디에 속하는지 컴퓨터가 판단하는 것이다. 시각인식 테스크에 고도화되어있는 사람의 시각체계와 달리 기계는 어려움이 있다.
컴퓨터는 이미지를 위와 같이 격자 모양의 숫자집합으로 인식한다. 각 픽셀은 세 개의 숫자로 표현하고 각각은 red, green, blue를 의미한다.
그래서 컴퓨터가 한 번에 이미지의 객체를 판단할 수 없고, 이것을 의미론적인 차이(semantic gap)이라고 한다. 이미지에 아주 미묘한 차이만 줘도 픽셀 값들이 쉽게 바뀔 수 있고 같은 객체라도 다른 각도, 색채 등으로 찍힌다면 모든 픽셀 값들이 다 달라진다. 첫번째 주의점은 위 사진의 Viewpoint variation이다.
두번째 주의점은 위 사진의 Illumination이다. 조명의 변화가 객체를 다르게 보이게 할 수 있다.
세번째 주의점은 객체의 다른 행동 등 모양 변화이다.
네번째 주의할 점은 가려짐이다. 객체가 일부만 보이더라도 그 객체가 무엇인지 판단할 수 있어야한다.
다섯번째 주의할 점은 배경과 비슷함(Background Clutter)이다.
여섯번째 주의할 점은 Intraclass variation, 즉 하나의 클래스 내에도 다양성이 존재할 수 있다는 것이다. 예를 들어, 고양이에 따라 생김새, 크기, 색, 나이가 각양각색인 것이다.
지금까지 말한 문제들을 모두 해결하면서 모든 객체에 적용 가능한 알고리즘을 만드는 것은 어렵다. 만약 Image Classifier API 코드를 작성한다고 한다면, 위와 같이 Python 메서드를 작성할 수 있을 것이다. 사물 인식의 경우 객체를 인식하는 직관적이로 명시적인 알고리즘은 존재하지 않는다.
사물은 인식하려면 예를 들어 위의 고양이의 경우에는 두 개의 눈, 한 개의 귀, 입, 코 등이 중요하겠고, Hubel과 Wiesel의 연구로 Edges가 중요하다는 것도 알고 있다. 지금까지 시도된 방법은 우선 이미지에서 edges를 계산하고, 다양한 corners와 edges를 각 카테고리로 분류한다.
예를 들어, 세 개의 선이 만나는 지점을 corner이라고 했을 때, 각각의 귀의 위치를 파악하는 등 고양이 인식을 위해 명시적인 규칙 집합을 써내려간다. 하지만 이런 방식은 잘 동작하지 못하는데, 첫째로 이런 알고리즘이 강인하지 못하고, 두번째로, 또 다른 객체를 인식해야한다면 다른 물체들에 대해서도 별도로 만들어야 한다. 즉, 이런 방식은 확장성이 없다. 그래서 다양한 객체들에게 유연하게 적용 가능한 확장성 있는 알고리즘을 개발해야 한다.
그 방법 중 하나는 데이터 중심 접근방법(Data-Driven Approach)이다. 각각의 객체가 어떠한지 일일이 규칙을 정하는 것 대신에 인터넷에서 다양한 많은 데이터를 수집하는데, 이 때 Google Image Search 등의 도구를 사용할 수 있다. ML 알고리즘은 이 데이터들을 잘 요약해서 다양한 객체들을 인식할 수 있는 모델을 만들어내고, 이 모델들로 새로운 이미지를 테스트해보면 각 카테고리를 잘 인식해낼 것이다.
이제 API를 두 개의 함수를 갖게 변경해보자. 하나는 Train 함수인데, 입력은 이미지나 레이블이고, 출력은 우리의 모델이다. 다른 한 함수는 Predict 함수인데, 입력이 모델이고, 출력은 이미지의 예측값이다. 이런 방식의 API는 지난 10~20년간 잘 동작했다.
● Nearest Neighbor(NN)
CNN 등 Deep Neural Network에 대해 알아보기 전에 조금 더 심플한 Classifier을 보도록 하겠다.
첫번째로 볼 단순한 classifier은 Nearest Neighbor(NN)인데, train step에서는 단순히 모든 학습 데이터를 기억한다. Predict step에서는 새로운 이미지가 들어오면 새로운 이미지와 기존의 학습 데이터를 비교해서 가장 유사한 이미지로 레이블링을 예측한다.
데이터셋으로는 CIFAR10을 사용할텐데, Machine Learning에서 자주 쓰는 연습용(테스트용) 데이터셋이다. 비행기, 자동차, 새, 고양이 등의 10가지 클래스가 있고, 각 클래스에 균일하게 분포한 50000여개의 학습용 이미지, 알고리즘 테스트용 10000여개의 테스트 이미지를 가지고 있다.
오른쪽 부분의 맨 왼쪽 열은 테스트 이미지이고, 그 오른쪽으로 학습 이미지 중 테스트 이미지와 유사한 순으로 정렬했다. 그런데 이 예시에서는 두 번째 행의 카테고리는 개이지만 오른쪽 예시들을 보면 사슴, 말 등도 있는 것을 알 수 있다.
이 이미지에 NN 알고리즘을 적용하면 트레이닝 셋에서 가장 가까운 샘플을 찾게 되는데, 이 샘플들이 학습 데이터이기 때문에 이것의 레이블을 알 수 있다.
위에서 테스트 이미지와 학습 데이터를 비교하듯이 이미지 쌍이 있을 때 어떻게 비교를 할지가 중요하다. 테스트 이미지 하나를 모든 학습 이미지들과 비교할 때 여러가지 비교 방법들 이 있고, 이것들은 어떤 비교 함수를 사용하는지에 달려있다.
이전 예제에서는 L1 Distance(Manhattan Distance)를 사용했다. L1 Distance는 이미지를 Pixel-wise로 비교한다. 위의 예는 4x4 테스트 이미지이다. 테스트와 트레이닝 이미지의 같은 자리의 픽셀을 서로 빼고 절댓값을 취한다. 이렇게 픽셀 간의 차이값을 계산하고 모든 픽셀의 수행 결과를 모두 더한다.
위에서 설명한 NN Classifier을 구현한 Python 코드는 numpy에서 제공하는 vectorized operations를 이용했기 때문에 위처럼 짧고 간결하다.
train 함수에서는 단지 이미지를 입력받은대로 그대로 저장한다.
test 함수에서는 이미지를 입력으로 받고, L1 Distance로 비교하고, 학습 데이터들 중 테스트 이미지와 가장 유사한 이미지들을 찾아낸다. 위 코드를 보면, numpy의 vectorized operations를 활용하면 구현은 python code 한두줄이면 충분하다.
그렇다면 각각의 함수의 시간복잡도는 어떻게 될까? 먼저 train 함수는 단순히 입력을 받아서 저장만하면 되기 때문에 O(1)의 시간이 걸리고, test 단계에서는 N개의 학습 데이터 전부를 테스트 이미지와 비교해야하기 때문에 O(N)이 된다. train 시간보다 test 시간이 더 길어서 상당히 뒤집어진 것(backwards)이다.
실제로 우리는 train time은 조금 느려도 되지만 실제 사용 단계인 test time에서는 빠르게 동작하기를 원한다. 핸드폰 등 좀 느린 환경에서 test를 해야하는 경우가 있을 수도 있기 때문에 test time이 더 빠르는 것이 좋은데, 그런 관점에서 NN 알고리즘은 정반대의 경우이다. CNN같은 parametic model들은 NN과는 정반대이다.
NN 알고리즘을 실제로 적용해본다면 어떤 모양일까? 위의 그림은 NN의 decision regions의 그림이다. 2차원 평면 상의 각 점은 학습 데이터이고, 점의 색은 클래스 레이블(카테고리)이다. 2차원 평면 내의 모든 좌표에서 각 좌표가 어떤 학습 데이터와 가장 가까운지 계산하고, 각 좌표를 해당 클래스로 칠했다. NN 분류기는 공간을 나눠서 각 레이블로 분류한다. 이 분류기의 문제점은 NN 알고리즘은 가장 가까운 이웃만을 보기 때문에 초록색 무리 가운데 가운데 노란색 부분과 같이 예외가 생긴다. 파란색 영역을 침범한 초록, 빨간 영역도 마찬가지이다. 이렇게 잡음(noise), 가짜(spurious)가 생긴다.
이러한 문제들이 발생하기 때문에 NN의 조금 더 일반화된 버전인 k-NN 알고리즘이 탄생했다. 단순하게 가장 가까운 이웃만 찾기보다는 distance mertic를 이용해서 가까운 이웃을 k개만큼 찾고, 이웃끼리 투표를 해서 가장 많은 득표수를 획득한 레이블로 예측한다. 투표를 하는 것은 거리별 가중치를 고려하는 등 다양하고 복잡한 방법들이 있을 수 있다. 가장 잘 동작하면서도 가장 쉬운 방법은 득표수만 고려하는 방법이다. k=1과 달리 k=3에서는 초록 영역 가운데의 노란 영역이 사라졌다. k=5가 되니 파란 영역을 침범한 초록, 빨강 영역 경계들도 부드럽고 좋아졌다.
대게 NN 분류기를 사용하면 K는 적어도 1보다는 큰 값으로 사용하는데, K가 1보다 커야 결정 경계가 더 부드러워지고 더 좋은 결과를 보이기 때문이다.
여기에서 한 학생의 질문은 레이블링이 안 된 흰색 지역은 어떻게 처리하는지이다. 흰색 영역은 k-NN이 대다수를 결정할 수 없는 지역인데, 흰색 영역을 메꿀 수 있는 더 좋은 방법들이 존재하긴 한다. 어떤 식으로든 추론을 해보거나, 임의로 정하는 등이다. 하지만 이것은 단순한 예제라서 가장 가까운 이웃이 존재하지 않으면 단순하게 흰색으로 칠했다.
컴퓨터 비전을 공부하는 동안에 다양한 관점을 유연하게 다루는 능력은 매우 유용한데, 그 중 하나는 이미지를 고차원 공간에 존재하는 하나의 점이라고 생각하는 것이고, 반대로 이미지를 이미지 자체로 보는, 즉 이미지의 픽셀들을 하나의 고차원 벡터로 생각할 수도 있을 것이다. 이 두가지 관점 사이를 유연하게 이동하는 사고를 구하는 것이 좋다.
이미지를 다루는 문제에서 k-NN을 사용하는 전략은 그닥 좋은 방법이 아니다. 위의 예시에서 잘 분류되었는지 아닌지를 초록/빨간색으로 표시한 것인데, 빨간색이 더 많은 것으로 보아서 성능이 별로 안 좋다.
그렇다면 k값을 높이는 게, 즉 가장 가까운 이웃뿐만 아니라 top-3/top=5 혹은 모든 행을 사용하면 어떨까? 더 많은 이웃들이 투표에 참여하면 각종 잡음들에 좀 더 강인해질 것임을 추측할 수 있다.
k-NN을 사용할 때 결정해야할 한 가지 사항은 서로 다른 점들을 어떻게 비교할 것인지이다. 지금까지는 L1 Distance, 즉 픽셀 간 차이 절대값의 합을 이용했다. 또 다른 방법은 L2, Euclidean Distance, 즉 제곱 합의 제곱근을 거리로 이용하는 방법이다.
어떤 거리 척도(distance metric)를 선택할지는 아주 흥미로운 주제인데, 왜냐하면 서로 다른 척도에서는 해당 공간의 근본적인 기하학적 구조 자체가 서로 다르기 때문이다.
왼쪽의 사각형은 사실 L1 Distance의 관점에서는 원인데, 생긴 모습은 원점을 기준으로 하는 사각형의 모양이다. L1의 관점에서는 사각형 위의 점들이 모두 원점으로부터 동일한 거리만큼 떨어져 있다. 반면, L2, Euclidean distance의 관점에서는 원이다.
이 두 가지 거리 척도간에는 아주 흥미로운 차이점이 있는데, L1은 어떤 좌표 시스템이냐에 따라 많은 영향을 받는다. 예를 들어, 기존의 좌표계를 회전시키면 L1 Distance가 변한다. 반면 L2 Distance의 경우에는 좌표계와 아무 관련이 없다. 만약 특징 벡터의 각각 요소들이 개별적인 의미를 가진다면(예: 키, 몸무게), L1이 더 적합할 수 있다. 하지만 특징 벡터가 일반적인 벡터이고, 요소들간의 실질적인 의미를 잘 모르는 경우라면 아마도 L2 Distance가 조금은 더 잘 어울릴 수 있다.
k-NN에 다양한 거리 척도를 적용하면 k-NN으로 벡터나 이미지 외에도 다양한 종류의 데이터를 다룰 수 있다. 예를 들어, 문장을 분류하는 문제를 k-NN 분류기로 다루려면 어떤 거리 척도를 사용할지만 정해주면 된다. 이렇게 k-NN은 아주 단순한 알고리즘이고, 새로운 문제를 접했을 때 간단하게 시도할 수 있다.
그러면 어떤 거리 척도를 사용하는지에 따라서 실제 기하학적으로 어떻게 변하는지 알아보도록 하자. 위 예에서 양쪽 모두 동일한 데이터인데 왼쪽은 L1 Distance, 오른쪽은 L2 Distance를 사용했다. 결과를 보면 거리 척도에 따라서 결정 경계의 모양 자체가 달라짐을 알 수 있다. 왼쪽은 결정 경계가 좌표 축에 영향을 받는데 L1 Distance가 좌표 시스템의 영향을 받기 때문이다. L2 Distance는 좌표 축의 영향을 받지 않고 결정 경계를 만들기 때문에 조금 더 자연스럽다.
저스틴의 위 웹 데모사이트에서 여러분만의 k-NN 분류기를 설계할 수 있다. k와 거리 척도를 바꿔보면서 어떻게 결정 경계가 만들어지는지 직관을 얻을 수 있다.
실제로 k-NN을 사용하려고 한다면 반드시 선택해야하는 몇 가지 항목이 있는데 앞에서 설명한 k, L1/L1같은 거리 척도 외에도 어떻게 하면 내 "문제"와 "데이터"에 꼭 맞는 모델을 찾을 수 있을지 잘 생각해봐야한다. K와 거리 척도를 "하이퍼 파라미터"라고 한다.
하이퍼파라미터는 train time에 학습하는 것이 아니므로 학습 전 사전에 반드시 선택해야만 한다. 데이터로 직접 학습시킬 방법이 없다. 그렇다면 하이퍼파라미터를 어떻게 정해야할까?
하이퍼파라미터를 정하는 일은 문제의존적(problem-dependent)이다. 가장 간단한 방법은 데이터에 맞게 다양한 하이퍼파라미터 값을 시도해보고 가장 좋은 값을 찾는다.
어떤 학생의 질문은 어떤 경우가 L1 Distance가 L2 Distance보다 더 좋은지인데 이것도 문제 의존적이다. 어떤 경우에 이 둘 중의 하나를 쓸지 결정하는 것은 어렵겠지만 L1은 좌표계에 의존적이므로 그 데이터가 좌표계에 의존적인지를 판단하는 것이 판단 기준이 될 수 있다. 만약 어떤 특징 벡터가 있고 각 요소가 어떤 특별한 의미를 가지고 있다면, 예를 들어 직원들을 분류하는 문제가 있을 때, 봉급, 근속년수와 같은 데이터의 각 요소가 직원들의 다양한 특징에 영향을 줄 수 있다. 이렇게 각 요소가 특별한 의미를 가지고 있다면 L1을 사용하는 것이 좀 더 나을 것이다.
하지만 일반적으로 하이퍼파라미터 선택은 어떤 문제와 데이터인지에 의존적이다. 그러므로 하이퍼파라미터는 단지 여러가지 시도를 해보고 좋은 것을 선택하는 것이 좋다. 그래서 하이퍼파라미터 값들을 실험해보는 작업도 다양하다.
다양한 하이퍼파라미터를 시도해보는 것과 그 중 최고를 선택하는 것이 무슨 뜻일까?
첫번째 아이디어는 학습데이터의 정확도와 성능을 최대화하는 하이퍼파라미터를 선택하는 것이다. 이 방법은 최악이므로 절대 사용하지 말아야한다.
예를 들어, NN 분류기의 경우 k=1일 때 학습 데이터를 가장 완벽하게 분류한다. 그러므로 이 관점에는 k=1일 때가 최고일 것이다. 하지만 앞에서도 살펴보았듯이 실제로는 k를 더 큰 값으로 선택하는 것이 학습 데이터에서는 몇 개 잘못 분류할 수는 있지만 학습 데이터에 없던 데이터에 대해서는 더 좋은 성능을 보일 수 있다.
궁극적으로 기계학습에서는 학습 데이터를 얼마나 잘 맞추는지는 중요하지 않고, 우리가 학습시킨 분류기가 한 번도 보지 못한 데이터를 얼마나 잘 예측하는지가 중요하다. 그러므로 이렇게 학습 데이터에만 신경쓰는 것은 최악이다.
두번째 아이디어는 전체 데이터셋 중 학습 데이터를 쪼개서 일부를 테스트 데이터로 사용하는 것이다.
학습 데이터로 다양한 하이퍼파라미터 값들을 학습시키고 테스트 데이터에 적용시킨다음 하이퍼파라미터를 선택하는 방법이다.
좀 더 합리적이게 보이지만 이 방법도 끔찍하고 절대 하면 안 된다. 기계학습의 궁극적인 목적은 한 번도 보지 못한 데이터에서 잘 동작해야하는데 테스트셋으로는 한 번도 보지 못했던 데이터에서의 알고리즘의 성능을 측정할 수 있어야한다. 그런데 만약 학습시킨 모델들 중 테스트 데이터에 가장 잘 맞는 모델을 선택한다면 우리는 그저 테스트 셋에서만 잘 동작하는 하이퍼파라미터를 고른 것일 수 있다. 그렇게 되면, 더이상 테스트 셋에서의 성능은 한 번도 보지 못한 데이터에서의 성능을 대표할 수는 없다.
훨씬 더 일반적인 방법은 데이터를 세 부분으로 나누는 것이다.
데이터의 대부분은 training set으로 나누고, 일부는 validation set, 그리고 나머지는 test set으로 나눈다.
그리고 다양한 하이퍼파라미터로 training set을 학습시킨다. 그 후 validation set에서 가장 좋았던 하이퍼파라미터를 선택해서 검증을 한다. 뒤이어 개발 / 검증을 모두 마친 후에 validation set에서 가장 좋았던 분류기를 가지고 test set에서는 오로지 한 번만 수행하고, 이것이 이 알고리즘이 한 번도 보지 못한 데이터에서 얼마나 잘 동작하는지를 실질적으로 말해줄 수 있다.
실제로 validation data와 test data를 엄격하게 나눠놓는 것은 상당히 중요하다. 정직하게 연구를 수행했고 수치를 공정하게 측정했다는 것을 보장하기 위해서 테스트 셋은 아주 마지막에만 사용해야 하고, 잘 통제되어야한다.
또다른 하이퍼파라미터 선택 전략은 cross validation(교차 검증)이다. 이 방법은 작은 데이터셋일 경우 많이 사용하고 딥러닝에서는 많이 사용하진 않는다. 이 아이디어는 우선 테스트 데이터를 정해놓고 이것은 아주 마지막에만 사용된다. 그리고 나머지 데이터는 training / validation으로 딱 나눠놓는 대신에 training data를 여러 부분으로 나눠준다. 이런 식으로 번갈아가면서 validation set을 지정해준다.
위의 그림에서는 5-fold validation set을 사용하는데, 처음 4개의 fold에서 하이퍼파라미터를 학습시키고 남은 한 fold에서 알고리즘을 평가한다. 그리고 1,2,3,5 fold에서 다시 학습시키고 4 fold로 평가한다. 이런 식으로 계속 순환하는 것이다. 이런 방식으로 최적의 하이퍼파라미터를 확인할 수 있다.
이런 방식은 거의 표준이긴 하지만 실제로는 딥러닝같은 큰 모델을 학습시킬 때는 학습 자체가 계산량이 많기 때문에 실제로는 잘 쓰지 않는다.
어떤 학생의 질문은 구체적으로 training set과 validation set의 차이가 무엇인지이다.
k-NN의 예를 들자면 training set은 우리가 레이블을 기억하고 있는 이미지들이다. 어떤 이미지를 분류하려면 training data의 모든 이미지들과 비교하게 되겠고, 가장 근접한 레이블을 선택한다. 알고리즘은 이렇게 training set 자체를 기억할 것이다.
이제는 validation set을 가져와서 training set과 비교한다. 그리고 이를 통해서 validation set에서는 분류기가 얼마만큼의 정확도가 나오는지 확인한다. 이것이 training / validation set의 차이점이다. training set의 레이블을 볼 수 있지만 validation set의 레이블은 볼 수 없다. validation set의 label은 알고리즘이 얼마나 잘 동작하는지를 확인할 때만 사용하는 것이다.
또다른 학생의 질문은 테스트 셋이 한 번도 보지 못한 데이터를 대표할 수 있는지이다. 이것은 실제로 문제가 될 수 있는데, 기본적인 통계학적 가정에서는 여러분의 데이터는 독립적이며, 유일한 하나의 분포에서 나온다는 것이다(i.i.d assumption). 그러니 모든 데이터는 동일한 분포를 따른다고 생각해야하는데 실제로는 그렇지 않은 경우가 많다.
이런 류의 문제는 datasets creators와 dataset curator가 생각해 볼 문제이다. 데이터셋을 수집할 때, 일관된 방법론을 가지고 대량의 데이터를 한 번에 수집하는 전략을 사용한다. 그 다음에 무작위로 training data와 test data를 나눠준다.
한 가지 주의해야할 점은 데이터를 지속적으로 모으고 있는 경우이다. 먼저 수집한 데이터들을 트레이닝 데이터로 쓰고, 이후에 모은 데이터를 테스트 데이터로 사용한다면 문제가 될 수 있다. 대신에 데이터셋 전체를 무작위로 섞어서 데이터셋을 나누는 것이 그 문제를 완화시킬 수 있는 한가지 방법일 수 있다.
교차 검증을 수행하고 나면 위와 같은 그래프를 볼 수 있다. x축은 k-NN의 K이고, y축은 분류 정확도이다.
이 경우에는 5-fold 교차검증을 수행하였고, 각 k마다 5번의 교차 검증을 통해 알고리즘이 얼마나 잘 동작하는지를 알려준다.
그리고 테스트셋이 알고리즘 성능 향상에 미치는 영향을 알아보려면 k-fold 교차 검증이 도움이 될 수 있다.
여러 validation folds 별 성능의 분산(variance)을 고려해 볼 수 있다. 분산을 같이 계산하게 되면, 어떤 하이퍼파라미터가 가장 좋은지뿐만 아니라, 그 성능의 분산도 알 수 있다. 여기에서는 k = 7인 경우에 가장 좋은 성능을 낸다.
실제로는 입력이 이미지인 경우에는 앞서 이야기한 문제들 때문에 k-NN 분류기를 잘 사용하지 않는다.
한 가지 문제는 k-NN이 test일 때 더 느리다는 것이고, 또 하나의 문제는 L1 / L2 Distance가 이미지 간의 거리를 측정하기에 적절하지 않다는 것이다.
이 벡터간의 거리 측정 관련 함수들은 (L1 / L2) 이미지들 간의 지각적 유사성을 측정하는 척도로는 적절하지 않다.
우리들은 이미지 간의 차이를 어떻게 지각하는 것일까? 위의 예시에는 왼쪽에 여성의 사진이 있고, 오른쪽에는 세 개의 왜곡된 이미지가 있다. 눈과 입을 가려보고, 몇 픽셀씩 이동도 시켜보고, 전체 이미지에 파란색 색조도 추가해보았다.
그런 뒤 각 이미지와 원본의 사이의 Euclidean Distance를 측정해보면 이들은 모두 동일한 L2 Distance를 가지고, 이것은 좋지 않다. 이것은 L2 Distance가 이미지들 간의 "지각적 유사도"를 측정하기에는 적합하지 않다는 의미이기 때문이다.
어떤 학생의 질문은 왜 저 이미지들의 L2 Distance가 같은지이다. 저스틴이 위의 translation과 offset에도 Distance가 일치하도록 만든 이미지이기 때문이다. 저스틴은 단지 L2 Distance가 이미지간의 유사도를 측정하는 데는 좋지 않다는 점을 강조하고 싶었다고 한다.
또 다른 학생의 질문은 이미지들이 모두 같은 사람이므로 distance가 같으면 좋은 것 아닌지이다. 이 예시에서는 그럴 수도 있으나, 반례가 있을 수 있다. 가령 서로 다른 두 개의 원본 이미지가 있고 어떤 적절한 위치에 박스를 놓거나, 색을 더하거나 하게 되면 결국 두 이미지의 distance를 엄청 가깝게 만들 수 있을 것이다. 그러니 다양한 서로 다른 이미지들이 같은 distance를 가지는 경우라면 잘못될 수도 있는 것이다.
k-NN의 또다른 문제 중 하나는 바로 "차원의 저주"이다. k-NN에서 하는 일은 트레이닝 데이터를 이용해서 공간을 분할하는 일이었다. 이는 k-NN이 잘 동작하려면 전체 공간을 조밀하게 커버할 만큼의 충분한 training sample이 필요하다는 것을 의미한다. 그렇지 않다면 이웃이 사실은 엄청 멀 수도 있고 그렇게 되면 테스트 이미지들을 제대로 분류할 수 없을 것이다.
그래서 공간을 조밀하게 덮으려면 충분한 양의 학습 데이터가 필요하고 그 양은 차원이 증가함에 따라 기하급수적으로 증가한다. 이것은 좋지 않고, 고차원이라면 거의 불가능할 수도 있다.
k-NN을 사용하려면 이 두가지 문제를 꼭 기억해야한다.
어떤 학생의 질문은 위 그림의 초록색 점과 녹색 점이 무엇을 의미하는지인데, 각 점은 트레이닝 샘플들을 의미한다. 점 하나하나가 training sample이다. 그리고 각 점의 색은 training sample이 속한 카테고리를 나타낸다.
1차원을 보면 이 공간을 조밀하게 덮으려면 training sample 4개면 충분하다. 2차원 공간을 다 덮으려면 16개가 필요하다. 1차원의 4배이다. 이렇게 각 공간을 조밀하게 덮기 위해 필요한 training sample의 수는 차원이 늘어남에 따라 기하급수적으로 증가한다.
2차원에서는 curve shape가 있고, 더 높은 차원에서는 일종의 sample들의 manifolds(여러 층을 말하는 듯)가 있을 수 있다. 하지만 k-NN 알고리즘은 샘플들의 manifolds를 가정하지 않기 때문에 k-NN이 제대로 동작할 수 있는 유일한 방법은 공간을 조밀하게 덮을 만큼 충분히 많은 training sample을 가지는 것이다.
요약을 해보자면 "이미지"와 "정답 레이블"이 있는 training set이 있었고, test set을 예측하는 데 이용하였다.
어떤 학생의 질문은 "최적의 하이퍼파라미터를 찾을 때까지 학습을 다시 시키는 것이 흔한 방법인지"이다. 실제로 사람들은 가끔 그렇게 하곤 하는데 하지만 그때그때 다르다고 할 수 있다. 만약 시간이 별로 없어서 데이터셋 전부를 다시 학습시키는 것이 너무 오래걸리면 다시 학습시키기 쉽지 않을 것이다. 하지만 다시 학습시킬 여유가 있고 1%의 성능이라도 짜내고 싶다면 하나의 트릭이 될 수 있다.
지금까지 k-NN이 기계학습 알고리즘이라는 점에서 지닌 다양한 특성들에 대해 배웠는데, 하지만 실제로는 성능이 엄청 좋지는 않고, 특히 이미지에는 잘 사용하지 않는다.
● Linear Classification
linear classification은 아주 간단한 알고리즘이지만 아주 중요하고 NN과 CNN의 기반 알고리즘이다. 일부 사람들은 Neural Network를 레고 블럭에 비유한다. NN을 구축할 때 다양한 컴포넌트를 사용할 수 있는 것이다. 이 컴포넌트들을 한데 모아서 CNN이라는 거대한 타워를 짓는 것이다.
앞으로 보게 될 다양한 종류의 딥러닝 알고리즘들의 가장 기본이 되는 블럭 중 하나가 바로 Linear Classifier이다.
NN의 구조적 특성을 설명하는 또다른 예시는 Image captioning과 관련된 것인데, image captioning에서는 이미지가 입력이고, 이미지를 설명하는 문장이 출력이다.
이미지를 인식하기 위해서 CNN을 사용하고, 그리고 언어를 인식하기 위해서는 RNN을 사용한다. 우리는 그저 CNN과 RNN을 레고 블럭처럼 붙히고 한 번에 학습시키고, 그러면 이렇게 어려운 문제도 해결할 수 있다.
다시 한 번 보자면 CIFAR-10은 50000여 개의 training sample이 있고, 각 이미지는 32x32 픽셀을 가진 3채널 컬러 이미지였다. linear classification에서는 k-NN과는 조금은 다른 접근 방법을 이용한다.
Linear Classifier은 parametric model의 가장 단순한 형태이다. parametric model에는 두 가지 요소가 있다. 입력 이미지를 x라고 하고, 파라미터, 즉 가중치는 W라고도 하고, 세타(theta)라고도 한다.
작성하는 함수는 data X와 parameter W를 가지고 10개의 숫자를 출력한다. 이 숫자는 CIFAR-10의 각 10개의 카테고리의 스코어이다. 이 스코어를 해석해보자면, "고양이"의 스코어가 높다는 것 입력 X가 "고양이"일 확률이 크다는 것을 의미한다.
이 예에서 32 x 32 x 3에서의 3은 Red, Green, Blue 3 채널을 의미한다. 보통은 컬러 이미지를 다룬다. 컬러 정보는 버리기 아까운 유용한 정보이다.
직전에 배웠던 k-NN은 파라미터가 없었다. 그저 전체 training set을 가지고 있었고 모든 training set을 test time에 사용했다. 하지만 parametric approach에서는 training data의 정보를 요약하고 그 요약된 정보를 파라미터 W에 모아준다. 이런 방식을 사용하면 test time에서 더 이상 training data가 필요하지 않다. 그래서 이런 방법은 핸드폰과 같은 작은 디바이스에서 모델을 동작시켜야할 때 아주 효율적이다.
그래서 딥러닝은 이 함수 F의 구조를 적절하게 잘 설계하는 일이라고 할 수 있다. 어떤 식으로 가중치 W와 데이터를 조합할지를 여러가지 복잡한 방법으로 고려해볼 수 있는데 이 과정들이 모두 다양한 NN 아키텍처를 설계하는 과정이다. 가중치 W와 데이터 X를 조합하는 가장 쉬운 방법은 그냥 이 둘을 곱하는 것이고, 이것이 Linear Classification이다.
그래서 F(x, W) = Wx라는 쉬운 식이 나온다.
입력 이미지는 32 x 32 x 3이었다. 이 값을 길게 펴서 열 벡터로 만들면 3072-dim 벡터가 된다. 3072-dim열 벡터가 10-classes 스코어가 되어야한다. 이는 10개 카테고리에 해당하는 각 스코어를 의미하는 10개의 숫자를 얻고 싶은 것이다. 따라서 행렬 W는 10 x 3072가 되어야한다. 이 둘을 곱하면 10-classes 스코어를 의미하는 10 x 1짜리 하나의 열벡터를 얻게 된다.
가끔은 bias도 더해준다. bias는 10-dim 열 벡터인데, 입력과 직접 연결되지는 않는다. 대신에 데이터와 무관하게 특정 클래스에 우선권을 부여한다. 가령 고양이 데이터가 개 데이터보다 훨씬 더 많은 데이터셋이 불균형한 상황을 생각해보면 이 상황에서는 고양이 클래스에 상응하는 bias가 더 커지게 되는 것이다.
위의 그림을 보면 왼쪽에 2 x 2이고 전체 4개의 픽셀을 가진 입력 이미지가 있다. 이 linear classifier은 2 x 2 이미지를 입력으로 받고 이미지를 4-dim 열 벡터로 쭉 편다. 10개의 클래스 중 고양이, 개, 배의 3가지 클래스만 여기서 예시로 보겠다. 가중치 행렬 W는 4 x 3 행렬이 되고, 이런 식을 입력은 픽셀 4개고, 클래스는 총 3개이다. 그리고 추가적으로 3-dim bias 벡터가 있어서 bias는 데이터와 독립적으로 각 카테고리에 연결된다.
고양이 스코어는 입력 이미지의 픽셀 값들과 가중치 행렬을 내적한 값에 bias term을 더한 것이다. 이러한 관점에서 Linear classification은 템플릿 매칭과 거의 유사하다. 가중치 행렬 W의 각 행은 각 이미지에 대한 템플릿으로 볼 수 있고 그 행 벡터와 이미지의 열벡터 간의 내적을 계산하는데 여기서 내적이란 결국 클래스 간 템플릿의 유사도를 측정하는 것과 유사함을 알 수 있다. bias는 데이터 독립적으로 각 클래스에 scailing offsets를 더해주는 것이다.
템플릿 매칭의 관점에서 linear classification을 해석해보면 가중치 행렬 W의 한 행을 뽑아서 이를 이미지로 시각화시켜보면 linear classifier가 이미지 데이터를 인식하기 위해서 어떤 일을 하는지 짐작할 수 있다. 이 예제에서는 linear classifier가 이미지를 학습하고, 슬라이드 하단의 이미지는 실제로 가중치 행렬이 어떻게 학습되는지를 볼 수 있다.
CIFAR-10의 각 10개의 카테고리에 해당하는 행 벡터를 시각화시킨 것이다. 이렇게 시각화된 이미지를 살펴보면 어떤 일이 일어나는지 알아볼 수 있다.
가령 아래에서 맨 왼쪽의 이미지는 비행기 클래스에 대한 템플릿 이미지이다. 이 이미지는 전반적으로 파란색이고 가운데에는 어떤 물체가 있다. 그래서 이 이미지를 해석해보면 linear classifier가 비행기를 분류할 때 푸르스름한 것들을 찾고 있는 것 같다. 이러한 특징들이 이 분류기가 비행기를 더 잘 찾도록 도와준다고 해석해볼 수 있다.
바로 옆에 있는 차 클래스를 보겠다. 중앙은 불그스름하고 상단은 푸르스름해서 마치 자동차의 앞유리같다. 하지만 실제 자동차처럼 보이지는 않는다. 그래서 linear classifier의 문제 중 하나는 각 클래스에 대해서 단 하나의 템플릿만을 학습한다는 것이다. 한 클래스 내에 다양한 특징들이 존재할 수 있지만 모든 것들을 평균화시키기 때문에 다양한 모습들이 있더라도 각 카테고리를 인식하기 위한 템플릿은 단 하나밖에 없다.
이 문제점은 말을 분류하는 템플릿에서도 여전히 드러난다. horse 클래스의 그림에서는 바닥은 푸르스름해보이는데, 보통 말이 풀밭에 서 있으니 템플릿이 바닥을 푸르스름하게 학습한 것이다. 그런데 유심히 살펴보면 말의 머리가 각 사이드마다 하나씩 달려있어서 두 개이다. 그리고 머리 두 개 달린 말은 존재하지 않는다. 하지만 linear classifier가 클래스 당 하나의 템플릿밖에 허용하지 않으므로 이 방법이 최선이다.
하지만 Neural Network같은 복잡한 모델이라면 클래스 당 하나의 템플릿만 학습할 수 있다는 것과 같은 제약조건이 없다면 조금 더 정확도 높은 결과를 볼 수 있을 것이다.
Linear Classifier의 또 다른 관점은 이미지를 고차원 공간의 한 점으로 보는 것이다. Linear classifier은 각 클래스를 구분시켜주는 선형 결정 경계를 그어주는 역할을 한다. 위의 예에서 비행기를 구분해주는 파란색 선을 보자. Linear Classifier은 파란색 선을 학습해서 비행기와 다른 클래스를 구분할 수 있다. 임의의 값으로 초기화된 모델이 데이터들을 잘 분류하려고 노력하는 것이다. 하지만 이미지가 고차원 공간의 하나의 점이라는 관점으로 해석해보면 Linear Classification이 직면할 수 있는 문제가 있다.
이 Linear Classifier을 망가뜨릴 수 있는 예제를 만드는 일은 생각보다 어렵지 않다.
맨 왼쪽 그림은 두 개의 클래스를 가진 데이터 셋이다. 데이터가 조금은 인위적일 수 있지만, 데이터셋에는 파랑/빨강 두 개의 카테고리가 있다. 파랑색 카테고리는 0보다 큰 픽셀이 홀수 개인 경우이다.
(예: [3, -1]이면 0보다 큰 수 : 3(1개, 홀수 개) -> 파랑)
반면 0보다 큰 수가 짝수 개면 빨간 카테고리로 분류한다. 좌표 평면에 이같은 규칙으로 그려보면 두 개의 사분면에는 파란 클래스, 두 사분면에는 빨간색 클래스를 볼 수 있다.
(예: (1, 1) : 2(짝), (-1, 1) : 1(홀), (-1, -1): 0(짝))
이 데이터를 선 하나로 분류할 방법은 없다. Linear Classifier로는 풀기 힘든 문제이다.
이렇게 픽셀 개수를 세는 대신에 영상 내 동물이나 사람의 수가 홀수 / 짝수인지를 분류하는 문제일 수도 있다. 홀/짝수를 분류하는 것과 같은 반전성 문제(parity problem)은 일반적으로 linear classification으로는 풀기 힘든 문제이다.
Linear Classifier로 풀기 힘든 또 하나는 Multimodal problem이고, 위의 그림에서 맨 오른쪽의 경우이다. 여기서는 파란색이 분포하는 세 개의 섬들이 있다. 그 밖의 빨간색은 전부 다른 카테고리에 속한다. 앞에서 말한 것처럼 multimodal problem은 언제든 실제로 일어날 수 있다. 왼쪽 머리가 하나의 섬이 될 수 있고 오른쪽 머리가 또 하나의 섬이 될 수 있다. 섬이 두 개인데 선을 하나만 긋는 것은 그닥 좋은 방법이 아닌 것이다.
Multimodal data라면 한 클래스가 다양한 공간에 분포할 수 있으며 이 문제는 Linear Classifier로는 풀 수 없다. 이처럼 Linear Classifier에는 문제점이 일부 있긴 하지만 아주 쉽게 이해하고 해석할 수 있는 알고리즘이다.
이번 시간에는 linear classifier가 단순히 행렬과 벡터 곱의 형태라는 것을 배웠고, 템플릿 매칭과 관련이 있고, 이 관점에서 해석해보면 각 카테고리에 대해 하나의 템플릿을 학습한다는 것을 배웠다. 그리고 가중치 행렬 W를 학습시키고 나면 새로운 학습 데이터에도 스코어를 매길 수 있다.
오늘은 어떻게 가중치 행렬 W를 구할 수 있는지는 배우지 않았다. 오늘은 Linear Classifier가 어떻게 생겼고, 어떻게 동작하는지만 가볍게 알아보았다.
다음 시간에는 적절한 가중치 행렬 W를 고르는 법과 다양한 알고리즘들에 대해서 다뤄보도록 하겠다. 그리고 더 나아가 비용함수, 최적화, ConvNet에 대해서 배울 것이다.
'AI > CS231n Lectures' 카테고리의 다른 글
[CS231n] 11. Detection and Segmentation (0) | 2020.02.16 |
---|---|
[CS231n] 1. Introduction to Convolutional Neural Network (0) | 2020.01.29 |