NUTS pymc3 не может хорошо работать с моей иерархической моделью для байесовских нейронных сетей?

У меня есть иерархическая модель для изучения байесовских сетей с единственным скрытым слоем. Сетевые параметры разделены на 4 группы весов и смещений «вход-скрытый» и «скрытый-выход». Гауссовский априор определяется для каждой группы параметров. Гиперпараметры, стандартные отклонения этих априорных значений, имеют гамма-распределения с параметрами альфа = 1. и бета = 1/60. выходной шум также является гауссовским; с гаммой (альфа = 1, бета = 200), превышающей стандартное отклонение. Функция шага NUTS используется для выборки, где ее параметр масштабирования установлен на Максимум апостериори только для параметров (за исключением гиперпараметров). данные являются одномерными и из [0,1], где используется простая одномерная функция синусоиды, обеспечивают наблюдения. Я ожидал, что набор выбранных сетей будет интерполировать данные и начнет расходиться / расходиться при увеличении расстояния от этих наблюдаемых точек, создавая формы, подобные тем, которые создаются моделями гауссовских процессов. Удивительно, но результаты оказались не такими, как я ожидал. Похоже, некоторые раздражающие ограничения мешают сэмплеру работать нормально и производить выборку со всей апертуры: введите описание изображения здесь( красная линия создается сетью MAP, черная линия - это основная функция, а 3 маленькие красные точки - это данные), ребята, pymc3, у вас есть какие-либо объяснения о причине этой проблемы и как я могу ее исправить?

import numpy as np
import  theano
import theano.tensor as T
import pymc3 as pm
import matplotlib.pyplot as plt
import scipy

#
co = 3 #  4 ,5,6,7 ,8
numHiddenUnits = 100
numObservations= 3  # 6 ,7, 8
randomSeed = 1235
numSamples = 5500



def z_score(x,mean=None,std=None):
    if mean is None or std is None:
        mean,std = np.mean(x,axis=0),np.std(x,axis=0)
    return x - mean/std,mean,std



def sample(nHiddenUnts,X,Y):
    '''
     samples a set of ANNs from the posterior
   '''
    nFeatures = X.shape[1]
    with pm.Model() as model:

        #Gamma Hyperpriors

        alpha,beta = 1.,1./60.
        # standard deviation: Bias(Hidden-out)
        bhoSd =  pm.Gamma('bhoSd',alpha=alpha,beta=beta)
        #standard deviation: Weights (Hidden-out)
        whoSd =  pm.Gamma('whoSd',alpha=alpha,beta=beta)
        bihSd =  pm.Gamma('bihSd',alpha=alpha,beta=beta)
        #standard deviation: Bias (input-hidden)
        wihSd =  pm.Gamma('wihSd',alpha=alpha,beta=beta)
        #standard deviation:  output noise
        noiseSd = pm.Gamma('noiseSd',alpha=alpha,beta=200.)

        wihSd.tag.test_value= bihSd.tag.test_value=   whoSd.tag.test_value= bhoSd.tag.test_value = 200
    noiseSd.tag.test_value = 0.002


        #priors
        #Bias (HiddenOut)
        bho = pm.Normal('bho',mu=0,sd=bhoSd)
        bho.tag.test_value = 1
        who = pm.Normal('who',mu=0,sd=whoSd,shape=(nHiddenUnts,1) )
        who.tag.test_value =  np.random.normal(size=nHiddenUnts,loc=0,scale=1).reshape(nHiddenUnts,1)  #np.ones(shape=(nHiddenUnts,1))
        #Bias input-hidden
        bih = pm.Normal('bih',mu=0,sd=bihSd ,shape=nHiddenUnts)
        bih.tag.test_value =np.random.normal(size=nHiddenUnts,loc=0,scale=1)#np.ones(shape=nHiddenUnts)
    wih= pm.Normal('wih',mu=0,sd=wihSd ,shape= (nFeatures,nHiddenUnts))
        wih.tag.test_value =np.random.normal(size=nFeatures*nHiddenUnts,loc=0,scale=1).reshape(nFeatures,nHiddenUnts)#np.ones(shape= (nFeatures,nHiddenUnts))


        netOut=T.dot( T.nnet.sigmoid( T.dot( X , wih ) + bih ) , who ) + bho


        #likelihood
        likelihood = pm.Normal('likelihood',mu=netOut,sd=noiseSd,observed= Y)

        print("model built")
        #==================================================================

        start1 = pm.find_MAP(fmin=scipy.optimize.fmin_l_bfgs_b, vars=[bho,who,bih,wih],model=model)
        #start2 = pm.find_MAP(start=start1,    fmin=scipy.optimize.fmin_l_bfgs_b, vars=[noiseSd,wihSd,bihSd ,whoSd,bhoSd],model=model)
        step = pm.NUTS(scaling=start1)
        #step =  pm.HamiltonianMC(scaling=start1,path_length=5.,step_scale=.05,)
        trace = pm.sample(10,step,start=start1, progressbar=True,random_seed=1234)[:]
        step1 = pm.NUTS(scaling=trace[-1])
        print '-'
        trace = pm.sample(numSamples,step1,start=trace[-1], progressbar=True,random_seed=1234)[100:]

           #========================================================================
        return trace,start1

#underlying function
def g(x):
    global co
    return np.prod( x+np.sin(co*np.pi*x),axis=1)

np.random.seed(randomSeed)
XX= np.atleast_2d(np.random.uniform(0,1.,size =numObservations)).T
Y = np.atleast_2d(g(XX)).T
X,mean,std = z_score(XX)

trace,map_= sample(numHiddenUnits, X, Y)


 data =np.atleast_2d( np.linspace(0., 1., 100)).T
 theano.config.compute_test_value = 'off'

 d = T.dmatrix()
 w= T.dmatrix()
 b = T.vector()
 bo = T.dscalar()
 wo = T.dmatrix()
 y= T.dot( T.nnet.sigmoid( T.dot(d,w)+b),wo)+bo
 f = theano.function([d,w,b,wo,bo],y)


 data1,mean,std = z_score(data, mean, std)
 print trace['wih'].shape
 for s in trace[::1]:
     plt.plot(data, f(data1,s['wih'],s['bih'],s['who'],s['bho']),c='blue',alpha =0.15)


 plt.plot(data,g(data),'black')

 # prediction of maximum a posteriori network
 plt.plot(data,   f(data1,map_['wih'],map_['bih'],map_['who'],map_['bho']),c='red')
 plt.plot(XX,Y,'r.',markersize=10)

 plt.show()

Обновление: я изменил код следующим образом: Во-первых, кажется, что назначение test_values ​​параметров модели проблематично! но без значения для 'test_value' find_MAP не будет сходиться к правильной точке, поэтому я удалил назначения test_value и скармливаю find_MAP () начальную точку (initpoint). Второй. Чтобы упростить задачу, я заменил гиперприоры Gamma на Half_Normals. Ступенчатый метод также заменен на Метрополис. Знайте, что пример функции выглядит следующим образом: def sample (nHiddenUnts, X, Y): nFeatures = X.shape 1 с pm.Model () в качестве модели:

        bhoSd =  pm.HalfNormal('bhoSd',sd=100**2)
        whoSd =  pm.HalfNormal('whoSd',sd=100**2)
        bihSd =  pm.HalfNormal('bihSd',sd=100**2)
        wihSd =  pm.HalfNormal('wihSd',sd=100**2)
        noiseSd = pm.HalfNormal('noiseSd',sd=0.001)



        #priors
        bho = pm.Normal('bho',mu=0,sd=bhoSd)
        who = pm.Normal('who',mu=0,sd=whoSd,shape=(nHiddenUnts,1) )
        bih = pm.Normal('bih',mu=0,sd=bihSd ,shape=nHiddenUnts)
        wih= pm.Normal('wih',mu=0,sd=wihSd ,shape= (nFeatures,nHiddenUnts))


        netOut=T.dot( T.nnet.sigmoid( T.dot( X , wih ) + bih ) , who ) + bho

        #likelihood
        likelihood = pm.Normal('likelihood',mu=netOut,sd=noiseSd,observed= Y)

        #========================================================
        initpoint = {'bho':1,
                   'who':np.random.normal(size=nHiddenUnts,loc=0,scale=1).reshape(nHiddenUnts,1),
                   'bih':np.random.normal(size=nHiddenUnts,loc=0,scale=1),
                   'wih':np.random.normal(size=nFeatures*nHiddenUnts,loc=0,scale=1).reshape(nFeatures,nHiddenUnts),
                   'bhoSd':100,
                   'bihSd':100,
                   'whoSd':100,
                   'wihSd':100,
                   'noiseSd':0.1
                   }

        start1 = pm.find_MAP(start=initpoint,fmin=scipy.optimize.fmin_l_bfgs_b, vars=[bho,who,bih,wih],model=model)
        step = pm.Metropolis(tune=True,tune_interval=10000)
        trace = pm.sample(numSamples,step,start=start1,progressbar=True,random_seed=1234)[10000::5]
        #========================================================

        return trace,start1

результат после рисования 15000 образцов выглядит следующим образом: введите описание изображения здесьТолько когда я увеличиваю стандартное отклонение для Both NoiseSd гиперпараметр и 'noisSd' в точке инициализации (начальная точка для find_MAP) до 0,1 результаты меняются следующим образом:   введите описание изображения здесь Однако такой высокий уровень шума нежелателен.


person mashall aryan    schedule 06.07.2015    source источник


Ответы (1)


Как выглядит модель со стандартным пробоотборником Metropolis? Это должно дать некоторое представление о том, связана ли проблема с алгоритмом или где-то еще. Тот факт, что оценки MAP и NUTS сопоставимы, по-видимому, предполагает последнее.

person Chris Fonnesbeck    schedule 07.07.2015
comment
Поскольку Metropolis и NUTS дали аналогичные результаты и поскольку это совершенно разные алгоритмы, реализованные отдельно, я не думаю, что это ошибка сэмплеров. Я недостаточно знаком с вашей проблемой, чтобы дать представление, но я бы предложил убрать детали из модели (например, исправить параметры), пока вы не получите что-то, что имеет для вас смысл, и двигаться дальше. - person Chris Fonnesbeck; 07.07.2015