在玻尔兹曼机器中学习权重


14

我试图了解Boltzmann机器的工作原理,但是我不太确定如何学习权重,也无法找到清晰的描述。以下正确吗?(此外,指向任何好的玻尔兹曼机器解释的指针也将很棒。)

我们有一组可见单元(例如,对应于图像中的黑色/白色像素)和一组隐藏单元。权重以某种方式初始化(​​例如,统一从[-0.5,0.5]开始),然后我们在以下两个阶段之间交替,直到达到某个停止规则:

  1. 固定阶段-在此阶段,所有可见单位的值都是固定的,因此我们仅更新隐藏单位的状态(根据Boltzmann随机激活规则)。我们更新直到网络达到平衡。一旦达到平衡,我们将继续更新ñ次(对于一些预定义的),同时跟踪的平均值(其中是节点和j的状态)。在这N个均衡更新之后,我们更新w_ij = w_ij + \ frac {1} {C}平均(x_i x_j),其中CñX一世XĴX一世XĴ一世Ĵñw一世Ĵ=w一世Ĵ+1个C一种vË[R一种GËX一世XĴC是一定的学习速度。(或者,不是在最后进行批量更新,而是在均衡步骤之后进行更新?)

  2. 自由阶段-在此阶段,将更新所有单元的状态。一旦达到平衡,我们类似地会继续更新N'次,但是除了在末尾添加相关性之外,我们减去:。w一世Ĵ=w一世Ĵ-1个C一种vË[R一种GËX一世XĴ

所以我的主要问题是:

  1. 每当我们处于固定阶段时,我们都将可见单位重置为我们要学习的模式之一(以某种频率表示该模式的重要性),还是将可见单位保持在它们处于的状态在免费阶段结束时?

  2. 我们是在每个阶段结束时批量更新权重,还是在阶段的每个平衡步骤中更新权重?(或者,可以吗?)

Answers:


6

直观地,您可以将可见单位视为“模型所见”,将隐藏单位视为“模型的心态”。将所有可见单位设置为某些值时,将“显示数据到模型”。然后,当您激活隐藏的单位时,模型会将其心理状态调整为所见。

接下来,让模型自由运行并幻想。它将关闭,并从字面上看到它所生成的某些事物,并根据这些图像生成新的思想状态。

通过调整权重(和偏差),我们所做的就是使模型更多地相信数据,而更少相信自己的幻想。这样一来,经过一番训练,它就会相信一些(希望地)非常好的数据模型,例如,我们可以问“您相信这对(X,Y)吗?您找到它的可能性如何?玻尔兹曼机?”

最后,这里是对基于能量的模型的简要说明,它应该给您一些直觉,即钳位和自由相的来源以及我们如何运行它们。

http://deeplearning.net/tutorial/rbm.html#energy-based-models-ebm

有趣的是,从模型生成数据的对数似然性的推导中得出了直观清晰的更新规则。

考虑到这些直觉,现在可以更轻松地回答您的问题:

  1. 我们必须将可见单位重置为我们希望模型相信的一些数据。如果我们使用自由阶段结束时的值,它将继续幻想,最终强制执行其自身的误导信念。

  2. 最好在阶段结束后进行更新。特别是在固定阶段,最好给模型一些时间来“关注”数据。较早的更新会减慢收敛速度,因为当模型尚未调整到现实状态时,它们会强制连接。尽管我没有经验,但是在每个平衡步骤之后更新重量并幻想化的危害应该较小。

如果您想改善对EBM,BM和RBM的直觉,我建议您观看Geoffrey Hinton关于该主题的一些演讲,他有一些很好的类比。


2
  1. 是的,“我们将可见单位重置(钳制)为我们要学习的模式之一(以某种频率表示该模式的重要性)。”

  2. 是的,“我们在每个阶段结束时都会对权重进行批处理更新。” 我认为更新“阶段中每个平衡步骤的权重”不会导致快速收敛,因为网络会因瞬时错误而“分散注意力” —我已经以这种方式实施了Boltzmann机器,并且我记得它不能很好地工作直到我将其更改为批量更新。


0

这是基于Paul Ivanov的代码的Boltzmann机器的Python示例代码

http://redwood.berkeley.edu/wiki/VS265:_Homework_assignments

import numpy as np

def extract_patches(im,SZ,n):
    imsize,imsize=im.shape;
    X=np.zeros((n,SZ**2),dtype=np.int8);
    startsx= np.random.randint(imsize-SZ,size=n)
    startsy=np.random.randint(imsize-SZ,size=n)
    for i,stx,sty in zip(xrange(n), startsx,startsy):
        P=im[sty:sty+SZ, stx:stx+SZ];
        X[i]=2*P.flat[:]-1;
    return X.T

def sample(T,b,n,num_init_samples):
    """
    sample.m - sample states from model distribution

    function S = sample(T,b,n, num_init_samples)

    T:                weight matrix
    b:                bias
    n:                number of samples
    num_init_samples: number of initial Gibbs sweeps
    """
    N=T.shape[0]

    # initialize state vector for sampling
    s=2*(np.random.rand(N)<sigmoid(b))-1

    for k in xrange(num_init_samples):
        s=draw(s,T,b)

    # sample states
    S=np.zeros((N,n))
    S[:,0]=s
    for i in xrange(1,n):
        S[:,i]=draw(S[:,i-1],T,b)

    return S

def sigmoid(u):
    """
    sigmoid.m - sigmoid function

    function s = sigmoid(u)
    """
    return 1./(1.+np.exp(-u));

def draw(Sin,T,b):
    """
    draw.m - perform single Gibbs sweep to draw a sample from distribution

    function S = draw(Sin,T,b)

    Sin:      initial state
    T:        weight matrix
    b:        bias
    """
    N=Sin.shape[0]
    S=Sin.copy()
    rand = np.random.rand(N,1)
    for i in xrange(N):
        h=np.dot(T[i,:],S)+b[i];
        S[i]=2*(rand[i]<sigmoid(h))-1;

    return S

def run(im, T=None, b=None, display=True,N=4,num_trials=100,batch_size=100,num_init_samples=10,eta=0.1):
    SZ=np.sqrt(N);
    if T is None: T=np.zeros((N,N)); # weight matrix
    if b is None: b=np.zeros(N); # bias

    for t in xrange(num_trials):
        print t, num_trials
        # data statistics (clamped)
        X=extract_patches(im,SZ,batch_size).astype(np.float);
        R_data=np.dot(X,X.T)/batch_size;
        mu_data=X.mean(1);

        # prior statistics (unclamped)
        S=sample(T,b,batch_size,num_init_samples);
        R_prior=np.dot(S,S.T)/batch_size;
        mu_prior=S.mean(1);

        # update params
        deltaT=eta*(R_data - R_prior);
        T=T+deltaT;

        deltab=eta*(mu_data - mu_prior);
        b=b+deltab;


    return T, b

if __name__ == "__main__": 
    A = np.array([\
    [0.,1.,1.,0],
    [1.,1.,0, 0],
    [1.,1.,1.,0],
    [0, 1.,1.,1.],
    [0, 0, 1.,0]
    ])
    T,b = run(A,display=False)
    print T
    print b

它通过创建数据补丁来起作用,但是可以对其进行修改,以便代码始终可以对所有数据起作用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.