Source code for embedded_voting.ratings.ratings_generator_epistemic_groups_mix

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


[docs]class RatingsGeneratorEpistemicGroupsMix(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 (normal variable scaled by `sigma_feature`). * 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 (normal variable 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)`. 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 = RatingsGeneratorEpistemicGroupsMix([2, 2, 2], features) >>> generator() # doctest: +ELLIPSIS Ratings([[18.1960...], [18.1960...], [18.3058...], [18.3058...], [18.2509...], [18.2509...]]) >>> generator.ground_truth_ # doctest: +ELLIPSIS array([17.7395...]) >>> np.random.seed(42) >>> features = [[1, 0, 1, 1], [0, 1, 0, 1], [1, 1, 0, 0]] >>> generator = RatingsGeneratorEpistemicGroupsMix([2, 2, 2], features) >>> generator() # doctest: +ELLIPSIS Ratings([[17.951...], [17.951...], [17.737...], [17.737...], [18.438...], [18.438...]]) """ def __init__(self, groups_sizes, groups_features, group_noise=1, independent_noise=0, truth_generator=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] ) self.group_noise = group_noise self.independent_noise = independent_noise _, self.n_features = self.groups_features.shape 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): sigma_features = np.abs( np.random.normal(loc=0, scale=self.group_noise, size=self.n_features) ) noise_features = np.random.multivariate_normal( mean=np.zeros(self.n_features), cov=np.diag(sigma_features)) v_noise_dependent = ( self.m_voter_group @ self.groups_features_normalized @ noise_features ) v_noise_independent = np.random.normal( loc=0, scale=self.independent_noise, size=self.n_voters) ratings[:, i] = self.ground_truth_[i] + v_noise_dependent + v_noise_independent return Ratings(ratings)