본문 바로가기
Research/Machine Learning

RBM, Contrastive Divergence

by IMCOMKING 2014. 7. 23.

http://deepcumen.com/2015/04/restricted-boltzmann-machine/#comment-437

http://147.46.219.139:8889/tree/DeepLearningTutorials/code


RBM 학습 알고리즘 다시 정리 :

cost = T.mean(self.free_energy(self.input)) - T.mean(self.free_energy(chain_end))

이 cost function을 최소화하는 gradient descent를 수행한다.
이 cost function은 
(input데이터에 대한 free energy)-(input데이터로 k번 왔다갔다하면서 gibbs 샘플링한 V노드의 데이터의 free energy)

이다. 이 둘이 최대한 같아지도록 gradient descent를 하는 것.

free energy는 -log시그모이드(weighted sum) 로 계산한다. 즉 대충 weighted sum 해서 위로 올리는 것.


RBM : Input 과 Hidden 의 2개 레이어로 구성된 뉴럴 네트워크이며, 같은 레이어끼리 이외에는 모두 Fully Connected 되어있다. 기본적으로 unsupervised learning으로 학습한다.(같은 레이어끼리도 Fully Connected 이면 그냥 Boltzmann Machine이다.)
RBM은 값으로 0과 1만 올 수 있다.

rbm에서는 올라갈 때는  hbias로 학습

내려갈 때는 vbias로 학습


RBM에서 높은 레이어로 갈 수록 각 클래스에 대한 mod가 쉽게 왔다갔다 한다.

즉 낮은 레이어에서는 숫자 1,2,3 에 해당하는 mod로 옮겨가기가 어려운데,

높은 레이어에서는 이게 쉽게 옮겨가진다.가까워서?


Gibbs sampling : RBM은 깁스 샘플링으로 데이터를 재생성한다.

MNIST이미지의 경우 각각의 픽셀을 하나의 차원으로보고, 확률적으로 픽셀 마다 따로따로 샘플링 

하는느낌인듯. 아래의 코드를 보면 이해가 쉬움


def sample_v_given_h(self, h0_sample):
""" This function infers state of visible units given hidden units """
# compute the activation of the visible given the hidden sample
pre_sigmoid_v1, v1_mean = self.propdown(h0_sample) # 이건 그냥 weighted sum에 시그모이드 한것임
# get a sample of the visible given their activation
# Note that theano_rng.binomial returns a symbolic sample of dtype
# int64 by default. If we want to keep our computations in floatX
# for the GPU we need to specify to return the dtype floatX

v1_sample = self.theano_rng.binomial(
size=v1_mean.shape, n=1, p=v1_mean, dtype=theano.config.floatX
) # 이건 위에서 구한 시그모이드 통과, 액티베이션 값을 확률로 넣고 0or1을 샘플링 한 것임. 이 과정에서 바로 P( X_t | ~X_t ) 의 샘플링이 모든 X에 대해서 계산 됨.
return [pre_sigmoid_v1, v1_mean, v1_sample]


def gibbs_hvh(self, h0_sample):
""" This function implements one step of Gibbs sampling,
starting from the hidden state"""
pre_sigmoid_v1, v1_mean, v1_sample = self.sample_v_given_h(
h0_sample
) # 즉 v|h 로 먼저 내려가는 걸 깁스 샘플링하고
pre_sigmoid_h1, h1_mean, h1_sample = self.sample_h_given_v(
v1_sample
) # 그다음 다시 h|v로 올라가는 걸 샘플링 함
return [pre_sigmoid_v1, v1_mean, v1_sample, pre_sigmoid_h1, h1_mean, h1_sample]



gaussRBM : RBM 의 값에 실수값이 올 수 있도록 변형시킨 것. gauss분포를 따르도록 전제를 깔고 있어 많이 쓸 수록 오히려 성능 저하가 일어날 수 있다고한다. 따라서 Deep Belief Network에서는 오직 실수로 된 input을 받을 때에만 gaussRBM을 쓰고, 나머지 위쪽 레이어에서는 RBM으로 pretraining한다.


Contrastive Divergence : 해석하면 대조적 발산, RBM을 학습하기위한 알고리즘이다.

간단히 정리하면, RBM에서 먼저 input 뉴런들에 값을 집어 넣고, 랜덤으로 작게(0~0.1) 정해준 Weight를 이용해서 Hidden의 값을 시그모이드로 계산한다.

이때 input 뉴런들의 값과 hidden 뉴런의 값을 곱한것을 (Si*Sj)0 이라고 하며, 잘 저장해둔다.

그다음 다시 Hidden의 값들을 역방향으로 Weight를 이용해서 input의 뉴런값을 계산한다.
(이것을 reconstruction 이라고 부른다.) 그리고나서 또 다시 Hidden의 값을 계산한다. 이때의 두 뉴런 레이어의 곱은 마찬가지로 (Si*Sj)1이라고 표기한다.

이런식으로 계속 반복해서 대충 50번까지 값을 계산해서 최종적으로 (Si*Sj)50 을 계산한다. (원래는 50이아니라 n번임)

그리고 우리는 이 한 번의 과정 (epoch이라고 함.)에서 (Si*Sj)0 과 (Si*Sj)50 을 구해냈다.
이렇게 한번의 epoch이 끝났으면 이제 Weight를 학습해야한다.

그래서 아까 구한 (Si*Sj)0 과 (Si*Sj)50을 이용해서, CD = Average(Si*Sj)0 - Average(Si*Sj)50 를 계산한다.
아직은 epoch이 1번만 진행됬기 때문에 Average는 원래 값과 같다.

이때 왼쪽 Average는 CDpositive라고하고 오른쪽 Average는 CDnegative라고 한다.

그렇게 CD를 계산했으면, W = W + alpha*CD 으로 W를 갱신한다. 이때의 alpha는 learning rate 이다.

Weight를 학습했으면 다시 처음으로 돌아가 두번째 epoch을 시작한다.

이런식으로 epoch을 계속 반복해서 Error = ((Input 뉴런의 데이터) - (reconstruction 한 input 뉴런의 데이터))^2 값이 충분히 작아져서 수렴하게되면 중단하고 학습이 끝나게 된다.


-------

그러나 이것은 Energy Based Model 의 수식을 유도해서 RBM에 적용한 것임.
따라서 일반적인 RBM모델들에 적용하려면 EBM 수식을 알아야함.


(EBM에대해서는 Bengio, 2009년 논문 5장을 참고할 것.)

  • Learning Deep Architecture for AI (Y. Bengio, 2009), Ch5. Energy-Based Models and Boltzmann Machines

RBM 수식 : http://image.diku.dk/igel/paper/AItRBM-proof.pdf

http://imonad.com/rbm/restricted-boltzmann-machine/

http://abipictures.tistory.com/773

댓글