본문 링크 (Original Link)

마술 파헤치기: ARKit을 사용한 스도쿠 해결기

2017.10.27

#

by Brad Dwyer, translated by pilgwon

머신 러닝에 대한 첫 번째 시도에서 얻은 교훈

image1 매직 스도쿠 앱이 나왔습니다. 여기서 다운받으세요.

Brad Dwyer는 Iowa의 Des Moines에 있는 게임이나 모바일 앱을 만드는 회사인 Hatchlings의 설립자입니다.

몇 주 전에 Hatchlings에서 매직 스도쿠라는 iOS 11을 위한 앱이 나왔습니다. 이 앱은 컴퓨터 비전, 머신 러닝 그리고 증강 현실을 이용해서 스도쿠 퍼즐을 해결합니다. 지금 앱 스토어에서 아이폰 6S (또는 그 이상) 혹은 아이패드 프로에서 만나볼 수 있습니다.

매직 스도쿠는 9GAG의 첫 페이지에 올라가는 것을 포함해 수많은 관심을 받았고, GizmodoCNET의 잘 만든 ARKit 앱 리스트에도 올라갔습니다. 그리고 Fast Company의 디자인 블로그에도 “냄새”나지 않는 AR 앱으로 소개됐습니다.

많은 사람들이 이 앱에 대해 물어봤고 그래서 저는 이 앱을 어떻게 만들고 왜 만들었는지에 대해 공유하는 것도 재밌을 거 같다는 생각이 들었습니다.

이 글은 총 3편 중 2편입니다. 1편은 매직 스도쿠를 왜 만들었는지에 설명하고 어떤것이 다른 증강 현실 앱과 다른지에 대해 설명합니다. 그리고 3편에서는 비즈니스 측면을 살펴볼 예정입니다.

미디엄을 구독하거나 트위터에서 팔로우하시면 3편이 언제 나오는지 가장 먼저 알 수 있으실 것입니다. 그리고 앱을 다운로드 받는 것도 잊지마시고 직접 시도해보세요!

매직 스도쿠는 어떻게 작동할까요?

간단한 것은 복잡한 것보다 어려울 수 있습니다, 생각을 깔끔하고 간단하게 만들기 위해선 어려운 작업이 필요합니다 - 스티브 잡스

image2 매직 스도쿠는 사용자의 경험을 심리스(seamless)하고 간단하게 만들기 위해 복잡한 기술들을 위화감 없이 연결합니다.

매직 스도쿠는 컴퓨터 비전, 머신 러닝 그리고 증강 현실을 조합해서 사용하기에, 사용자는 폰을 스도쿠 퍼즐에 갖다 대는 것만으로도 “그냥 작동하는” 마법 같은 사용자 경험을 선사합니다. 어플리케이션의 가장 기본적인 흐름은 다음과 같습니다:

이 모든 과정이 초당 여러번 발생합니다.

저는 ARKit의 영역이나 스도쿠 해결 알고리즘 또는 실제 머신 러닝 모델 자체에 그렇게 오래 머물러있지 않았습니다. (각 주제에 맞는 튜토리얼이 이미 많이 존재합니다.)

저에게 가장 흥미로웠던 것은 첫 번째 머신 러닝 알고리즘을 훈련시키는 것의 실용적인 측면이었습니다.

머신 러닝에서 배웠던 것들

처음에는 작동하지 않을 여러가지 방법을 배웠습니다

스도쿠 해결기를 첫 번째 AR 앱으로 고른 가장 큰 이유는 숫자를 식별하는 것이 머신 러닝에서는 “Hello World”를 출력하는 것과 같다고 알고 있었기 때문입니다. 저는 실제 세계의 문제를 해결하는데에 머신 러닝을 사용하고 싶었습니다.

저만의 모델을 훈련시키기 전에, 실제로 작동될 때 많은 것들을 더 쉽게 만들어줄 몇 가지 전략을 시도했습니다.

첫 번째로, 저는 광학 문자열 인식 라이브러리인 SwiftOCR을 사용하려고 했습니다. SwiftOCR을 사용하는데에 문제점은 SwiftOCR이 개별 문자보다는 문자열을 읽는데에 특화돼 있다는 것입니다. (기프트카드 같이요) 또한, “이것은 빈 정사각형입니다” 와 “이 숫자를 읽을 수 없습니다” 를 구별할 수 없었습니다. 몇 시간의 실험 후, 이것이 무작위로 숫자를 추측하는 것보다 나은 것이 없었습니다. SwiftOCR에게 뭐라고 하는 것이 아닙니다. SwiftOCR은 대단한 라이브러리지만 이 특정한 문제를 해결하는데에 적합하지 않았을 뿐입니다.

두 번째로, 저는 CoreML로 변환이 되어있는 미리 훈련된 MNIST 모델로 향했습니다. MNIST는 1990년에 배포된 손으로 쓰여진 숫자의 오픈 데이터셋입니다. 미리 훈련된 모델을 사용하는 것이 좋은 해결책이 될 수 있을 것 같았습니다. .mlmodel 파일은 완벽하게 자체 포함하고 있고 기본적으로 블랙 박스 오라클로 사용할 수 있는 Swift로 클래스를 노출합니다. MNIST를 사용하는 것은 첫 번째 내부의 프로토타입이 처음부터 끝까지 “작동”하는 목적에 닿게 한 방법입니다. 불행하게도, 수기로 적힌 MNIST 데이터셋의 숫자들은 컴퓨터 폰트와 너무 달라서 일반화하기엔 어려웠고 그래서 첫 번째 프로토타입은 아주 까다롭고 에러가 나기 쉬웠습니다.

이 시점에서 일어난 일들은 제가 옳은 길에 있다는 것을 알게할만큼 충분히 잘 작동하고 있었습니다. 저는 현실 세계의 스도쿠 퍼즐에서 추출한 데이터로 정확하고 믿을 수 있는 머신 러닝 모델을 훈련할 수 있기를 바랬습니다.

데이터 모으기

다음 단계는 제가 모을 수 있는 한 가장 많은 스도쿠 퍼즐을 모으는 것입니다. 저는 동네에 있는 Half Price Book Store에 갔고 거기 있는 모든 스도쿠 책을 구매했습니다.

저는 Hatchlings에 팀이 있었고, 그들에게 이 책들을 다 찢어달라고 했고 프로토 타입 앱을 수정하여 스캔한 작은 정사각형을 CoreML 모델을 통해 실행하는 대신 서버에 업로드 했습니다.

image3 우리의 보물은 동네 중고 서점에서 얻은 실제 데이터입니다

가벼운 작업을 하기 위해 많은 손이 사용됐습니다

이제 문제가 생겼습니다. 책에서 아주 방대한 퍼즐을 스캔한 이후에, 제 서버는 대략 600,000개의 이미지를 저장하게 되었습니다. 하지만 그것들은 완전히 라벨링되어있지 않았습니다.

image4 간단한 식별 도구

그래서 편법을 살짝 썼습니다. 숨겨진 비밀의 슈퍼파워를 사용했죠. 수 천명의 Hatchlings 사용자들은 자신들이 가장 좋아하는 게임의 개발자들을 도우는 데에 거리낌이 없었습니다.

저는 간단한 관리자 도구를 만들었고 유저들이 이미지를 식별하고 그에 맞는 숫자를 키보드로 입력하게 하였습니다. Hatchlings 페이스북 그룹에 도움을 청한 이후에, 사용자들은 빠르게 작업을 들어갔고 24시간 이내에 60만 이미지가 식별 완료 되었습니다!

image5 실수를 가려내기 위한 관리자 도구

불행하게도, 약간의 소수가 이 업무를 제대로 이해하지 못해서 꽤나 의미있는 양의 잘못 인식된 이미지가 있었습니다.

이것을 고치기 위해 두 번째 도구를 만들었습니다. 이 도구는 사용자에게 100개의 이미지(다 같은 숫자라고 가정된)를 보여주고, 사용자에게 다른 숫자를 고르게 하는 것이었습니다. (이렇게 하면 잘못 식별된 숫자가 재식별되어 원래 자리로 돌아가게 됩니다.)

첫 번째 통과 이후에는 저는 인증된 데이터를 충분히 가지게 되었고 미래를 위해 자동 정확성 확인기를 두 도구에 넣을 수 있게 되었습니다. (그것은 주기적으로 사용자가 아는 이미지를 보여줄 것이고 그들의 대답이 얼마나 믿을 수 있는지 확인할 것입니다)

그 다음 몇 주 동안은 사용자들이 스캔한 데이터들을 여러번 식별해주었습니다. 사용자들의 도움으로 인해 앱을 런칭할 시기에는 백만개 이상의 스도쿠 정사각형 이미지가 훈련되어 있었습니다.

저는 이 데이터셋을 MNIST 데이터셋의 위치에 사용했고 Keras를 사용한 신경망 네트워크를 만들기 위한 튜토리얼을 사용했습니다. 결과는 제가 예상했던 것보다 훨씬 잘나왔습니다: 98.6% 였습니다! 그 다음 버전에서 99%의 정확도를 가질 수 있게 되었습니다.

실제 세계의 데이터로 훈련하기

이제 서점에서 구한 스도쿠 퍼즐은 전부 다 잘 작동합니다. 아직 깨닫지 못한 것이 있다면 이것은 야생에서 우리를 기다리는 것에 비하면 아주 소수라는 점입니다.

런칭 직후에 앱이 컴퓨터같은 화면에서 작동하지 않는다는 제보를 받기 시작했습니다. 당연히! 사람들은 앱을 시도해보고 싶지만 당장 자신의 앞에 퍼즐이 없기 때문에 Google에서 검색해서 시도해볼것입니다. 돌이켜보면 당연하지만 출시 당일에는 우리를 눈멀게 만들었습니다.

첫 번째 문제는 우리의 머신 러닝 모델이 종이 퍼즐에서만 훈련되었다는 것입니다. 화면에 있는 픽셀에 대해서는 어떻게 생각해야할 지 모른다는 것입니다. 저는 첫 주를 완전히 야근했고 모델이 컴퓨터 화면에도 작동하도록 재훈련시켰습니다.

두 번째 문제는 ARKit은 테이블이나 바닥같은 평면에서만 작동한다는 것입니다. 이것을 해결하는 것은 꽤나 까다로운 문제였지만 결국 해커스러운 해결방법을 찾아냈습니다. 저는 약간의 휴리스틱과 FeaturePoint 탐색을 통해 수평이 아닌 평면에도 퍼즐을 놓을 수 있게 되었습니다.

image6 우리 ML 모델이 이제 블러 처리된 이미지도 훈련했답니다!

또 다른 예상치 못 한 이슈는 ARKit이 고정된(하드코딩된) 초점 길이를 가지고 있다는 것입니다. 자동으로 초점을 잡아주지 않는다는 것입니다. 그리고 또한 기기의 다양성도 있었습니다. (iPhone 7의 센서로는 작동하지만 iPhone 6S는 가까이 가면 초점을 못 잡는 현상이 있었습니다) 해결책은 바로 훈련할 데이터셋에 블러된 이미지도 넣는 것이었습니다. 이 이미지에서 유용한 정보를 구할 수 있을지 확신할 수 없었습니다… 하지만 모델의 정확성에 영향을 주지 않는 것 같습니다. 현재 버전의 앱은 이미지의 숫자가 엄청나게 블러 처리 되어 있어도 잘 작동합니다.

클라우드

마지막으로, 저는 AWS의 GPU 인스턴스를 딥 러닝에 쓰는 것Google Cloud의 딥 러닝 제안들에 대한 광고를 많이 들었습니다. 그래서 그것들을 시험해보기로 했습니다. (그리고 또한 “딥 러닝을 위한 Heroku” 플랫폼인 FloydHub도 시도하기로 했습니다.)

그것들은 작동은 했습니다. 하지만 아주 느렸습니다. 저의 2016년형 맥북프로로 돌리는 tensorflow-cpu가 AWS의 GPU 인스턴스인 p2.xlarge보다 잘 돌아갔습니다. 제 의심은 제대로 만들어지지 않은 디스크가 훈련에 있어서 병목현상을 일으킨다는 것이었습니다.

클라우드 인스턴스는 또한 가격이 비쌉니다. 제 계산에 의하면, 지금까지 제가 했던 훈련을 클라우드로 하면 2개월의 시간이 필요했습니다. 그래서 저는 1200달러 선에서 상대적으로 겸손한 기기를 만들었고 부모님의 지하실에 두었습니다. 이 기기는 실험해보고 있던 AWS GPU 인스턴스에 비해 3배나 빨랐고 곧 그 댓가를 치러야 했습니다.

다음에 할 일

저는 여전히 머신 러닝 초보이지만 매직 스도쿠를 만들면서 많은 것을 배웠습니다.

그리고 몇 주 동안 버그 수정과 지금의 기능에 추가 기능을 만들어야 했습니다. 저는 이상한 폰트, 두께, 공백, 블러에 대한 대부분의 이슈를 해결했고 다음에 제가 해야 할 일은 휴리스틱이 좀 더 퍼즐을 잘 인식하게 하는 것입니다.

현재 버전(v1.4)은 퍼즐 사이에 공백이 너무 적거나 모서리가 종이의 끝과 가깝거나 모서리에 텍스트가 있을 경우 제대로 작동하지 않습니다. 저에겐 이 이슈들을 어떻게 해결할 지에 대한 이론이 있지만 많은 시도와 에러가 있어야 할 것 같습니다.

만약 휴리스틱을 작동시키지 못한다면 잘못된 스캔을 필터링하기 위해 다른 신경망을 훈련시키는데에 사용할 제대로 정렬된 퍼즐과 잘못된 스캔의 데이터셋을 수집하고 있습니다.

장기적으로 몇가지 꽤나 훌륭한 기능을 추가할 계획을 가지고 있습니다. 예를 들면, “체커” 기능을 완성된 퍼즐에 추가할 것입니다. 계획한 새로운 기능의 대부분은 컴퓨터로 주어진 숫자에서 필기된 숫자를 읽고 분리해야 하므로 전 세계의 사용자로부터 필기 샘플을 수집하여 새로운 기계 학습 모델을 교육해야 합니다.

또한 비즈니스 모델을 연구해야 합니다. 하지만 그건 3편에서 다룰 이야기 입니다. 그 동안, 앱을 다운로드 받으시고 여러분이 어떻게 생각하는지 알게 해주세요!

기대하세요…

이것은 3편 중 2편입니다. 1편은 왜 매직 스도쿠를 만들기로 했는지와 무엇이 그것을 희귀하게 만드는지를 설명합니다. 3편은 앱 런칭의 비즈니스적인 측면을 살펴보고 지금까지 어떻게 됐는지를 알아볼 것입니다.

미디엄을 구독하거나 트위터에서 팔로우하시면 3편이 언제 나오는지 가장 먼저 알 수 있으실 것입니다. 그리고 앱을 다운로드 받는 것도 잊지마시고 직접 시도해보세요!