2016년 9월 11일 일요일

Batch Normalization

Batch Normalization은 딥러닝 네트웍의 학습에서 gradient vanishing과 exploding을 회피하기 위한 방법 중의 하나이다.

딥러닝 알고리즘은 층이 깊어질수록 표현 능력과 추상화 레벨이 높아지는 것으로 알려져 있다. 그러나 층이 깊어질 때 출력단의 Loss값의 gradient가 내부로 도달하지 않고 소멸해버리는 현상으로 학습에 한계가 있었다. 이러한 문제점을 해결하고 깊은 층을 가지는 넷을 설계하기 위해, ReLU 활성함수, Dropout, 학습 샘플 초기화 전략, Learning rate 조절 등의 여러가지 방법이 개발되어 왔다.

딥러닝 구조의 내재적 불안정성은 Internal Covariance Shift 현상에 의한 것으로 BN 논문의 저자는 주장한다. 이것은 넷 각 층의 입력 값의 분포(variance)가 일관성없이 계속해서 달라지는 현상을 말한다.
레이어 입력값 분포의 변화가 발생하면 입력을 받아들이는 레이어는 새로운 분포에 계속해서 적응해야 한다. 레이어의 입력 값은 이전의 모든 레이어 파라메터에 의해 영향을 받고, 네트웍 파라메터의 작은 변화는 네트웍이 깊어질 때 증폭되고 학습의 복잡성은 증가한다.

이에 대한 해결책으로 각 층의 입력값의 평균을 구해 제거하고 분산으로 값들을 나누어 표준편차를 1로 만드는 것을 생각할 수 있다.
그러나 이 방법은 역행렬의 요구 등으로 계산량이 많은 점과 $f=Wx+b$의 연산에서 오프셋 $b$의 영향이 소거되는 등의 문제로 적용이 어렵다.

또한 층의 입력 값을 정규화를 통해 평균 0, 분산 1로 고정시키는 것은 Activation 함수의 가장 중요한 역할인 비선형성을 없애 버릴 수 있다. 즉, 넷은 비선형성을 가지고 있어야 복잡한 함수를 표현할 수 있는데 이 능력이 사라질 수 있다.  예를 들면, sigmoid 활성함수의 입력 값이 평균 0, 분산 1이라면 입력 값의 범위는 -1~+1이 되고, 이 범위의 sigmoid 함수 값은 0.5를 중심으로 0.2~0.7사이의 거의 직선인 선형 영역이다.
이 점을 보완하기 위해 정규화된 값에 scale 팩터($\gamma$)와 shift 팩터($\beta$)을 도입하고 정규화된 값에 곱하고 더해준다. 두 인자는 오차 역전파 과정에서 학습해 준다. 이를 통해 활성함수로 들어가는 값의 범위를 바꾸어줌에 의해 비선형성을 부여할 수 있다.


$BN(x_i)=\gamma(\frac{x_i-\mu_B}{\sqrt{\sigma^2_B+\epsilon}})+\beta$

BN의 적용 방식은 현재 입력되는 학습 샘플의 mini-batch에 대해 특징 맵 별로 정규화를 수행한다. 이 값에 scale과 shift팩터를 곱하고 더해 적용하게 된다. 따라서, 맵 별 파라메터는 2개이다.
예를 들면, 어떤 중간층에서 BN유닛의 입력이 (mini-batch,128, 32, 32)였다면 (mini-batchx32x32)의 데이터에 대해 mean($\mu_B$)과 vari($\sigma_B$)를 구해 정규화를 수행한 후 scale, shift팩터를 위 식처럼 적용한다. 인자 수는  맵이 128개이므로 256개이다.


(Ref.)
[1] Batch Normalization: Accelerating deep network training by reducing internal covariance shift, ICML2015.
[2] Batch Normalization의 설명 및 구현
[3] Understanding the backward pass through BN Layer


2016년 8월 6일 토요일

선형 분류기

정의

하나의 층(layer) 만을 가진 분류기이다. 층의 수를 셀 때 입력층은 제외하므로 입력층 하나와 출력층 하나만을 가진 신경망이며 딥 신경망의 가장 기본적인 형태이다. 선형분류기의 학습에 필요한 수식과 용어들을 살펴보자.  

score 함수: 입력 데이터를 부류별 득점(스코어) 값으로 바꾸는 함수
loss 함수: 스코어 값과 참 값(ground true)이 얼마나 잘 일치하는지를 수치화한 함수

선형분류기의 연산은 다음 수식을 통해 수행된다.

$f(x_i, W, b) =  W x_i + b$
여기서 $f$는 score 함수이고 $x$는 입력, $(W, b)$는 분류기의 파라메터 값이다. Loss 함수는 스코어 함수를 이용하여 구성된다. 



Loss 함수

SVM loss와 cross entropy(softmax) loss 두가지에 대해 살펴본다. Loss는 손실이니 손실이 작아지도록 분류기를 설계해야 한다. 

(1) SVM Loss


Multiclass SVM

기계학습에서 소개되는 기존의 전통적 SVM(support vector machine)은 마진을 최대화하는 이진 분류기(binary classifier)를 얻는 것이었다. 
여기서는 다 부류를 분류하는 경우에 어떻게 SVM으로 비용(penalty)을 정의하는지에 대해 살펴본다. 

어떤 입력이 들어가 선형분류기를 통과해서 클래스당 스코어 값을 얻었다고 하자. 이 때 SVM Loss는 부류별 출력 값 중 입력이 속해야 하는 정 부류(correct class)의 스코어가  부 부류(incorrect class)의 스코어보다 어떤 마진이상 더 큰 값을 가지도록 하는 Loss이다.
스코어 값 차이가 마진보다 크면 SVM 로스는 0, 그렇지 않으면 차이 값에 의한 Loss가 나타난다.

$L_i = \sum_{j\neq y_i} \max(0, s_j - s_{y_i} + \Delta)$,  where $s_j = f(x_i, W)_j$.

여기서 $s_j$는 입력 $x_i$가 선형분류기 $f$를 통과해서 얻어진 부류 $j$에 대한 score 값을 나타낸다. $s_{y_i}$는 정 부류에 대한 스코어 값이다.


(예제) 
만일 3개의 부류(즉, 출력 클래스)를 가지고 있고, 어떤 입력 데이터에 대해 스코어 $s=[13, -7, 11]$가 나왔다고 하자, 첫번째 클래스가 true 클래스라고 가정하고, 마진 값은 10이라 가정한다. 위 수식에 넣어서 계산하면,

$L_i=max(0,-7-13+10)+max(0,11-13+10)$.

수식의 두 항중에서 첫번째 항은 0이다. 즉 13> -7이고 10이상의 차이가 난다. 두번째 항은 13>11이지만 2밖에 차이가 안나고, 8의 값이 나온다. 즉, 정 부류의 스코어 13은 부 부류의 스코어 11과의 마진이 10이 될 만큼 충분하지 않아 loss가 8이 생기고, 전체 로스도 8이다. 

Regularization


분류기가 같은 Loss 값을 주었다고 해도 이 Loss를 결정하는 파라메터 $(W, b)$는 유일하지 않을 수 있다. 이 문제를 해결하고 분류기의 일반화 능력을 높이기 위해  Loss 값에 Regularization이라 불리는 두번째 항을 추가한다. 
$R(W)$는 weigts 행렬의 각 요소 값들의 절대치 합(L1 penalty), 또는 제곱 합(L2 penalty)으로 요소값이 커지는 것을 억제한다.

$L =  \underbrace{ \frac{1}{N} \sum_i L_i }_\text{data loss} + \underbrace{ \lambda R(W) }_\text{regularization loss} \\\\$


Regularization항은 일반화 능력을 높이고 $w$값의 확산을 유도한다.

(예제)
입력이 $x=[1,1,1,1]$이다. 선택 가능한 가중치에 $w_1=[1,0,0,0]$과 $w_2=[0.25,0.25,0.25,0.25]$가 있다면 둘 중 어떤 것을 선택할지에 대해 살펴본다. 두 가중치에 대한 선형 분류기 연산은

$w_1^Tx = w_2^Tx = 1$

로 둘 다 1이다. 따라서 위의 식 $L$에 대입해 보면 두 가중치 벡터는 같은 값의 data Loss(첫번째 항의 값)을 준다. 그러나 두 번째 항을 살펴보면, $w_1$의 L2 penalty는 1이고, $w_2$는 0.25이다. 따라서 더 작은 $w_2$가 선호된다. 

$w_2$는 $w_1$보다 크기가 더 작고 값이 더 퍼져(diffuse)있다. 이것은 입력 $x$의 4개 값 중의 특정 부분에 집중하는 것 보다는 모든 입력요소가 골고루 기여하게 하고, 이것은 일반화 능력의 상승과 과적합(overfitting)의 감소로 나타난다. 


(2) Cross-entropy Loss


Softmax classifier


SVM 로스 외에 보편적인 Loss 중의 하나인 cross entropy 로스를 사용하는 softmax 분류기를 살펴 본다. data loss항은 다음과 같다. 

$L_i = -\log\left(\frac{e^{f_{y_i}}}{ \sum_j e^{f_j} }\right) $


cross-entropy는 정보 이론(information theory)에서 왔는데 참 분포 $p$와 추정 분포 $q$ 사이의 cross-entropy[2]는 

$H(p,q) = - \sum_x p(x) \log q(x)$

처럼 정의된다. 두 확률 분포의 겹칩의 정도를 표현하는 식이다. 
따라서 softmax와 비교하여 $q = e^{f_{y_i}} / \sum_j e^{f_j}$이고, $p=[0,…,1,…0]$라면(즉, one-hot 벡터처럼 정확한 부류 하나만 1이고 나머지는 0인 경우) 두 식은 같다.
두 식의 모양은 동일하며 softmax 분류기는 cross-entropy loss 분류기로 불린다. 



수치적 안정성

큰 지수 값을 가진 $exp$ 함수는 값이 아주 크고, 큰 두 값의 나누기는 수치적 불안정성을 야기한다. 
이를 해결하기 위해 

$C=-\max_j{f_j}$

가 되도록 선정된 $C$값을 분자/분모에 곱하여 해결한다($exp$의 지수 값이 0근처로 shift 된다). 

$\frac{e^{f_{y_i}}}{\sum_j e^{f_j}}$ $= \frac{Ce^{f_{y_i}}}{C\sum_j e^{f_j}}$$= \frac{e^{f_{y_i} + \log C}}{\sum_j e^{f_j + \log C}}$



softmax의 확률값

확률값이 confidence를 의미하는 것은 아니다. 만일 regularization의 $\lambda$를 더 증가시키면 $w$ 값이 더 퍼지고 이에 따라 클래스의 스코어 값이 퍼지도록 변화된다. 따라서 스코어의 ordering이 중요하지 절대 값은 변화 가능하다.



References

[1] cs231n linear classification
[2] 오일석, 패턴인식, 부록, 교보문고













2016년 7월 12일 화요일

Policy Gradients

직관적 이해

제어할 대상 시스템(환경, $env$), 시스템에 가하는 $action$, 이 $action$을 만들어 내는 제어기(DNN, CNN, or RNN)가 있다고 하자. 
요점은 $env$에 가해지는 최적 $action$ 샘플링 하나를 얻는 것이라기 보다, 랜덤 샘플링(가능한 여러 $action$ 중의 하나)을 제공하는 확률 분포(DNN 출력이 만드는)를 개선하는 것이다. 
$env$ 상태(state, 이미지 등) 입력에 대해 제어기(DNN)가 준 랜덤 $action$을 시스템($env$)에 가했을 때 받은 보상값($reward$)을 loss에 반영하여 DNN 학습을 반복하면, 이 샘플링을 발생 시켰던 분포(DNN 출력)가 $reward$를 크게하는 방향으로 개선된다.  



수식

신경망 $\pi$의 출력은 확률분포이며 기대값의 가중치로 사용된다. 아래 식 우측 [~] 부분은 loss의 grad이다.  




수렴성

Policy gradient는 여러 RL(강화 학습) 학습 방법 중에서 Alphago가 사용하였다. 확률분포가 $reward$를 크게하는 방향으로 수렴함을 확인해 보자.

용어들은 $^{각주1}$을 참고한다.


RL에서 학습이란 파라메터 값을 잘 바꾸어 분포를 조정함에 의해 $action$ 샘플링이 주는 보상함수를 높이는 것이 목표이다.
보상함수 $f(x)$ 기대치를 높이는 것이 목표이므로

$\nabla_\theta{E_x[f(x)]}$

처럼 기대치 $E$의 $\theta$에 대한 구배를 계산한다. 즉, 구배를 계산하여 갱신하면 $\theta$ 값을 바꿀 수 있다. $\theta$를 통해 $p$가 바뀌게 되고 여기서 샘플링되는 $action$이 바뀌게 된다. 위 식은 약간의 계산 절차를 통해

$E_x{[f(x){\nabla_\theta}\log{p(x)}]}$

가 되고, 이 값은 샘플링된 모든 $x$에 대해, 보상함수 $f(x)$와 ${\nabla_\theta}\log{p(x)}$의 곱에 대한 평균이다.




[from Karphaty's blog]

간단한 2차원 Gaussian $p(x)$로 위 수식에 따른 샘플들과 그 보상값이 분포를 어떻게 바꾸는지 확인해 보자.
$\log{p(x)}$에 대한 분포 파라메터(여기서는 평균값 $m$, 따라서 $p(x;\ m)$이다)에 대해 도함수를 계산하면

${\nabla_\theta}\log{p(x)}$ = $c_1(x-m)$

이다. 즉, 평균점 $m$에서 샘플 점 $x$를 향하는 벡터가 된다. 첫번째 그림에서 파란색 점은 샘플점들을 나타내고 화살표는 그 방향을 보여준다.

두번째 그림에서 샘플들 위치에서 얻어진 보상함수 값을 표현한다. 특정 샘플은 +1의 보상치(녹색)를 가지고 나머지는 -1 보상치(주황색)를 가진다.
보상치와 벡터들을 곱하고 평균을 내면 분포 파라메터(여기서는 mean 위치 $m$)가 움직여야 하는 방향이 계산되고, 왼쪽 아래 방향이 나오게 된다.

계산된 방향에 따라 분포(평균 위치)를 조정하면 세번째 그림이 되고, 이제 새로운 분포에서 샘플링된 점들은 보상치가 +1이 될 가능성이 더욱 높아지게 된다.



실제 적용 예는 OpenAI의 pong게임을 이용한 것으로 초기에는 컴퓨터가 주로 이기나, 학습이 진행될수록 agent가 이기는 확률이 높아진다.




(각주 1)

$\bullet$ $p(x;\theta)$: 입력 $x$와 결합된 파라메터 $\theta$의 조합으로 값 $p$가 결정된다는 의미이고 $p$는 확률 분포(비슷한 내용으로 여기 참고)이다.  즉, $p$는 agent action을 만들어 내는 policy를 나타낸다. agent가 선택하는 action은 확률분포 $p$에서 샘플링을 통해서 생성된다.

예를 들어 $p$가 어떤 입력에 대해 action분포를 만들어 내는 CNN으로 구성된 policy network이라면, 이미지 $I$가 입력 되었을 때 action에 대한 분포인 $p(a|I;\theta)$가 되고, $\theta$는 넷 내부 weights 등 파라메터가 된다.

$p(x)$는 $p(a)$이고, 분포 $p(a)$를 바꾸려면 이미지 입력에 의해 만들어지는 $p(a)$에 관여하는 파라메터 $\theta$를 바꾸어야 한다.


$\bullet$ $f(x)$: 함수 $f$ 인자인 $x$는 $p$상에서 sampling되며 선택된 샘플(action)이 만들어 내는 보상 함수(scalar값을 가짐)이다. 선택된 action으로 끝까지 게임을 진행했을 때 win, fail에 대한 보상치이다.





References
[1] Mastering the game of Go with deep neural networks and tree search, Nature, 2016.
[2] http://karpathy.github.io/2016/05/31/rl/
[3] 한정수, 정책기울기 값 강화학습을 이용한 적응적 QoS라우팅 기법연구, 컴퓨터정보학회, 2011.

[4] What's right way of implementing policy gradient?





2016년 5월 31일 화요일

github 사용법

글올리기, 간편 안내
funmv

git init # 내 컴퓨터의 파일이 있는 특정 폴더로 가서 실행
git add pg_pong.ipynb # 로드할 파일 지정
git commit -m "policy gradients example"
git remote add origin https://github.com/funmv/RL.git # 먼저 git에 repository(폴더)를 만들어 놓아야 함

git push -u origin master # 여기서 id, pw를 필요로 함

그 외 명령: git clean -f 

2016년 5월 20일 금요일

(python) decoration, thread & yield

작성 중...

1. decoration pattern, @ 사용.
호출부에서 read_batches(50) 시,

read_batches = mpgen(read_batches(50))

처럼 원 함수의 기능 확장.


2. python에서는 GIL문제로 thread 대신에 multiprocessing 사용.
mpgen을 통해 주 프로세스와는 별도의 데이터 생성 프로세스가 시작
Queue는 thread에서 데이터 공유에 사용(아래, 최대 3개까지의 item 저장 가능)


3. yield
함수의 형태를 가지는 iterator (generator, 생성기라고 부름)를 만들어 줌.
iterator란?
c = iter(range(5))
c.next(), c.next(),... # 0,1,2,...

함수의 인자를 비휘발성으로 만듬
함수 재호출 시, yield 다음이 수행
return은 결과값 반환, yield는 iterator 반환


4. functools.wraps:
디버깅 시 func.__doc__ 또는 func.__name__ 등의 속성을 요청 시
원 함수 read_batches의 속성이 안나오고 decoration된 mpgen함수의 속성이 나오는 것을 방지.
함수 속성을 인자인 원 함수 f로 되돌리는 역할.
데코레이터에서 closure문제 해결을 위해 사용.



def mpgen(f):
    def main(q, args, kwargs):
        try:
            for item in f(*args, **kwargs):
                q.put(item)
        finally:
            q.close()

    @functools.wraps(f) 
    def wrapped(*args, **kwargs): #*args(리스트 받고), **kwargs(map 받음)
        q = multiprocessing.Queue(3)
        proc = multiprocessing.Process(target=main, args=(q, args, kwargs))
        proc.start()
        try:
            while True:
                item = q.get()
                yield item
        finally:
            proc.terminate()
            proc.join()

    return wrapped
     

@mpgen # mpgen의 인자함수로 read_batches을 사용함을 지정
def read_batches(batch_size):
    def gen_vecs():
        for im, c, p in gen.generate_ims(batch_size):
            yield im, code_to_vec(p, c)

    while True:
        yield unzip(gen_vecs()) # yield는 휘발성이 없는 함수(iterator 만듬)


2016년 5월 16일 월요일

(python) debugger

import ipdb 에서 빠져나올 때는 cntl+z
import pdb
pdb.set_trace()

명령법


(python) video read and write

opencv의 cv와 cv2의 차이
cv2 내에 cv있음. cv2가 최신.
import cv2.cv as cv

python 에서 버전 확인
import cv2
cv2.__version__

video 읽기
installed\opencv\3rdparty\ffmpeg\opencv_ffmpeg_64.dll 필요
이것을 작업 폴더에 복사해서 이름을 opencv_ffmpeg249_64.dll로 바꿈


테스트
import cv2
cap = cv2.VideoCapture('tmp1.mp4')
cap.grab() # true로 나와야 함


(Ref)
1. cv & cv2
2. about video working
3. opencv version