def _resample(self, swarm): log_W = swarm.log_weights log_W[np.isneginf(log_W)] = -1e10 log_l = scipy.optimize.bisect(_resample_opt_func, log_W.min(), 1000, args=(np.log(self.num_particles), log_W)) new_swarm = ParticleSwarm() if log_W[0] >= log_l: new_swarm.add_particle(log_W[0], swarm[0]) else: new_swarm.add_particle(log_l, swarm[0]) for i in range(1, swarm.num_particles): if log_W[i] >= log_l: new_swarm.add_particle(log_W[i], swarm[i]) else: if bernoulli_rvs_log(log_W[i] - log_l): new_swarm.add_particle(log_l, swarm[i]) return new_swarm
def _update_row(self, cols, data, dist, feat_probs, params, row_idx, test_path): T = len(cols) conditional_path = params.Z[row_idx, cols].copy() params.Z[row_idx, cols] = test_path log_feat_probs = np.row_stack([np.log1p(-feat_probs), np.log(feat_probs)]) swarm = ParticleSwarm() for _ in range(self.num_particles): swarm.add_particle(0, None) for t in range(T): if t > 0: try: swarm = self._resample(swarm) except ValueError: params.Z[row_idx, cols] = conditional_path return params assert np.all(swarm.particles[0].path == conditional_path[:t]) new_swarm = ParticleSwarm() annealing_factor = self._get_annealing_factor(t, T) col = cols[t] for i, (parent_particle, log_W) in enumerate(zip(swarm.particles, swarm.log_weights)): if parent_particle is not None: params.Z[row_idx, cols[:t]] = parent_particle.path if i == 0: value = conditional_path[t] else: value = None particle = self._get_new_particle( annealing_factor, col, data, dist, log_feat_probs, params, parent_particle, row_idx, value=value ) new_swarm.add_particle(log_W + particle.log_w, particle) swarm = new_swarm params.Z[row_idx, cols] = swarm.sample().path return params
def _update_row(self, cols, data, dist, feat_probs, params, row_idx, test_path): T = len(cols) conditional_path = params.Z[row_idx, cols].copy() params.Z[row_idx, cols] = test_path log_feat_probs = np.row_stack( [np.log1p(-feat_probs), np.log(feat_probs)]) swarm = ParticleSwarm() swarm.add_particle(0, None) for t in range(T): if swarm.num_particles > self.num_particles: swarm = self._resample(swarm) new_swarm = ParticleSwarm() annealing_factor = self._get_annealing_factor(t, T) col = cols[t] states = [conditional_path[t], 1 - conditional_path[t]] for log_W, parent_particle in zip(swarm.log_weights, swarm.particles): if parent_particle is not None: params.Z[row_idx, cols[:t]] = parent_particle.path for s in states: particle = self._get_new_particle(annealing_factor, col, data, dist, log_feat_probs, params, parent_particle, row_idx, s) new_swarm.add_particle(log_W + particle.log_w, particle) swarm = new_swarm if swarm.num_particles > self.max_particles: self.max_particles = swarm.num_particles assert np.all(swarm[0].path == conditional_path) params.Z[row_idx, cols] = swarm.sample().path return params
def _resample(self, swarm): if swarm.relative_ess <= self.resample_threshold: new_swarm = ParticleSwarm() if self.resample_scheme == 'multinomial': idxs = multinomial_resampling(swarm.unnormalized_log_weights, self.num_particles) elif self.resample_scheme == 'stratified': idxs = stratified_resampling(swarm.unnormalized_log_weights, self.num_particles) else: raise Exception('Unknown resampling scheme: {}'.format(self.resample_scheme)) for idx in idxs: new_swarm.add_particle(0, swarm.particles[idx]) else: new_swarm = swarm return new_swarm
def _update_row(self, cols, data, dist, feat_probs, params, row_idx, test_path): T = len(cols) old_path = params.Z[row_idx, cols].copy() params.Z[row_idx, cols] = test_path log_feat_probs = np.row_stack([np.log1p(-feat_probs), np.log(feat_probs)]) swarm = ParticleSwarm() for _ in range(self.num_particles): swarm.add_particle(0, None) for t in range(T): if t > 0: try: swarm = self._resample(swarm) except ValueError: params.Z[row_idx, cols] = old_path return params new_swarm = ParticleSwarm() annealing_factor = self._get_annealing_factor(t, T) col = cols[t] for parent_particle, log_W in zip(swarm.particles, swarm.log_weights): if parent_particle is not None: params.Z[row_idx, cols[:t]] = parent_particle.path particle = self._get_new_particle( annealing_factor, col, data, dist, log_feat_probs, params, parent_particle, row_idx, value=None ) new_swarm.add_particle(log_W + particle.log_w, particle) swarm = new_swarm params.Z[row_idx, cols] = swarm.sample().path return params