Изучение веса на машине Больцмана

14

Я пытаюсь понять, как работают машины Больцмана, но я не совсем уверен, как узнать вес, и не смог найти четкого описания. Правильно ли следующее? (Кроме того, ссылки на любые хорошие машинные объяснения Больцмана также были бы хорошими.)

У нас есть набор видимых единиц (например, соответствующих черно-белых пикселей на изображении) и набор скрытых единиц. Веса каким-то образом инициализируются (например, равномерно из [-0,5, 0,5]), а затем мы чередуем следующие две фазы, пока не будет достигнуто какое-то правило остановки:

  1. Фаза фиксации - на этом этапе все значения видимых единиц фиксированы, поэтому мы обновляем только состояния скрытых единиц (согласно правилу стохастической активации Больцмана). Мы обновляем, пока сеть не достигла равновесия. Как только мы достигаем равновесия, мы продолжаем обновлять еще раз (для некоторой предопределенной N ), отслеживая среднее значение x i x j (где x i , x j - состояния узлов i и j ). После этих обновлений N равновесия мы обновляем w i j = w i j +NNИксяИксJИкся,ИксJяJN, гдеC- некоторая скорость обучения. (Или вместо того, чтобы делать пакетное обновление в конце, мы обновляем после шага равновесия?)весяJзнак равновесяJ+1СAvерaграмме(ИксяИксJ)С

  2. Свободная фаза - на этом этапе обновляются состояния всех юнитов. Как только мы достигнем равновесия, мы аналогичным образом продолжаем обновлять N 'больше раз, но вместо добавления корреляций в конце мы вычитаем: .весяJзнак равновесяJ-1СAvерaграмме(ИксяИксJ)

Итак, мои основные вопросы:

  1. Всякий раз, когда мы находимся в фиксированной фазе, сбрасываем ли мы видимые единицы в один из паттернов, которые мы хотим изучить (с некоторой частотой, которая представляет важность этого паттерна), или мы оставляем видимые единицы в том состоянии, в котором они находились? в конце свободной фазы?

  2. Делаем ли мы пакетное обновление весов в конце каждой фазы или обновляем весы на каждом шаге равновесия в фазе? (Или один штраф?)

raegtin
источник

Ответы:

6

Интуитивно вы можете рассматривать видимые единицы как «то, что видит модель», а скрытые единицы - как «состояние ума модели». Когда вы устанавливаете все видимые единицы измерения на некоторые значения, вы «показываете данные модели». Затем, когда вы активируете скрытые юниты, модель настраивает свое состояние ума на то, что видит.

Затем вы отпускаете модель и фантазируете. Он станет замкнутым и буквально увидит некоторые вещи, которые генерирует его разум, и создаст новые состояния ума на основе этих образов.

То, что мы делаем путем корректировки весов (и смещений), заставляет модель больше верить в данные и меньше в свои собственные фантазии. Таким образом, после некоторого обучения он поверит в какую-то (надеюсь) довольно хорошую модель данных, и мы можем, например, спросить: «Верите ли вы в эту пару (X, Y)? Насколько вероятно, что вы найдете ее? Каково ваше мнение, мистер?». Машина Больцмана? "

Наконец, вот краткое описание моделей на основе энергии, которые должны дать вам некоторую интуицию, откуда берутся фазы зажима и освобождения и как мы хотим их запустить.

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

Забавно видеть, что интуитивно понятные правила обновления появляются из логарифмической вероятности генерации данных моделью.

Имея в виду эту интуицию, теперь легче ответить на ваши вопросы:

  1. Мы должны сбросить видимые единицы измерения до некоторых данных, в которые мы хотели бы, чтобы модель поверила. Если мы будем использовать значения с конца свободной фазы, она будет просто продолжать фантазировать, а затем приводить в исполнение собственные ошибочные убеждения.

  2. Обновления лучше делать после окончания фазы. Особенно, если это ограниченная фаза, лучше дать модели некоторое время, чтобы «сосредоточиться» на данных. Более ранние обновления замедляют конвергенцию, так как они усиливают связи, когда модель еще не приспособила свое состояние к реальности. Обновление веса после каждого шага равновесия во время фантазий должно быть менее вредным, хотя у меня нет такого опыта.

Если вы хотите улучшить свою интуицию в области EBM, BM и RBM, я бы посоветовал посмотреть некоторые лекции Джеффри Хинтона по этому вопросу, у него есть несколько хороших аналогий.

sjm.majewski
источник
2
  1. Да, «мы сбрасываем (зажимаем) видимые единицы измерения к одному из шаблонов, которые мы хотим изучить (с некоторой частотой, которая представляет важность этого шаблона)».

  2. Да, «мы делаем пакетное обновление весов в конце каждого этапа». Я не думаю, что обновление «весов на каждом шаге равновесия в фазе» приведет к быстрой конвергенции, потому что сеть «отвлекается» из-за мгновенных ошибок - я реализовал машины Больцмана таким образом, и я помню, что они работали не очень хорошо пока я не изменил его на пакетное обновление.

Нил Г
источник
0

Вот пример кода 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

Он работает путем создания патчей данных, но его можно изменить, чтобы код работал со всеми данными постоянно.

BBDynSys
источник