ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [cs231n] 3강 손실 함수와 최적화 (1/4, 멀티클래스 (multiclass) SVM)
    AI 2021. 1. 10. 21:42

    3강에 오신 것을 환영합니다. 오늘은 손실 함수와 최적화에 대해서 이야기 할 겁니다.

    2강을 돌아보면, 인식할 때의 챌린지들에 대해 얘기했고, 이 데이타 추진 아이디어들에 대해 연마했습니다. 이미지 분류에 대한 아이디어에 대해 얘기했는데, 왜 어려운지를 얘기했고, 컴퓨터가 보는 거대한 그리드 숫자와 우리가 보는 이미지 사이의 의미적 갭에 대해서도 얘기했습니다. 다양한 챌린지에 대해서도 얘기했죠. 조명, 형태 변화, 등등이 있었고, 비록 사람의 눈과 시각으론 너무나도 쉬운 거지만, 왜 이게 정말 정말 어려운 문제인지에 대해서 얘기했습니다.

    또한 데이타 추진 마인드셋 전체에 대한 간단한 도입으로, kNN 분류기에 대해 얘기했죠. CIFAR 10 데이타셋에 대해 얘기했는데, 위 그림 왼쪽 위에 보이는 예를 볼 수 있는데죠. 거기보면 CIFAR 10은 비행기, 자동차 등 10개의 다른 카테고리가 있고, 우리는 K 최근접 이웃 분류기가 학습 데이타에 기반해서 어떻게 결정 바운더리를 학습하는데 즉, 이 데이타 점들을 클래스로 나누는데 사용할 수 있는 지를 얘기했습니다. 이를 통해 교차 검증 아이디어와 여러분의 데이타를 학습, 검증, 테스트 셋으로 나눠서 하이퍼 파라미터를 정하는 것에 대해 토의했습니다.

    지난 시간에 또 우리가 신경망으로 나아가면서, 첫 빌딩 블록으로 선형 분류에 대해 배웠는데요. 파라미터 분류기의 예인데, 학습 데이타에 관한 모든 지식이 훈련 단계에서 이 파라미터 W 매트릭스로 요약되어 들어가 정해집니다. 선형 분류기는 정말 간단한데, 우리가 이미지를 받아서 하나의 긴 벡터로 늘입니다 위에서 이미지가 X인데, 32 x 32 x 3 이미지를 받아서 긴 열 벡터로 늘이니까, 32 x 32 x 3인 길이겠죠. 32와 32는 높이와 넓이고, 3은 3개 색깔 채널, 빨강, 초록, 파랑을 의미하죠. 그리곤 어떤 파라미터 매트릭스 W가 있는데, 이미지 픽셀을 의미하는 이 긴 열 벡터를 받아서, 이걸 바꿔서 10개의 숫자를 줍니다. CIFAR 10의 10개의 클래스에 대한 점수죠. 여기서, 우리는 고양이 클래스에 대한 더 큰 점수는 분류기가 그 이미지에 대해 고양이일 가능성이 더 클 것 같다고 얘기하는 거라고 해석합니다. 개나 차에 대한 더 낮은 값은 그 클래스들이 그 이미지일 가능성은 더 낮다고 나타내구요.

    지난 시간에 이 해석을 하는데 클래스 마다의 학습 템플릿으로서 선형 분류기라는 점이 좀 명확하지 않았던 것 같은데요. 위 그림 왼쪽 아래 다이어그램을 보면 이미지의 모든 픽셀에 대해서, 그리고 10개의 모든 클래스에 대해서, 그 픽셀이 그 클래스에 얼마나 영향을 주는지를 얘기해 주는 어떤 항목이 매트릭스 W에 있습니다. 그 말은 매트릭스 W의 이 행들이, 그 클래스의 템플릿에 해당한다는 겁니다. 그 행들을 꺼내 보면 각 행은 이미지의 픽셀값과 그리고 그 클래스 사이의 가중치에 해당하죠. 그래서 행을 꺼내서 이미지로 다시 만들면 각 클래스에 대해서학습된 템플릿으로 시각화 할 수 있죠. 어떤 고차원 공간에서 픽셀간의 선형 결정 바운더리로서 선형 분류에 대해 이해를 했고, 공간의 차원은 픽셀 강도 값에 해당합니다.

    우리가 마지막으로 봤던 건, 이 선형 분류기에 대한 아이디어를 얻는데 까지였고, W를 어떻게 고를지는 얘기하지 않았습니다. 어떻게 학습 데이타를 실제로 사용하는지, W의 어떤 값이 최선이 되는지를 결정하기 위해서요. 우리가 배운 것은 어떤 W 세팅에 대해, 어떤 이미지에 대해서 이 W를 사용해서 우리의 10개 클래스의 점수를 얻을 수 있습니다. 우리가 본 이 간단한 예에서, 클래스 점수들 중 몇 개는 더 좋거고 몇 개는 더 나쁘겠죠. 3개의 이미지에 대한 학습 데이타를 보면, 이 이미지들에 대해, 어떤 W 값에 대해 예측된 10개의 클래스 점수가 있습니다. 볼 수 있듯이 어떤 점수는 상대적으로 좋고 어떤 점수는 좋지 않네요.

    예를 들면, 위쪽을 보면, 왼쪽 이미지는 고양이인데, 여러분은 사람이니까, 고양인 걸 알죠. 그러나 지정된 점수를 보면, 이 W 셋팅으로는 분류기가 아마도 고양이 클래스에 2.9점을 줬나봅니다. 반면, 개구리 클래스에는 3.78을 주죠. 아마도, 분류기가 이 이미지에 대해서 잘 하고 있지 않아 보입니다. 우리는 그 참인 클래스 점수가 사실 제일 높길 바랍니다. 반면, 다른 예들에 대해서도 보면, 자동차 클래스는 6.04인데, 다른 모든 클래스들 보다 높아서 좋네요. 개구리를 보면, 예측된 점수는 -4로 다른 모든 것들에 비해 훨씬 낮습니다. 나쁜 예입니다.

    이건 일종의 논리가 부족한 접근 방법인데, 그냥 눈을 굴려 점수를 보고 어떤 게 좋은지 어떤게 나쁜지 알아내는 거죠. 이것에 대해 알고리즘을 작성해서, 자동으로 어떤 W가 최선인지 결정하도록 해야 합니다. 우리는 모든 특정 W에 대해서 이 나쁨의 정도를 정량화할 방법이 필요합니다. 이 함수는 W를 받아서, 점수를 보고 얼마나 정량적으로 나쁜지를 말해 줍니다. 우리는 그것을 손실 함수라고 부릅니다. 이 강의에서, 이 이미지 분류 예를 위해서 사용할 수 있는 몇 개의 손실함수 예들를 볼겁니다.

    일단 우리가 이 손실 함수 아이디어를 갖게 되면, 이것으로 우리는 주어진 어떤 W에 대해 얼마나 좋은지 나쁜지에 대해 정량화 할 수 있습니다. 그러나 그리고 나서 우리는 모든 가능한 더블유의 공간 전체를 탐색하고 실제로 뭐가 정확한 값인지 즉, 가장 덜 나쁜 W를 찾을 효율적인 절차를 찾아야 하죠. 이 절차가 최적화 과정이고 여기에 대해 더 얘기할 겁니다.

    이 예를 좀 줄여볼까요. 10개 클래스는 약간 다루기 좀 불편해서요.

    우리는 이 강좌를 진행하면서 장난감 같은 작은 데이타로 작업할 건데요. 3개의 예로 되어 있고 3개의 클래스로 되어 있습니다. 이 예를 보면 고양이는 아마도 정확하게 분류된 것 같지 않고, 자동차는 맞았네요. 이 W 세팅은 이 개구리 이미지에는 완전히 틀렸죠. 왜냐면 개구리 점수가 제일 낮으니까요.

    이걸 약간 정형화하면, 보통 손실 함수에 대해서 이야기 할 때, 우리는 우리가 x와 y로 이루어진 학습 데이타 셋을 가지고 있다고 가정합니다, 보통 N개의 예제들이고, x들은 알고리즘으로의 입력인데, 이미지 분류에서 x는 사실 이미지의 픽셀 값이죠. y는 알고리즘이 예측하고 싶은 값이구요. 이미지 분류의 경우에는 보통 그걸 레이블이나 타겟이라고 부르죠. 우리는 CIFAR 10의 경우 이 이미지를 10개중 하나의 카테고리로 분류하려고 한다는 걸 기억하고 있어야 합니다. 그래서 레이블 y는 프로그래밍 언어에 따라서 1과 10사이, 혹은 0부터 9까지의 정수 (integer)일거고, 그 정수가 그 이미지 x 각각에 대해서 뭐가 맞는 카테고리인지를 말해 줍니다.

    우리의 손실 함수는 Li로 표시됩니다. 우리는 예측 함수 f가 있어서 예제 x와 가중치 매트릭스 W를 받아서 y에 대한 예측을 합니다. 이미지 분류의 경우엔, 이게 10개의 숫자일거고. 그 다음 우리는 함수 f로부터 나오는 예측 점수와 레이블 y의 참인 타겟을 받아들인 손실 함수 Li를 정의할 겁니다. 그 학습 예제에 대해 그 예측이 얼마나 나쁜지에 대한 정량적인 값을 주는 함수입니다. 그리고 최종적인 손실 L은 우리의 데이타 셋 N개 예제에 걸쳐 전체 데이타 셋을 합친 것에 대한 이 손실들의 평균입니다. 

    이것은 사실 매우 일반적인 공식이고, 실제로 이미지 분류 외에 다른 분야로도 확장됩니다. 앞으로 딥러닝의 다른 작업들을 보면, 일반적인 셋업이라라면 어떤 작업이든지, 여러분은 x와 y가 있을 것이고, 어떤 손실 함수를 작성할 거고 그 함수는 특정 셋팅 W에 대해 여러분이 얼마나 행복한지에 대해 정량화할 겁니다. 그리고 나면 여러분은 결국 W 공간을 탐색해서 데이타셋에 대한 손실을 최소화하는 W를 찾을 겁니다.

    구체적인 손실 함수의 첫번째 예로, 이미지 분류로 작업하기 좋은 멀티클래스 SVM 손실을 이야기 할 겁니다. 여러분은 바이너리 SVM (binary SVM)을 아마 봤을 지도 모르겠습니다. 멀티클래스 SVM은 여러 클래스를 다루기 위해서 그걸 일반화 한겁니다. 바이너리 SVM에서는 단지 2개의 클래스만 있죠. 각 예제 x는 단지 긍정과 부정 예제로만 분류되구요. 그러나 이제 우리는 10개 카테고리가 있어서, 이 노션을 일반화해서 여러 클래스를 다룰 수 있습니다.

    이 손실 함수는 일종의 웃긴 함수 형태를 갖는데, 다음 슬라드에서 좀 자세히 훑어 보죠. 이게 얘기하는 건, 손실 Li가 yi가 참인 카테고리만 빼고 모든 카테고리 y에 대해서 각 예제 하나하나에 대해 합을 구하는 건데요. 그래서, 우리는 맞는 카테고리 점수와 모든 틀린 카테고리를 비교해서, 만약 맞는 카테고리 점수가 틀린 카테고리 점수보다 어떤 안전 마진 차이 보다 더 높으면, 우리는 마진을 1로 했는데요, 그런 경우라면, 참인 카테고리의 점수가 다른 거짓인 카테고리 보다 그만큼 더 크면, 그럼 우리는 0인 손실을 갖죠.

    데이타 셋의 하나의 예인 우리 이미지에 대해서 모든 틀린 카테고리를 모두 더할거고, 이것이 우리에게 최종 손실을 줄 겁니다. 그리고 우리는 전체 데이타 셋에 대한 손실의 평균을 취하죠. 이건 일종의 if then 문장 같은 건데, 만약 참인 점수가 다른 것보다 훨씬 크면을 이런 if then 공식으로 간략화시키죠. 시그마 max(0, s_j - s_y_i +1)로요.

    그러나 항상 노테이션이 약간 헷갈리기 마련이고, 이 두 경우에 어떤 일이 벌어지는지를 정확히 알기 위해서는 이런 종류의 케이스 기반 노테이션 (notation)으로 쓰는 게 도움이 됩니다.

    그런데, 0과 어떤값 중에 최대값을 취하는 이런 스타일의 손실 함수는 종종 힌지 손실 (hinge loss)이라고 부른데, 이 이름은 그래프 모양에서 온 겁니다. x 축은 S_y_i에 해당하는데, 어떤 학습 예제에 대해 참인 클래스의 점수죠. y축은 손실입니다. 이 예에서 참인 클래스의 점수가 증가하면, 우리가 이 안전 마진 (safety margin)에 다다를 때까지, 손실은 선형으로 줄어들죠. 그때 손실이 0이 되죠. 우리는 이미 올바르게 이 예를 분류했으니까요.

    이 작은 3개 데이타 셋에 대해 명시적으로 예제들을 거쳐가 보죠. 케이스 기반 노테이션 대신, 0, 1 노테이션으로 썼습니다.

    왼쪽에 있는 이 첫 학습 예제에 대해 멀티클래스 SVM 손실 계산을 생각해 보죠. 우리는 반복해서 모든 틀린 클래스들에 대해서 할 건데, 이 예제에서는 고양이가 맞는 클래스죠. 우리는 차와 개구리에 대해서도 반복하구요. 차 점수 5.1에서 캣 점수 3.2를 빼고, 1을 더해서 고양이와 차를 비교하는 건데 약간의 손실을 만들죠. 차 점수가 고양이 점수보다 높아서요. 나쁜 것이죠. 이 하나의 클래스에 대한 이 하나의 예제에서 2.9의 손실이 발생했네요. 우리가 고양이 점수와 개구리 점수를 비교하면, 고양이는 3.2인데, 개구리는 -1.7이니까 고양이가 개구리보다 1이상 더 크죠. 즉, 이 두 클래스 사이에는 손실이 0이라는 겁니다. 이 학습 예제에 대한 이 멀티클래스 SVM 손실은 이 클래스들의 짝에 대한 손실들의 합입니다. 2.9 더하기 0은 2.9죠. 여기서 얘기하는 것은 2.9는 우리의 분류기가 이 학습 예제에서 얼마나 망쳤는지에 대한 정량적 측정 값이라는 겁니다.

    같은 절차를 자동차 이미지에 대해서도 합니다. 참인 클래스는 자동차죠. 모든 다른 카테고리에 대해서도 반복하구요. 차와 고양이 점수를 비교하면, 차가 고양이보다 1이상 크니까 손실이 없구요. 차와 개구리를 비교하면, 차가 또 개구리보다 1이상 크죠. 여기서도 손실이 없죠. 이 훈련 이미지에 대한 총 손실은 0이네요.

    이제 여러분은 이게 어떤 건지 알 거라고 생각되는데요. 개구리를 보면, 개구리를 고양이와 비교하면 손실이 크게 발생하죠. 개구리 점수가 매우 낮으니까요. 개구리와 차를 비교하면, 또 큰 손실이 발생하죠. 이 예제에 대한 우리의 손실은 12. 9네요.

    전체 데이타 셋에 대한 우리의 최종 손실은 이 여러 예제 걸친 평균입니다. 다 더하고 해 보면, 약 5.3이죠. 우리의 분류기가 이 데이타 셋에 대해 5.3만큼 나쁘다는 것을 의미하는 일종의 정량적 측정값입니다.

    이 손실이 뭘 의미하는 지에 대해 몇 가지 질문들을 생각해 보는 게 유용할 것 같네요.

    첫 질문은 만약 차 이미지를 약간 바꾸면 손실에 무슨 일이 생길까요? 우리가 이 차 이미지에 대한 점수를 바꾸면, 약간만 바꾸면, 손실은 변하지 않습니다. SVM 손실은 맞는 점수가 틀린 점수보다 1이상 더 큰지에 관심이 있죠. 이런 경우, 차 점수가 다른 점수보다 이미 꽤 크다면, 이 예에 대한 이 클래스에 대한 점수가 약간 변한다면, 이 1의 마진이 여전히 얻어질 것이고, 손실은 변하지 않을 겁니다. 여전히 0 손실을 얻습니다.

    다음 질문은 가능한 최대, 최소 손실값은 뭘까요? 최소 손실는 0이죠. 왜냐면 모든 클래스에 대해서 맞는 점수가 훨씬 크면 모든 클래스에 걸쳐서 0 손실을 만들 수 있으니까요. 만약, 우리가 봤던 힌지 손실 플롯을 다시 생각해 보면 알 수 있는데, 만약 맞는 점수가 매우 음수로 간다면, 우리는 잠재적으로 무한대의 손실을 만들 수 있습니다. 그래서 최소는 0이고 최대는 무한대죠.

    다음 질문은 이걸 초기화 할 때, 바닥에서 부터 학습을 시작할 때요, 일반적으로 W를 작은 랜덤 값으로 할 수 있습니죠. 학습 초기에 결과 점수는 작은 일정한 랜덤 값인 경향이 있죠. 여기서 질문은, 만약 모든 s가 즉 모든 점수가, 대략 0이고 대략 같다면, 멀티클래스 SVM을 사용할 때 어떤 손실을 기대할 수 있을까요? 답은 클래스 숫자 빼기 1인데 왜냐면, 모든 틀린 클래스를 반복하면, 클래스 숫자 - 1 클래스들에 대해 반복하면, 두 s들은 같을 거고, 우리는 1의 손실을 얻을 겁니다 . 마진 (margin)때문에,  C (전체 클래스 숫자를 의미) - 1을 겁니다. 이건 유용한 디버깅 전략이죠. 학습을 시작하면, 여러분의 손실이 얼마일지 예상해 봐야 합니다. 학습 초기 즉, 첫 반복 (interation)에서 보는 손실이 C - 1이 아니면, 버그 (bug)가 있다는 걸 의미하죠, 코드를 확인해 봐야 할 테니, 실제로 체크해 봐야 하는 유용한 도구입니다.

    다음 질문은 모든 클래스에 대해 SVM을 다 더하면 어떻게 될까요? 답은 손실이 1씩 커진다입니다. 일반적으로 0 손실은 잃는 것이 없다는 것을 의미하는 좋은 해석이죠. 모든 카테고리를 다 돌아도 여러분의 답은 바뀌지 않고 같은 분류기를 찾는 것으로 끝날 겁니다. 그러나 관습적으로 맞는 클래스를 생략합니다. 우리의 최소 손실이 0이 되도록요.

    다음 질문은 만약 다 더하는 대신에 평균을 사용하면 어떻게 될까요? 답은 똑같죠. 우리가 데이타셋을 선택할 때, 클래스의 숫자는 이미 결정된 거고, 전체 손실 함수를 상수로 그냥 스케일을 변경할 뿐입니다. 상관없죠. 그 문제 에 대해서는 우리는 참 점수 값에 관심 없고, 참 손실의 값에 관심이 있죠.

    다른 예가 있는데, 만약 우리가 이 손실 공식을 바꿔서 max의 제곱항을 더하면 어떻게 되나요? 같은 걸로 끝날까요? 혹은 다른 분류기 알고리즘이 될까요? 답은 달라질거라는 겁니다. 이 아이디어는 좋은 것과 나쁜 것 사이의 트레이드 오프 (trade-off)를 비 선형적인 방법으로 바꿔서 이건 결국 다른 손실 함수가 되고 맙니다.

    이 제곱 힌지 손실 아이디어는 실제에서 때때로 사용되곤 하는데, 그건 여러분 자신의 손실함수를 만들때, 자신의 문제를 위해 여러분이 알고 있어야 할, 또 다른 트릭입니다. 

    여기 작은 넘파이 (numPy)로 벡터화된 코드 조각이 있는데, 이걸 보면 넘파이를 써서 벡터화된 코드 몇줄로 구현하기 쉽다는 것을 알 수 있고, 실제로 여러분이 볼 수 있는 좋은 트릭이 있죠. 여기서 들어가서 맞는 클래스면 마진에서 0으로 없애고요. 좋은 벡터화된 트릭입니다. 하나의 클래스만 빼고 반복하면서, 즉 건너뛰고 싶은 걸 0으로 없애고, 합을 계산하네요. 고려해 볼 만한 좋은 트릭이죠.

    손실 함수에 대한 또 다른 질문인데요. 운이 좋아서 어떤 W를 찾았는데, 손실이 0인거죠. 손실이 전혀 없고, 완벽하게 얻기만 한다고 해보죠. 이 W는 유일할까요? 다른 W들이 또 0 손실을 달성할 수 있을까요? 네 답은 '다른 W도 있다'입니다.

    특히 우리가 스케일링에 대해 좀 얘기 했으니까, W에 따라서 문제 전체를 위 혹은 아래로 스케일링 (scale) 할 수 있죠. 여러분은 W 곱하기 2를 취할 수 있는데, 이 2배의 W도 0 손실을 달성합니다.

    이것의 구체적인 예로, 여러분이 좋아하는 예로 돌아가서 숫자를 가지고 해보죠. 만약 W를 취해서 2배로 하면, 맞는 점수와 틀린 점수의 마진도 2배가 되고, 그 말은 이 모든 마진이 이미 1보다 큰 데, 그걸 두배해서, 여전히 1보다 클 거고 여러분은 여전히 0 로스를 가지죠. 좀 흥미로운 건 만약 어떤 W를 우리가 원하는 지를 우리 손실 함수가 우리가 분류기에 얘기하는 방식이죠. 이게 좀 이상한 건, 여기에 비일관성이 있기 때문입니다. 어떻게 분류기가 모두 0 손실을 달성하는 다른 버전의 W들 중에서 고르는지에 대해서요.

    댓글

Designed by Tistory.