ボルツマンマシンでの重みの学習


14

私はボルツマンマシンがどのように機能するかを理解しようとしていますが、重量がどのように学習されるかについてはよくわかりませんし、明確な説明を見つけることができませんでした。次は正しいですか?(また、適切なボルツマンマシンの説明へのポインターも素晴らしいでしょう。)

可視ユニットのセット(たとえば、画像の黒/白ピクセルに対応)と非表示ユニットのセットがあります。重みは何らかの方法で初期化され(たとえば、[-0.5、0.5]から均一に)、停止ルールに達するまで次の2つのフェーズを交互に繰り返します。

  1. 固定フェーズ-このフェーズでは、可視ユニットのすべての値が固定されているため、非表示ユニットの状態のみを更新します(ボルツマン確率的活性化規則に従って)。ネットワークが平衡に達するまで更新します。平衡に達すると、さらに回(定義済みの)更新を続け、(はノードおよび)の平均を追跡します。これらの平衡の更新後、を更新します。ここでNNバツバツjバツバツjjNwj=wj+1CAverageバツバツjCある程度の学習率です。(または、最後にバッチ更新を行う代わりに、平衡ステップ後に更新しますか?)

  2. フリーフェーズ-このフェーズでは、すべてのユニットの状態が更新されます。平衡に達したら、同様にN 'をさらに数回更新し続けますが、最後に相関を追加する代わりに、を引きます。wj=wj1CAverageバツバツj

私の主な質問は次のとおりです。

  1. クランプフェーズにいるときはいつでも、可視ユニットを学習したいパターンの1つにリセットします(そのパターンの重要性を表す頻度で)、または可視ユニットを元の状態のままにしますか自由相の終わりに?

  2. 各フェーズの終わりに重みのバッチ更新を行いますか、それともフェーズの各平衡ステップで重みを更新しますか?(または、どちらかでいいですか?)

回答:


6

直観的には、目に見えるユニットは「モデルが見るもの」、隠されたユニットは「モデルの心の状態」と考えることができます。すべての表示単位をいくつかの値に設定すると、「データをモデルに表示する」ことになります。次に、非表示のユニットをアクティブにすると、モデルは心の状態を見たままに調整します。

次に、モデルを無料で空想させます。それは閉じ込められ、文字通り心が生成するものを文字通り見、それらのイメージに基づいて新しい心の状態を生成します。

重み(およびバイアス)を調整することで行うことは、モデルがデータをより重視し、それ自体の空想をより少なくすることです。こうすることで、何らかのトレーニングの後、いくつかの(できれば)かなり良いデータモデルを信じることができます。たとえば、「このペア(X、Y)を信じますか?それを見つける可能性はどうですか?あなたの意見はどうですか?」ボルツマンマシン?」

最後に、エネルギーベースのモデルの簡単な説明を示します。これは、クランプフェーズとフリーフェーズがどこから来て、どのように実行するかを直感的に理解できるようにするものです。

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

直感的に明確な更新ルールが、モデルによるデータ生成の対数尤度の派生から生まれることを見るのは面白いです。

これらの直感を念頭に置いて、質問に答えるのが簡単になりました。

  1. 目に見える単位を、モデルに信じさせたいデータにリセットする必要があります。フリーフェーズの終わりから値を使用する場合、空想を続け、それ自体の誤った信念を強制します。

  2. フェーズの終了後に更新を行うことをお勧めします。特に、固定フェーズの場合は、モデルにデータに「焦点を合わせる」ための時間を与える方が良いでしょう。以前の更新では収束が遅くなります。これは、モデルが実際の心の状態をまだ調整していないときに接続を強制するためです。空想中に各平衡ステップの後にウェイトを更新することは、それほど害はありませんが、私はそれを経験していません。

EBM、BM、RBMの直感を改善したい場合、Geoffrey Hintonの主題に関する講義をご覧になることをお勧めします。彼はいくつかの良い例えを持っています。


2
  1. はい、「可視ユニットを学習したいパターンの1つにリセット(クランプ)します(そのパターンの重要性を表す頻度で)。」

  2. はい、「各フェーズの終わりに重みのバッチ更新を行います。」「フェーズの各平衡ステップの重み」を更新すると、ネットワークが瞬間的なエラーによって「気を散らされる」ため、収束が速くなるとは思いません。そのようにボルツマンマシンを実装しましたが、うまく機能しなかったことを覚えていますバッチ更新に変更するまで。


0

以下は、Paul Ivanovのコードに基づいたBoltzmann Machinesのサンプル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

データのパッチを作成することで機能しますが、コードを常にすべてのデータで機能するように変更できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.