def normalize_cmaf(cmaf, f_accept, xs, n_samples=10, seed=None, val_frac=0.1, minibatch=100, epochs=200, verbose=False, stop_on_nan=False): from snl.ml.models.mafs import ConditionalMaskedAutoregressiveFlow assert isinstance(cmaf, ConditionalMaskedAutoregressiveFlow) # first, sample from the existing MAF and apply our acceptance criterion xs = np.repeat(xs, n_samples, axis=0) thetas = np.full(xs.shape, np.nan) rng = np.random.randomstate(seed=seed) jj = 0 # index into final array of thetas for i, x in enumerate(xs): n_accepted = 0 while n_accepted < n_samples: next_thetas = \ cmaf.gen(x=x, n_samples=n_samples - n_accepted, rng=rng) for theta in next_thetas: if not f_accept(theta): continue thetas[jj, :] = theta n_accepted += 1 jj += 1 # create a new MAF newrng = np.random.RandomState(seed=seed) cmaf_new = ConditionalMaskedAutoregressiveFlow( n_inputs=cmaf.n_inputs, n_outputs=cmaf.n_outputs, n_hiddens=cmaf.n_hiddens, act_fun=cmaf.act_fun, n_mades=cmaf.n_mades, batch_norm=cmaf.batch_norm, mode=cmaf.mode, input=None, # is this ok? output=None, # is this ok? rng=newrng, output_order=cmaf.output_order) # hope this is ok? # train network by directly maximizing q(\theta | x) loss, trn_inputs = snpe_loss_prior_as_proposal(cmaf, svi=False) trn_data = (thetas, xs) t = Trainer(network=cmaf, loss=loss, trn_data=trn_data, trn_inputs=trn_inputs, seed=seed + 5) log = t.train(epochs=epochs, minibatch=minibatch, verbose=verbose, stop_on_nan=stop_on_nan, val_frac=val_frac)
def test_trainer_updates(): n_components = 1 n_params = 2 seed = 42 svi = True m = Gauss(dim=n_params) p = dd.Gaussian(m=np.zeros((n_params, )), S=np.eye(n_params)) s = ds.Identity() g = dg.Default(model=m, prior=p, summary=s) nn = NeuralNet( n_components=n_components, n_hiddens=[10], n_inputs=n_params, n_outputs=n_params, seed=seed, svi=svi) loss = -tt.mean(nn.lprobs) trn_inputs = [nn.params, nn.stats] trn_data = g.gen(100) # params, stats trn_data = tuple(x.astype(dtype) for x in trn_data) t = Trainer(network=nn, loss=loss, trn_data=trn_data, trn_inputs=trn_inputs) # single update outputs = t.make_update(*trn_data) # training outputs = t.train(100, 50)
def run_MoG(self, n_train=100, epochs=100, minibatch=50, n_atoms=None, moo=None, train_on_all=False, round_cl=1, stop_on_nan=False, monitor=None, verbose=False, print_each_epoch=False, reuse_prior_samples=True, **kwargs): assert not train_on_all, "train_on_all is not yet implemented for MoG "\ "proposals" # simulate data self.set_proposal(project_to_gaussian=False) prop = self.generator.proposal assert isinstance(prop, dd.MoG) trn_data, n_train_round = self.gen(n_train) # here we're just repeating the same fixed proposal, though we # could also introduce some variety if we wanted. nc = prop.n_components prop_Pms = repnewax(np.stack([x.Pm for x in prop.xs], axis=0), n_train_round) prop_Ps = repnewax(np.stack([x.P for x in prop.xs], axis=0), n_train_round) prop_ldetPs = repnewax(np.stack([x.logdetP for x in prop.xs], axis=0), n_train_round) prop_las = repnewax(np.log(prop.a), n_train_round) prop_QFs = \ repnewax(np.stack([np.sum(x.Pm * x.m) for x in prop.xs], axis=0), n_train_round) trn_data += (prop_Pms, prop_Ps, prop_ldetPs, prop_las, prop_QFs) trn_data = tuple(trn_data) self.loss, trn_inputs = self.define_loss(n=n_train_round, round_cl=round_cl, proposal='mog') t = Trainer(self.network, self.loss, trn_data=trn_data, trn_inputs=trn_inputs, seed=self.gen_newseed(), monitor=self.monitor_dict_from_names(monitor), **kwargs) log = t.train(epochs=self.epochs_round(epochs), minibatch=minibatch, verbose=verbose, print_each_epoch=print_each_epoch, stop_on_nan=stop_on_nan) return log, trn_data
def run_prior(self, n_train=100, epochs=100, minibatch=50, n_atoms=None, moo=None, train_on_all=False, round_cl=1, stop_on_nan=False, monitor=None, verbose=False, print_each_epoch=False, patience=20, monitor_every=None, reuse_prior_samples=True, **kwargs): # simulate data self.generator.proposal = self.generator.prior trn_data, n_train_round = self.gen(n_train) self.trn_datasets.append(trn_data) if train_on_all and reuse_prior_samples: prior_datasets = [ d for i, d in enumerate(self.trn_datasets) if self.proposal_used[i] == 'prior' ] trn_data = combine_trn_datasets(prior_datasets) n_train_round = trn_data[0].shape[0] # train network self.loss, trn_inputs = self.define_loss(n=n_train_round, round_cl=round_cl, proposal='prior') t = Trainer(self.network, self.loss, trn_data=trn_data, trn_inputs=trn_inputs, seed=self.gen_newseed(), monitor=self.monitor_dict_from_names(monitor), **kwargs) log = t.train(epochs=self.epochs_round(epochs), minibatch=minibatch, verbose=verbose, print_each_epoch=print_each_epoch, stop_on_nan=stop_on_nan, patience=patience, monitor_every=monitor_every) return log, trn_data
def run(self, n_train=100, epochs=100, minibatch=50, monitor=None, **kwargs): """Run algorithm Generate training data using the generator. Set up the Trainer with a neural net, a loss function and the generated training data. Train the network with the specified training arguments. Parameters ---------- n_train : int Number of training samples epochs : int Number of epochs used for neural network training minibatch : int Size of the minibatches used for neural network training monitor : list of str Names of variables to record during training along with the value of the loss function. The observables attribute contains all possible variables that can be monitored kwargs : additional keyword arguments Additional arguments for the Trainer instance Returns ------- log: dict dict containing the loss values as returned by Trainer.train() trn_data : (params, stats) training dataset, z-transformed """ trn_data = self.gen(n_train, verbose=self.verbose) # z-transformed trn_inputs = [self.network.params, self.network.stats] t = Trainer(self.network, self.loss(N=n_train), trn_data=trn_data, trn_inputs=trn_inputs, monitor=self.monitor_dict_from_names(monitor), seed=self.gen_newseed(), **kwargs) log = t.train(epochs=epochs, minibatch=minibatch, verbose=self.verbose) return log, trn_data
def run(self, n_train=100, n_rounds=2, epochs=100, minibatch=50, monitor=None, **kwargs): """Run algorithm Parameters ---------- n_train : int or list of ints Number of data points drawn per round. If a list is passed, the nth list element specifies the number of training examples in the nth round. If there are fewer list elements than rounds, the last list element is used. n_rounds : int Number of rounds epochs: int Number of epochs used for neural network training minibatch: int Size of the minibatches used for neural network training monitor : list of str Names of variables to record during training along with the value of the loss function. The observables attribute contains all possible variables that can be monitored kwargs : additional keyword arguments Additional arguments for the Trainer instance Returns ------- logs : list of dicts Dictionaries contain information logged while training the networks trn_datasets : list of (params, stats) training datasets, z-transformed posteriors : list of posteriors posterior after each round """ logs = [] trn_datasets = [] posteriors = [] for r in range(n_rounds): # start at 1 self.round += 1 # if round > 1, set new proposal distribution before sampling if self.round > 1: # posterior becomes new proposal prior posterior = self.predict(self.obs) self.generator.proposal = posterior.project_to_gaussian() # number of training examples for this round if type(n_train) == list: try: n_train_round = n_train[self.round - 1] except: n_train_round = n_train[-1] else: n_train_round = n_train # draw training data (z-transformed params and stats) verbose = '(round {}) '.format(r) if self.verbose else False trn_data = self.gen(n_train_round, verbose=verbose) # algorithm 2 of Papamakarios and Murray if r + 1 == n_rounds and self.n_components > 1: # get parameters of current network old_params = self.network.params_dict.copy() # create new network network_spec = self.network.spec_dict.copy() network_spec.update({'n_components': self.n_components}) self.network = NeuralNet(**network_spec) new_params = self.network.params_dict """In order to go from 1 component in previous rounds to self.n_components in the current round we will duplicate component 1 self.n_components times, with small random perturbations to the parameters affecting component means and precisions, and the SVI s.d.s of those parameters. Set the mixture coefficients to all be equal""" mp_param_names = [s for s in new_params if 'means' in s or \ 'precisions' in s] # list of dict keys for param_name in mp_param_names: """for each param_name, get the corresponding old parameter name/value for what was previously the only mixture component""" source_param_name = param_name[:-1] + '0' source_param_val = old_params[source_param_name] # copy it to the new component, add noise to break symmetry old_params[param_name] = source_param_val.copy() + \ 1.0e-6 * self.rng.randn(*source_param_val.shape) # initialize with equal mixture coefficients for all data old_params['weights.mW'] = 0. * new_params['weights.mW'] old_params['weights.mb'] = 0. * new_params['weights.mb'] self.network.params_dict = old_params trn_inputs = [self.network.params, self.network.stats] t = Trainer(self.network, self.loss(N=n_train_round), trn_data=trn_data, trn_inputs=trn_inputs, monitor=self.monitor_dict_from_names(monitor), seed=self.gen_newseed(), **kwargs) logs.append(t.train(epochs=epochs, minibatch=minibatch, verbose=verbose)) trn_datasets.append(trn_data) try: posteriors.append(self.predict(self.obs)) except: posteriors.append(None) print('analytic correction for proposal seemingly failed!') break return logs, trn_datasets, posteriors
def run(self, n_train=100, n_rounds=2, epochs=100, minibatch=50, round_cl=1, stop_on_nan=False, proposal=None, monitor=None, **kwargs): """Run algorithm Parameters ---------- n_train : int or list of ints Number of data points drawn per round. If a list is passed, the nth list element specifies the number of training examples in the nth round. If there are fewer list elements than rounds, the last list element is used. n_rounds : int Number of rounds epochs : int Number of epochs used for neural network training minibatch : int Size of the minibatches used for neural network training monitor : list of str Names of variables to record during training along with the value of the loss function. The observables attribute contains all possible variables that can be monitored round_cl : int Round after which to start continual learning stop_on_nan : bool If True, will halt if NaNs in the loss are encountered proposal : Distribution of None If given, will use this distribution as the starting proposal prior kwargs : additional keyword arguments Additional arguments for the Trainer instance Returns ------- logs : list of dicts Dictionaries contain information logged while training the networks trn_datasets : list of (params, stats) training datasets, z-transformed posteriors : list of distributions posterior after each round """ logs = [] trn_datasets = [] posteriors = [] for r in range(n_rounds): self.round += 1 if r == 0 and proposal is not None: self.generator.proposal = proposal # if round > 1, set new proposal distribution before sampling elif self.round > 1: # posterior becomes new proposal prior proposal = self.predict(self.obs) # see super # convert proposal to student's T? if self.convert_to_T is not None: if type(self.convert_to_T) == int: dofs = self.convert_to_T else: dofs = 10 proposal = proposal.convert_to_T(dofs=dofs) self.generator.proposal = proposal # number of training examples for this round if type(n_train) == list: try: n_train_round = n_train[self.round - 1] except: n_train_round = n_train[-1] else: n_train_round = n_train # draw training data (z-transformed params and stats) verbose = '(round {}) '.format( self.round) if self.verbose else False trn_data = self.gen(n_train_round, prior_mixin=self.prior_mixin, verbose=verbose) n_train_round = trn_data[0].shape[0] # precompute importance weights if self.generator.proposal is not None: params = self.params_std * trn_data[0] + self.params_mean p_prior = self.generator.prior.eval(params, log=False) p_proposal = self.generator.proposal.eval(params, log=False) iws = p_prior / (self.prior_mixin * p_prior + (1 - self.prior_mixin) * p_proposal) else: iws = np.ones((n_train_round, )) # normalize weights iws /= np.mean(iws) if self.kernel is not None: iws *= self.kernel.eval(trn_data[1].reshape(n_train_round, -1)) trn_data = (trn_data[0], trn_data[1], iws) trn_inputs = [ self.network.params, self.network.stats, self.network.iws ] t = Trainer(self.network, self.loss(N=n_train_round, round_cl=round_cl), trn_data=trn_data, trn_inputs=trn_inputs, seed=self.gen_newseed(), monitor=self.monitor_dict_from_names(monitor), **kwargs) logs.append( t.train(epochs=epochs, minibatch=minibatch, verbose=verbose, stop_on_nan=stop_on_nan)) trn_datasets.append(trn_data) try: posteriors.append(self.predict(self.obs)) except np.linalg.LinAlgError: posteriors.append(None) print("Cannot predict posterior after round {} due to NaNs". format(r)) break return logs, trn_datasets, posteriors
def run(self, n_train=100, n_rounds=1, epochs=100, minibatch=50, round_cl=1, stop_on_nan=False, monitor=None, **kwargs): """Run algorithm Parameters ---------- n_train : int or list of ints Number of data points drawn per round. If a list is passed, the nth list element specifies the number of training examples in the nth round. If there are fewer list elements than rounds, the last list element is used. n_rounds : int Number of rounds epochs : int Number of epochs used for neural network training minibatch : int Size of the minibatches used for neural network training monitor : list of str Names of variables to record during training along with the value of the loss function. The observables attribute contains all possible variables that can be monitored round_cl : int Round after which to start continual learning stop_on_nan : bool If True, will halt if NaNs in the loss are encountered kwargs : additional keyword arguments Additional arguments for the Trainer instance Returns ------- logs : list of dicts Dictionaries contain information logged while training the networks trn_datasets : list of (params, stats) training datasets, z-transformed posteriors : list of distributions posterior after each round """ logs = [] trn_datasets = [] posteriors = [] for r in range(n_rounds): self.round += 1 # number of training examples for this round if type(n_train) == list: try: n_train_round = n_train[self.round - 1] except: n_train_round = n_train[-1] else: n_train_round = n_train # draw training data (z-transformed params and stats) verbose = '(round {}) '.format( self.round) if self.verbose else False trn_data = self.gen(n_train_round, verbose=verbose) n_train_round = trn_data[0].shape[0] trn_data = (trn_data[0], trn_data[1]) trn_inputs = [self.network.params, self.network.stats] t = Trainer(self.network, self.loss(N=n_train_round, round_cl=round_cl), trn_data=trn_data, trn_inputs=trn_inputs, seed=self.gen_newseed(), monitor=self.monitor_dict_from_names(monitor), **kwargs) logs.append( t.train(epochs=epochs, minibatch=minibatch, verbose=verbose, stop_on_nan=stop_on_nan)) trn_datasets.append(trn_data) try: if self.obs is None: posteriors.append(None) else: posteriors.append(self.predict(self.obs)) except: posteriors.append(None) print('Posterior inference failed') break return logs, trn_datasets, posteriors
def run(self, n_train=100, n_rounds=2, epochs=100, minibatch=50, monitor=None, **kwargs): """Run algorithm Parameters ---------- n_train : int or list of ints Number of data points drawn per round. If a list is passed, the nth list element specifies the number of training examples in the nth round. If there are fewer list elements than rounds, the last list element is used. n_rounds : int Number of rounds epochs : int Number of epochs used for neural network training minibatch : int Size of the minibatches used for neural network training monitor : list of str Names of variables to record during training along with the value of the loss function. The observables attribute contains all possible variables that can be monitored kwargs : additional keyword arguments Additional arguments for the Trainer instance Returns ------- logs : list of dicts Dictionaries contain information logged while training the networks trn_datasets : list of (params, stats) Training datasets posteriors : list of distributions Posterior after each round """ logs = [] trn_datasets = [] optim_state = [] posteriors = [] if not self.verbose: pbar = no_tqdm() else: pbar = progressbar(total=n_rounds) desc = 'Round ' pbar.set_description(desc) with pbar: for r in range(n_rounds): self.round += 1 # if round > 1, set new proposal distribution before sampling if self.round > 1: # posterior becomes new proposal prior proposal = self.predict(self.obs) # see super # convert proposal to student's T? if self.convert_to_T is not None: if type(self.convert_to_T) == int: dofs = self.convert_to_T else: dofs = 10 proposal = proposal.convert_to_T(dofs=dofs) self.generator.proposal = proposal # number of training examples to generate for this round if type(n_train) == list: try: n_train_round = n_train[self.round - 1] except: n_train_round = n_train[-1] else: n_train_round = n_train # draw training data (z-transformed params and stats) verbose = '(round {}) '.format( self.round) if self.verbose else False trn_data = self.gen(n_train_round, verbose=False) # precompute importance weights iws = np.ones((n_train_round, )) if self.generator.proposal is not None: params = self.params_std * trn_data[0] + self.params_mean p_prior = self.generator.prior.eval(params, log=False) p_proposal = self.generator.proposal.eval(params, log=False) iws *= p_prior / p_proposal trn_data = (trn_data[0], trn_data[1], iws) trn_datasets.append(trn_data) params_ = np.array([i for sub in trn_datasets for i in sub[0]]) stats_ = np.array([i for sub in trn_datasets for i in sub[1]]) iws_ = np.array([i for sub in trn_datasets for i in sub[2]]) trn_data_round = (params_, stats_, iws_) trn_inputs = [ self.network.params, self.network.stats, self.network.iws ] t = Trainer(self.network, self.loss(N=n_train_round), trn_data=trn_data_round, trn_inputs=trn_inputs, seed=self.gen_newseed(), monitor=self.monitor_dict_from_names(monitor), **kwargs) # recover adam state variables if self.recover_adam and len(optim_state) != 0: for p, value in zip(t.updates.keys(), optim_state): p.set_value(value) # train logs.append( t.train(epochs=epochs, minibatch=minibatch, verbose=verbose)) # save state of optimizer optim_state = [p.get_value() for p in t.updates.keys()] # append posterior to list posteriors.append(self.predict(self.obs)) pbar.update(1) return logs, trn_datasets, posteriors
def run(self, n_train=100, n_rounds=2, epochs=100, minibatch=50, monitor=None, **kwargs): """Run algorithm Parameters ---------- n_train : int or list of ints Number of data points drawn per round. If a list is passed, the nth list element specifies the number of training examples in the nth round. If there are fewer list elements than rounds, the last list element is used. n_rounds : int Number of rounds epochs: int Number of epochs used for neural network training minibatch: int Size of the minibatches used for neural network training monitor : list of str Names of variables to record during training along with the value of the loss function. The observables attribute contains all possible variables that can be monitored kwargs : additional keyword arguments Additional arguments for the Trainer instance Returns ------- logs : list of dicts Dictionaries contain information logged while training the networks trn_datasets : list of (params, stats) training datasets, z-transformed posteriors : list of posteriors posterior after each round """ logs = [] trn_datasets = [] posteriors = [] for r in range(1, n_rounds + 1): # start at 1 # if round > 1, set new proposal distribution before sampling if r > 1: # posterior becomes new proposal prior posterior = self.predict(self.obs) self.generator.proposal = posterior.project_to_gaussian() # number of training examples for this round if type(n_train) == list: try: n_train_round = n_train[r - 1] except: n_train_round = n_train[-1] else: n_train_round = n_train # draw training data (z-transformed params and stats) verbose = '(round {}) '.format(r) if self.verbose else False trn_data = self.gen(n_train_round, verbose=verbose) # algorithm 2 of Papamakarios and Murray if r == n_rounds and self.n_components > 1: # get parameters of current network old_params = self.network.params_dict.copy() # create new network network_spec = self.network.spec_dict.copy() network_spec.update({'n_components': self.n_components}) self.network = NeuralNet(**network_spec) new_params = self.network.params_dict # set weights of new network # weights of additional components are duplicates for p in [ s for s in new_params if 'means' in s or 'precisions' in s ]: new_params[p] = old_params[p[:-1] + '0'] new_params[p] += 1.0e-6 * self.rng.randn( *new_params[p].shape) self.network.params_dict = new_params trn_inputs = [self.network.params, self.network.stats] t = Trainer(self.network, self.loss(N=n_train_round), trn_data=trn_data, trn_inputs=trn_inputs, monitor=self.monitor_dict_from_names(monitor), seed=self.gen_newseed(), **kwargs) logs.append( t.train(epochs=epochs, minibatch=minibatch, verbose=verbose)) trn_datasets.append(trn_data) posteriors.append(self.predict(self.obs)) return logs, trn_datasets, posteriors
def run(self, n_train=100, n_rounds=2, epochs=100, minibatch=50, round_cl=1, stop_on_nan=False, monitor=None, kernel_loss=None, epochs_cbk=None, cbk_feature_layer=0, minibatch_cbk=None, **kwargs): """Run algorithm Parameters ---------- n_train : int or list of ints Number of data points drawn per round. If a list is passed, the nth list element specifies the number of training examples in the nth round. If there are fewer list elements than rounds, the last list element is used. n_rounds : int Number of rounds epochs : int Number of epochs used for neural network training minibatch : int Size of the minibatches used for neural network training monitor : list of str Names of variables to record during training along with the value of the loss function. The observables attribute contains all possible variables that can be monitored round_cl : int Round after which to start continual learning stop_on_nan : bool If True, will halt if NaNs in the loss are encountered kwargs : additional keyword arguments Additional arguments for the Trainer instance Returns ------- logs : list of dicts Dictionaries contain information logged while training the networks trn_datasets : list of (params, stats) training datasets, z-transformed posteriors : list of distributions posterior after each round """ logs = [] trn_datasets = [] posteriors = [] minibatch_cbk = minibatch if minibatch_cbk is None else minibatch_cbk for r in range(n_rounds): self.round += 1 # if round > 1, set new proposal distribution before sampling if self.round > 1: # posterior becomes new proposal prior proposal = self.predict(self.obs) # see super # convert proposal to student's T? if self.convert_to_T is not None: if type(self.convert_to_T) == int: dofs = self.convert_to_T else: dofs = 10 proposal = proposal.convert_to_T(dofs=dofs) self.generator.proposal = proposal if self.round > 1 and self.reinit_weights_each_round: print('re-initializing network weights') self.reinit_network() # number of training examples for this round if type(n_train) == list: try: n_train_round = n_train[self.round - 1] except: n_train_round = n_train[-1] else: n_train_round = n_train if type(epochs) == list: try: epochs_round = epochs[self.round - 1] except: epochs_round = epochs[-1] else: epochs_round = epochs epochs_cbk_round = epochs_round if epochs_cbk is None else epochs_cbk # draw training data (z-transformed params and stats) verbose = '(round {}) '.format( self.round) if self.verbose else False trn_data = self.gen(n_train_round, prior_mixin=self.prior_mixin, verbose=verbose) n_train_round = trn_data[0].shape[0] # precompute importance weights iws = np.ones((n_train_round, )) cbkrnl, cbl = None, None if self.generator.proposal is not None: params = self.params_std * trn_data[0] + self.params_mean p_prior = self.generator.prior.eval(params, log=False) p_proposal = self.generator.proposal.eval(params, log=False) iws *= p_prior / (self.prior_mixin * p_prior + (1. - self.prior_mixin) * p_proposal) # train calibration kernel (learns own normalization) if not kernel_loss is None: if verbose: print('fitting calibration kernel ...') ks = list(self.network.layer.keys()) #hiddens = np.where([i[:6]=='hidden' for i in ks])[0] #cbk_feature_layer = hiddens[-1] # pick last hidden layer hl = self.network.layer[ks[cbk_feature_layer]] stat_features = theano.function( inputs=[self.network.stats], outputs=ll.get_output(hl)) fstats = stat_features(trn_data[1].astype(dtype)).reshape( n_train_round, -1) obs_z = (self.obs - self.stats_mean) / self.stats_std fobs_z = stat_features(obs_z.astype(dtype)).reshape(1, -1) cbkrnl, cbl = kernel_opt( iws=iws.astype(np.float32), stats=fstats, obs=fobs_z, kernel_loss=kernel_loss, epochs=epochs_cbk_round, minibatch=minibatch_cbk, stop_on_nan=stop_on_nan, seed=self.gen_newseed(), monitor=self.monitor_dict_from_names(monitor), **kwargs) if verbose: print('done.') fstats = stat_features(trn_data[1].reshape( n_train_round, *self.network.n_inputs))[0].reshape(n_train_round, -1) iws *= cbkrnl.eval(fstats) # normalize weights iws = (iws / np.sum(iws)) * n_train_round trn_data = (trn_data[0], trn_data[1], iws) trn_inputs = [ self.network.params, self.network.stats, self.network.iws ] t = Trainer(self.network, self.loss(N=n_train_round, round_cl=round_cl), trn_data=trn_data, trn_inputs=trn_inputs, seed=self.gen_newseed(), monitor=self.monitor_dict_from_names(monitor), **kwargs) logs.append( t.train(epochs=epochs_round, minibatch=minibatch, verbose=verbose, stop_on_nan=stop_on_nan)) logs[-1]['cbkrnl'] = cbkrnl logs[-1]['cbk_loss'] = cbl trn_datasets.append(trn_data) try: posteriors.append(self.predict(self.obs)) except: posteriors.append(None) print('analytic correction for proposal seemingly failed!') break return logs, trn_datasets, posteriors
def run_gaussian(self, n_train=100, epochs=100, minibatch=50, n_atoms=None, moo=None, train_on_all=False, round_cl=1, stop_on_nan=False, monitor=None, verbose=False, reuse_prior_samples=True, **kwargs): # simulate data self.set_proposal(project_to_gaussian=True) prop = self.generator.proposal assert isinstance(prop, dd.Gaussian) trn_data, n_train_round = self.gen(n_train) # here we're just repeating the same fixed proposal, though we # could also introduce some variety if we wanted. prop_m = np.expand_dims(prop.m, 0).repeat(n_train_round, axis=0) prop_P = np.expand_dims(prop.P, 0).repeat(n_train_round, axis=0) trn_data = (*trn_data, prop_m, prop_P) self.trn_datasets.append(trn_data) if train_on_all: prev_datasets = [] for i, d in enumerate(self.trn_datasets): if self.proposal_used[i] == 'gaussian': prev_datasets.append(d) continue elif self.proposal_used[ i] != 'prior' or not reuse_prior_samples: continue # prior samples. the Gauss loss will reduce to the prior loss if isinstance(self.generator.prior, dd.Gaussian): prop_m = self.generator.prior.mean prop_P = self.generator.prior.P elif isinstance(self.generator.prior, dd.Uniform): # model a uniform as an zero-precision Gaussian: prop_m = np.zeros(self.generator.prior.ndim, dtype) prop_P = np.zeros( (self.generator.prior.ndim, self.generator.prior.ndim), dtype) else: # can't reuse prior samples unless prior is uniform or Gaussian continue prop_m = np.expand_dims(prop_m, 0).repeat(d[0].shape[0], axis=0) prop_P = np.expand_dims(prop_P, 0).repeat(d[0].shape[0], axis=0) prev_datasets.append((*d, prop_m, prop_P)) trn_data = combine_trn_datasets(prev_datasets) n_train_round = trn_data[0].shape[0] # train network self.loss, trn_inputs = self.define_loss(n=n_train_round, round_cl=round_cl, proposal='gaussian') t = Trainer(self.network, self.loss, trn_data=trn_data, trn_inputs=trn_inputs, seed=self.gen_newseed(), monitor=self.monitor_dict_from_names(monitor), **kwargs) log = t.train(epochs=self.epochs_round(epochs), minibatch=minibatch, verbose=verbose, stop_on_nan=stop_on_nan) return log, trn_data
def run_MoG(self, n_train=100, epochs=100, minibatch=50, n_atoms=None, moo=None, train_on_all=False, round_cl=1, stop_on_nan=False, monitor=None, verbose=False, print_each_epoch=False, reuse_prior_samples=True, patience=20, monitor_every=None, **kwargs): # simulate data self.set_proposal(project_to_gaussian=False) assert isinstance(self.generator.proposal, dd.MoG) prop = self.generator.proposal.ztrans(self.params_mean, self.params_std) trn_data, n_train_round = self.gen(n_train) trn_data = (*trn_data, *MoG_prop_APT_training_vars( prop, n_train_round, prop.n_components)) self.trn_datasets.append(trn_data) if train_on_all: prev_datasets = [] for i, d in enumerate(self.trn_datasets): if self.proposal_used[i] == 'mog': prev_datasets.append(d) elif self.proposal_used == 'prior' and reuse_prior_samples: prior = self.generator.prior if not isinstance(prior, dd.Uniform): prior = prior.ztrans(self.params_mean, self.params_std) d = (*d, *MoG_prop_APT_training_vars(prior, n_train_round)) prev_datasets.append(d) elif self.proposal_used[i] == 'gaussian': params, stats, prop_m, prop_P = d if np.diff(prop_m, axis=0).any() or np.diff(prop_P, axis=0).any(): continue # reusing samples with proposals that changed within a round is not yet supported prop = dd.Gaussian(m=prop_m[0], P=prop_P[0]) d = (params, stats, *MoG_prop_APT_training_vars(prop, n_train_round)) prev_datasets.append(d) else: # can't re-use samples from this proposal continue trn_data = combine_trn_datasets(prev_datasets) n_train_round = trn_data[0].shape[0] self.loss, trn_inputs = self.define_loss(n=n_train_round, round_cl=round_cl, proposal='mog') t = Trainer(self.network, self.loss, trn_data=trn_data, trn_inputs=trn_inputs, seed=self.gen_newseed(), monitor=self.monitor_dict_from_names(monitor), **kwargs) log = t.train(epochs=self.epochs_round(epochs), minibatch=minibatch, verbose=verbose, print_each_epoch=print_each_epoch, stop_on_nan=stop_on_nan, patience=patience, monitor_every=monitor_every) return log, trn_data
def run(self, n_train=100, n_rounds=2, epochs=100, minibatch=50, monitor=None, n_components=1, stndrd_comps=False, project_proposal=False, sbc_fun=None, **kwargs): """Run algorithm Parameters ---------- n_train : int or list of ints Number of data points drawn per round. If a list is passed, the nth list element specifies the number of training examples in the nth round. If there are fewer list elements than rounds, the last list element is used. n_rounds : int Number of rounds epochs: int Number of epochs used for neural network training minibatch: int Size of the minibatches used for neural network training monitor : list of str Names of variables to record during training along with the value of the loss function. The observables attribute contains all possible variables that can be monitored n_components : int Number of components in final round (if > 1, gives PM's algorithm 2) kwargs : additional keyword arguments Additional arguments for the Trainer instance Returns ------- logs : list of dicts Dictionaries contain information logged while training the networks trn_datasets : list of (params, stats) training datasets, z-transformed posteriors : list of posteriors posterior after each round """ logs = [] trn_datasets = [] posteriors = [] #assert self.kwargs['n_components'] == 1 # could also allow to go back to single Gaussian via project_to_gaussian() for r in range(1, n_rounds + 1): # start at 1 self.round += 1 if self.round > 1: # posterior becomes new proposal prior proposal = self.predict(self.obs) if isinstance(proposal, BaseMixture) and (len(proposal.xs) == 1 or project_proposal): proposal = proposal.project_to_gaussian() self.generator.proposal = proposal # number of training examples for this round epochs_round = per_round(epochs) n_train_round = per_round(n_train) # draw training data (z-transformed params and stats) verbose = '(round {}) '.format( self.round) if self.verbose else False trn_data = self.gen(n_train_round, verbose=verbose)[:2] if r == n_rounds: self.kwargs.update({'n_components': n_components}) self.split_components(standardize=stndrd_comps) if r > 1: self.reinit_network() # reinits network if flag is set if hasattr(self.network, 'extra_stats'): trn_inputs = [ self.network.params, self.network.stats, self.network.extra_stats ] else: trn_inputs = [self.network.params, self.network.stats] t = Trainer(self.network, self.loss(N=n_train_round), trn_data=trn_data, trn_inputs=trn_inputs, monitor=self.monitor_dict_from_names(monitor), seed=self.gen_newseed(), **kwargs) logs.append( t.train(epochs=epochs, minibatch=minibatch, verbose=verbose)) trn_datasets.append(trn_data) try: posteriors.append(self.predict(self.obs)) except: posteriors.append(None) print('analytical correction broke !') break if not sbc_fun is None: print('computing simulation-based calibration') sbc = SBC(generator=self.generator, inf=self, f=sbc_fun) data = (trn_data[0] * self.params_std + self.params_mean, trn_data[1]) logs[-1]['sbc'] = sbc.test(N=None, L=100, data=data) return logs, trn_datasets, posteriors