서비스에서 야경 좋은 식당 찾기 — Vision, Semi-supervised learning, Hierarchical classification

Doyoung Gwak
네이버 플레이스 개발 블로그
11 min readAug 19, 2021

좋은 야경의 식당이나 차분한 카페를 찾아주는 시스템을 생각해보셨나요?

그림1. (왼)야경이 좋은 식당, (중앙)레트로 감성의 카페, (오)편안한 카페
그림1. (왼)야경이 좋은 식당, (중앙)레트로 감성의 카페, (오)편안한 카페

안녕하세요. 국내외 지역 기반 서비스들을 만들어가는 NAVER Glace의 곽도영입니다. 저희 팀은 Glace에서도 AI를 활용하여 사용자에게 새로운 가치를 제공하는 것을 목표로 하고 있는데요. 식당 리뷰를 남길 수 있는 국내/외 서비스[1] [2]가 있으며, 식당의 분위기를 인식하여 사용자에게 제공할 수 있는 기능을 만들어보고자 했습니다. 이번 글에서 소개해 드릴 내용은 식당 리뷰 이미지만으로 식당의 분위기를 판단하는 모델 제작 경험을 공유해 드리도록 하겠습니다.

참고로, 이 글의 전반적인 내용은 서비스 응용 관점에서의 아이디어가 많기 때문에 복잡한 수식이나 어려운 개념은 없습니다. ML에 조금 덜 익숙한 분이시라도 안심하시고 읽어주셔도 괜찮을 것이라 생각합니다 :)

그림2. 일본 맛집 리뷰 서비스인 LINE CONOMI

분류하고자 하는 식당 분위기를 정의하고, 사용자가 올리는 식당 리뷰 사진들에 레이블을 달아서 지도학습 방식의 이미지 분류기를 만들고자 했습니다. 처음에는 문제 정의가 간단하다고 생각했지만 아래와 같은 문제점이 있었습니다.

  1. 전체 리뷰 이미지 분포에서 분위기와 관련 없는 사진이 많아 학습셋 구축의 어려움
  2. 원치 않는 카테고리의 사진들이 분위기 사진으로 분류됨

위의 문제점을 1번 문제는 준지도학습(semi-supervised learning)[3]을 통해 해결하려고 하였고, 2번 문제는 계층적 분류 문제(hierarchical classification)[4]로 정의하여 해결하려 했던 과정을 소개해 드립니다.

문제 1. 리뷰 이미지의 4%만이 분위기 관련임

전체 리뷰 이미지 중 약 4%만이 의미 있게 학습에 사용 가능한 분위기 이미지였습니다. 사용자의 리뷰 프로세스로 들어오는 이미지들은 음식 사진, 식당 실내 사진, 식당 실외 사진, 영수증 사진 등 다양합니다. 리뷰 서비스 UI에서 적절한 사진만 올리도록 가이드하고 있지만, 많은 사용자가 대량의 리뷰를 쓰다보니 생각보다 다양한 사진들이 있었습니다. 따라서 학습셋을 만드는 데 비용이 많이 들었고 빠르게 학습셋을 구축할 수 있도록 ML을 활용하여 초벌 학습셋을 만들어 레이블링을 수행하는 방법을 사용했습니다.

그림3. 클러스터링으로 데이터셋 구축을 위한 분석 과정

지도 학습과 비지도 학습을 모두 활용하여 학습을 수행했는데요, 준지도학습(semi-supervised learning)[3]이라고 볼 수 있습니다. 레이블링한 데이터와 레이블링하지 않은 데이터를 모두 사용하여 학습하는 목적에서, 클러스터링된 데이터에서 일부를 레이블링해봤을때 적절히 의미있는 집단으로 판단이 가능한 클러스터만 사용하여 데이터셋 구축 후 지도학습을 수행한 방식으로 준지도학습을 수행했다고 볼 수 있겠습니다.

초벌 학습셋을 위한 대분류기 모델 제작

전체 사진들로부터 식당 실내외 사진만 찾아낼 수 있는 분류기 모델(이하 대분류기)을 제작했습니다. 대분류기는 식당의 실내/실외인지 아닌지를 판단할 수 있는 multi-class image classification으로 문제를 정의하여 학습을 수행했습니다.

당시에는 당장에 대분류기 모델에 사용할 적당한 데이터셋이 없었습니다. 따라서 입력으로 들어오는 사진 100만 장을 RexNet[5]과 FAISS[6]를 활용하여 100가지로 클러스터링을 수행할 수 있었고, 이 100가지 클러스터는 꽤 의미있는 사진들끼리 모인 결과를 얻을 수 있었습니다. 특히 영수증 사진들끼리는 잘 모이는 모습이나, 간판 사진들끼리 잘 모이는 모습, 음식 사진들끼리 잘 모이는 모습 등을 확인할 수 있었습니다. 클러스터링의 모든 사진을 하나하나 확인해보지는 못했지만, 임의의 사진들을 확인하여 클러스터링이 잘 된 클러스터 번호를 찾아냈고, 여기서 식당 실내 클러스터, 식당 실외 사진 클러스터, 음식 사진 클러스터, 음료 사진 클러스터, 영수증 사진 클러스터 등 총 9가지 대분류 카테고리를 정의하고 클러스터끼리 묶어 대분류기 학습셋을 구축할 수 있었습니다. 클러스터링과 분석 과정은 그림3에서 표현하였습니다.

기계가 구축한 데이터셋이기 때문에 분명 노이즈가 존재하겠지만 여러 이미지 분류기 모델로 학습 실험을 해보았을 때 초벌 데이터셋 구축용 모델로는 사용이 가능하겠다고 판단하여 대분류기 모델을 만들 수 있었습니다.

그림 4–1. 메뉴판 사진들이 모인 클러스터(왼), 그림 4–2. 포장 음료 사진들이 모인 클러스터(오)

적절한 결과를 얻기 위해서 이미지 100만 장을 여러 번 클러스터링하였습니다. 원본이미지는 복제하지 않고 이미지 경로만으로 클러스터링 결과를 저장하고 뷰잉할 수 있는 서버-클라이언트 앱을 제작하였습니다. 관심 있는 분께서는 tucan9389/image-clustering-browser[7] 이 저장소를 참고해주세요!

식당 실내/외 사진만 걸러내어 레이블링 대상 이미지 제공

레이블링시 그림4와같이 메뉴판이나 포장 음료 같은 사진은 분위기를 포함하지 않는 사진인 경우가 많습니다. 따라서 대분류기 추론을 수행하여 메뉴판, 포장 음료 등의 분위기가 없다고 정의한 카테고리인 이미지는 걸러내고 식당 실내사진, 식당 실외사진으로 추론된 이미지만 레이블링 대상 이미지로 만들어 분위기 레이블링을 수행하였습니다.

레이블링은 사내에 CDA 어노테이션 도구를 활용하여 이미지 분류 데이터셋을 구축할 수 있었습니다. CDA에서 제공하는 cross checking 기능을 활용하여 두 레이블러가 한 이미지를 중복으로 레이블링할 수 있게 세팅해서 레이블링을 수행했습니다. 분위기를 판단한다는 문제에서 명확한 기준을 내리기가 어려웠기 때문에 레이블링된 이미지 중, 두 레이블러가 동일한 카테고리로 레이블링한 데이터만 선별해서 사용했습니다.

처음 전체 이미지의 4%만이 분위기를 담고 있던 분포에서 16%까지 끌어올려 제한된 시간 안에 분위기 분류기 데이터셋을 보다 빠르고 많이 만들 수 있었습니다.

문제 2. 원치 않는 카테고리의 사진들이 분위기 사진으로 분류됨

처음부터 사용자의 입력 데이터를 분석하고, 실데이터 분포에 따라 분류기 카테고리를 잘 정의하는 것이 이상적이지만, 서비스 입장에서 꼭 찾고자 하는 카테고리도 정의하고 싶기 마련입니다. 그러다 보니 학습 데이터가 불균형한 문제, 찾고자 하는 데이터가 적은 문제들이 있었고, 실데이터 입력에 대해서는 분류기가 잘못 예측하는 경우가 있었습니다.

불완전한 모델이 음식 진열대 사진이나 영수증 사진이 분위기가 있다고 자신있게 주장해버리는 문제 (틀렸는데 99% confidence로 예측)가 더러 있었습니다. 이러한 경우를 막기 위해 찾고 싶지 않는 카테고리를 정의하여 분위기 분류기 모델 앞단에서 걸러내는 2-stage 방식을 사용하였습니다 (그림5).

그림5. 1 depth에서 리뷰 이미지에 대한 큼직한 분류를 하고 2 depth에서 실내외 사진에 대한 분위기 분류를 수행

찾고 싶지 않은 카테고리들을 추가하여 (예를 들면 영수증, 메뉴가판대, 간판 등) 학습하고, 1 stage에서 해당 카테고리로 추론된 경우 분위기 분류기 모델 추론을 수행하지 않도록 만들었습니다. 이러한 2-stage 방식으로, 실데이터 분포에는 많이 존재하지만 분위기와 관련 없는 이미지들을 제외할 수 있었습니다.

현재 분위기 분류기의 제일 높은 성능 모델과 정확도는?

처음에는 이미지에서 분위기를 찾는다는 문제 정의 자체가 잘못되진 않았을까하는 생각을 했었습니다. 하지만 분기로 쏟아져 나오는 최신 논문의 모델들을 다양하게 실험해보면서 성능이 높아지는 모습을 확인하면서, 이미지만으로 어디까지 성능이 높아질 수 있을지 한계를 찾는 중입니다.

그림6. CLIP 기반 분위기 분류기의 모델 구조

EfficientNet부터 여러 가지 모델로 전이학습 실험하여 현재는 사전학습된 CLIP[8](RN50x16)을 backbone으로하는 모델이 가장 좋은 성능을 내고 있습니다. CLIP을 간단히 설명해 드리자면 이미지와 텍스트를 각각 입력으로 받아서 각각 embedding vector를 출력으로 주며, 두 embedding vector의 유사도를 측정할 수 있도록 설계된 OpenAI의 모델입니다. 이미지 추론하는 부분은 image encoder라고 부르는데요. 분위기 분류기에서 사용한 모델은 image encoder를 backbone으로 하고 top에 fully connected layer를 쌓아 만들었습니다 (그림6).

그림7. 모델별 분위기 분류기의 f1-score, accuracy, precision, recall 비교

CLIP 모델이 이전 모델(BiT)보다 약 4% 높은 67%의 f1-score를 기록했는데요(그림6). 여러 가지 최신 모델로 실험을 해보았을 때 63% 최고 성능을 간당간당하게 넘지 못하던 모델들과 달리 CLIP의 image encoder가 좋은 성능을 내서 이유를 분석해보고 있는데요. 방대한 양의 4 million 이미지로 학습된 backbone이라 그런 것이 아닐지 추측해 봅니다.

아직은 더 개선할 수 있는 점수가 많이 남아있습니다. 다음에는 더 다양한 방법으로 모델 성능 개선 시도를 해나갈 생각입니다.

정리

이번 글을 정리하면 다음과 같습니다.

  • 일부 리뷰 이미지들만이 분위기 정보를 담고 있어, 비지도 학습인 클러스터링으로 대분류 클러스터 셋을 만들었고, 분위기 클러스터 내의 이미지들만 대상으로 보다 빠른 레이블링 수행
  • 추론 성능 향상을 위해 분위기와 관련 없는 이미지들을 사전에 걸러냄. 이를 위해 대분류기에서 걸러내고 싶은 카테고리를 추가하여 학습 수행
  • CLIP 구조로 학습된 RN50x16 모델이 최고 성능 달성

다음 할 일과 다른 Vision 문제들

  • 대분류기 학습셋은 현재 노이즈가 많지만, 깨끗한 테스트셋이 준비가 된다면 robust learning 연구에서 여러 가지 아이디어를 얻을 수 있을 것으로 기대중
  • 이미지 분류기 성능을 올릴 수 있는 여러 노하우[9]를 적용하여 성능 개선 기대중

저희는 분위기 분류기 문제 뿐만 아니라 리뷰 사진으로 여러 가지 분류기 제작을 시도하고 있습니다. 300여가지의 음식을 분류해주는 음식 인식기나, 영수증 이미지를 판단해주는 영수증 판별기 등이 있습니다. 단순한 문제 정의가 될때도 있지만 실데이터 기반으로 문제를 해결하려다보면 다양한 재밌는 난관들을 만나게 되는데요. ML로 실제 문제들을 정의하고 해결하는데에 관심 있으신 분들은 아래 링크를 확인해주세요!

https://www.naver-monthlyopening.com/#category-glace-ai-1

끝까지 읽어주셔서 감사합니다!

참고

[1] https://m.place.naver.com/my/pick
[2] https://lineconomi.me/
[3] https://en.wikipedia.org/wiki/Semi-supervised_learning
[4] https://en.wikipedia.org/wiki/Hierarchical_classification
[5] https://github.com/clovaai/rexnet
[6] https://github.com/facebookresearch/faiss
[7] https://github.com/tucan9389/image-clustering-browser
[8] https://openai.com/blog/clip/
[9] https://arxiv.org/abs/1812.01187

--

--