얼굴 검증(Face Verification)은 주어진 사진이 동일 인물인지 아닌지를 구분하는 기능을 말한다. 데이터 베이스에 존재하는 사진과 입력값으로 주어진 이미지가 같은 사람인지를 구분하기 위해서는 학습과정에서 같은 대상의 사진 뿐만 아니라 다른 사람의 사진도 같이 학습할 수 있어야 한다.
비교하려는 사진이 같은 사람인지를 확인하기 위해서는 두 사진이 얼마나 유사한지를 확인해야 한다. 이를 위해서는 적절하게 사진을 벡터로 인코딩을 할 수 있어야 한다. 벡터화된 이미지 사이의 거리를 구하여 최종적으로 같은 사람인지를 판단하게 된다.
인코딩을 이용하여 예측을 하는 이유는 실제 학습 과정에서 사용할 수 있는 사진이 매우 소량인 것에 있다. 얼굴 검증, 인식과 같은 문제는 데이터 베이스에 존재하는 한개의 사진을 통해서 이뤄져야 할 수 있기 때문에(One-shot Learning) 한사람의 다양한 얼굴을 통해 학습할 수 있는 여건이 되지 못한다. 따라서 좋은 인코더 모델을 생성하는 것이 좋은 얼굴 검증 체계를 만들기 위한 기반이 된다.
위의 방식은 두 벡터를 L2 놈의 방식으로 각 요소의 차이에 제곱을 해준 결과를 모두 더한 것을 의미한다. 위의 결과를 바탕으로 일정 기준치를 넘는 다면 같은 인물로 그렇지 않다면 다른 인물로 인식을 하게 된다.
삼항 손실(Triplet Loss)를 이용해서 학습을 하는 이유는 얼굴 검증 문제는 같은 사람(positive) 뿐만 아니라 다른 인물(negative)까지 구분할 수 있어야 하기 때문에 세 정보를 이용하여 손실함수를 만들게 된다. 손실함수를 정의하기 위해선 (anchor), (positive), 마지막으로 (negative)가 필요하다.
def triplet_loss(y_true, y_pred, alpha = 0.2):
anchor, positive, negative = y_pred[0], y_pred[1], y_pred[2]
# Step 1: Compute the (encoding) distance between the anchor and the positive
pos_dist = tf.math.reduce_sum(tf.math.square(tf.math.subtract(anchor, positive)), -1)
# Step 2: Compute the (encoding) distance between the anchor and the negative
neg_dist = tf.math.reduce_sum(tf.math.square(tf.math.subtract(anchor, negative)), -1)
# Step 3: subtract the two previous distances and add alpha.
basic_loss = tf.math.add(tf.math.subtract(pos_dist, neg_dist), alpha)
# Step 4: Take the maximum of basic_loss and 0.0. Sum over the training examples.
loss = tf.math.reduce_sum(tf.math.maximum(basic_loss, 0.0))
return loss
삼항 손실을 이용해서 학습을 시킬 때 가장 중점이 되는 문제는 인식하기 어려운 예제들로 학습을 시키는 것에 있다. 무작위로 예제를 추출하여 기울기 강하를 시킬 경우 더우 쉬운 예제들로 학습된 모델의 경우 실제 상황에서 좋은 성능을 내기 어렵다.
얼굴 인식(Face Recognition) 문제는 단순히 사진간의 유사성을 판단하는 것이 아닌 얼굴을 인식해서 데이터 베이스에 저장된 사진 중 같은 인물이 존재하는지 확인을 할 수 있어야 한다.
def who_is_it(image_path, database, model):
encoding = img_to_encoding(image_path, model)
# Initialize "min_dist" to a large value, say 100
min_dist = 100
# Loop over the database dictionary's names and encodings.
for (name, db_enc) in database.items():
dist = np.linalg.norm(encoding - db_enc)
if dist < min_dist:
min_dist = dist
identity = name
if min_dist > 0.7:
print("Not in the database.")
else:
print ("it's " + str(identity) + ", the distance is " + str(min_dist))
return min_dist, identity
코드에서 보이는 바와 같이 데이터 베이스에 존재하는 모든 사진과 거리를 구하여 임계값을 넘는 유사도가 측정되는 정보가 있다면 그 사진과 이름을 매칭시키는 방식이다.