작년 9월, '블레이드앤소울(이하 블소)' 글로벌 e스포츠 대회인 '블소 토너먼트 월드 챔피언십' 결선에선 꽤나 충격적인 일이 벌어졌다. 내로라하는 프로게이머들이 의문의 유저에게 참패를 당한 사건이다. 특히 한국선수와의 경기에선 전에 보지 못한 빠른 공격을 바탕으로 적을 압도하는 모습을 보여줬다. 경기가 끝나고 나서야 밝혀진 이 고수의 정체는 엔씨소프트가 개발한 비무 전용 AI였다. '블소' PvP 콘텐츠에 적용될 이 인공지능은 딥러닝을 적용한 심층강화학습 기술로 스스로 다양한 전투법을 몸에 익힌 똑똑한 친구다. 알파고나 알파스타같은 지능 위주 게임이 아닌 수십 분의 일 초 단위 판단이 필요한 MMORPG PvP 모드에서 딥러닝 AI가 적용된 사례는 굉장히 드물다. 이 AI는 어떤 방식으로 학습했길래 프로게이머와 겨룰 수준의 실력을 갖게 됐을까? 이번 GDC 현장에서 엔씨소프트 강화학습 팀 정지년 팀장과 노승은 연구원이 발표한 <강화학습을 이용한 프로게이머 수준의 '블소' 비무 AI 개발> 강의에서 그 방법을 구체적으로 들을 수 있었다.
인공지능이 게임 시스템을 이해하는 것부터 차근차근 AI에게 프로게이머 수준의 경기력을 지니게 하기 위해선 일단 스킬 시스템을 이해시키는 것이 제일 중요했다. 군중 제어기와 대미지 딜링용 스킬을 연계해서 쓸 수 있게 하고 회피와 반격을 위해 적절한 타이밍과 거리를 재도록 해야 했다. 더불어 각 스킬이 가진 상성을 이해시키고 어떤 움직임이 제일 효율적인지를 체크할 수 있도록 만들 일련의 과정이 필요했다. 이를 위해선 몇 가지 과제를 수행해야만 했다. 첫 번째는 복잡성을 줄이는 과정이다. '블소'에서 한 번 전투가 벌어질 때 발생하는 경우의 수는 바둑의 몇백 배는 될 정도로 복잡하다. 덕분에 딥러닝을 통해서 AI가 배워야 할 것도 기하 급수적으로 늘어난다. 이를 줄이기 위해 정지년 팀장은 활동 공간을 눈에 띄게 줄이는 방향으로 갔다. AI로 하여금 불펼요한 움직임은 처음부터 하지 않도록 가르친 것이다.
두 번째는 실시간 반응이었다. 행동 하나하나에서 뻗어나올 경우의 수를 모두 계산한다면 유저의 공격에 실시간으로 반응하는 것이 불가능 할 것이다. 이를 위해 제작지는 인공신경망 네트워크를 사용했다. 비슷한 상황을 계속해서 제공함으로써 먼 미래의 결과 예측보다는 그때 그때의 효율적인 움직임을 추구할 수 있도록 구성했다. 이 실시간 반응과 함께 고려되어야 하는 것이 바로 추상화 작업이었다. 사람마다 다른 패턴을 스스로 분석하고 일반화 시켜 상황에 따른 답안을 내놓을 수 있도록 추가적인 훈련이 필요했다. 이를 위해서 다양한 프로 선수들의 경기를 반복적으로 학습하게 만들었다. 수없이 많은 움직임 중에서도 가장 모범적인 움직임들을 보고 일반화 과정을 이해하는데 성공했다.
보상을 이용해 본격적인 싸움 법을 알려주기 마지막으로 AI가 보다 기민하면서도 다채로운 움직임을 보여주기 위해선 다양한 방식의 전투법을 익혀야 했다. 각각 공격적인 형태와 방어적인 싸움법, 공수를 골고루 사용하는 스타일을 자유자재로 구사하는 것이 필요했다. 연구팀은 이를 위해서 '보상을 통한 강화학습'을 선택했다.
보상을 통한 강화학습은 행동하는 법을 직접적으로 알려주는 것이 아니라, 맞는 행동을 했을 때는 일정한 보상을 주고 맞지 않은 행동을 했을 때는 불이익을 줘 스스로 계속 보상을 따라서 맞는 행동을 찾아가게 만드는 시스템이다. 아이가 걸음마를 익히는 과정을 연상하면 쉽다. 아이가 한발짝씩 제대로 걸을 때는 제대로 걷는다는 보상이 있지만 넘어지면 그 보상이 다 날아가게 된다. 결국 아이는 더 많은 보상을 위해 스스로 걷는 방법을 터득해나간다. 연구팀이 AI에게 설정한 기본적인 보상은 승리와 더 많은 HP였다. 쉽게 말해 더 큰 HP 차이를 유지한 채 이기면 더 큰 보상을 얻고 반대의 경우는 보상을 얻지 못하는 것이다. 더불어 스타일에 따라 거리 패널티, 공격 연계의 딜레이, 자신과 적 사이의 HP 비율 등으로 시작 조건을 다르게 구성해 상황에 맞는 전술을 구사하도록 학습 과정을 설정했다.
이후에는 자기자신을 상대로 반복적인 대련을 하며 최상의 보상을 찾아 스스로 연구하는 기회를 지속적으로 제공했다. 163시간을 훈련한 AI가 3시간, 142시간, 87시간 훈련한 AI와 지속적으로 대련하며 학습을 거쳤다. 딥러닝이 적용되지 않은 AI를 상대로 5시간 만에 승률 100%를 달성할 정도로 학습 속도는 빠른 편이었다. 이후에는 사람과 직접 맞붙으며 다른 방식을 학습했다. 특히, 사람과의 대련이 지속될 수록 AI 맹점이 하나 둘 드러났기 때문에 이를 보완하기 위해 다양한 선수들과 대련을 펼쳤다. 결과적으로 프로게이머와의 공식적인 전적에서 공격적 스타일의 경우 92% 승률, 밸런스 타입은 42%, 방어형 AI는 50% 승률이라는 준수한 성적을 보였다. 보상을 통한 강화학습이 효과적으로 작용함을 입증한 것이다. ▲ 지난 9월에 있었던 블라인드 매치 전경기 (영상출처: OGN 유튜브) 유저들에게 그 자체로 새로운 콘텐츠가 될 수 있는 연구 AI가 실제 사람처럼 움직이면서도 프로게이머 못지 않은 실력을 지니고 있다면 이는 그 자체로 훌륭한 콘텐츠가 될 수 있다. 더불어 그동안 나왔던 연습용 더미보다 훨씬 좋은 연습상대가 되어줄 것이다. 물론, 앞에서 이야기했듯이 보상을 이용한 강화학습도 완벽한 것은 아니다. 인간과 오랜시간 대련하다 보면 약점이 드러난다는 점에서 알 수 있다. 다만, 그 과정을 스스로 깨우치는 AI가 제대로 개발된다면, 머지 않아 진짜 프로게이머 수준의 AI가 유저의 연습상대가 되어줄지도 모를 일이다.
Copyright ⓒ 게임메카. 무단전재 및 재배포 금지 안녕하세요, 프로메디우스 인턴사원 간정현입니다. 이번 포스팅에서는 YOLO와 다크넷 프레임워크를 간단히 소개하고, 다크넷 사용 후기를 공유하려고 합니다. 부족한 글이지만 재밌게 봐주시면 감사하겠습니다! You Only Look Once 😎OverviewYOLO(You Only Look Once)는 빠른 추론 속도와 상당한 정확도를 자랑하는 오브젝트 디텍션 모델입니다. 오브젝트 디텍션은 객체의 위치와 크기를 예측하는 문제와 해당 객체의 클래스를 분류하는 문제로 세분화할 수 있습니다. 모델에 따라서 이 두 가지 문제를 한번에 처리하기도 하고, 두 단계로 나누어 처리하기도 합니다. YOLO는 이름에서 알 수 있듯이 하나의 네트워크에서 객체의 위치와 크기, 클래스를 동시에 예측하는 방식을 채택합니다. YOLO의 아이덴티티는 실시간 수준의 빠른 예측 속도를 유지하면서도 꽤 정확한 예측을 내놓는다는 점에 있습니다. 일반적으로 위치 예측과 클래스 분류를 한꺼번에 수행하는 간결한 파이프라인을 채택할 경우 예측 속도 면에서는 유리하지만 정확도 면에서는 불리합니다. YOLO 역시 정확도만 놓고 보면 가장 뛰어난 모델이라고는 할 수 없습니다. 하지만 추론 속도를 함께 고려하면 상황이 달라집니다. 위 그림처럼 실시간 수준의 추론 속도를 가진 모델들 중 YOLOv4는 압도적인 성능을 보입니다. YOLOv1: outputsYOLOv1을 통해서 모델의 학습 과정을 조금 살펴봅시다. 위 그림은 네트워크의 아웃풋을 나타낸 것입니다. 아웃풋이 만들어지는 과정을 보다 구체적으로 살펴보면 아래와 같습니다.
논문에서는 모델이 내놓는 YOLOv1: loss위 수식은 YOLOv1의 로스 함수입니다. 😈 무시무시하게 생겼지만 사실 자세히 뜯어보면 그렇게까지 험악한 친구는 아닙니다 😇 기본적으로 좌표, 크기, 컨피던스, 클래스 확률의 평균제곱오차를 계산한 후 모두 더하는 구조로 되어있습니다. 여기에서 로스의 모든 디테일을 리뷰할 수는 없으니 "responsible" 의 개념에 대해서만 짚고 넘어가려 합니다. (p.2) If the center of an object falls into a grid cell, that grid cell is responsible for detecting that object. 위 인용을 보면 "responsible" 이라는 개념은 그리드 셀에 대해서도, 바운딩 박스에 대해서도 쓰입니다. 하지만 로스의 관점에서 "responsible" 은 결국 바운딩 박스에 대한 개념으로 생각하면 됩니다. 즉 하나의 물체에 대한 예측을 책임지는 유일한 바운딩 박스를 결정하는 문제입니다. 수식을 보면예측에 대해 "responsible" 하지 않은 박스의 좌표 크기 로스 텀은 0이 되는 것을 알 수 있습니다. 즉 책임이 없는 박스들에 대해서는 좌표와 크기의 로스를 면제해주자는 아이디어입니다. 천천히 따져봅시다! 먼저그리드 셀의 단위에서는 해당 셀이 어떤 물체의 중심을 포함하는 경우 그 물체의 탐지에 대해 "responsible"하다고 합니다.하지만 모델의 구조상 하나의 그리드 셀은 여러 개의 바운딩 박스를 예측하게 됩니다. 하나의 물체에 대해 정확히 하나의 바운딩 박스를 대응시키기 위해 바운딩 박스에 대해서도 "responsible" 의 조건을 정의해야 합니다. 바운딩 박스에 대해서는, 물체에 대해 가장 높은 IOU를 갖는 박스를 물체에 대해 "responsible" 하다고 정합니다. 정리하면, 어떤 물체의 중심을 포함하는 셀에서 예측된 바운딩 박스 중 실제 바운딩 박스와 가장 큰 IOU를 갖는 박스를 그 물체에 대해 "responsible" 하다고 말합니다. Darknet다크넷은 Joseph Redmon이 YOLO 학습을 위해 개발한 프레임워크입니다. 하지만 대부분의 사용자들은 YOLOv4의 저자인 Alexey Bochkovskiy의 버전을 사용하는 듯 하고, 업데이트도 포크 버전에서 더욱 활발하게 이루어지는 것 같습니다. 저 역시 포크 버전을 사용했는데, 개인적으로는 프레임워크 전반에 대한 문서와 설명이 오리지널 웹사이트보다 훨씬 상세하다고 느꼈습니다. 저뿐만 아니라 다른 분들도 다양한 이유로 오리지널 버전보다는 Alexey 버전을 선호하시는 것 같습니다! 데이터셋 제작 다크넷 라벨 데이터 형식모델을 만들기 위해서는 우선 데이터가 있어야겠죠? 다크넷 학습을 위해서는 이미지와 라벨의 쌍으로 이루어진 데이터셋이 필요합니다. 저는 흉부 X-ray 사진에서 L 자 마커를 찾아내는 모델을 학습시키기 위해 사내 데이터 2,200장, 오픈 데이터 200장을 직접 레이블링했습니다. 레이블링 작업은 정말 힘들고 괴롭지만 마치고 나면 묘한 성취감이 느껴져요 😄 레이블링 작업에는 Yolo_label이라는 툴을 사용했습니다. 이 툴의 장점은 다크넷의 라벨 데이터 형식을 그대로 따르기 때문에 만들어진 데이터를 별도의 전처리 없이 즉시 다크넷에 주입할 수 있다는 것입니다. 또한 드래그 & 드롭 방식이 아닌 클릭 & 클릭 방식을 사용해서 손목의 부담도 확실히 덜합니다. 사실 예전에도 3개월 정도 자율주행을 위한 데이터를 레이블링해본 적이 있는데, 그 당시 사용한 툴과는 비교도 되지 않을만큼 편했습니다. 직접 다크넷에 들어갈 데이터를 제작해야하는 상황이 또다시 생기면 고민 없이 사용할 것 같네요! 학습 준비자신의 데이터셋으로 다크넷 모델을 훈련시키려면 다크넷 깃허브의 How to train (to detect your custom objects)
파트에 설명된대로 몇 가지 준비가 더 필요합니다. 개인적으로는 이 과정이 헷갈려서 제 방식대로 다시 정리를 해봤습니다. 편의를 위해 그림과 같이
meta/train.txt meta/valid.txt
cfg/example.data cfg/example.namesYOLO의 각 버전에는 대응하는 다크넷
학습이제 모델을 학습시킬 준비가 모두 끝났습니다 😆 번거로운 준비과정에 비해서 학습과 성능 평가, 예측은 저는 사내 데이터 2,000장으로 YOLOv3의 학습과 검증을 진행한 후 사내 데이터 200장과 오픈 데이터 200장에 대해서 각각 mAP를 테스트해보았습니다. 테스트 결과 사내 데이터에 대한 성능은 0.9998로 꽤 높았지만 오픈 데이터에 대한 성능은 0.2020 정도로 매우 낮았습니다 😞 나름대로 이런저런 augmentation을 적용해서 성능을 끌어올린 결과인데, 생각보다 훈련 데이터에 오버피팅이 많이 되어있는 듯 합니다. 역시 시간이 허락하는 한 가장 좋은 방법은 더욱 다양한 데이터를 만드는 것인가봅니다. 아래 사진은 오픈 데이터에 대한 테스트 수행 결과입니다. Wrap up다크넷을 간단하게 사용해본 소감은 "귀찮지만 쉽다(혹은 쉽지만 귀찮다)" 입니다. 제 생각에 다크넷은 고난도의 태스크를 해결하기 위한 전문적 도구라기보다는 쉬운 난이도의 태스크를 해결하기 위한 범용적 도구인 것 같습니다 (YOLO의 가장 큰 장점으로 꼽히는 속도에 대해서는 사실 다른 모델을 사용해본 적이 없어서 뭐라고 말씀은 드리지 못하겠네요😅). 다크넷은 정말 쉽습니다. 다크넷의 학습 과정은 YOLO와 C에 대한 지식을 거의 요구하지 않습니다. 다크넷은 모델의 구조와 사전 훈련된 가중치를 모두 제공하기 때문에 사용자는 자신의 데이터를 준비한 후 훈련에 필요한 파일들을 만들고 수정하기만 하면 됩니다. 이 과정이 조금 번거롭기는 하지만, 가이드 문서에 설명이 상세하게 되어있기 때문에 인내심을 가지고 따라한다면 누구나 나쁘지 않은 성능을 가진 모델을 만들 수 있습니다. 하지만 이 준비 과정이 상당히 귀찮고, 반복적인 실험과 재현의 편의성 면에서 다른 프레임워크에 비해 뒤떨어집니다. 전처리 방식이나 학습 파라미터가 변경될때마다 이 준비과정을 계속 반복해야 한다고 생각하면 정말 끔찍합니다 😱 즉 가볍게 사용하기에는 좋지만, 반복적인 실험을 통한 성능 향상을 염두에 두고 있다면 조금 불편할 수 있는 프레임워크입니다. 머신러닝 모델의 성능 향상이 결국에는 수많은 실험에 기반하는 것이라면 다크넷의 단점은 꽤 치명적일수도 있지만, 1%의 성능 향상에 목숨을 걸어야 하는 상황이 아니라면 상당히 괜찮은 프레임워크이니 자신의 상황에 맞게 선택하면 될 것 같습니다! 참고
|