본문 바로가기

회고록/포스코 AIㆍBig Data 아카데미

[Part 1] 용의자의 신발을 찾아라: AI 기반 족적 검색 시스템을 개발하기까지 겪었던 시행착오들

연구 인턴을 통해 내가 얻은 것

포스코 빅데이터 아카데미를 마치고 운좋게 연구 인턴에도 선정이 되어, 두 달동안 AI 연구 개발에 매진할 수 있었다.

내 성과를 요약하자면 '막다른 길을 용감하게 찾아냈고 새로운 방안을 제시한 것'이라고 포장할 수 있겠다.

그 과정에서 물론 안타까운 시행착오도 겪었고 계획대로 되지 않았던 순간도 많았지만

AI 분야와 개발 전반에서 평생 기억할 만한 인사이트를 얻었다고 생각한다.

 

내가 진행했던 연구를 크게 두 편으로 나누어 정리해보았다.

 

 

 

연구 배경

작년(2023년) 10월 중순부터 두달 간 포항공대 인공지능연구원(PIAI)에서 인턴을 하면서 진행했던 연구 내용을 정리했다.

연구원에서 진행하는 주제는 다양했지만 그 중 내가 맡은 프로젝트는 <폴리스랩 2.0>의 일환이었다.

 

폴리스랩 2.0은 2023년부터 과기부와 경찰청 주도로 진행하는 연구 개발 사업으로,

경찰의 치안・수사 업무에 과학 기술을 적용해서 치안 역량을 강화하고 서비스를 향상하고자 하는 게 목표다.

 

이 폴리스랩 사업에 PIAI가 연구 업체로 선정되었고 나는 그 중 <AI 기반 족적 자동 검색 시스템>이라는 프로젝트에 가담하게 되었다.

 

 

 

 

족적이란?

족적(跡). 말은 어렵지만 신발 족 자에 발자취 적 자를 쓰니까 결국 신발 자국이라는 뜻이다. 

그러면 왜 신발 자국을 가지고 연구할까? 바로 신발 자국이 범죄 용의자를 잡는 데 결정적인 증거가 될 수 있기 때문이다.

 

 

그림만 봐도 딱 감이 오지 않는가? 용의자가 현장에 남긴 신발 자국을 잘만 확보한다면 확실한 물증으로 제출할 수 있다.

 

 

 

 

족적 검색 시스템이 작동하는 방식

족적이 왜 필요한지 알았다면, 이제 족적 검색 시스템이 작동하는 방식을 이해할 차례다.

 

 

검색 시스템의 개요

 

 

용의자가 현장에 남긴 신발 자국을 잘 수집해서 이미지로 저장한다. 이런 이미지를 '현장 이미지' 또는 '유류 이미지'라고 한다.

 

  1. 수사기관(경찰청)이 확보한 족적 이미지 데이터베이스에서 현장 족적과 유사한 이미지를 검색한다.
  2. 데이터베이스에 저장된 신발 자국 이미지를 '등록 이미지' 또는 'DB 이미지'라고 한다.
  3. 신발 자국의 크기, 모양, 문양 패턴 등을 비교하여 현장 족적과 가장 유사한 이미지를 선택한다.
  4. 가장 유사한 등록 이미지에 해당하는 신발 모델(A)을 찾아서 용의자가 실제로 모델 A의 신발을 신었는지 확인한다.

 

검색 시스템을 구축하려면 결국 양질의 등록 이미지를 많이 확보해놓아야 하는데,

이 등록 이미지 DB는 어떻게 구축한 걸까?

 

내가 건너 들은 바로는 경찰청 관계자분들이 초창기에 시장에서 신발을 사다가 일일이 신발 밑창을 프린팅한 다음 DB에 등록했다고 한다.

그리고 일부 유명한 신발 브랜드들은 밑창 이미지를 따로 갖고 있기 때문에 경찰청이 협조를 요청해서 그 이미지를 넘겨받는다고 하는데,

이 신발 밑창 이미지 데이터베이스를 초창기부터 구축했던 분들의 노고를 상상하면 정말 짐작이 잘 안 갈 정도다.

 

 

 

 

기존 검색 시스템의 문제점

기존에 경찰청이 보유한 족적 검색 시스템의 문제는 무엇일까?

기대보다는 등록 이미지를 정확하게 찾지 못한다는 점이다.

그래서 하나의 현장 이미지를 입력하면 수백, 수천장의 비슷한 이미지를 출력한다.

그리고 이렇게 컴퓨터가 한 차례 걸러낸 등록 이미지들을 사람이 일일이 현장 이미지와 비교하고 대조해야 한다.

 

즉, 용의자의 신발 자국이 어떤 신발인지 알아내기 위해서는

족・윤적을 전문적으로 다루는 감정관들이 많게는 수천 장의 이미지를 하나씩 눈으로 확인해가면서 비교・대조해야 한다는 뜻이다.

 

 

연구 목표: AI를 이용해서 자동으로 이미지를 찾자

그럼 이 번거롭고 힘든 작업을 컴퓨터의 도움을 받아서 쉽게 할 순 없을까? 라고 생각할 수 있고,

그래서 등장한 게 AI이다. 인공지능의 본질은 사람이 하던 힘든 일을 기계에게 외주 맡기는 것이기 때문이다.

 

결국 내가 맡은 연구의 핵심을 한 문장으로 정리하면

'사람 대신 AI가 자동으로 신발 자국 이미지를 찾게 하자'라고 할 수 있겠다.

 

 

 

 

 

족적 자동 검색 시스템이 생각보다 어려운 이유

내가 처음 연구 주제를 들었을 땐 금방 끝낼 수 있을 거라 자신만만했다.

복잡한 생성형 AI를 쓰는 것도 아니고, 생소한 LLM을 쓰는 것도 아닌데 학습 데이터는 단순 2D 이미지네?

Task도 결국엔 이미지 검색(image retrieval)이니 관련 SoTA 모델만 잘 찾아서 적용하면 되겠다 싶었다.

그런데 막상 좀 더 공부하고 보니 만만치 않은 문제라는 걸 깨달았다. 왜일까?

 

 

1. 신발 자국 이미지는 절대적으로 부족하다

인공지능을 한 번이라도 배워본 사람이라면 알겠지만 AI란 결국 데이터 싸움이다.

딥러닝 모델을 제대로 학습하려면 기본적으로 수 천장 단위의 이미지 데이터가 필요하다.

 

하지만 신발 자국 이미지는 구하기 정말 쉽지 않았다.

신발 자국 이미지를 확보한 주체는 대부분 수사기관인데 선뜻 자기 데이터를 외부에 공개하려는 수사기관이 있을 리 만무하기 때문이다.

설마 악용될 리가 있겠느냐만, 보안을 철저히 다루는 수사기관인만큼

실제 범죄 현장에서 수집한 신발 자국 이미지를 일반인에게 공유하는 게 힘든 건 납득이 간다.

 

그래도 선한 마음씨를 가진 연구자들이 작게나마 구축한 데이터셋이 몇 개 알려져 있다.

현재 인터넷에서 찾을 수 있는 족적 이미지에 대한 공개 데이터셋을 정리해보았다.

 

  1. FID-300: 현장(300장) + 등록(1175장) 이미지, 약 100MB
  2. WVU2019: 혈흔, 먼지 등 수집 방식에 따라 597장의 이미지 수집
  3. 2D Footwear outsole impressions hosted at Iowa State University: 150켤레 신발에 대한 총 1500장의 이미지를 수집
  4. Walmart Shoe Database: 월마트가 확보한 신발 밑창(RGB 이미지) 및 모델 정보 데이터

 

데이터셋의 규모를 보면 대부분 천 장 단위, 적게는 백 장 단위인 게 대부분이다.

딥러닝 모델의 컴퓨터 비전 task 벤치마크 데이터셋 중 하나인 ImageNet1K가 약 1백20만장인 걸 감안하면 터무니없이 작은 편이다.

 

참고로 쓸만한 오픈 데이터셋을 찾아 뒤지다가 Everspry라는 중국 회사를 발견한 분이 계실지 모르겠다.

나도 이 링크(http://wx.f.menshoeslist.com/everen/service/data_open.htm)로 들어갔는데,

족적 이미지(무려 10만장!)를 공유하는 줄 알고 이메일로 몇 번이나 요청했지만 답은 끝내 오지 않았다.

어차피 안 주는 것 같으니 나처럼 헛된 희망을 품지 마시길...!

 

 

 

 

2. 흐릿하고, 뭉개져있고 불분명한 신발 자국들

족적 검색 모델 개발이 어려운 이유는 사실 족적 데이터 그 자체에 있다.

백문이 불여일견이라고, 외부 공개 데이터셋 FID-300의 현장 이미지(tracks_cropped) 몇 장을 먼저 살펴보자.

 

 

 

 

저 사진에서 신발 자국을 제대로 구별할 수 있는가?

물론 패턴과 문양이 보이긴 하지만 사람 눈으로 확인하는 걸로는 만족할 수 없다.

우리 목표는 컴퓨터에게 저 이미지를 주고는 신발 모델을 찾아내도록 시켜야 하기 때문이다.

 

위에서 보여준 이미지는 그나마 상태가 양호한 편이다. 

실제 현장 이미지는, '이걸 사람 눈으로도 정말 알아볼 수 있을까?' 싶을 정도로 열악한 경우가 대부분이다.

 

신발 자국 중 일부만 찍혀있는 건 양반이고 아예 흐릿해서 안 보이거나 신발 자국이 여러 개 겹쳐있는 경우도 있는데다

타일, 흙바닥, 먼지랑 뒤섞여서 형체를 알아보기 힘들다.

어떤 신발 자국은 먼지에 찍혀있지만 어떤 건 흙바닥, 어떤 건 낙엽 위에 찍히는 등 배경이 천차만별인 것도 문제다. 

이렇게 온전하지 못한 학습 데이터는 AI의 학습을 더욱 방해하는 요인이 된다.

 

 

 

3. 기존 연구가 미흡하다

마지막 이유로, 기존 족적 검색 관련 연구가 너무 적은데다 한계가 뚜렷하기 때문이다.

'족적 검색(영어로는 forensic shoeprint/footprint/footwear)'이라는 분야가 워낙 협소한데다가

이전 연구들은 대부분 자기들만 갖고 있는 데이터셋을 바탕으로 진행했기 때문에

실험을 재현하거나 기존 연구를 발전시켜 개선할 여지도 없었다.

 

그리고 딥러닝 모델을 기반으로 한 연구는 더더욱 적었는데 내가 찾아본 (어느 정도 신빙성 있는) 논문으로는 많아봤자 3~4편에 불과했던 걸로 기억한다.

 

 

 

 

 

진행 현황: 어디까지 연구를 진행했는가?

사실 내가 오기 전에도 이 연구 프로젝트는 PIAI에서 진행하고 있었다.

나의 사수님과 직전 인턴 분께서 열심히 기획하고 논문 서칭하고 코드를 짜준 덕분에 나는 그걸 토대로 발전시킬 여지가 있었다.

내가 첫 주동안 이전 자료를 열심히 읽고 나서 파악한 진행 현황은 다음과 같았다.

 

  1. ResNet 모델에 Siamese Network 구조를 결합해서 이미지 학습
  2. MCNCC(Multi-Channel Normalized Cross-Correlation) 논문을 기반으로 구현해보기

 

1번은 기존 인턴 분이 작성한 코드가 이미 있었고, 1차 성능 평가까지 끝내놓은 상태였다.

ResNet 모델을 쓴 이유는 컴퓨터 비전 task에서 가장 안정적인 성능을 보이기도 하고

PyTorch에서 코드 한 줄이면 모델 가중치를 가져다 쓸 수 있기 때문이라고 생각한다.

Siamese Network 구조를 시도한 것도 타당했다고 보는데, image retrieval task에서는 Siamese Network 구조를 쓰는 게

가장 보편적이고 성능 또한 우수하다는 게 많은 연구로 입증이 됐기 때문이다.

다만 FID-300 데이터셋에 대해서 accuracy 성능이 30%대로 많이 낮다는 게 한계점이었다.

 

2번 MCNCC는 Cross-Domain Forensic Shoeprint Matching (2017)이라는 제목의 논문에서 고안한 모델이다.

이 논문을 선택했던 이유는 1) 우리도 쉽게 구할 수 있는 FID-300 오픈 데이터셋으로 실험을 했고 2) 논문에서는 80% 이상의 정확도를 보였다고 했기 때문이다.

 

 

 

 

첫 번째 시도: 논문 구현에 도전하다

내가 첫 주차에 어렴풋이 연구 방향을 파악하고 오랜만에 코딩할 생각에 들떠서 바로 착수한 건 2번, MCNCC이었다.

1번은 아무래도 이미 누군가가 완성한 작품이었고, 그래서 당장 발전시킬 여지가 보이지 않았기 때문이다.

그리고 MCNCC 논문에선 정확도 80%를 보였다는데 이걸 재구현을 안해볼 사람이 어디 있겠는가?

 

그리고 운이 좋게도 논문 1저자가 공개한 깃허브 리포지토리도 있었다.

아싸! 하고 속으로 환호성을 지르려고 하는 순간 내 눈을 의심했다.

 

 

콩 박사님, 그냥 평범하게 파이썬을 쓰실 순 없었나요?

 

 

안타깝게도 모든 코드가 다 매트랩 MATLAB으로 짜여있었던 것이다.

하지만 그때만 해도 패기 넘치던 나는 이런 생각을 했다.

 

'시간도 아직 많이 남았겠다, 챗GPT라는 강력한 무기도 있는데 매트랩에서 파이썬으로 고치는 것 쯤이야 금방 하겠는데?'

 

그리고 솔직히 말하자면, 내가 구현만 한다면 족적 검색을 연구하는 사람들에게

유의미한 contribution을 할 수 있을 거라는 희망에 부풀어올라 있었던 것 같다.

만약 MCNCC가 정말 족적 시스템에서 획기적인 성과를 보인 논문이고,

이걸 사람들이 쉽게 가져다 쓸 수 있게 파이썬으로 구현한다면 내가 별개의 업적을 남기는 거라 생각했기 때문이다.

 

그렇게 잘못된 희망을 품고 나는 점점 헤어나올 수 없는 구렁텅이로 빠져들게 되었다.

 

 

고백하자면 내 인턴은 삽질로 시작했던 게 아닐까?

 

 

 

 

 

내가 삽질을 할 수밖에 없었던 이유

처음에는 할 만하다고 생각했다. 챗GPT의 도움이 워낙 효과적이었기 때문이다.

내가 매트랩의 문법이나 논리 구조에 대해서 모르는 부분이 있을 때마다 코드를 복붙해서 챗GPT에 물어보면

열에 일곱은 감탄할 만한 대답을 해주었다.

하지만 점점 진도를 나가면서 예상치 못한 에러가 자꾸 발생했다.

게다가 매트랩으로 딥러닝 모델을 구현하는 과정에서 패키지 에러가 나를 가로막았다.

 

그렇게 일주일을 쏟아부었는데도 진척이 별로 없으니까 슬슬 포기를 하고 싶었다.

하지만 이미 건너버린 강이었기 때문에, 어떻게 해서든 끝까지 마무리하고 싶다는 집념이 생겼다.

간절한 심정으로 매달린 끝에 결국 2주 반만에 거의 모든 코드를 파이썬으로 돌아가게 고칠 수 있었다.

그렇게 번역 작업을 웬만큼 마무리하고 한숨 돌릴 즈음, 충격적인 사실을 하나 깨닫게 되었다.

 

당연히 구현되어 있을 거라 생각했던 핵심 코드가 아예 없었다.

분명 논문의 내용을 끝까지 구현했다면 논문에서 선정한 딥러닝 모델들에 대해 Multi-Channel Normalized Cross-Correlation이라는 통계적 기법으로 데이터를 처리한 다음 학습을 해야 하는데, 모델 train 파트를 아예 찾을 수 없었다.

 

뒤통수를 세게 얻어맞은 느낌이었다.

피인용수도 좀 있는 논문인데 설마 구현을 모두 안해놓았겠어, 하고 아무 의심 없이 앞만 보고 달린 내 잘못이었다.

 

 

 

 

 

 

무한도전이 내게 준 교훈: 우리는 나무에 달려들기 전에 숲을 둘러보아야 합니다

 

무한도전 무인도 특집 1편에서.

 

 

 

무한도전 레전드 특집이라고 불리는 무인도 편을 아시는가?

1편을 보면 멤버들이 무인도에 도착한 지 얼마 안돼서 열매를 따려고 높은 야자수 한 그루를 열심히 공략한다.

올라가다가 팔도 긁히고, 긴 나뭇가지로 찔러보고 목마도 태워보고 그렇게 한참을 고생하다가,

나중에 근처에서 팔 뻗으면 닿을 야자수를 발견하고는 어처구니 없어 한다.

 

지난 2주동안 코드를 짜는 나도 어떻게 보면 야자수 한 그루만 보고 무작정 돌진한 무한도전 멤버 같았던 게 아닐까?

숲(프로그램 전체)을 보고 가장 쉬운 방법은 무엇인지, 막다른 길은 아닌지 확인한 다음

더 이상 대안이 없다는 걸 확인했을 때 선택한 길을 열심히 팠어야 했다.

 

 

 

 

 

그렇다 쳐도... 왜 논문 저자는 구현을 하다 만 걸까?

결국 MCNCC 논문을 구현하는 건 포기했지만 여전히 내 머릿속엔 의문이 떠나지 않았다.

왜 연구자들은 자기 논문에 코드를 제대로 안 올리는 걸까?

내가 겪은 설움을 과거에 다른 사람들도 많이 느꼈나보다.

그 질문에 사람들이 달아놓은 답변을 찬찬히 읽어보면서 어느 정도 내 상황도 수긍할 수 있었다.

 

가장 큰 이유는 남들이 자기 연구를 베껴서 허락없이 이용할 거라는 불안함 때문이겠지만,
생각보다 많은 연구자들이 자기 코드에 대해 자신이 없거나(자기 코드가 조잡하거나 에러가 있다는 비판을 받기 두렵다),
연구 결과를 운좋게 얻어 걸렸다거나(한 마디로 cherry picking한 셈이다),
코드를 정리하고 올릴 시간이 없는 경우가(에잇 귀찮아! 올려서 뭐해) 허다하기 때문이라는 것이다.

 

 

짐작건대 내가 살펴봤던 논문의 저자는 '내가 여기까진 다 구현해놨어. 근데 궁금하면 나머지는 너네가 알아서 구현해.'

라는 생각으로 코드를 일부만 공개한 것 같다.

부차적인 기능은 모두 구현되어 있지만, 핵심 파트인 통계적 기법과 딥러닝 모델의 학습 부분은 빠져 있었기 때문이다.

참고로 막판에 쥐푸라기라도 잡고 싶은 심정으로 이 부분에 대한 이슈도 깃허브 리포에 달아놓았지만 끝내 답변은 오지 않았다.

 

 

 

 

교훈 2: 다른 도메인의 프로그래밍 언어로 번역하는 작업은 상상 이상으로 어렵다

내가 크게 착각했던 게 또 한 가지 있다.

바로 프로그래밍 언어를 바꾸어서 코드를 고치는 게 단순한 작업일 거라 생각했다는 점이다.

 

결과적으로 말하면 '상상 이상으로 어려웠다'. 특히 매트랩이나 파이썬 같이 특징이 완전히 다른 프로그래밍 언어라면 말이다.

 

 

1. 프로그래밍 언어를 바꾼다는 건 프로그램의 설계 방식을 바꾸는 것과 같다

어떤 프로그램의 언어를 변환한다는 건 단순히 문법만 고치는 데서 끝나지 않는다.

그 프로그램을 설계한 방식 자체를 뒤집고 새로 설계하는 걸 의미한다.

 

매트랩으로 구현한 MCNCC 논문은 철저하게 절차 지향적인 방식으로 쓰여 있었다.

그러다보니 다중 for 문이 빈번하게 쓰이고 변수도 여기저기 알아보기 어렵게 흩어져 있었다.

이걸 파이썬으로 고치다보니 객체(클래스)를 새로 정의하고, 반복되는 부분은 함수로 정의해서 모듈화하는 과정이 필요했다.

게다가 매트랩에서는 당연히 지원하는 기능을 파이썬에선 지원하지 않는 경우도 많아

이걸 파이썬의 스타일에 맞게 고치는 작업도 거쳐야 했다.

 

 

 

2. 모듈과 라이브러리의 불일치

프로그래밍 언어가 다르면 쓰는 모듈과 라이브러리도 다르다.

그렇기 때문에 어떤 동일한 객체나 변수에 대해서도 접근 방식이 다르고 결과마저 완전히 달라질 수 있다.

 

예를 들어 매트랩에선 CNN(Convolution Network)을 활용하기 위해 MatConvNet 라이브러리를 쓰는데,

파이썬에선 PyTorch를 쓴다.

문제는 똑같은 종류의 CNN 모델이라고 해도 MatConvNet이 모델 layer 인스턴스를 다루는 방식과

PyTorch가 다루는 방식이 완전히 달랐다는 점이다.

그렇기 때문에 기존 CNN 모델의 backbone만 추출해서 학습에 쓰려고 하는데 모델 layer와 크기가 서로 다른 결과로 이어졌다.

 

 

 

3. 환경 설정과 패키지 설치 에러

만약에 다른 언어였다면 어땠을지 모르겠지만, 매트랩이었기 때문에 구현하기가 매번 힘들었던 것 같다.

매트랩은 기본적으로 라이센스가 있어야 프로그램을 설치・실행할 수 있고

특히 딥러닝 모델을 매트랩에서 에러 없이 돌리려면 툴박스 설치와 컴파일러 파일 설정 등 자잘자잘한 세팅을 해놓아야 했기 때문이다.

 

한 가지 덧붙이자면, 매트랩에서는 행렬을 다루는 파일 확장자도 .mat이기 때문에

파이썬에서 이 파일을 다루기 위한 별도 조치를 해야 했다.

다른 언어는 얼마나 쉬울지 모르겠지만 크게 상황이 다를 것 같지는 않다.

 

 

 

 

챗GPT에 대한 소감

내가 매트랩 프로그램을 파이썬으로 바꿔놓겠다는 무모한 시도를 도전하게 된 데에는 사실 챗GPT의 영향이 많이 컸다.

그만큼 챗GPT가 내 예상을 뛰어넘는 수준으로 도움을 많이 주었기 때문이다.

사실 이 친구가 아니었으면 인턴이 끝날 때까지도 번역 작업에 끙끙 대며 매달렸을지도 모르겠다.

 

하지만, 챗GPT가 모든 문제를 해결해주는 마법사는 아니었다.

물론 코드 일부분만 입력하면 무난하게 작동하는 코드를 순식간에 번역해냈고

어쩔 땐 내가 찾지 못했던 에러의 원인을 코드로부터 추론해서 알려주기도 했다.

하지만 거기까지일 뿐,

챗GPT는 변수가 쓰이는 맥락을 파악해서 자주 쓰이는 부분을 모듈화하고

객체 지향적인 방식으로 재설계한 다음 '파이썬스럽게' 코드를 다듬는 세세한 작업을 한번에 수행하지는 못했다.

 

 

 

 

결론 & 성과

족적 검색 시스템에서 딥러닝 모델을 활용하며 성능이 뛰어나다고 알려진(추정되는) 논문인

MCNCC(Multi-Channel Normalized Cross Correlation)을 직접 재구현했고,

AI 분야에서는 비교적 생소한 매트랩 기반 코드를 파이썬과 PyTorch 기반 코드로 직접 재설계해서

다른 개발자들이 나중에 쉽게 발전시킬 수 있도록 오픈소스로 공개했다(https://github.com/seanshnkim/MCNCC).

 

그 과정에서 논문 구현이 제대로 이루어져 있지 않은 사실을 알아낸 건 덤.

논문에서 사용한 Siamese Network 기반의 딥러닝 모델을 학습하는 코드를 추가한다면

좋은 성능을 보일 수 있을지도 모른다. 이건 추가 검증이 필요하다.

 

 

 

 

 

다음 편에서는...

그렇게 인턴 첫 3주를 코딩으로 하얗게 불태우고 나는 다시 원점으로 돌아왔다.

이제는 정말 눈에 보이는 성과를 내고 싶었다.

이후로 내가 어떤 시도를 했고 어떤 결과를 얻었는지,

내가 이 과정에서 최종적으로 얻은 건 무엇인지 설명하려고 한다.

 

다음 편에서 계속!