반응형

원본 링크



Large Scale Face Recognition for Deep Learning

얼굴 인식 기술은 주로 얼굴 검증(face verification)이 기본이다. 모든 시나리오는 두개의 얼굴 사진을 CNN(Convolutional Neural Networks)에 전달하고 그것의 벡터 표현을 찾는 것에 의존한다. 그리고 결정은 이들 벡터간의 거리로 결정되지만 이 부분은 어렵지 않다.

반면 CNN 모델을 구축하는 것과 이것의 예측 함수를 호출하는 것 모두 비용이 비싼 연산이다. 그렇기 때문에 대규모 데이터셋에 얼굴 인식을 적용하는 것은 문제있어 보인다. 이 글에서는 쉽고 빠른 방법으로 대규모 얼굴 인식을 다루기 위한 해결방법을 알아본다.


Jason Bourne



얼굴인식 파이프라인(A Face Recognition Pipeline)

현대 얼굴 인식 파이프라인의 흐름을 기억하자.


탐지(detect), 정렬(align), 표현(represent), 검증(verify)의 4단계로 구성된다. 이 글에서는 표현과 검증 단계에 집중할 것이다.



Big O Notation

우선, 점근 표기법(Big O Notation)으로 얼굴 검증은 O(1) 복잡도를 갖는 반면 얼굴인식은 O(n) 복잡도를 갖는다. 즉, 얼굴인식은 얼굴검증 함수를 n번 호출해야 한다는 것이다. 여기서 n은 데이터베이스에 있는 인스턴스의 수이다.



Vlog

이제, 아래 비디오를 보거나 이 글을 계속 읽을 수 있다. 둘 다 대규모 얼굴 인식에 관한 주제이다.




근사 최근접 이웃(Approximate Nearest Neighbor)

그러나, 수백만개의 데이터레벨에서는 문제가 있을 수 있다. 이런 경우, 복잡도를 줄이기 위해 근사 최근접(approximate nearest neighbor) 알고리즘을 적용할 수 있다. Spotify Annoy, Facebook Faiss, NMSLIB는 매우 유명한 a-nn 라이브러리이다.


여기서 Elasticsearch는 NMSLIB를 포함하지만 매우 확장성이 뛰어난 특성도 함께 있다. 우리는 이것을 많은 클러스터에서 실행할 수 있다.




얼굴인식은 복잡한 작업이다(Face recognition is a complex task)

얼굴인식 모델을 구축하는 것과 이것의 예측 함수를 호출하는 것 모두 비용이 비싼 연산이다.


Time complexity of face recognition models

위 테이블을 기준으로 100개의 샘플로 구성된 데이터셋에서 얼굴을 찾는데 필요한 시간을 상상해 보자.

모델을 구축하는 시간과 100번의 검증 시간이 필요하다는 것은 받아들이기 힘들다.



The hacker’s way

데이터베이스에 수백장의 얼굴 사진을 가지고 있다고 하자. 파이프라인의 검증 단계는 데이터베이스내 각 이미지 벡터와 목표 이미지의 벡터간 거리(distance)를 찾아야 한다.

비결은 데이테베이스에 얼굴의 벡터표현을 이미 저장할 수 있다는 것이다.


from deepface.commons import functions
from deepface.basemodels import VGGFace, OpenFace, Facenet, FbDeepFace
#--------------------------
model = VGGFace.loadModel()
input_shape = model.layers[0].input_shape[1:3]
#--------------------------
employees = []

for r, d, f in os.walk(db_path): # r=root, d=directories, f = files
    for file in f:
        if ('.jpg' in file):
            exact_path = r + "/" + file
            employees.append(exact_path)
#--------------------------
representations = []
for employee in employees:
    img = functions.detectFace(employee, input_shape, enforce_detection = enforce_detection)
    representation = model.predict(img)[0,:]

    instance = []
    instance.append(employee)
    instance.append(representation)
    representations.append(instance)
#--------------------------
import pickle
f = open('representations.pkl', "wb")
pickle.dump(representations, f)
f.close()

따라서 우리는 이미 얼굴인식 작업 호출시 데이터베이스에 존재하는 신원에 대한 표현을 가지고 있게 된다.

그리고 얼굴을 찾을 때 오직 하나의 목표 얼구에 대한 벡터 표현만을 찾아야 한다.


from deepface.commons import functions
target_img = functions.detectFace(target, input_shape)
target_representation = model.predict(target_img)[0,:]

게다가 이미 얼굴인식 모델을 구축하여 목표 얼굴을 기다릴 수 있다. 이런 경우 검증 열에서 언급했던 시간이 필요하다. 최악의 경우에 1초 미만으로 지속된다.

그러면 필요한 모든 것은 목표와 소스 이미지 벡터간 거리를 찾는 것이다. 이것은 매우 빠르게 다뤄질 수 있다.


#load representations of faces in database
f = open('representations.pkl', 'rb')
representations = pickle.load(f)

distances = []
for i in range(0, len(representations)):
    source_name = representations[i][0]
    source_representation = representations[i][1]
    distance = dst.findCosineDistance(source_representation, target_representation)
    distances.append(distance)
#find the minimum distance index
idx = np.argmin(distances)
matched_name = representations[idx][0]

(저자의) 실험은 얼굴인식 모델이 이미 구축되었다면 10개의 인스턴릇로 구성된 데이터셋에서 신분을 찾는 것은 1초 미만에 완료되는 것을 볼 수 있다.



근사 최근접 이웃(Approximate nearest neighbors)

얼굴인식은 실제 k-nn(k-nearest neighbor) 알고리즘의 형태이고 O(n X d)배의 복잡도를 갖는다. 여기서 n은 인스턴스의 수, d는 펩터 차원의 수이다. 이것은 수백만의 데이터에서 문제일 수 있다.

근사 최근접 이웃 알고리즘은 훨씬 더 빠르게 최근접 이웃을 찾는다. Annoy는 a-nn알고리즘을 구현한 Spotify engineering team이 개발한 소프트웨어 패키지이다. 이것은 시간 복잡도(time complexity)를 O(log n)으로 줄여준다.



DeepFace

DeepFace는 이 동작을 조작하기 위해 바로 사용할 수 있는 find 함수를 제공한다. 이 모든 단계는 백그라운드에서 동작한다.


DeepFace

보이는 것과 같이 단지 몇줄의 코드로 조작할 수 있다.



Conclusion

이 글에서는 대규모 얼굴인식에 대해 알아보았다. 비록 얼굴인식 파이프라인 구축이 복잡한 절차라도 해결책을 찾는 몇가지 해킹 기술을 적용하는 방법으로 대규모 데이터셋에더 단지 몇초안에 원하는 얼굴을 찾을 수 있다.

여기에서 소스코드를 찾을 수 있다.

반응형

+ Recent posts