Computing

Image Embedding과 Triplet Loss 간단 설명 본문

Deep Learning/개념

Image Embedding과 Triplet Loss 간단 설명

jhson989 2023. 10. 18. 23:55

Image Embedding

ChatGPT에 따르면 Image Embedding이란 다음과 같다.

이미지 임베딩(Image Embedding)은 컴퓨터 비전과 기계 학습 분야에서 사용되는 중요한 개념 중 하나입니다. 이것은 이미지를 수치적인 형태로 표현하는 기술입니다. 이미지 임베딩은 컴퓨터가 이미지를 이해하고 처리하기 위해 사용되며, 이미지를 공간적으로 유용한 표현으로 변환하는 과정입니다. 이러한 표현은 이미지 간 유사성을 측정하거나, 이미지를 검색하고 분류하는 데 사용될 수 있습니다.

 

Image Embedding이란 이미지를 저차원의 벡터로 표현하는 방법을 의미한다. N*M 짜리 RGB 이미지가 있다고 하자. 이미지 자체도 사실 컴퓨터가 보기에는 N*M*3 차원 벡터이다. 다만 이미지가 HD 화질이라고 가정한다면 무려 1280×720×3 = 2,764,800 차원의 벡터로 표현된다. 이러한 매우 큰 차원의 벡터는 계산하기에도 매우 부담이 될 뿐만 아니라, 이미지 벡터의 모든 차원이 중요한 정보가 아닐 가능성도 있다. (이미지의 픽셀 1%정도는 사라져도 이미지 구별에는 크게 문제되지 않을 것이다)

 

Image Embedding을 통해 이미지간 구별이 가능할 정도의 저차원의 벡터(ex, 128차원)로 차원 축소가 가능하다면 상당한 이점이 있을 것이다. 예를 들어, 같은 이미지인지의 여부를 확인할 경우 128개의 숫자만을 비교하면 된다. 극단적으로 이미지를 입력순서대로 번호를 매기는 방식을 이용하면 이미지를 1차원 벡터(0번 이미지, 1번 이미지, 2번 이미지, ...)로도 표현할 수 있다. (이 경우 이미지 비교에는 사용될 수 없겠지만...)

 

추가로 Image Embedding 기법은 단순히 이미지 벡터를 저차원으로 차원 축소만을 목표로 하지는 않고, 축소된 차원을 가지는 벡터가 기하학적으로 유용한 의미를 담을수 있도록 한다.  

 

만약 비슷한 이미지는 비슷한 값을 가지도록 변환하는 Image Embedding 방식이 있다고 하자. 비슷한 사진 2개(사진 A, B)가 있다면 각각은 비슷한 값을 가지는 벡터로 변환될 것이고, 이것들과 다른 사진 1개(사진 C)가 있다면 상이한 값을 가지는 벡터로 변환될 것이다. 이러한 Embedding 방식을 이용하면 유사한 사진들끼리의 클러스터링에도 활용할 수 있을 것이다.

 

이처럼 Image Embedding 기법은 이미지를 저차원 벡터로 축소하는 것뿐만 아니라, 이미지 간의 상관관계를 수치화할 수 있는 저차원 임베딩 벡터 공간의 점들로 변환하는 것을 목표로 한다. (유사한 이미지의 벡터간의 거리는 최소화되고, 상이한 이미지의 벡터 거리는 최대화되는 변환 등) 최근에는 이미지의 특징을 스스로 학습하여 뽑아내는 딥러닝 기법을 이용한 Image Embedding 기법이 연구가 많이 진행되고 있다고 한다.

 

 

 

FaceNet과 Triplet Loss

FaceNet[1]은 CNN을 이용해 얼굴 사진을 128차원 벡터로 표현하는 방법을 제안하는 논문이다. Fig 1.은 FaceNet 네트워크를 통해 이미지를 128차원 벡터로 변환하는 과정을 나타내는 그림이다. 중요한 것은, 이때 FaceNet은 비슷한 얼굴을 의미하는 벡터간의 L2 거리는 최소화하고 다른 얼굴을 의미하는 벡터간의 L2 거리는 최대화하도록 변환을 수행한다고 한다. FaceNet이 만드는 128차원 벡터는 얼굴의 특징을 잘 나타내는 것으로 여겨져, FaceNet은 얼굴 인식 분야에서 자주 사용된다고 한다.

 

Fig 1. FaceNet을 이용한 이미지-to-벡터 변환 [2]

 

일반적으로 어떤 Task 용 딥러닝 네트워크를 학습시키기 위해서는 해당 Task에 맞는 데이터를 학습시켜 주어야 한다. 즉 얼굴 간의 유사도를 수치화할 수 있는 FaceNet을 학습시키기 위해서는 당연히 얼굴 간의 유사도 데이터가 준비되어야 한다. 문제는 얼굴 간의 유사도 데이터를 어떻게 준비하냐는 것이다. 사람 A, B, C가 있을 때, A, B, C 얼굴의 유사도를 어떻게 수치화하여 데이터를 만들 것인가? 애초에 얼굴의 유사도를 수치화하지 못하기에 딥러닝을 이용해 보자고 시도하는 것인데, 사람이 유사도를 수치화할 수 있다면 FaceNet이 필요 없지 않을까?

 

얼굴 간의 수치화된 유사도 정보 없이도, 얼굴 간의 유사도를 수치화할 수 있도록 [1]의 저자들은 Triplet Loss를 제안하였다. Triplet Loss의 원리는 다음 Fig 2.와 같다.

 

Fig 2. Triplet Loss의 원리 [1]

 

사람 A의 사진 2장(Anchor, Positive), 사람 B의 사진 1장(Negative)이 있다고 하자. [Anchor와 Positive간의 L2 거리]를 AP 거리, [Anchor와 Negative간의 L2 거리]를 AN 거리라고 한다면

 TripletLoss = AP 거리 - AN 거리

로 정의된다.

 

FaceNet은 Triplet Loss를 최소화하는 방법으로 학습한다. 같은 사람의 벡터간의 거리(i.e. AP 거리)는 작게 만들고, 다른 사람들의 벡터간의 거리(i.e. AN 거리)를 크게 만드는 방향으로 학습하도록 한다. 즉 학습을 거치다보면 AP 거리는 줄어들고, AN 거리는 증가하여 <Triplet Loss = AP - NP>는 감소할 것이다.

 

이처럼 Triplet Loss는 사진에 대한 Label(i.e. 수치화된 저차원 벡터) 없이도 사진들간의 관계를 통해 학습가능하도록 한다. (이를 Self-supervised learning이라고 한다. label을 구하기 쉬운 혹은 컴퓨터가 스스로 labeling 할 수 있는 다른 task를 통해 원하는 task를 풀도록 학습하는 것) 따라서 수치화된 유사도 label이 없이도 유사도 문제를 해결할 수 있다.

 

Triplet loss의 정확한 정의는 다음과 같다.

 

Fig 3. Triplet loss 식 [3]

 

Fig 3. 에서 a, p, n은 각각 anchor, positive, negative의 vector들, 함수 d()는 두 vector간의 거리(L2 거리 등)를 의미한다. 이때 max() 함수와 margin이라는 개념이 등장한다. 일단 max() 함수가 필요한 이유는 쉽게 loss는 0보다 작아지면 안되기 때문이다. loss 자체가 예측과 정답의 틀린 정도를 의미하는데, 틀린 정보가 음수가 되면 말이 안되기 때문이다. 그렇기에 항상 0보다 크거나 같도록 max() 함수를 이용한다.

 

margin은 d(a,p)가 d(a,n)보다 최소 얼마나 더 작아야 하는 지를 의미한다. 예를 들어 margin이 1이면, d(a,p)는 d(a,n) 보다 최소 1보다 작아지도록 학습된다. 이러한 margin은 hyper-parameter로 사용자가 설정하는데 (pytorch에서 default로 1), margin은 학습에서 매우 중요한 역할을 가진다.

 

당연히 상황에 따라 다르겠지만, 개인적인 생각으로 margin을 작게 설정한다면 under-fitting (서로 다른 이미지를 같다고 구분함)이 발생하고, margin을 크게 설정한다면 over-fitting(비슷한 이미지도 다르다고 구분함)이 발생할 수 있을 것 같다. 

 

 

 

Reference

[1] F. Schroff, D. Kalenichenko and J. Philbin, "FaceNet: A unified embedding for face recognition and clustering," 2015 IEEE Conference on Computer Vision and Pattern Recognition (CVPR), Boston, MA, USA, 2015, pp. 815-823, doi: 10.1109/CVPR.2015.7298682.

[2] https://arsfutura.com/magazine/face-recognition-with-facenet-and-mtcnn

[3] computer vision - What's the triplet loss back propagation gradient formula? - Stack Overflow