brunch

매거진 AI

You can make anything
by writing

C.S.Lewis

머신러닝 활용한 유해 이미지 차단 기술

[카카오 AI 리포트] 개발자가 직접 쓴 '유해 이미지 분류' AI 기술

들어가기에 앞서: 이 브런치를 통해, 카카오가 유해 콘텐츠 차단을 위해 AI를 활용하는 정책을 개괄적으로 소개해 드린 바 있습니다. 그 구체적인 사례가 지난 2019년 8월 말 개최되었던 if kakao 2019에서 "성인 이미지 세계에서 살아남는 방법"이라는 제목으로 발표됐습니다. 발표된 내용의 골자는 유해 이미지를 단시간에 차단하기 위해 활용되는 AI 기술이었습니다. 아래 글은 담당 개발자가 직접 기술한 것입니다. 


 

프로젝트의 목적


이번 글에서는 세션에서 발표했던 내용을 자세하게 풀어서 설명하고자 합니다. 본격적인 기술 소개에 앞서, 프로젝트의 배경부터 설명드리겠습니다. 콘텐츠 수의 증가에 따라, '좋은' 이미지 뿐만 아니라. '나쁜' 이미지의 양도 함께 늘어납니다. 이렇게 늘어나는 이미지량에 비해 검수할 수 있는 리소스는 한정적입니다. 전체 유입 이미지의 약 0.6 %만이 규제해야 할 이미지이며, 상대적으로 정상 이미지의 비중이 높아 유해 이미지가 검수되기 까지 많은 시간이 소요되었습니다. 그래서 유해한 이미지를 최대한 짧은 시간에 찾아낼 수 있는 방법을 연구하기 시작했습니다.

 


연구 시작 전 상황


이미지의 해시(hash) ID가 동일한 이미지를 찾아  자동으로 처리하는 방식을 적용했을 시 초기 이미지가 100개라고 가정했을 때 약 28개의 이미지를 중복으로 제거하였습니다(약 28% 제거). 아래 [그림 1]에서 볼 수 있듯이 단순 리사이즈(resize) 처리된 이미지도 동일한 처리 값을 가지도록 하였고, 이를 통해 남은 72개의 이미지 중 6개를 더 줄여 최종 66개의 이미지만 검수되도록 적용하였습니다.

[ 그림 1 ] 이미지 사이즈 변화에 대한 처리 값


 위에서 설명드린 각 단계별 이미지 제거 과정을 요약해보면 아래 그림과 같습니다.

[ 그림 2 ] 이미지 해시 ID를 이용한 중복 이미지 제거 자동 처리 과정

 

평균 100장의 이미지 중 34장의 이미지를 중복으로 처리하여 검수량을 줄였습니다. 그럼에도 불구하고 유해 이미지 검수 과정을 더 효율적으로 진행할 방법이 없을까 고민하다 메인 프로젝트와는 별도의 사이드 프로젝트로 진행하였고, 어느 정도의 성과와 가능성이 확인되어 정식 프로젝트화를 진행하였습니다. 상세 연구 내용을 살펴보겠습니다.



프로젝트 상세 내용

 

Step 1 ) 이미지 색상 분포를 활용한 분류 시도

 

일반적으로 성인 이미지를 생각해보면 이미지에 살색 분포가 높고, 상대적으로 풍경 사진에는 살색의 분포가 적을 테니 "색상 분포도 기준으로 이미지를 분류해보면 어떨까?"라는 가정을 했습니다.


첫 번째, '성인 이미지의 색상 분포도를 표현하면 대부분이 특정 색(피부색)에 집중될 것이다'라는 가설을 세웠습니다.


[ 그림 3 ] 일반 vs 성인 이미지 색상 분포도


[ 그림 3 ]은 실제 정상∙성인으로 처리된 이미지의 색상 분포도를 평균 내어 만든 도표입니다. 정상과 성인이 약간의 차이는 있으나 색상은 비슷한 분포도를 보였습니다. 특히 피부색에 중점을 둘 경우 가족사진, 모임 사진 등에 포함된 사람 얼굴이 정확한 이미지 판별에 문제가 되었습니다.

 

두 번째, '하늘 + 바다 풍경 이미지의 색상 분포도는 성인 이미지 색상 분포도와 다를 것이다'라는 가설을 세웠습니다. 


[ 그림 4 ] 하늘∙바다 풍경 vs 성인 이미지 색상 분포도


바닷속에서 찍은 사진 또는 피사체가 극도로 작은 해변가 누드 사진의 경우 단순히 하늘과 바다 풍경 색을 분류하여 비교하는 것은 쉽지 않았습니다. '그렇다면 단순히 색상의 분포도를 가설로 잡아서 하는 것은 불가능한 것일까?'라는 고민에 빠졌고 정상∙성인 이미지의 색상 분포도를 이용해 가까운 이미지의 거리 값을 이용하면 비슷한 이미지끼리 묶일 것이라 추측하였습니다. 


그래서 머신러닝 알고리즘 중에서 이런 상황에 가장 적합하게 활용할 수 있는 KNN(K-Nearest Neighbor, 최근접 이웃)을 사용했습니다. KNN 알고리즘은 가장 가까운 거리에 있는 K개의 값을 통해 분류하는 방식입니다.

[ 그림 5 ] KNN(K-Nearest Neighbor) 알고리즘 모식도



[ 그림 5 ]에서 검은색 원이 질의한 이미지로 가정하겠습니다. 검은색 원을 'K = 3'로 가정하면, 가장 가까운 이웃 3개를 찾겠다는 의미입니다. 가장 가까운 거리에 있는 이미지 3개는 [ 그림 6 ]에서 검은색 원과 연결된 3개의 원입니다.

[ 그림 6 ] KNN 알고리즘 모식도(K=3 경우)



이때 해당 이미지를 분류하는 방법은 대표적으로 두 가지가 있습니다. 첫 번째는 다수결 방식입니다. 파란색 원이 2개, 빨간색 원이 1개 이므로 해당 검은색 원은 파란색 원이라 할 수 있겠습니다. 두 번째는 거리의 가중치를 계산하는 방법입니다. 이 경우는 가장 거리가 가까운 빨간색 원이 될 것입니다.

 

KNN 알고리즘의 장단점을 보면, 장점으로는 특별한 학습 과정이 필요 없으며 데이터 노이즈 영향이 적은 '편'에 속하는 알고리즘입니다. 단점으로는 새로운 데이터마다 거리 값을 전부 계산해야 하는 비용 문제와 고차원으로 분류되는 이미지 데이터를 단순히 2차원 거리가 가까운 것만으로 해당 이미지의 거리 값이 유사한지 확실히 알기는 어렵다는 점입니다.

 

우선 비용 문제(속도 문제)는 많은 연구가 있는데 대표적으로 Approximate KNN 알고리즘이 있습니다. KNN 알고리즘 원리가 '가장 가까운 이웃 K개 찾기'라면 Approximate KNN 알고리즘은 '근사(근접)한 거리를 가진 이웃 K개 찾기'입니다. 실제로 KNN과 동일한 데이터를 가지고 실험했을 때 새로운 이미지의 값을 분류하는데 300분이 소요되었고, Approximate KNN은 단 1분 10초에 이미지 값을 분류했습니다. 단, 정확도는 2% 정도 감소하여 약 23%라는 결과를 얻었습니다. 하지만 하나의 이미지를 분류하는데 많은 시간이 소요되고, 성능 개선이 필요하였습니다.


 

Step 2) CNN을 이용한 이미지 분류기

 

Step 1에서 알게 된 것은 단순한 픽셀 정보로는 좋은 이미지 분류기를 만들기 어렵다는 것이었습니다. 또한 실시간 분류기에 사용하기 위해서 분류 속도가 보장되어야 했습니다. 이를 위해 좀 더 이미지의 다양한 특성(픽셀, 선, 위치, 질감 등)과 분류 속도를 보장할 수 있도록 연구가 필요했습니다.

 

스터디 주제를 정하던 중 우연히 '골빈 해커의 3분 딥러닝 텐서 플로 맛'이라는 책을 만나 공부하게 되었습니다. 해당 책의 11장. 구글의 핵심 이미지 인식 모델, Inception에 소개된 코드를 그대로 이용해 분류기를 개발해보았습니다. 단순히 지표로 비교했을 때 KNN 알고리즘에 비해 성능이 월등히 상승했습니다.([ 표 1 ])

※ 참고로 이번에 진행한 학습을 1차 학습이라 명명하겠습니다

[ 표 1 ] 알고리즘 성능 비교(KNN vs CNN)

 

좀 더 정확도를 높이기 위해 오답 데이터를 분석했더니 몇 가지 문제점을 발견했습니다.


[ 그림 7-1 ] 흑백 만화책 이미지 분류 결과


[ 그림 7-2 ] 컬러 카툰 이미지  분류 결과


[ 그림 7-3 ] 저품질 이미지 분류 결과


[ 그림 7 ]의 흑백 사진 또는 품질이 낮은 이미지에서 발생할 수 있는 부정확한 이미지 분류 결과의 이유를 살펴보겠습니다. 우선 학습 당시에 강렬한 색감을 가진 성인만화들의 유통이 많았습니다. 이런 이유로 해당 스타일의 이미지들이 규제되면서 학습에 반영되었던 것으로 보입니다. 또한 정상 데이터가 성인 데이터에 비해 압도적으로 학습 데이터의 양이 많아 'Imbalanced Data(불균형 데이터)' 문제가 발생하였고 이로 인해 Overfitting(과적합) 현상이 발생했습니다.

 

그렇다면 이런 불균형 데이터 문제는 어떻게 해결할 수 있을까요? 우선 가장 쉬운 방법은 많은 쪽의 데이터를 샘플링 기법을 통해 축소하여 균형을 맞추는 방법입니다. 다양한 샘플링 기법 중 해당 프로젝트는 Random Under Sampling, Tomek Link, Condensed Nearest Neighbor을 이용하여 샘플링하였고, 해당 샘플링 기법을 적용하여 정상 데이터를 샘플링함으로써 어느 정도의 균형을 맞출 수 있었습니다.

 

Random Under Sampling - 무작위로 데이터를 제거하는 기법

[ 그림 8-1 ] Random Under Sampling(Before)
[ 그림 8-2 ] Random Under Sampling(After)


 

Tomek Link - 서로 다른 클래스 값이 거리 값이 가까운 경우를 찾아서 데이터가 많은 클래스 값은 제거하는 샘플링 기법

[ 그림 9-1 ] Tomek Link(Before)
[ 그림 9-2 ] Tomek Link(After)


 

Condensed Nearest Neighbor - 가까운 거리의 같은 클래스인 경우 제거하는 샘플링 기법

[ 그림 10-1 ] Condensed Nearest Neighbor(Before)
[ 그림 10-2 ] Condensed Nearest Neighbor(After)


 

불균형 데이터를 해결하는 두 번째 방법은 부족한 데이터를 더 만들어 주는 것입니다. 이를 위해 데이터를 증식하는 Data Augmentation(데이터 증대) 기법을 이용해 성인 이미지의 양을 늘려 주었습니다([ 그림 11 ]).

[ 그림 11 ] 불균형 데이터 해결을 위한 데이터 증식 예시

 


1차 학습에서 발생한 또 다른 문제는 반복적으로 코드를 작성하는 것이었습니다. 단순히 학습시키는 행위를 위해 번거롭게 코드를 작성하고 파라미터 수정하는 등 불편한 경우가 발생했습니다. 이 문제를 해결하기 위해 다방면으로 방법들을 조사하였고, Tensorflow-Slim을 발견하여 반복적인 코드 작성 최소화를 위해 해당 기법을 적용하였습니다. 또한 Pre-trained Model에 미세 조정(Fine tuning)을 적용하여 정확도를 높이기 위한 시도를 하였고 모델 네트워크를 Inception V3에서 Inception Resnet V2로 변경하였습니다. 결국 23% 의 정확도를 가졌던 분류기는 1차, 2차 실험을 거쳐 85% 의 정확도를 가진 분류기로 개선되었습니다. 단, 학습 시간이 기존 13일 에서 25일까지 늘어나는 문제는 있었습니다.

[ 그림 12 ] 이미지 분류기의 정확도 개선 결과 (Inception Resnet V2 적용)

 


2차 학습의 정확도를 좀 더 향상하기 위해 몇 가지 고민을 시작하였습니다. 우선 주로 잘못 판단한 이미지를 분석해보니 '눈, 눈썹 등만 클로즈업된 이미지', '신체 일부가 클로즈업된 이미지' 등이 성인 이미지로 분류되는 문제가 있었습니다. 원인을 분석해보니 Tensorflow Slim에서 기본적인 이미지를 전 처리하는 방식이 내부적으로 고민 중인 문제 해결에는 적합하지 않은 전처리 방식을 사용하고 있었습니다.

[ 그림 13 ] Tensorflows Slim의 이미지 전처리 결과(원본 vs 전처리)


[ 그림 13 ]의 원본 그림의 성인 이미지 판단에 콘이 가장 중요한 인자로 영향을 주었다면 해당 이미지는 정상으로 분류되었을 것이고, 이 경우 무지의 얼굴이 과도하게 학습되는 문제가 발생하였을 것입니다. 성인 이미지는 이미지의 특정 부분만으로도 성인 카테고리로 분류할 수 있으나 이런 방식의 이미지 분류 디렉팅은 어려운 난이도의 작업이었습니다. 이미지의 전체적인 느낌을 학습에 반영하기 위해, 대부분의 전처리 작업은 제거하고 모델 네트워크 크기에 맞도록 리사이즈하고, 랜덤 하게 채도를 적용하는 수준의 전처리만 적용하였습니다. 그리고 더 높은 정확도를 얻기 위해 하이퍼 파라미터(Hyperparameter)를 튜닝하는 실험을 진행하였습니다. 이 과정에서 일련의 무한 반복 작업은 스크립트를 통해 자동화하였고 생산성을 확보하였습니다.


[ 그림 14 ] 정확도 향상을 위한 파라미터 튜닝

 

지금부터는 학습 속도를 개선하기 위한 방법들을 설명드리겠습니다. 아무리 장독대에 고이 담아둔다고 하여도 25일이라는 학습시간은 결과를 보기까지 오랜 시간이라는 생각이 들었습니다. 해결 방법을 찾기 위한 고민들을 시작하였고, 이 문제를 해결하기 위한 해답은 Tensorflow Slim Parameter에 있다는 것을 알게 되었습니다. 

[ 그림 15 ] Tensorflow Slim Parameter 코드 구조



작업 클론 개수를 GPU 수만큼 늘리고 Preprocessing Threads의 개수를 CPU 코어 개수만큼 늘려주니 학습시간이 10일까지 줄어드는 결과를 확인할 수 있습니다. 이러한 일련의 작업들을 통해 89% 정확도를 가진 분류기를 개발하게 되었습니다.

[ 그림 16 ] 이미지 분류기의 정확도 개선 결과 (Parameter Tuning)


 

Step 3) Ensemble(앙상블)

 

머신러닝 기법 중 여러 모델의 결과를 이용해 하나의 모델보다 좋은 결과를 만드는 기법을 앙상블이라고 표현합니다. 지금까지 실험한 분류기와 앞으로 실험할 분류기, 그리고 카카오 사내 다른 분류기들을 이용해서 좀 더 효율 적인 '성인(스팸) 이미지 추천 시스템'을 개발하였습니다.

[ 그림 17 ] 정확도 향상을 위한 앙상블 기법


위의 예시처럼 여러 학습 결과를 활용하여 데이터를 분류하였고 이를 통해 각 모델 분류 값의 일정 조건을 만들면 좀 더 성능이 좋은 결과를 만들어 낼 수 있었습니다.

[ 그림 18 ] 여러 모델의 결과를 이용해 결정하는 방법(의사결정 트리)


 

마무리

 

[ 그림 19 ] 프로젝트 요약정리

 



저희는 불법(성인) 이미지 분류기를 만들었고, 이를 통해 대부분의 이미지들을 자동으로 분류하여 불법 이미지들은 규제하고 있습니다. 사람의 육안으로 모니터링하는 영역은 일부에 불과하며, 육안으로 검사한 검수 결과를 다시 학습에 반영하여 더 나은 모델을 개발하기 위해 노력하고 있습니다.



글 | 오창화  herschel.alway@kakaocorp.com
여행과 술을 좋아하는 개발자입니다. 서버, 프런트 개발자로 일하면서, 어쩌다 보니 세상의 흐름에 이끌려 ML/DL 업무를 담당하고 있습니다. 스팸 관련 업무를 하시는 많은 분들과 의견을 나누고 싶습니다.

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari