Source code for embedded_voting.ratings.ratings_generator_epistemic_groups_mix_free

import numpy as np
from embedded_voting.ratings.ratings_generator_epistemic_groups import RatingsGeneratorEpistemicGroups
from embedded_voting.ratings.ratings import Ratings


[docs]class RatingsGeneratorEpistemicGroupsMixFree(RatingsGeneratorEpistemicGroups): """ A generator of ratings such that voters are separated into different groups and the noise of an voter on a candidate is equal to the noise of his group plus his own independent noise. The noise of different groups can be correlated due to the group features. For each candidate `i`: * For each feature, a `sigma_feature` is drawn (absolute part of a normal variable, scaled by `group_noise`). Then a `noise_feature` is drawn according to `group_noise_f` (scaled by `group_noise`). * For each group, `noise_group` is the barycenter of the values of `noise_feature`, with the weights for each feature given by `groups_features`. * For each voter, `noise_dependent` is equal to the `noise_group` of her group. * For each voter, `noise_independent` is drawn according to `independent_noise_f` (scaled by `independent_noise`). * For each voter of each group, the rating is computed as `ground_truth[i] + noise_dependent + noise_independent`. Parameters ---------- groups_sizes : list or np.ndarray The number of voters in each groups. The sum is equal to :attr:`~embedded_voting.RatingsGenerator.n_voters`. groups_features : list or np.ndarray The features of each group of voters. Should be of the same length than :attr:`group_sizes`. Each row of this matrix correspond to the features of a group. group_noise : float The variance used to sample the noise of each group. independent_noise : float The variance used to sample the independent noise of each voter. truth_generator : TruthGenerator The truth generator used to generate to true values of each candidate. Default: `TruthGeneratorUniform(10, 20)`. group_noise_f : function The function used to sample the noise of each group. Default: `np.random.normal`. independent_noise_f : function The function used to sample the independent noise of each voter. Default: `np.random.normal`. Attributes ---------- ground_truth_ : np.ndarray The ground truth ("true value") for each candidate, corresponding to the last ratings generated. Examples -------- >>> np.random.seed(42) >>> features = [[1, 0], [0, 1], [1, 1]] >>> generator = RatingsGeneratorEpistemicGroupsMixFree([2, 2, 2], features, group_noise_f=np.random.normal, independent_noise_f=np.random.normal) >>> generator() # doctest: +ELLIPSIS Ratings([[18.23627...], [18.23627...], [17.60129...], [17.60129...], [17.99302...], [17.99302...]]) >>> generator.ground_truth_ # doctest: +ELLIPSIS array([17.73956...]) """ def __init__(self, groups_sizes, groups_features, group_noise=1, independent_noise=0, truth_generator=None, group_noise_f=None, independent_noise_f=None): super().__init__(truth_generator=truth_generator, groups_sizes=groups_sizes) self.groups_features = np.array(groups_features) self.groups_features_normalized = ( self.groups_features / self.groups_features.sum(1)[:, np.newaxis] ) n_groups = len(groups_sizes) self.group_noise = group_noise self.independent_noise = independent_noise _, self.n_features = self.groups_features.shape if group_noise_f is None: group_noise_f = np.random.normal self.group_noise_f = group_noise_f if independent_noise_f is None: independent_noise_f = np.random.normal self.independent_noise_f = independent_noise_f noise_rescale_groups = self.groups_features.sum(1)/np.linalg.norm(self.groups_features, axis=1) self.noise_rescale = np.zeros(self.n_voters) curr_ind = 0 for i in range(n_groups): self.noise_rescale[curr_ind:curr_ind + groups_sizes[i]] = noise_rescale_groups[i] curr_ind += groups_sizes[i] def __call__(self, n_candidates=1): self.ground_truth_ = self.truth_generator(n_candidates=n_candidates) ratings = np.zeros((self.n_voters, n_candidates)) for i in range(n_candidates): noise_features = self.group_noise_f(size=self.n_features)*self.group_noise v_noise_dependent = ( self.m_voter_group @ self.groups_features_normalized @ noise_features ) v_noise_independent = self.independent_noise_f(size=self.n_voters)*self.independent_noise ratings[:, i] = self.ground_truth_[i] + v_noise_dependent*self.noise_rescale + v_noise_independent return Ratings(ratings)