딥러닝 기반 얼굴 인식이나 텍스트/이미지 임베딩을 다루다 보면 거의 항상 등장하는 개념이 있다.
바로 Cosine Similarity(코사인 유사도)다.
FaceNet, ArcFace 같은 얼굴 인식 모델뿐 아니라 CLIP, SBERT 같은 최신 임베딩 모델들도 대부분 코사인 기반으로 유사도를 계산한다. 단순히 “벡터 유사도 계산 방법 중 하나”라서 사용하는 것이 아니라, 딥러닝 임베딩 공간의 구조와 매우 잘 맞기 때문에 사실상 표준처럼 사용된다.
왜 딥러닝에서 코사인 유사도가 많이 사용되는지, 그리고 FaceNet과 ArcFace가 왜 cosine 기반 loss를 사용하는지까지 딥러닝 관점에서 자세히 정리해 보려고 한다.
먼저 딥러닝 모델이 얼굴이나 문장을 어떻게 표현하는지부터 이해할 필요가 있다.
얼굴 인식 모델은 입력 이미지를 그대로 비교하지 않는다. 대신 CNN이나 Transformer를 통해 고차원 임베딩 벡터(embedding vector)를 생성한다. 예를 들어 얼굴 이미지를 모델에 넣으면 다음과 같은 512차원 벡터가 나온다.
[0.12, -0.44, 0.87, ..., 0.31]
이 벡터는 해당 얼굴의 특징을 표현하는 수치 표현이다.
얼굴 인식 시스템은 이렇게 생성된 벡터를 데이터베이스에 저장하고, 새로운 얼굴이 들어왔을 때 벡터 간 유사도를 계산해 같은 사람인지 판단한다.
두 벡터가 얼마나 비슷한지 측정하는 방법은 대표적으로 두가지가 있다.
- Euclidean Distance (유클리드 거리)
- Cosine Similarity (코사인 유사도)
유클리드 거리는 distance(x, y) = ||x - y|| 익숙한 거리 개념이다.
반면에 코사인 유사도는 cos(θ) = (x · y) / (||x|| ||y||) 두 벡터 사이의 각도를 이용해 유사도를 계산한다. 값의 범위는 -1에서 1 사이이며, 1에 가까울수록 두 벡터의 방향이 비슷하다.


딥러닝 임베딩에서는 보통 벡터의 크기보다 방향이 더 중요한 의미를 갖는다.
예를 들어 같은 사람의 얼굴 두 장이 있다고 하자. 조명이나 해상도 때문에 모델이 생성한 임베딩 벡터의 크기는 달라질 수 있다.
x = [0.2, 0.4, 0.1]
y = [0.4, 0.8, 0.2]
이 두 벡터는 사실상 같은 방향을 가리키고 있다. 단지 스케일만 다르다. 이런 경우 유클리드 거리로 보면 두 벡터는 꽤 멀어 보일 수 있다. 하지만 코사인 유사도를 계산하면 거의 1에 가까운 값이 나온다. 즉 코사인 유사도는 벡터의 방향을 기준으로 유사도를 측정한다.
딥러닝 임베딩에서는 바로 이 특성이 중요하다. 모델이 학습하는 것은 절대적인 숫자가 아니라 특징 패턴의 방향이기 때문이다.
실제로 많은 얼굴 인식 모델은 임베딩 벡터를 생성한 뒤 다음과 같은 L2 normalization을 수행한다.
x = x / ||x||
이렇게 하면 모든 임베딩 벡터의 길이가 1이 된다. 즉 모든 벡터가 단위 구면(unit hypersphere) 위에 존재하게 된다.
이 상태에서는 벡터 간 관계가 사실상 각도(angle) 로 표현된다. 벡터의 길이는 모두 동일하므로 두 벡터가 얼마나 비슷한지는 각도가 얼마나 작은지로 결정된다.
이때 유클리드 거리와 코사인 유사도의 관계를 살펴보면 흥미로운 사실이 나온다. 두 벡터가 정규화되어 있다고 가정하면
||x|| = 1
||y|| = 1
이때 유클리드 거리 제곱은 다음과 같이 전개된다.
||x - y||² = ||x||² + ||y||² - 2x·y
= 1 + 1 - 2x·y
= 2 - 2cos(θ)
즉 L2 normalization을 하면 유클리드 거리와 코사인 유사도는 사실상 같은 정보를 표현하게 된다. 단지 표현 방식만 다를 뿐이다. 이 때문에 딥러닝 임베딩에서는 보통 해석이 직관적인 코사인 유사도를 사용하는 경우가 많다.
FaceNet은 얼굴 인식 분야에서 큰 영향을 준 모델이다. 이 모델은 Triplet Loss라는 방식을 사용해 임베딩을 학습한다.

Triplet Loss는 세 개의 샘플을 사용한다.
- Anchor (기준 얼굴)
- Positive (같은 사람의 다른 사진)
- Negative (다른 사람의 얼굴)
학습 목표는 다음과 같다.
distance(anchor, positive) + margin < distance(anchor, negative)
같은 사람의 얼굴은 더 가깝게, 다른 사람은 더 멀어지도록 학습한다.
FaceNet 역시 임베딩을 정규화하기 때문에 결국 각도 기반으로 얼굴을 구분하는 구조가 된다.
하지만 Triplet Loss는 학습 효율이 좋지 않았다는 문제가 있다. 어떤 triplet을 선택하느냐에 따라 학습 성능이 크게 달라지기 때문이다. 그래서 이후 연구에서는 classification 방식과 metric learning을 결합한 새로운 방법들이 등장했다.
대표적인 것이 ArcFace다.
ArcFace는 일반적인 softmax 분류 구조를 기반으로 한다. 원래 softmax classifier는 다음과 같은 형태로 동작한다.
logit = W · x
여기서 W는 classifier weight이고 x는 feature vector다.
하지만 이 방식에는 문제가 있다. 모델이 분류 성능을 높이기 위해 벡터의 크기를 키워버릴 수 있다.
즉 임베딩 공간이 “유사도 기반 구조”가 아니라 단순히 분류 정확도를 높이는 방향으로 왜곡될 수 있다.
그래서 ArcFace는 두 가지 제약을 추가한다.
첫째, feature vector normalization이다.
||x|| = 1
둘째, classifier weight normalization이다.
||W|| = 1
이렇게 하면 분류 score가 다음과 같이 바뀐다.
W · x = cos(θ)
즉 classifier 자체가 각도 기반 분류기가 된다. 얼굴 인식 문제를 “각도 분리 문제”로 바꾸는 것이다.
하지만 여기서 또 하나의 문제가 있다. 같은 사람의 얼굴이라도 decision boundary 근처에 위치할 수 있다. 즉 intra-class 분포가 충분히 compact하지 않을 수 있다. 이를 해결하기 위해 등장한 개념이 margin이다.
CosFace는 다음과 같은 margin을 사용한다.
cos(θ) - m
즉 cosine 값에서 일정 값을 빼서 decision boundary를 조정한다.
ArcFace는 여기서 한 단계 더 나아간다. ArcFace는 cosine 값에 margin을 빼는 대신 각도 자체에 margin을 추가한다.
cos(θ + m)
이 방식이 중요한 이유는 기하학적으로 더 자연스럽기 때문이다.
임베딩 공간이 단위 구면 위에 존재하므로 실제 분리는 각도 기준으로 이루어져야 한다. ArcFace는 바로 이 각도 기준 margin을 직접 적용한다.
이렇게 하면 같은 사람의 얼굴은 더 작은 각도로 모이게 되고, 다른 사람은 더 멀어지게 되어 아래와 같은 효과가 생긴다.
- intra-class compactness 증가
- inter-class separability 증가
결과적으로 임베딩 공간이 다음과 같이 변한다.
기존 softmax에서는 클래스 분포가 서로 겹칠 수 있지만 ArcFace를 적용하면 각 클래스가 구면 위에서 명확하게 분리된 클러스터를 형성하게 된다. 이러한 구조 덕분에 ArcFace는 LFW, MegaFace 같은 얼굴 인식 벤치마크에서 매우 높은 성능을 기록했다.
지금까지 내용을 정리해보면 딥러닝 임베딩에서 코사인 유사도가 널리 사용되는 이유는 크게 세 가지다.
첫째, 딥러닝 임베딩에서는 벡터의 크기보다 방향이 의미를 담는 경우가 많다.
둘째, L2 normalization을 적용하면 임베딩 벡터가 unit hypersphere 위에 존재하게 되고 유사도는 각도로 표현된다.
셋째, ArcFace 같은 최신 얼굴 인식 모델은 angular margin을 통해 임베딩 공간을 더욱 명확하게 분리한다.
이러한 이유 때문에 얼굴 인식뿐 아니라 텍스트 임베딩, 이미지 검색, 추천 시스템 등 다양한 분야에서 “Embedding + Cosine Similarity” 구조가 사실상 표준처럼 사용되고 있다.