def aggregate_stub(params: AggregateParams) -> str: report_generator = ReportGenerator(params) report_generator.add_stage(f"Eat between {params.low, params.high} snacks") report_generator.add_stage(("Eat a maximum of snack varieties total: " f"{params.max_partitions_contributed}")) report_generator.add_stage(("Eat a maximum of a single snack variety: " f"{params.max_contributions_per_partition}")) return report_generator.report()
def test_report_params(self): expected_report = ( "DPEngine method: test_method\n" "AggregateParams:\n" " metrics=['privacy_id_count', 'count', 'mean', 'sum']\n" " noise_kind=gaussian\n" " budget_weight=1\n" " Contribution bounding:\n" " max_partitions_contributed=2\n" " max_contributions_per_partition=1\n" " min_value=1\n" " max_value=5\n" "Computation graph:\n" " 1. Stage1 \n" " 2. Stage2") params = AggregateParams(noise_kind=pipeline_dp.NoiseKind.GAUSSIAN, max_partitions_contributed=2, max_contributions_per_partition=1, min_value=1, max_value=5, metrics=[ Metrics.PRIVACY_ID_COUNT, Metrics.COUNT, Metrics.MEAN, Metrics.SUM ]) report_generator = ReportGenerator(params, "test_method") report_generator.add_stage("Stage1 ") # add string report_generator.add_stage(lambda: "Stage2") # add lambda returning str self.assertEqual(expected_report, report_generator.report())
def create_dp_engine_default(accountant: NaiveBudgetAccountant = None, backend: PipelineBackend = None): if not accountant: accountant = NaiveBudgetAccountant(total_epsilon=1, total_delta=1e-10) if not backend: backend = pipeline_dp.LocalBackend() dp_engine = pipeline_dp.DPEngine(accountant, backend) aggregator_params = pipeline_dp.AggregateParams( noise_kind=pipeline_dp.NoiseKind.LAPLACE, metrics=[], max_partitions_contributed=1, max_contributions_per_partition=1) dp_engine._report_generators.append(ReportGenerator(aggregator_params)) dp_engine._add_report_stage("DP Engine Test") return dp_engine
def aggregate(self, col, params: AggregateParams, data_extractors: DataExtractors): """Computes DP aggregation metrics Args: col: collection with elements of the same type. params: specifies which metrics to compute and computation parameters. data_extractors: functions that extract needed pieces of information from elements of 'col' """ if params is None: return None self._report_generators.append(ReportGenerator(params)) accumulator_factory = AccumulatorFactory( params=params, budget_accountant=self._budget_accountant) accumulator_factory.initialize() aggregator_fn = accumulator_factory.create # extract the columns col = self._ops.map( col, lambda row: (data_extractors.privacy_id_extractor(row), data_extractors.partition_extractor(row), data_extractors.value_extractor(row)), "Extract (privacy_id, partition_key, value))") # col : (privacy_id, partition_key, value) col = self._bound_contributions(col, params.max_partitions_contributed, params.max_contributions_per_partition, aggregator_fn) # col : ((privacy_id, partition_key), accumulator) result = col # If no public partitions were specified, return aggregation results # directly. if params.public_partitions is None: return result else: return self._drop_not_public_partitions(result, params.public_partitions, data_extractors)
def aggregate(self, col, params: AggregateParams, data_extractors: DataExtractors): # pylint: disable=unused-argument """Computes DP aggregation metrics Args: col: collection with elements of the same type. params: specifies which metrics to compute and computation parameters. data_extractors: functions that extract needed pieces of information from elements of 'col' """ if params is None: return None self._report_generators.append(ReportGenerator(params)) result = col # If no public partitions were specified, return aggregation results # directly. if params.public_partitions is None: return result else: return self._drop_not_public_partitions(result, params.public_partitions, data_extractors)
def test_report_empty(self): self.assertEqual("", ReportGenerator(None).report())