gimmesilver's blog

Agbird.egloos.com

포토로그



소리 아이 그 이후 단상

  2008년에 '소리아이'라는 다큐멘터리 영화를 굉장히 인상 깊게 보고선 블로그에 글을 쓴 적이 있다(http://agbird.egloos.com/4624292). 오늘 문득 그들이 현재 어떻게 지내는지 검색을 해 보니 이런 기사들을 발견했다.

 - 전주대사습놀이 판소리 일반부 장원: http://www.hnwoori.com/news/articleView.html?idxno=116306
 - '국악신동' 박성열, 방황 털고 양악 수술: http://www.iksanopennews.com/news/articleView.html?idxno=463149

  9년 전 다큐멘터리에서도 엘리트 코스를 밟던 수범이는 지금 전형적인 엘리트의 길을 가고 있는 반면 그 당시에도 파란만장한 어린 시절을 보내던 성열이는 여전히 쉽지 않은 인생을 살고 있단 생각에 마음이 아련해졌다.

데이터 분석을 이용한 게임 고객 모델링 #1 데이터분석

아래 글은 회사 블로그에 기고한 글의 초본입니다. 회사 커뮤니케이션실의 마사지를 받은 버전은 http://blog.ncsoft.com/?p=24178 에서 확인하실 수 있습니다.

---------------------------------

  혹시 MBTI 검사라는 말을 들어 보셨거나 직접 검사를 받아 보신 적 있으신가요? MBTI는 테스트를 통해 사람의 성격을 16가지 유형으로 분류하는 지표입니다. 비교적 단순한 검사와 몇 가지 유형만으로도 그럴듯하게 사람의 성격을 잘 분류하기 때문인지 지표가 개발된 지 수십 년이 지난 지금까지도 많은 인기를 끌고 있습니다.

MBTI는 양분되는 4가지 카테고리의 유형을 조합하여 총 16가지 유형으로 사람의 성격을 분류합니다.

  이처럼 다양한 사람들을 몇 가지 유형으로 분류하여 파악하는 방식은 비단 심리 테스트에서만 사용하는 것이 아닙니다. 고객관리 및 마케팅, 제품 설계, 서비스 기획 등의 분야에서도 저마다의 목적에 맞춰 다양하게 방식으로 고객을 유형별로 분류하여 그 결과를 활용하고 있죠. 이것을 ‘고객 세분화 (Customer Segmentation)’ 라고 부릅니다. 카드 회사에서 소비 패턴에 따른 맞춤형 신용 카드 상품을 설계한다거나 혹은 백화점이나 마트 등에서 성별, 거주지, 연령대 별로 소비 패턴을 분석하여 각 유형에 맞는 상품을 진열하고 카탈로그를 발송하는 등이 모두 고객 세분화의 활용 사례입니다.

  온라인 게임 역시 현실 세계 못지 않게 다양한 유형의 유저들이 존재합니다. 때문에 좋은 게임을 만들고 서비스하기 위해선 이런 다양한 유저의 특징을 잘 파악하여 적절하게 세분화하는 것이 필요합니다.

‘게임 유저’ 라고 하면 이런 이미지를 떠올릴지 모르겠지만……

무려 이런 사람들도 게임을 즐긴답니다!

  특히 온라인 게임에서는 유저가 수행하는 다양한 활동들이 로그에 꼼꼼히 기록되기 때문에 풍부하고 다양한 데이터를 바탕으로 유저 행동에 대한 세밀한 분석이 가능합니다. 이렇게 게임 활동을 관찰하여 유저의 특징을 파악하는 작업은 마치 프로파일러가 세밀한 관찰을 토대로 어떤 사람의 직업이나 나이, 성격 등을 추정하는 것과 비슷하다고도 볼 수 있습니다.

‘손목의 시계줄 자국과 딱딱한 말투에 단정히 빗은 머리로 지팡이를 짚은 모습을 보니 
너님은 아프칸 파병 갔다 의가사 제대한 군인인 듯……’

  물론 그렇다고 해서 게임 유저를 세분화할 때 ‘이 사람은 겉으론 까칠해 보여도 섬세한 내면의 감수성을 보유한 20대 도시남이군’ 이라고 파악하지는 못합니다. 저희가 볼 수 있는 것은 단지 게임 플레이 기록이기 때문에 실제 유저의 특성이 아니라 유저가 플레이한 캐릭터의 특성을 파악할 수 있을 뿐이죠. 예를 들면 ‘일주일에 10시간 정도 게임을 즐기는데 필드 사냥보다는 퀘스트나 인던 활동을 더 선호하는 유형’ 같은 식입니다. 

  이런 고객 세분화를위해 많이 사용되는 데이터 마이닝 기법으로 ‘군집화 (Clustering)’라는 것이 있습니다. 이름에서 알 수 있듯이 서로 다른 여러 가지 유형이 섞여 있는 데이터에서 유사한 특성을 갖는 유형끼리 군집을 묶어줄 때 사용하는 기법이죠.

어떤 데이터에서 유사한 특징을 갖는 대상끼리 군집을 묶어주는 기법을 ‘군집화(Clustering)’ 이라고 부릅니다.

  군집화 기법을 사용해 게임 유저의 유형을 분류할 때 우리는 크게 세 가지 측면에서 적용할 수 있습니다.

  첫째, 유저가 게임에서 하는 행동을 기반으로 군집화가 가능합니다.
  앞서 언급해 드린 소비 패턴에 따라 고객의 유형을 나누는 사례에서처럼 게임 유저 역시 게임 내 활동 패턴에 따라 유형을 나눌 수 있습니다. 이런 행동 기반 군집화는 다른 분야에서도 일반적으로 널리 사용하는 방식입니다.

  둘째, 시간에 따른 변화 과정을 기반으로 군집화할 수 있습니다.
  시간이 지남에따라 게임 업데이트로 인해 서비스 자체가 변할 뿐만 아니라 주변 환경이나 사람들의 성향 역시 조금씩 달라지기 마련입니다. 따라서 어떤 유저가 특정 시점에 A 유형이라고 분류됐다고 해서 앞으로도 영원히 A 유형을 유지할 것이라 단정할 수 없습니다. 실상은 유형이 달라질 가능성이 더 크죠. 그렇다면 만약 ‘가’라는 캐릭터는 A라는 유형에서 B를거쳐 C로 바뀌었고 ‘나’라는캐릭터는 E에서 D를 거쳐 C로 바뀐 경우 이 둘이 단지 마지막 분류 시점에서 볼 때 같은 C 유형이라고해서 동일한 취급을 하는 것이 맞을까요?
  아마도 비록 같은 C 유형이라고 하더라도 기존에 어떤 이력을 거쳐 현재의 상태에 도달했느냐를 고려하여 유형을 분류하는 것이 더 유저를 정확히 이해하는데 도움이 될 것입니다. 따라서 시간에 따라 달라지는 유형 정보 역시 군집화에 활용할 수 있습니다. 이렇게 일련의 순서를 갖는 정보를 이용하여 군집화 하는 기법을 ‘시퀀스 클러스터링 (Sequence Clustering)’ 이라고합니다.

동일한 유형의 유저라고 해도 어떤 이력을 거쳐 왔는지에 따라 구분이 필요할 수 있습니다.

  셋째, 유저가 속한 사회 집단을 기준으로 군집화가 가능합니다.
  대부분의 온라인 게임들은 유저 간의 상호 작용에 의한 사회 활동을 중요한 게임 콘텐트로 제공합니다. 가령, 파티나 혈맹 활동이 대표적이고 더 나아가 서로 아이템을 사고 파는 거래 활동 역시 그렇습니다. 이런 상호 작용을 통해 모든 게임 캐릭터들은 일종의 사회 집단을 형성하게 됩니다.
  따라서 단지 개개인의 특징만을 분석하는 것뿐만 아니라 각 게임 캐릭터가 어떤 사회 집단에 속해있는지 혹은 친밀한 관계를 갖는 주변 캐릭터의 유형은 무엇인지 등도 같이 분석한다면 유저의 유형이나 특징을 좀 더 정확하게 파악할 수 있을 것입니다.
이렇게 각 개체간의 사회 관계 데이터를 이용해 여러 가지 특징을 분석하는 기법을 ‘사회 연결망 분석 (Social Network Analysis)’ 이라고 합니다. 주로 페이스북이나 트위터 같은 SNS 데이터를 이용한 분석이 널리 알려져 있는데, 온라인 게임 역시 이런 분석이 가능합니다.

‘사회 연결망 분석 (Social Network Analysis)’은 유저 간의 관계에서 나타나는 여러 가지 특징들을 분석하는 기법입니다.

  정리하자면, 우리는 게임 유저가 어떤 행동 패턴을 갖고 있는지, 시간이 지남에 따라 패턴이 어떻게 변화하는지, 그리고 게임 유저가 긴밀한 관계를 갖고 있는 집단의 유형은 무엇인지를 이용하여 유저를 세분화할 수 있습니다.

  그럼 이 각각의 분석 기법을 이용해 실제 게임 유저를 유형별로 어떻게 세분화할 수 있는지 좀 더 구체적인 방법에 대해서는 다음 편에서 하나씩 소개하겠습니다.

기계 학습과 코딩의 종말 #2 - 연역적 프로그래밍과 귀납적 프로그래밍 데이터분석


-----------------------------------------
4. 기존의 프로그래밍과 기계 학습에 의한 프로그래밍
  단순화해서 보면 프로그램은 어떤 입력에 대해 특정한 출력을 하는 함수라고 생각할 수 있습니다. 예를 들어 여러분이 이 글을 볼 때 사용하는 웹 브라우저는 마우스 클릭 등의 사용자 행동을 입력으로 받으면 그에 맞는 웹 페이지를 출력하는 함수입니다. 그리고 프로그래머는 프로그래밍 언어를 이용해서 해당 프로그램(함수)의 내부 로직을 구현하죠. 이것을 도식화하면 <그림 7>과 같습니다.

<그림 7> 기존의 프로그래밍 방식

  한편, 기계 학습을 이용한다면 방식이 조금 달라집니다. <그림 8>에 나와있듯이 '기계 학습 프로그램'이 있고 이 프로그램에 사용자가 입력값과 그 입력값을 통해 출력되기 원하는 결과값으로 이뤄진 '학습 데이터'를 입력하면 이 '기계 학습 프로그램'이 사용자가 원하는 '프로그램'을 생성합니다. 비록 기계 학습 분야에서는 기계 학습 프로그램이 만든 프로그램을 '프로그램'이라고 부르지 않고 '모델'이라고 부릅니다만 위 관점에서 보자면 기계 학습 모델은 일종의 프로그램(혹은 함수)입니다. 마치 기존에는 사람이 어떤 물건을 직접 만들었다면 요즘에는 '어떤 물건을 만드는 로봇'을 사람이 한번 만들고 나면 그 로봇이 '물건'을 계속해서 생산하는 것과 비슷합니다.

<그림 8> 기계 학습을 이용한 프로그래밍 방식

  예를 들자면, 우리가 많이 사용하는 네이버나 구글 같은 웹 메일 서비스에서 흔히 제공하는 스팸 메일 분류기를 생각할 수 있습니다. 스팸 메일을 분류하기 위한 규칙을 정규 표현식 같은 방법을 써서 프로그래머가 직접 구현하는 방식이 <그림 7>과 같은 방식입니다(그리고 과거에는 실제 이런 식으로 분류기를 직접 개발하는 경우가 종종 있었습니다).
  반면, 나이브 베이지안 알고리즘과 같은 기계 학습 알고리즘을 사용하여 스팸 분류를 위한 기계 학습 프로그램을 구현한 후 이 프로그램에 대량의 스팸 메일과 일반 메일 데이터를 입력하여 학습을 시키는 방식이 <그림 8>과 같은 방식입니다. 이 프로그램은 수많은 메일 데이터를 이용해서 스팸을 적절히 분류할 수 있는 '스팸 메일 분류 프로그램'를 생성합니다. 그러면 웹 메일 서비스 업체에서는 이 기계 학습 프로그램이 생성한 '스팸 분류 프로그램'을 이용하는 것이죠. 
  대개의 경우 실전에서는 <그림 7>과 <그림 8>의 방식을 혼용해서 사용합니다. 예를 들어 기계 학습이 만든 스팸 필터를 이용해서 1차 분류를 한 다음 좀 더 정교한 분류 규칙은 프로그래머가 추가로 구현하는 것이죠. 그러나 점점 기계 학습 기법이나 성능이 발전하고 학습에 사용할 수 있는 데이터가 많아지면서 후자의 역할은 줄어들고 있습니다. 마치 기존에는 기계가 사람의 노동력을 보조하는 수준이었다면 이제는 점점 로봇에 의해 완전 자동화되고 있는 것처럼요.

5. 기계학습으로 8bit 덧셈기 구현하기
  '8bit 뎃셈기' 란 말 그대로 0~255 까지의 범위를 갖는 두 개의 숫자를 더한 값을 출력하는 디지털 회로를 의미합니다. '덧셈'은 너무나 단순하고 기본적인 연산이고 보통은 어떤 프로그래밍 언어에서든 기본으로 제공되기 때문에 간과하기 쉽지만, 사실 이것 역시 두 개의 숫자를 입력하면 두 숫자의 합을 출력하는 '프로그램(혹은 함수)' 입니다. <그림 9>는 논리 회로를 이용해 덧셈 연산을 구현한 도식입니다.

<그림 9> 논리회로를 이용해 구현한 8bit 덧셈기

  1편에서 소개했듯이 뉴럴 네트워크는 이론적으로 어떤 논리회로도 표현이 가능합니다. 따라서 적절히 학습만 한다면 <그림 9> 에 있는 덧셈 연산기 역시 뉴럴 네트워크를 이용해서 구현할 수 있습니다. 아래 코드는 H2O 라는 딥 러닝 라이브러리를 이용해서 덧셈 연산기를 구현하는 아주 간단한 R 코드입니다.

library(h2o)
h2o.init()
sample.size<-500000
x1<-sample(1:255, sample.size, replace=TRUE)
x2<-sample(1:255, sample.size, replace=TRUE)
y<-x1+x2
train<-data.frame(x1, x2, y)
adder<-h2o.deeplearning(x=1:2, y=3, training_frame=as.h2o(train), hidden = c(200, 200))

  보다시피 위 코드에서는 두 개의 숫자를 더하는 작업을 하는데 필요한 로직을 구현하는 코드를 찾아 볼 수 없습니다. 단지 0~255 사이에서 임의로 선택한 두 수와 그 합으로 구성된 데이터 50만개를 '기계 학습 프로그램'의 입력값으로 넣을 뿐입니다. 그러면 '기계 학습 프로그램'은 출력으로 덧셈을 계산하는 '프로그램'(위 코드에서 'adder')을 반환합니다.

<그림 10> 위 기계 학습 프로그램이 생성한 8bit adder 실행 예. 12 와 209 를 입력하면 221이라고 정답을 내놓습니다.

  어떤 분들은 이런 단순한 연산은 어찌 가능할지 몰라도 우리가 일반적으로 사용하는 복잡한 프로그램을 어떻게 훈련만으로 만들 수 있겠느냐고 생각하실지 모릅니다. 그러나 앞서 1편에서도 언급했듯이 우리가 사용하는 바로 그런 프로그램들 역시 모듈 단위로 점점 세분화해 보면 이런 단순한 연산자들의 조합일 뿐입니다. 따라서 그럼 복잡한 로직을 흉내내는데 필요한 데이터와 훈련 시간만 충분하다면 그런 프로그램을 뉴럴 네트워크를 통해 학습하지 못할 이유는 없습니다.

  다만 이것은 기존 관점에서 보면 '프로그래밍'이라고 부르기 힘듭니다. Wired 의 컬럼 제목인 'Soon we won't program computers. We'll train them like dogs' 에서 표현되어 있듯이 이것은 그저 우리가 개를 훈련시킬 때 원하는 행동을 계속 반복해서 가르치는 것과 비슷합니다. 기계 학습 프로그램에게 어떤 입력에 대한 출력을 반복해서 입력함으로써 원하는 로직을 학습시키는 것이죠.
  더 나아가 <그림 7>과 <그림 8>의 '프로그램'을 만드는 방식에는 논리적으로도 매우 큰 차이가 있습니다. <그림 7>에서 프로그램 로직은 사람의 연역적 사고에 의해 만들어집니다. 일종의 우리가 알고리즘이라고 부르는, 다시 말해 'A 이면 B 이고 B 이면 C 이니 A 이면 C 이다'와 같이 연역적으로 타당한 규칙의 흐름을 통해 로직을 구성합니다.
  반면 <그림 8>의 프로그램은 다릅니다. 기계 학습은 수많은 데이터를 통해 귀납적으로 로직을 구성합니다. 기계 학습 알고리즘은 실제 사용자의 의도에 대한 이해를 바탕으로 로직을 구성하는 것이 아니라 학습 데이터 상에 나온 어떤 입력에 대해서 정답과 최대한 근사한 값이 나오는 것을 목표로 로직을 구성합니다. 비약하자면, 물리 법칙에 맞춰 정확한 설계대로 자동차를 만드는 것이 기존의 프로그래밍 방식이라면 기계 학습은 부품들을 쭉 늘어놓고 마구잡이로 부품을 끼워 맞춰서 어찌됐던 굴러가는 무언가를 만드는 방식입니다. 그게 우연히 기존 자동차와 동일한 설계를 가질 확률은 거의 0에 가깝지만 그렇다고 해서 0은 아닙니다. 게다가 설령 전혀 기존 자동차와 다른 형태를 지녔더라고 해도 일단 굴러간다는 목적만 충족한다면 크게 상관이 없을 수도 있죠.

  그런데 바로 이런 점 때문에 (적어도 현재까지의) 기계 학습이 만드는 로직은 귀납법이 가진 한계를 똑같이 같고 있습니다.

6. 귀납의 오류
  위에서 예로 든 덧셈기는 사실 실제 덧셈기와 동일한 로직을 갖고 있지는 않습니다. 아니 좀 더 정확히 말하면 동일한지 아닌지를 알 수 없습니다. 단지 테스트를 해 보니 실제 덧셈기와 동일한 결과를 출력하니 그런가 보다 하는 것이죠. 이건 마치 존 설이 제기한 '중국어 방' 문제를 연상케 합니다.
  <그림 11> 존 설의 '중국어 방' - 중국어를 모르는 어떤 사람이 단지 주어진 메뉴얼대로 중국말에 답할 경우 이 사람이 중국어를 안다고 말할 수 있을까요?

  그런데 이 때문에 뉴럴 네트워크를 통해 구현한 덧셈기는 오류의 가능성을 내포하고 있습니다. 게다가 실제로도 그렇습니다. 위 덧셈기에 대해서 계속 덧셈 문제를 테스트해보면 약간의 오차가 발생합니다. 예를 들어 제가 아래와 같이 다양한 숫자에 대해서 1000번을 테스트를 해보면 기계 학습이 만든 덧셈기는 대략 0.5정도의 오차가 발생합니다. 

test.size<-1000
x1<-sample(1:255, test.size, replace=TRUE)
x2<-sample(1:255, test.size, replace=TRUE)
y<-as.numeric(x1+x2)
test<-data.frame(x1, x2, y)
result<-as.data.frame(h2o.predict(adder.model, as.h2o(test)))
test$pred<-round(result$predict)
sqrt(sum((test$pred-test$y)^2)/nrow(test)

  물론 이런 오차는 아마도 더 복잡한 뉴럴 네트워크를 구성하고 더 많은 데이터를 학습시킨다면 점차 줄어 들겠지만 완벽히 없앨 수 있다는 보장은 할 수 없습니다. 연역적으로 구성된 로직이라면 알고리즘에 대한 수학적 검증을 통해 알고리즘이 정확한지 여부를 알 수 있습니다. 반면 귀납적으로 구성된 로직은 모든 경우의 수를 테스트해 보지 않는한 정확성을 보장할 수 없습니다. 이 '모든 경우의 수'는 우리가 프로그램 QA를 할 때의 '모든 테스트 시나리오'와 다릅니다. QA에서 수행하는 테스트는 좀 더 추상화된 수준이지만 귀납적 로직에서의 '경우의 수'는 말 그대로 가능한 모든 경우의 입력 데이터를 말합니다. 따라서 현실적으로는 불가능에 가까운 수준입니다.
  바로 이런 점 때문에 기계 학습은 '프로그래밍에 의해 만든 프로그램'을 비슷하게 흉내낼 수는 있지만 정확히 그 프로그램을 '훈련'시킬 수는 없습니다.

7. 맺음말
  쓰고 나니 글이 불필요하게 길어진 것 같은데 짧게 요약하자면, 뉴럴 네트워크 기반의 기계 학습은 이론적으로 보면 기존의 프로그램을 그대로 표현할 수 있습니다. 하지만 기계 학습이 프로그램을 만드는 방식은 기존의 소프트웨어 개발과는 매우 다른 방식입니다. 어떤 복잡한 로직을 구현하기 위해 프로그래머가 머리를 싸맬 필요가 없고 단지 원하는 결과를 기계 학습이 제대로 구현할 때까지 반복해서 학습 시키기만 하면 될 뿐입니다. 이건 마치 프로그래머가 테스트 케이스를 먼저 만들어 놓고 이 테스트를 통과하도록 로직을 구현하는 TDD를 자동화하는 것과 비슷해 보이기도 합니다.
  그렇다면 이제 정말 프로그래밍이 더 이상 필요없어질까요? 아쉽게도 (아니 다행스럽게도) 이런 방식에는 현재까지로 볼 때 6장에서 언급한 것과 같은 치명적인 한계가 있습니다(만약 없다면 이 세상의 프로그래머들은 대부분 필요가 없어지겠죠). 그리고 바로 이런 한계를 극복하는 것이 아마도 기계 학습의 과제 중 하나이지 않을까 싶습니다. 다만 제가 생각하기에 초기의 자동차도 형편없는 효율성을 갖고 있었지만 결국 말과 마차를 넘어섰듯이 기계 학습에 의한 프로그램 역시 현재의 프로그래밍을 상당 부분 대체할 수 있지 않을까 생각합니다.

IEEE TIFS 논문 게재 단상

비록 숟가락만 얹은 논문이지만 그래도 내 이름이 들어간 논문이 무려 IEEE transactions 에 실리다니... 기쁘다.


pxd talks #70 - 데이터 분석을 통한 게임 유저 모델링 데이터분석

  지난 주 pxd 라는 회사에서 데이터 분석을 이용한 게임 유저 모델링을 주제로 발표를 했습니다. UX 관련 회사이고 직원분들 대부분이 데이터 분석과 직접적인 관련이 없다고 들었는데 예상외로 굉장히 열심히 들어주시고 질문도 많이 주셔서 놀랐습니다. 오히려 제가 충분히 원하시는 정보나 답변을 못드린 것 같아 죄송하네요. 
  혹시 관심있으신 분들을 위해 해당 자료 공유합니다.




1 2 3 4 5 6 7 8 9 10 다음