Học trọng lượng trong một máy Boltzmann


14

Tôi đang cố gắng hiểu làm thế nào các máy Boltzmann hoạt động, nhưng tôi không chắc chắn làm thế nào để học được trọng lượng và không thể tìm thấy một mô tả rõ ràng. Điều sau đây có đúng không? (Ngoài ra, con trỏ đến bất kỳ giải thích tốt về máy Boltzmann cũng sẽ rất tuyệt.)

Chúng tôi có một bộ các đơn vị hiển thị (ví dụ: tương ứng với các pixel đen / trắng trong một hình ảnh) và một bộ các đơn vị ẩn. Các trọng số được khởi tạo bằng cách nào đó (ví dụ: thống nhất từ ​​[-0,5, 0,5]), và sau đó chúng tôi luân phiên giữa hai giai đoạn sau cho đến khi đạt được một số quy tắc dừng:

  1. Pha kẹp - Trong pha này, tất cả các giá trị của các đơn vị nhìn thấy được cố định, vì vậy chúng tôi chỉ cập nhật trạng thái của các đơn vị ẩn (theo quy tắc kích hoạt ngẫu nhiên Boltzmann). Chúng tôi cập nhật cho đến khi mạng đạt đến trạng thái cân bằng. Khi chúng ta đạt đến trạng thái cân bằng, chúng ta tiếp tục cập nhật N nhiều lần hơn (đối với một số được xác định trước N), theo dõi trung bình của xixj (trong đó xTôi,xj là trạng thái của các nút vàj NTôij ). Sau những cập nhật cân bằng đó , chúng tôi cập nhật , trong đóNwTôij= =wTôij+1CMộtvermộtge(xTôixj)Clà một số tỷ lệ học tập. (Hoặc, thay vì thực hiện cập nhật hàng loạt vào cuối, chúng ta có cập nhật sau khi chúng ta cân bằng bước không?)

  2. Giai đoạn miễn phí - Trong giai đoạn này, trạng thái của tất cả các đơn vị được cập nhật. Khi chúng tôi đạt đến trạng thái cân bằng, chúng tôi tương tự tiếp tục cập nhật N 'nhiều lần hơn, nhưng thay vì thêm các tương quan ở cuối, chúng tôi trừ: wTôij= =wTôij-1CMộtvermộtge(xTôixj) .

Vì vậy, câu hỏi chính của tôi là:

  1. Bất cứ khi nào chúng ta ở trong giai đoạn bị kẹp, chúng ta sẽ đặt lại các đơn vị hiển thị thành một trong các mẫu mà chúng ta muốn tìm hiểu (với một số tần số thể hiện tầm quan trọng của mẫu đó) hoặc chúng ta để các đơn vị hiển thị ở trạng thái chúng ở vào cuối giai đoạn tự do?

  2. Chúng ta có thực hiện cập nhật hàng loạt các trọng số ở cuối mỗi giai đoạn hay cập nhật các trọng số ở mỗi bước cân bằng trong pha không? (Hoặc, một trong hai là tốt?)

Câu trả lời:


6

Theo trực giác, bạn có thể nghĩ các đơn vị hữu hình là "những gì mô hình nhìn thấy" và các đơn vị ẩn là "trạng thái tâm trí của mô hình". Khi bạn đặt tất cả các đơn vị hiển thị thành một số giá trị, bạn "hiển thị dữ liệu cho mô hình". Sau đó, khi bạn kích hoạt các đơn vị ẩn, mô hình sẽ điều chỉnh trạng thái của tâm trí với những gì nó nhìn thấy.

Tiếp theo bạn để mô hình tự do và tưởng tượng. Nó sẽ trở nên im lặng và thực sự thấy một số thứ mà tâm trí của nó tạo ra và tạo ra những trạng thái tâm trí mới dựa trên những hình ảnh đó.

Những gì chúng tôi làm bằng cách điều chỉnh các trọng số (và độ lệch) là làm cho mô hình tin tưởng nhiều hơn vào dữ liệu và ít hơn vào những tưởng tượng của riêng nó. Bằng cách này sau một số khóa đào tạo, nó sẽ tin vào một số mô hình dữ liệu khá tốt (hy vọng) và ví dụ chúng ta có thể hỏi "bạn có tin vào cặp này (X, Y) không? Bạn có thể tìm thấy nó như thế nào? Máy Boltzmann? "

Cuối cùng, đây là một mô tả ngắn gọn về Mô hình dựa trên năng lượng, sẽ cung cấp cho bạn một số trực giác nơi các giai đoạn Kẹp và Miễn phí đến từ đâu và cách chúng tôi muốn chạy chúng.

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

Thật buồn cười khi thấy rằng các quy tắc cập nhật rõ ràng bằng trực giác xuất phát từ hình thức khả năng tạo dữ liệu của mô hình.

Với những trực giác này, giờ đây việc trả lời câu hỏi của bạn trở nên dễ dàng hơn:

  1. Chúng ta phải đặt lại các đơn vị hiển thị thành một số dữ liệu mà chúng ta muốn mô hình tin tưởng. Nếu chúng ta sử dụng các giá trị từ cuối giai đoạn tự do, nó sẽ tiếp tục mơ mộng, chấm dứt niềm tin sai lầm của chính nó.

  2. Tốt hơn là nên cập nhật sau khi kết thúc giai đoạn. Đặc biệt nếu đó là giai đoạn kẹp, tốt hơn là cho mô hình một chút thời gian để "tập trung" vào dữ liệu. Các bản cập nhật trước đó sẽ làm chậm quá trình hội tụ, vì chúng thực thi các kết nối khi mô hình chưa điều chỉnh trạng thái của nó thành hiện thực. Cập nhật trọng lượng sau mỗi bước cân bằng trong khi tưởng tượng sẽ ít gây hại hơn, mặc dù tôi không có kinh nghiệm về điều đó.

Nếu bạn muốn cải thiện trực giác của mình về EBM, BM và RBM, tôi khuyên bạn nên xem một số bài giảng của Geoffrey Hinton về chủ đề này, anh ta có một số điểm tương đồng tốt.


2
  1. Có, "chúng tôi đặt lại (kẹp) các đơn vị hiển thị thành một trong những mẫu chúng tôi muốn tìm hiểu (với một số tần số thể hiện tầm quan trọng của mẫu đó)."

  2. Có, "chúng tôi thực hiện cập nhật hàng loạt các trọng số vào cuối mỗi giai đoạn." Tôi không nghĩ rằng việc cập nhật "các trọng số ở mỗi bước cân bằng trong pha" sẽ dẫn đến sự hội tụ nhanh vì mạng "bị phân tâm" bởi các lỗi tức thời - Tôi đã triển khai các máy Boltzmann theo cách đó và tôi nhớ nó không hoạt động tốt cho đến khi tôi thay đổi nó thành một bản cập nhật hàng loạt.


0

Dưới đây là mã Python mẫu cho Boltzmann Machines dựa trên mã của Paul Ivanov từ

http: // redwood.ber siêu.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

Nó hoạt động bằng cách tạo các bản vá dữ liệu, nhưng điều này có thể được sửa đổi để mã hoạt động trên tất cả dữ liệu mọi lúc.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.