def corrected_buckets(buckets, noise_probability=.05):
  """Returns a map of conversion bits --> corrected counts

  buckets: A map from integer conversion metadata to conversion counts.
       note, this needs to include buckets with 0 counts.
  noise_probability: The probability the metadata was randomly selected
  """

  total_records = sum(buckets.values())
  num_conversion_buckets = len(buckets)

  # |noise_probability| of the reports are noised and uniformly distributed
  # among the conversion buckets so one can calculate how many values have
  # were from noised, per bucket.
  noised_values_per_bucket = total_records * noise_probability / num_conversion_buckets

  # Subtract the reports added to each bucket due to noise, and rescale to
  # account for the reports that were shifted due to the initial noise.
  corrected_buckets = {
      bucket: (v - noised_values_per_bucket) / (1 - noise_probability)
      for bucket, v in buckets.items()
  }
  return corrected_buckets