def objectivefunction(self, simulation, evaluation): if self.used_algorithm == 'sceua' or self.used_algorithm == 'abc' or self.used_algorithm == 'fscabc': objectivefunction = rmse(evaluation=evaluation, simulation=simulation) elif self.used_algorithm == 'dream' or self.used_algorithm == 'demcz' or self.used_algorithm == 'mcmc': objectivefunction = log_p(evaluation=evaluation, simulation=simulation) else: objectivefunction = - rmse(evaluation=evaluation, simulation=simulation) return objectivefunction
def sample(self, repetitions, nChains = 5, burnIn = 100, thin = 1, convergenceCriteria = .8,variables_of_interest = None, DEpairs = 2, adaptationRate ='auto', eps = 5e-2, mConvergence = True, mAccept = True): """ Samples from a posterior distribution using DREAM. Parameters ---------- repetitions : int number of draws from the sample distribution to be returned nChains : int number of different chains to employ burnInSize : int number of iterations (meaning draws / nChains) to do before doing actual sampling. DEpairs : int number of pairs of chains to base movements off of eps : float used in jittering the chains Returns ------- None : None sample sets self.history which contains the combined draws for all the chains self.iter which is the total number of iterations self.acceptRatio which is the acceptance ratio self.burnIn which is the number of burn in iterations done self.R which is the gelman rubin convergence diagnostic for each dimension """ starttime=time.time() intervaltime=starttime self.min_bound, self.max_bound = self.find_min_max() repetitions=int(repetitions/nChains) ndraw_max = repetitions*nChains maxChainDraws = int(ndraw_max/nChains) dimensions=len(self.parameter()['random']) history = _SimulationHistory(maxChainDraws, nChains, dimensions) #minbound,maxbound=self.find_min_max() if variables_of_interest is not None: slices = [] for var in variables_of_interest: slices.append(self.slices[var]) else: slices = [slice(None,None)] history.add_group('interest', slices) # initialize the temporary storage vectors currentVectors = np.zeros((nChains, dimensions)) currentLogPs = np.zeros(nChains) self.accepts_ratio = 0 #) make a list of starting chains that at least spans the dimension space # in this case it will be of size 2*dim nSeedChains = int(np.ceil(dimensions* 2/nChains) * nChains) nSeedIterations = int(nSeedChains/nChains) if nSeedIterations <=2: nSeedIterations=2 burnInpar=[] for i in range(nSeedIterations): vectors = np.zeros((nChains, dimensions)) for j in range(nChains): randompar = self.parameter()['random']#+np.random.uniform(low=-1,high=1) vectors[j] = randompar #print randompar burnInpar.append(vectors) history.record(vectors,0,0) #use the last nChains chains as the actual chains to track #add the starting positions to the history for i in range(len(burnInpar)): self._logPs=[] param_generator = ((rep,list(burnInpar[i][rep])) for rep in xrange(int(nChains))) for rep,vector,simulations in self.repeat(param_generator): likelist=objectivefunctions.log_p(simulations,self.evaluation) simulationlist=simulations self._logPs.append(likelist) #Save everything in the database self.datawriter.save(likelist,vector,simulations=simulations) #print len(self._logPs) #print len(burnInpar[i]) history.record(burnInpar[i],self._logPs,1) # for chain in range(nChains): # simulationlist=self.model(vectors[chain])#THIS WILL WORK ONLY FOR MULTIPLE CHAINS # likelist=objectivefunctions.log_p(simulationlist,self.evaluation) # self._logPs.append(likelist) # self.datawriter.save(likelist,list(vectors[chain]),simulations=list(simulationlist),chains=chain) # history.record(vectors,self._logPs,1) gamma = None # initilize the convergence diagnostic object grConvergence = _GRConvergence() covConvergence = _CovarianceConvergence() # get the starting log objectivefunction and position for each of the chains currentVectors = vectors currentLogPs = self._logPs[-1] #2)now loop through and sample iter = 0 accepts_ratio_weighting = 1 - np.exp(-1.0/30) lastRecalculation = 0 # continue sampling if: # 1) we have not drawn enough samples to satisfy the minimum number of iterations # 2) or any of the dimensions have not converged # 3) and we have not done more than the maximum number of iterations while iter<maxChainDraws: if iter == burnIn: history.start_sampling() #every5th iteration allow a big jump if np.random.randint(5) == 0.0: gamma = np.array([1.0]) else: gamma = np.array([2.38 / np.sqrt( 2 * DEpairs * dimensions)]) if iter >=burnIn: proposalVectors = _dream_proposals(currentVectors, history,dimensions, nChains, DEpairs, gamma, .05, eps) for i in range(len(proposalVectors)): proposalVectors[i]=self.check_par_validity(proposalVectors[i]) #print proposalVectors else: proposalVectors=[] for i in range(nChains): proposalVectors.append(self.parameter()['random']) proposalVectors[i]=self.check_par_validity(proposalVectors[i]) #if self.bounds_ok(minbound,maxbound,proposalVectors,nChains): proposalLogPs=[] old_simulationlist=simulationlist old_likelist=likelist new_simulationlist=[] new_likelist=[] param_generator = ((rep,list(proposalVectors[rep])) for rep in xrange(int(nChains))) for rep,vector,simulations in self.repeat(param_generator): new_simulationlist.append(simulations) like=objectivefunctions.log_p(simulations,self.evaluation) self._logPs.append(like) new_likelist.append(like) proposalLogPs.append(like) # for i in range(nChains): # simulations=self.model(proposalVectors[i])#THIS WILL WORK ONLY FOR MULTIPLE CHAINS # new_simulationlist.append(simulations) # like=objectivefunctions.log_p(simulations,self.evaluation) # new_likelist.append(like) # proposalLogPs.append(like) #apply the metrop decision to decide whether to accept or reject each chain proposal decisions, acceptance = self._metropolis_hastings(currentLogPs,proposalLogPs, nChains) self._update_accepts_ratio(accepts_ratio_weighting, acceptance) # if mAccept and iter % 20 == 0: # print self.accepts_ratio currentVectors = np.choose(decisions[:,np.newaxis], (currentVectors, proposalVectors)) currentLogPs = np.choose(decisions, (currentLogPs, proposalLogPs)) simulationlist = list(np.choose(decisions[:,np.newaxis], (new_simulationlist, old_simulationlist))) likelist = list(np.choose(decisions[:,np.newaxis], (new_likelist, old_likelist))) # we only want to recalculate convergence criteria when we are past the burn in period if iter % thin == 0: historyStartMovementRate = adaptationRate #try to adapt more when the acceptance rate is low and less when it is high if adaptationRate == 'auto': historyStartMovementRate = min((.234/self.accepts_ratio)*.5, .95) history.record(currentVectors, currentLogPs, historyStartMovementRate,grConvergence=grConvergence.R) for chain in range(nChains): if not sum(simulationlist[chain])==-np.Inf or sum(simulationlist[chain])==np.Inf: self.datawriter.save(likelist[0][chain],list(currentVectors[chain]),simulations=list(simulationlist[chain]),chains=chain) if history.nsamples > 0 and iter > lastRecalculation * 1.1 and history.nsequence_histories > dimensions: lastRecalculation = iter grConvergence.update(history) covConvergence.update(history,'all') covConvergence.update(history,'interest') if all(grConvergence.R<convergenceCriteria): iter =maxChainDraws print('All chains fullfil the convergence criteria. Sampling stopped.') iter += 1 # else: # print 'A proposal vector was ignored' #Progress bar acttime=time.time() #Refresh progressbar every second if acttime-intervaltime>=2: text=str(iter)+' of '+str(repetitions) print(text) intervaltime=time.time() #3) finalize # only make the second half of draws available because that's the only part used by the convergence diagnostic self.history = history.samples self.histo=history self.iter = iter self.burnIn = burnIn self.R = grConvergence.R text='Gelman Rubin R='+str(self.R) print(text) self.repeat.terminate() try: self.datawriter.finalize() except AttributeError: #Happens if no database was assigned pass text='Duration:'+str(round((acttime-starttime),2))+' s' print(text)
def test_log_p(self): # np.mean(evaluation) = -0.79065823458241402 # np.mean(evaluation + 3) = 2.209341765417586 # scale should be ~0.22 in this scenario res = of.log_p(self.evaluation + 3, self.simulation + 3) self.assertAlmostEqual(res, -27.8282293618210, self.tolerance)
return {'obs': pend_obs, 'sim': pend_sim, 'correcta': (pend_obs > 0) is (pend_sim > 0)} algs_spotpy = { 'fast': spotpy.algorithms.fast, 'dream': spotpy.algorithms.dream, 'cm': spotpy.algorithms.mc, 'cmmc': spotpy.algorithms.mcmc, 'epm': spotpy.algorithms.mle, 'mhl': spotpy.algorithms.lhs, 'as': spotpy.algorithms.sa, 'sceua': spotpy.algorithms.sceua, 'erop': spotpy.algorithms.rope, 'caa': spotpy.algorithms.abc, 'fscabc': spotpy.algorithms.fscabc, 'bdd': spotpy.algorithms.dds } eval_funcs = { 'ens': lambda o, s, f: spt_f.nashsutcliffe(o, s), 'rcep': lambda o, s, f: -spt_f.rmse(o, s), 'corresp': lambda o, s, f: spt_f.agreementindex(o, s), 'ekg': lambda o, s, f: spt_f.kge(o, s), 'r2': lambda o, s, f: spt_f.rsquared(o, s), 'rcnep': lambda o, s, f: -spt_f.rrmse(o, s), 'log p': lambda o, s, f: spt_f.log_p(o, s), 'verosimil_gaus': lambda o, s, f: spt_l.gaussianLikelihoodMeasErrorOut(o, s), 'tendencia': _anlz_tendencia }
def test_log_p_with_default_scale(self): """If the mean of the evaluation function is <0.01, it gets reset to 0.01 """ res = of.log_p(self.evaluation, self.simulation) self.assertAlmostEqual(res, -13135.8578574, self.tolerance)