एक बोल्ट्जमैन मशीन में वज़न सीखना


14

मैं यह समझने की कोशिश कर रहा हूं कि बोल्ट्जमन मशीनें कैसे काम करती हैं, लेकिन मुझे पूरा यकीन नहीं है कि कैसे वजन सीखा जाता है, और एक स्पष्ट विवरण नहीं मिल पाया है। निम्नलिखित सही है? (इसके अलावा, किसी भी अच्छे बोल्ट्ज़मन मशीन स्पष्टीकरण के संकेत भी महान होंगे।)

हमारे पास दृश्य इकाइयों का एक सेट है (उदाहरण के लिए, एक छवि में काले / सफेद पिक्सेल के अनुरूप) और छिपी हुई इकाइयों का एक सेट। वज़न को किसी भी तरह से आरंभ किया जाता है (उदाहरण के लिए, [-0.5, 0.5] से समान रूप से), और फिर हम निम्नलिखित दो चरणों के बीच वैकल्पिक करते हैं जब तक कि कुछ रोक नियम तक नहीं पहुंच जाते:

  1. एनएनएक्समैंएक्सजेएक्समैं,एक्सजेमैंजेएनwमैंजे=wमैंजे+1सीvआरजी(एक्समैंएक्सजे)सी

  2. wमैंजे=wमैंजे-1सीvआरजी(एक्समैंएक्सजे)

तो मेरे मुख्य प्रश्न हैं:

  1. जब भी हम क्लैंप किए गए चरण में होते हैं, तो क्या हम दिखाई देने वाली इकाइयों को उन पैटर्न में से एक में रीसेट करते हैं, जिन्हें हम सीखना चाहते हैं (कुछ आवृत्ति के साथ जो उस पैटर्न के महत्व का प्रतिनिधित्व करता है), या क्या हम दिखाई देने वाली इकाइयों को उस स्थिति में छोड़ देते हैं जिसमें वे थे मुक्त चरण के अंत में?

  2. क्या हम प्रत्येक चरण के अंत में वजन का एक बैच अपडेट करते हैं, या चरण में प्रत्येक संतुलन कदम पर वजन का अद्यतन करते हैं? (या, या तो एक ठीक है?)

जवाबों:


6

सहज रूप से, आप दिखाई देने वाली इकाइयों के बारे में सोच सकते हैं कि "मॉडल क्या देखता है" और छिपी हुई इकाइयों को "मॉडल की मन की स्थिति" के रूप में देखा जाता है। जब आप सभी दृश्य इकाइयों को कुछ मूल्यों पर सेट करते हैं, तो आप "मॉडल को डेटा दिखाते हैं"। फिर, जब आप छिपी हुई इकाइयों को सक्रिय करते हैं, तो मॉडल समायोजित करता है कि यह मन की स्थिति है जो इसे देखता है।

इसके बाद आप मॉडल को स्वतंत्र होने दें और कल्पना करें। यह शट-इन हो जाएगा और शाब्दिक रूप से कुछ चीजें देखेंगे जो मन उत्पन्न करता है, और उन छवियों के आधार पर मन की नई अवस्थाएं उत्पन्न करता है।

वजन (और पक्षपाती) को समायोजित करके हम क्या कर रहे हैं जो मॉडल को डेटा में अधिक विश्वास करता है और अपनी स्वयं की कल्पनाओं में कम है। इस तरह से कुछ प्रशिक्षण के बाद यह कुछ (उम्मीद है) डेटा के बहुत अच्छे मॉडल में विश्वास करेगा, और हम उदाहरण के लिए पूछ सकते हैं "क्या आप इस जोड़ी (एक्स, वाई) में विश्वास करते हैं? आपको यह कैसे लगता है? आपकी राय क्या है? बोल्ट्ज़मन मशीन? "

अंत में यहां एनर्जी बेस्ड मॉडल्स का संक्षिप्त विवरण दिया गया है, जो आपको कुछ अंतर्ज्ञान दे सकते हैं कि क्लैम्पड और फ्री चरण कहां से आते हैं और हम उन्हें कैसे चलाना चाहते हैं।

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

यह देखना हास्यास्पद है कि सहज रूप से स्पष्ट अपडेट नियम मॉडल द्वारा डेटा उत्पन्न करने की लॉग-लाइबिलिटी के रूप में सामने आते हैं।

इन सवालों को ध्यान में रखते हुए अब आपके सवालों का जवाब देना आसान हो गया है:

  1. हमें दिखाई देने वाली इकाइयों को कुछ डेटा पर रीसेट करना होगा जिसे हम मॉडल पर विश्वास करना चाहते हैं। यदि हम नि: शुल्क चरण के अंत से मूल्यों का उपयोग करते हैं तो यह केवल कल्पना करना जारी रखेगा, अंत में यह गलत धारणाएं हैं।

  2. चरण के अंत के बाद अपडेट करना बेहतर है। खासकर अगर यह क्लैंप्ड चरण है, तो मॉडल को डेटा पर "फोकस" करने के लिए कुछ समय देना बेहतर है। पहले के अद्यतन अभिसरण को धीमा कर देंगे, क्योंकि वे कनेक्शन को लागू करते हैं जब मॉडल समायोजित नहीं होता है तो यह वास्तविकता के लिए दिमाग की स्थिति है। कल्पना करते समय प्रत्येक संतुलन कदम के बाद वजन का अद्यतन करना कम हानिकारक होना चाहिए, हालांकि मुझे इसके साथ कोई अनुभव नहीं है।

यदि आप EBM, BM और RBM पर अपने अंतर्ज्ञान को सुधारना चाहते हैं, तो मैं इस विषय पर ज्यॉफ्री हिंटन के कुछ व्याख्यान देखने की सलाह दूंगा, उनके पास कुछ अच्छी उपमाएँ हैं।


2
  1. हां, "हम उन इकाइयों में से एक को दृश्यमान इकाइयों को रीसेट (क्लैंप) करते हैं जिन्हें हम सीखना चाहते हैं (कुछ आवृत्ति के साथ जो उस पैटर्न के महत्व का प्रतिनिधित्व करता है)।"

  2. हां, "हम प्रत्येक चरण के अंत में भार का एक बैच अपडेट करते हैं।" मुझे नहीं लगता कि "चरण में प्रत्येक संतुलन कदम पर वजन" को अपडेट करने से तेजी से अभिसरण होगा क्योंकि नेटवर्क "तात्कालिक त्रुटियों से" विचलित हो जाता है - मैंने बोल्ट्जमन मशीनों को इस तरह से लागू किया है, और मुझे याद है कि यह बहुत अच्छी तरह से काम नहीं कर रहा है। जब तक मैंने इसे बैच अपडेट में नहीं बदला।


0

यहाँ पॉल इवानोव के कोड के आधार पर बोल्ट्ज़मन मशीनों के लिए नमूना पायथन कोड है

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

यह डेटा के पैच बनाकर काम करता है, लेकिन इसे संशोधित किया जा सकता है इसलिए कोड हर समय सभी डेटा पर काम करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.