본문 바로가기
Coursera 강의/Deep Learning

Face recognition

by 별준 2020. 11. 30.
해당 내용은 Coursera의 딥러닝 특화과정(Deep Learning Specialization)의 네 번째 강의 Convolutional Neural Networks를 듣고 정리한 내용입니다. (Week 4)

[What is face recognition?]

얼굴 인식 분야에서 세부적으로 얼굴 검증(Verification)과 인식(Recognition)으로 분류된다.

Face Verification의 경우에는 사람의 이름이나 ID, 이미지가 주어졌을 때, 이 사람이 맞는가에 대한 여부를 확인한다. 1:1 문제라고도 부르고, 요청한 그 사람이 맞는지 여부를 알게 한다. 

반면에 Face Recognition의 경우에는 1:K 문제라고도 하는데, K 명의 database가 있으면 주어진 이미지를 통해서  K명의 database에 속하는 사람인 지를 판단해야한다. 

얼굴 인식은 얼굴 검증 문제보다 훨씬 어려운데, 99%의 정확성을 갖춘 인식 시스템일지라도 데이터베이스에 100명이 있다면 오차가 생길 확률은 100명 중에 한명꼴로 발생한다. 따라서 허용 가능한 오류를 원한다면 실제로 99.9%이상의 정확성을 갖추어야 할 수 있다.

 

[One Shot Learning]

얼굴 인식에서의 도전 중에 하나는 One Shot Learning 문제를 해결해야한다는 것이다. 대부분 얼굴인식 application에서 이것이 의미하는 바는 한 사람을 인식하는데, 하나의 이미지만 주어진다는 것이다. 

전통적으로, 딥러닝 알고리즘은 one training example을 가지고 있다면 성능이 좋지 않았다. 

위의 예시를 살펴보자. 4명의 등록된 직원이 있고, 사무실 누군가가 게이트를 지난다고 가정해보자. 게이트의 시스템은 각 직원의 사진 하나씩만을 가지고, 게이트를 지나는 사람이 직원인지 아닌지 인식해야 한다. 따라서 One Shot Learning 문제에서는 한 가지 example만을 통해서 그 사람을 다시 인식해야한다. (대부분의 얼굴 인식 시스템에 필요한 성능이다)

그래서 시도해볼 수 있는 방법 중의 하나는 직원 데이터베이스의 이미지를 ConvNet의 입력으로 사용해서 Output Y 레이블을 출력하게 한다. 직원이 4명이기 때문에 인식하지 못하는 경우까지 총 5개의 label의 가진 softmax uint output이 된다. 

하지만, 이 방법은 실제로는 잘 동작하지 않는다. 이렇게 작은 training set으로는 deep neural network를 훈련시키기에 충분하지 않기 때문이다. 

그리고 새로운 직원이 추가된다면 어떻게 될까? 

5개의 output에서 6개의 output으로 바껴야하고, ConvNet을 다시 학습시켜야 할까?

이 방법은 좋은 방법이 아니다. 

 

따라서, 얼굴 인식에서 one shot learning을 수행하기 위해서 할 수 있는 방법은 similarity funcion을 학습하는 것이다.

즉, 두 이미지의 차이 정도를 output으로 출력하는 similarity function를 학습하는데, 이미지가 많이 다르면 값이 크고, 유사하다면 값이 작다. 그래서 어느 정도 이상 크다면 같은 사람으로 인식하고, 작다면 다른 사람으로 인식한다.

따라서 새로운 이미지가 주어진다면, similarity 함수를 사용해서 두 이미지를 비교한다.

위의 경우에는 왼쪽 두번째 이미지와의 similarity 함수 값이 가장 작기 때문에 같다라고 판단한다.

이렇게 similarity 함수를 통해서 새로운 사람이 추가되어도 재학습할 필요없이 잘 동작할 수 있게 된다.

 

[Siamese network]

위에서 배웠던 d함수는 두 얼굴 이미지를 입력하고, 두 이미지가 얼마나 유사한지, 얼마나 다른지 알려준다. 이것을 수행하기 좋은 방법은 Siamese network를 사용하는 것이다.

위의 ConvNet에서 \(x^{(1)}\)라는 이미지를 입력하면 일련의 convolution, pooling, fc를 통해서 feature vector로 마무리되고, softmax unit으로 분류를 하는 것에 익숙한데, 이번 강의에서는 출력단은 제거하고 feature vector에 초점을 맞출 것이다. 이 feature vector는 fc에 의해서 계산된 값이다.

이 feature vector의 이름을 \(f(x^{(1)})\)이라고 부르고, 이 함수는 \(x^{(1)}\)의 input 이미지를 encoding하는 것이라고 생각하면 된다. 즉, input 이미지를 취해서 128개의 feature vector로 encoding하는 것이다.

 

이것을 이용해서 얼굴 인식 시스템으로 구축할 수 있는 방법은 두 장의 사진을 동일한 파라미터를 가진 신경망을 통해서 이 128개의 feature vector를 각각 얻어서 비교한다.

따라서 두 이미지 \(x^{(1)}, x^{(2)}\)를 신경망을 통해서 인코딩된 \(f^{(1)}, f^{(2)}\)를 얻을 수 있다. 

이렇게 인코딩된 값이 두 이미지를 잘 나타낸다고 생각한다면, \(x^{(1)}\)과 \(x^{(2)}\) 사이의 거리 d를 구할 수 있는데, 거리 d는 두 이미지의 인코딩된 값 차이의 norm으로 정의할 수 있다.

 

이렇게 두 개의 서로 다른 인풋을 동일한 ConvNet을 통해서 인코딩된 값을 얻어서 비교하는 개념을 Siamese Neural Network Architecture라고 부르기도 한다.

이 아이디어는 DeepFace 논문에서 비롯되었다.

정리하자면,

  • 신경망의 파라미터를 \(f(x^{(i)})\)의 인코딩으로 정의하고,
  • 같은 두 사람의 이미지 \(x^{(i)}, x^{(j)}\)가 있다면, 이 인코딩 사이의 norm을 최소화하는 것이다. 만약 두 이미지가 다르다면, 인코딩 사이의 norm이 커야한다.

다음으로 d함수를 학습하기 위해서 loss function을 어떻게 정의해야되는지 살펴보자.

 

[Triplet loss]

신경망의 파라미터를 학습해서 얼굴 인식을 위한 좋은 인코딩을 학습하는 방법은 triplet loss function을 적용한 GD를 정의하는 것이다. 

Triplet Loss를 적용하려면, 이미지 쌍을 서로 비교해야한다. 위의 예시처럼 동시에 여러 이미지를 살펴봐야하는데, 왼쪽의 이미지 쌍은 같은 사람이기 때문에 인코딩이 유사해야되고, 오른쪽 이미지 쌍은 다른 사람이기 때문에 인코딩이 꽤 차이가 나야한다. 

여기서 Triplet Loss는 하나의 Anchor 이미지를 두고, Positive와 Negative와의 사이의 거리를 동시에 살펴본다.

즉 Anchor-Positive의 인코딩과 Anchor-Negative의 인코딩 차이를 같이 살펴본다는 것이다.

(Anchor는 A, Positive는 P, Negative는 N으로 축약한다.)

 

위 내용을 공식으로 나타내면 다음과 같다.

A와 P는 같은 사람이기 때문에 d(A, P)가 작고, A와 N은 다른 사람이기 때문에 d(A, N)이 크다. 따라서 d(A, P)가 d(A, N)보다 작도록 하는 것이 목표이다.

하지만 주의해야할 점이 있는데 모든 이미지의 인코딩이 같아지면 안된다. 모든 이미지의 인코딩이 같아진다면, d(A, P)와 d(A, N)이 모두 0이 되어서 위 공식을 항상 만족하게 된다. 

위와 같은 상황을 방지하기 위해서 \(\alpha\)라는 하이퍼 파라미터를 추가하는데, margin이라고 부르기도 한다.

 

margin의 역할은 다음과 같다.

d(A, P) = 0.5 / d(A, N) = 0.51 이라면 margin이 없을 때에는 공식이 만족하게 된다(다른 사람임에도 불구하고 d(A,N)이 더크다). 하지만, \(\alpha = 0.2\)가 존재한다면, d(A, N)이 0.7이 되거나 d(A, P)가 0.31이 되는 식으로 학습을 가능하도록 만들어 준다.

즉, A-P와 A-N이 서로 더 멀어질 수 있도록 하는 역할을 한다.

 

Triplet Loss Function을 정의하면 다음과 같다.

\[\mathscr{L}(A,P,N) = \text{max}(\| f(A) - f(P) \|^2 - \| f(A) - f(N) \|^2 + \alpha, 0)\]

0보다 작다면, 같은 사람이라고 판단하고 0으로 설정한다.

Cost는 

\[J = \sum_{i=1}^{m}\mathscr{L}(A^{(i)},P^{(i)},N^{(i)})\]

로 정의된다.

 

training set으로는 1,000명의 사람들의 사진 10,000장으로 위와 같이 triplet을 생성하고 GD를 사용해서 학습시키면 된다. 한 사람당 평균 10장의 사진을 가지고 데이터를 구성하는데, 각 사람의 사진이 하나뿐이라면 이 시스템을 실제로 훈련할 수는 없다.

물론, 학습이 완료된 후에는 얼굴 인식 시스템을 위한 One Shot Learning에 적용할 수는 있다. 하지만, 학습할 때 training set에서는 Anchor / Positive의 쌍을 이룰 수 있도록 몇몇 사람들만이라도 동일한 사람의 이미지가 여러 개가 있는지 확인하는 것이 필요하다.

 

그리고, A-P는 같은 사람이고 A-N은 다른 사람이기 때문에 무작위로 고를 때, A-N의 데이터가 매우 많이 뽑힐 확률이 높다. 따라서 training set를 구성할 때는 훈련하기 어려운 A,P,N 중의 하나를 선택하는 것이 중요하다.

같은 사람이지만 d(A,P) 값은 낮고, 다른 사람이지만 d(A,N)의 값이 높은 set로 구성을 한다면 학습에 더욱 도움이 될 것이다.

 

정리를 하면,

  • Triplet Loss를 가지고 학습하기 위해서는 training set에서 A-P와 A-N의 쌍을 매핑해야 하고,
  • 이 training set를 가지고 Cost J를 최소화하기 위해 GD를 사용한다.
  • 학습은 같은 사람일 경우에는 d가 최소가 되고, 다른 사람일 경우에 d가 최대가 되도록 최적화된다.

 

[Face Verification and Binary Classification]

Triplet Loss는 얼굴 인식을 위한 ConvNet의 파라미터 학습에 좋은 방법 중의 하나이다. 

또 다른 방법으로는 얼굴 인식을 Binary Classification 문제로 변형해서 사용할 수 있는데, 한 번 살펴보도록 하자.

이미지를 128개의 feature vector로 나타내기 위해서 ConvNet을 통과시켜 embeding(encoding)시키고, 128개의 feature vector를 Logistic Regression을 통해서 예측하도록 한다. 목표 output은 두 이미지가 같다면 1을 출력하고, 다른 사람이라면 0이 된다. 

따라서, 얼굴 인식을 Binary Classification 문제로 취급하는 것이다.

output \(\hat{y}\)는 sigmoid 함수이고, 인코딩된 값들 사이에서 차이점을 알아내서 예측한다.

 

공식으로 나타낸다면 다음과 같이 나타낼 수 있다.

인코딩된 값의 차이를 구하는 수식에는 다양한 방법이 있으며, 초록색으로 나타낸

\[\frac{(f(x^{(i)})_k - f(x^{(j)})_k)^2}{f(x^{(i)})_k - f(x^{(j)})_k}\]

으로 사용할 수도 있다. 이는 카이 제곱 유사도라고 불린다.

 

그리고, 이 방법을 사용할 경우에 유용한 방법이 하나 있는데, database에서 이미지가 입력으로 사용된다고 한다면, 매번 embeding을 다시 할 필요없이, embeding된 값을 저장해서 ConvNet을 통과시킬 필요없이 바로 예측에 사용할 수 있다.이 방법을 사용하면 이미지를 저장할 필요가 없고, 데이터베이스가 매우 큰 경우에도 매번 모든 사원의 인코딩을 계산할 필요가 없기 때문에 효율이 높아진다.

 

댓글