예제 #1
0
    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
예제 #2
0
    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
예제 #3
0
    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
예제 #4
0
    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
예제 #5
0
    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