쉬어가는 타이밍, 냉수 한 사발이 필요하다

어느덧 벌써 5월 중순이다. 2012년도 거의 반이 간셈. 요즘 여러모로 힘들다보니 시간이 생각보다 더 빨리 지나갔다. 무리한 일정으로 시간이 부족해서 육체적으로 힘든것도 있지만 고민거리가 많아서 심적으로도 버거웠다. 올초부터 듣던 Cousera 강의가 대부분 끝났다(가장 어려운 PGM이 남았지만). 이제 한숨 돌릴 시간이 됬다 싶었는데, 다시 바뻐질것 같다(…)

일단 지금 끝난 과목 또는 수료한 과목은 Game thoery, Design and Analysis of Algorithm I, Natural Language Processing. 알고리즘은 무난히 통과했고, NLP는 어제 마지막 과제를 제출했다. 수료증은 충분히 받을듯하다. PGM도 몇주면 이 곧 끝나니까, 올해 처음 계획한 강의는 모두 마치게된다(ㅠㅠ).

주기적으로 쓰던 탑코더 알고리즘 에필로그도 거의 10개는 밀린것 같다(꾸준히 하고는 있다). 알고리즘 에필로그 뿐만 아니라 영어공부나 책 읽는 시간도 많이 줄었다. 너무 많은걸 한다 싶어서 Coursera에서 새롭게 시작할 강의의 수는 좀 줄이기로 했다.

얼마전부터 새롭게 시작하는 강의 중에 듣고 싶은게 너무 많았다. 그래서 일단 등록은 무지막지하게 해놨는데, 등록하고 보니 과목수가, 학부생때 18학점으로 들었던 과목수 보다 더 많다-_-; 연초부터 들은 5과목도 꽤 빡셌던 터러 현실적으로 이건 불가능하다 싶어서, ML, CS101, Computer Vision으로 압축했다. 사실 몇과목 더 들어도 될 조합 및 난이도이긴한데, PGM을 복습할 생각으로 시간을 좀 비어뒀다(대학원때를 생각해보면 한 학기에 3과목 정도씩 들었는데 이것도 적은건 아닌가-_-;)

올해 자기개발 목표 중에 Coursera에서 세운 계획은 1년을 약 3학기로 나눠서 수업을 꾸준히 듣는건데, 이제 1학기가 끝났다. 남은 2,3학기도 꾸준히 들어서 많은 것을 배울 수 있는 한 해가 됐으면 좋겠다. 수료증은 몇개나 모을 수 있을까?

그나저나 어쩌면 신변의 변화가 생길 것 같다. 올해가 내 인생에 있어서 중요한 터닝 포인트가 될 것 이라고 1-2년전 부터 생각하고있기 때문에 이래저래 고민하던게 많은 것도 있고, 변수(?)가 생기기도 했다. 그래서 요즘 뒤숭숭하다. 어찌되던간에 한숨 돌리면서 중심을 한번 잡아야 하는 타이밍인것 같다.

Dual Decomposition

1. Intuition

Dual Decomposition은 MAP(Maximum A Posteriori)값을 구하는 알고리즘 중에 하나이다. Dual Decomposition의 기본 컨셉은 분할 정복법(divide and conquer)이다.

Factor \theta_i를 단일 random variable로 구성된 singleton factor, \theta_F를 large factor라고 할때,

\displaystyle MAP(\theta) = \arg\max_x (\sum^n_{i=1}{\theta_i(x_i)}+\sum_F{\theta_F(x_F)})

는 singleton factor와 large factor의 MAP를 따로 구하는 문제로 바꿀 수 있다.

\displaystyle \sum^n_{i=1} \arg\max_x{\theta_i(x_i)} + \sum_F \arg\max_x{\theta_F(x_F)}

이 대로는 몇가지 문제가 있는데, 그 중에 하나는 local optimum이 문제이다: Singleton factor(혹은 large factor)에 대한 MAP값이 다른 factor에 대해서 최적해를 보장하지 못한다. 즉, 지역 최적화가 전역 최적화를 만족하지 못한다.

처음으로 돌아가서 MAP(\theta)

\displaystyle \arg\max_x (\sum(\theta_i(x_i) + \sum_{F:i\in F}{\lambda_{Fi}(x_i)}) + \sum_F(\theta_F(x_F)-sum_{i\in F}\lambda_{Fi}(x_i)))

로 바꿔 쓸수 있고, 동일하다.

다시 여기서 분할정복을 적용하면,

\displaystyle L(\lambda) = \sum^n_{i=1} \arg\max_{x_i} (\theta_i(x_i) + \sum_{F:i\in F} \lambda_{Fi}(x_i)) + \sum_F \arg\max_{x_F}(\theta_F(x_F)-\sum_{i\in F}\lambda_{Fi}(x_i))

이 된다. Regulization을 적용하는 것과 흡사하나 생겼다. 좌항의 singleton factor에는 패널티 텀으로써 large factor 중에 singleton factor를 포함하는 scope를 가진 large factor에대한 \lambda_{Fi}를 더해줬고, 우항의 large factor에는 패널티텀으로써 singleton factor를 포함하는 scope를 갖는 \lambda_{Fi}를 빼줬다.

L(\lambda)의 좌항을 \bar{\theta}^\lambda_i, 우항을 \bar{\theta}^\lambda_F라고 할때, MAP(\theta)는 전체 factor에 대한 최적화이고, 자유도가 더 높은 공간에서의 최적화이기 때문에 L(\lambda)는 항상 MAP(\theta)의 upper bound이다.

\displaystyle L(\lambda) = \bar{\theta}^\lambda_i + \bar{\theta}^\lambda_F

where

\displaystyle \bar{\theta}^\lambda_i = \sum^n_{i=1} \arg\max_{x_i} (\bar{\theta}^\lambda_i(x_i) + \sum_{F:i\in F} \lambda_{Fi}(x_i))

\displaystyle \bar{\theta}^\lambda_F = \sum_F \arg\max_{x_F}(\bar{\theta}^\lambda_F(x_F)-\sum_{i\in F}\lambda_{Fi}(x_i))

Dual Decomposition을 적용하면 전체 factor 공간에서의 최적화 문제를 factor의 부분집합에서의 최적화 문제로 바꿀 수 있고, local optimum 문제도 손쉽게 다룰 수 있다. 일반적인 MAP문제라면 별 문제 없이 적용 가능하고, 이론적으로 최적해를 보장한다. 또한 가장 빠른 알고리즘은 아니지만 빠르다. 하지만 여러군데 튜닝이 필요한 포인트가 있다는 단점이 있다.

2. Algorithms

최적해를 구하는 문제니 만큼, gradient descent 방법론과 같이 단순한 linear regression, logistic regression, L2-BFGS 등 다양한 방법으로 해결이 가능하다. 중요한 것은 dual composition에서 각 스코프안에서는 항상 전역 최적화로 수렴하지만 같은(shared) variable에 대한 assignment가, 다르게 정의되는 scope들이 존재할 수가 있다(disagree).

그러므로 MAP의 assignment를 만족하기 위해서는, 전역최적화를 만족하더라도, 모든 스코프의 팩터가 shared variable에 대해서 assignment가 다른 경우가 없도록 만들어야 하는데(decoding problem), 이 문제 역시 다양한 방법으로 해결이 가능하다. 휴리스틱한 방법 하나는 최적화 과정에서 모델의 score \theta(score(x), 를 계산하고, 모든 factor들의 shared variable assignment가 동일한, 모델 후보들 중에서 score(x)가 가장 높은 모델을 구하면 된다.

언제까지 반복을 해야할까. score(x)와 MAP, L(\theta)의 관계는 score(x) \leq MAP(\theta) \leq L(\theta)이다. 그런데 MAP(\theta)는 알지 못한다(안 구했으니까 :) ). 대신 MAP(\theta)-score(x) \leq L(\theta)-score(x)이므로, 우항이 가능한 작아질수록 upper bound에 가까워진다는 것을 알 수 있다.

일반적인 얘기지만 learning rate \alpha 설정도 중요하다. 이 값에 따라서 수렴하는데 필요한 시간이 기하급수적으로 늘수도 있고, 최적해를 찾지 못할 수도 있다(over-shooting). 적절한 값 설정이 필요한데, dev/test/train에서의 수렴정도를 보고 튜닝해도 되고 다른 방법론을 적용해도, 마음대로(?) 해도 안될건 없다.

2012 Google Codejam 예선전

올해 코드쨈에서는 티셔츠를 받을 수 있을까? 얼마전 열린 한국지역 코드쨈에서는 하나 얻었지만, 코드쨈은 쉽지 않을듯..

요즘 탑코더 리뷰를 거의 못하고 있다. 거진 6-7개는 밀린듯.. 탑코더할 시간까지 못낼순 없지만 짬내서 리뷰하는 시간까지는 힘들다. 강의가 어느정도 끝나면 가능할 것 같은데, 끝나는 강의보다 새로 시작하는 강의다 더 많으니.. ㅋㅋ

코드쨈 예선 당일도, 강의 듣느냐, 결혼식 모임가느냐 시간이 없는 관계로, 예선 통과 점수인 20점만 빠르게 획득하고 관뒀다. 예전 같으면 예선 24시간 내내 풀 수 있는 문제는 다 풀었을텐데.. 그래서 좀 빨리 풀고자, Python을 사용했다.

총 4문제였고, A번은 small만, 나머지 B,C,D는 small/large로 나뉘어져있었다. A, B small/large만 풀고 접었다. 35점 받고 통과.

A. Speaking in Tongues

재밌는 문제였다. Googlerese라는 언어가 있는데, 영어에서 각 알파벳이 다른 알파벳으로 매핑된 형태로 표현가능하다. 문제는 영어의 각 알파벳이 어느 알파벳으로 매핑이 되야 Googlerese언어가 되는지 모른다는건데, 지문에는 3개의 규칙만 주어지고 나머지는 예제에서 찾아야한다.

함정이 하나있다. 예제를 샅샅이 살펴보아도 2 알파벳에 대한 매핑 정보는 알 수 없다. ㅋㅋ 결국 submit할때 받는 input파일을 보고 잽싸게 판단해서 2개의 알파벳 정보를 추가해야한다. 그렇지 않으면 1 wrong. 처음에 이 두 개의 알파벳이 빠진걸 모르고 input을 다운받고 답을 출력해보니 뭔가 이상해서 눈치를 챘다. 코드쨈은 input파일을 다운 받은 후에 small은 4분, large는 6분 안에 제출해야하므로 잽싼 코드 수정 스킬이 필요하다.

import sys
rl = sys.stdin.readline
n = int(rl().strip())

rules = {' ': ' ', 'a': 'y', 'c': 'e', 'b': 'h', 'e': 'o', 'd': 's', 'g': 'v', 'f': 'c', 'i': 'd', 'h': 'x', 'k': 'i', 'j': 'u', 'm': 'l', 'l': 'g', 'o': 'k', 'n': 'b', 'p': 'r', 's': 'n', 'r': 't', 'u': 'j', 't': 'w', 'w': 'f', 'v': 'p', 'y': 'a', 'x': 'm', 'z': 'q', 'q':'z'}

for i in xrange(n):
    line = rl().strip()
    tkn = [ t for t in line ]
    for j in range(len(tkn)):
        tkn[j] = rules[tkn[j]]

    print 'Case #%d: %s' % (i+1, "".join(tkn))

B. Dancing With the Googler

구글러들이 댄스를 하는 파티를 열었다. 3명의 심사자들은 춤을 춘 구글러에 대해서 0점에서 10점사이의 점수로 평가를 한다. 3명의 심사자들은 기준이 매우매우 흡사해서, 각 심사자들이 평가한 점수는 2점이상 차이가 날 수 없다. 예를 들어, (6,7,8), (8,8,8)와 같은 평가점수는 있을 수 있지만, (1,6,9), (4,4,7)과 같은 평가점수는 있을 수 없다.

한가지 특별한 경우가 있다. 3명의 심사자들이 평가한 점수중에 “2″점이상 차이나는 점수가 있는 평가점수를 “놀라운 케이스”라고 부른다. (4,4,6)은 놀라운 케이스이고, (5,5,6)은 아니다.

문제는, 3명의 심사자들이 각 구글러를 평가한 점수들이 주어지는게 아니라, 각 구글러에 평가된 3개의 점수의 합이 주어진다는 것이다. 예를 들어 3명의 구글러가 댄스에 참여 했다면, 20, 14, 30 이런식으로 입력이 주어진다.

진짜 문제는ㅋㅋ. N명의 구글러가 받은 점수의 총합 Score={s1, s2, … sn}이 주어졌을 때, 조건 1) N명 중에 “놀라운 케이스”인 구글러가 정확히 p명일때, 조건 2) 각 구글러가 받은 평가 점수가 상수 q를 넘는 구글러의 수를 출력 하는 것이다. 이 조건을 만족하는 경우의 수가 여러개일 경우에, 상수 q를 넘는 구글러의 수가 최대가 되는 경우를 출력하면된다.

import sys
rl = sys.stdin.readline

n = int(rl().strip())

ot = [i for i in range(0,11) ] # one to ten
for i in range(n):
    tkn = rl().strip().split()
    nn = int(tkn[1])
    ns = int(tkn[2])
    p = int(tkn[3])
    numSuprise = 0
    numGreater = 0
    for j in range(3, len(tkn)):
        num = int(tkn[j])
        isSuprise=False
        greaterThan=False
        sample = set()
        for a in ot:
            for b in ot:
                if abs(a-b) > 2: continue
                for c in ot:
                    if abs(a-c) > 2: continue
                    if abs(b-c) > 2: continue
                    if a+b+c == num:
                        if abs(a-c)==2 or abs(a-b) == 2 or abs(b-c) == 2:
                            isSuprise=True
                        if a>=p or b>=p or c>=p:
                            greaterThan=True
                        sample.add( (isSuprise, greaterThan) )
                        isSuprise, greaterThan = False, False
        if (False, True) in sample :
            numGreater += 1
        elif (True, True) in sample:
            numSuprise += 1
    ans = numGreater
    ans = ans + min(numSuprise, ns)
    print 'Case #%d: %d' % (i+1, ans)

간만에 국내 학술대회 논문 투척

요즘 연구를 주로하고 있다. 올해 논문 목표는 중급 이상 해외학회 1편 이상(개인적으로)이라, 나름대로 연구할 주제에 대해서 공부를 좀 하고 있는 중이다. 그런데 때마침, 정보과학회의 종합학술대회 일정이 떴다. 아직 논문 주제를 잡지 못한 상황이여서, 요즘 연구 주제인 토픽 모델링과 추천시스템의 기본적인 수준을 실습(?)하는 차원에서 한편 썼다.

그런데 제출 마감일이 4월 27일로 잘못 알고 있었던 바람에, 실제 마감일인 4월 17일 한 3일전에 알았다. 17일이였다는것을 ㄷㄷ. 그래서 급하게 실험하느랴 논문쓰느랴 좀 정신이 없었다.

정보과학회에서 하는 학술대회 규모가 국내에서 제일 크긴한데, 보통은 논문접수 일정이 연기되서, 연기되겄거니 했는데, 제주도에서 열려서 그런지 의외로 투고자가 꽤 많은것 같다. 접수 마지막날까지 연기가 되지 않아서, 부랴부랴 논문접수를 했는데, 어라 홈페이지 에러가 뜬다?

윈도우7 크롬, 오페라, IE9에서 모두 스크립트 오류가 뜨면서 제출이 안됐다. 마감시간은 다가오고, 제출은 안되고.. 혹시 윈도우7이 64비트라서 그런가하는 별로 가능성도 없는 생각에 윈도우XP 가상머신으로 띄워서 IE6에서 시도. 스크립트 에러… 그런데 이 와중에 논문접수현황에 새로 접수한 사람들이 보인다. 이건 뭐지? 나만 이런 에러를 겪는건가 orz.

결국에 스크립트 에러를 뜯어봤는데, 저자정보를 지운것을 확인하는 팝업창에서 확인 버튼을 누를때, 논문 접수 FORM의 submit을 호출하는 부분이 null 참조였다. 디버그 콘솔에서 논문 접수 form의 submit을 강제로 호출 하고 논문 접수 완료.

흠.. 뭐가 문제였으려나.

우역곡절끝에 논문은 제출했는데, 다음날 출근해보니 연기됬다. 요즘 게임 이론 수업을 듣는 중이라 그런지, 학회측에서 이런 훌륭한 dominent sterategy를 펼치다니.. 감동받았다. 젠장.

고작 3-4일 밀렸을 뿐인데, 주말에 풀타임으로 듣는 시간을 놓쳐버려선지 강의 압박이 꽤 심해졌다. 아아.. 이제 곧 악마가 올텐데 어쩌지.

서평 – 뉴욕 의사의 백신영어

  • 뉴욕 의사의 백신 영어 : 내 생애 마지막 영어 공부법
  • 고수민
  • 출판사: 은행나무
  • ISBN-13: 9788956603124
  • 링크

요즘 책 읽는 시간이 많이 줄어들었다. 짬을내서 읽더라도 수강중인 강의와 관련된 서적들 뿐이다. 이 와중에도 시간 쪼개서 틈틈히 읽은 책이 있는데, 바로 고수민님께서 쓰신 뉴욕 의사의 백신영어이다. 이전에 블로그에 소개한 뉴욕의사의 Story 영단어의 같은 저자이다. 사실 발간된 순서로는 백신 영어가 먼저 나왔지만, 어쩌다보니 Story 영단어부터 읽게되었다

read more »

Social Widgets powered by AB-WebLog.com.