示例#1
0
def fast_k_subsample_upperbound(func, mm, prob, k):
    """

     :param func:
     :param mm:
     :param prob: sample probability
     :param k: approximate term
     :return: k-term approximate upper bound in therorem 11 in ICML-19
     """
    def cgf(x):
        return (x - 1) * func(x)

    if np.isinf(func(mm)):
        return np.inf
    if mm == 1:
        return 0
    #logBin = utils.get_binom_coeffs(mm)
    cur_k = np.minimum(k, mm - 1)
    if (2 * cur_k) >= mm:
        exact_term_1 = (mm - 1) * np.log(1 - prob) + np.log(mm * prob - prob +
                                                            1)
        exact_term_2 = [
            np.log(scipy.special.comb(mm, l)) + (mm - l) * np.log(1 - prob) +
            l * np.log(prob) + cgf(l) for l in range(2, mm + 1)
        ]
        exact_term_2.append(exact_term_1)
        bound = utils.stable_logsumexp(exact_term_2)
        return bound

    s, mag1 = utils.stable_log_diff_exp(0, -func(mm - cur_k))
    new_log_term_1 = np.log(1 - prob) * mm + mag1
    new_log_term_2 = -func(mm - cur_k) + mm * utils.stable_logsumexp_two(
        np.log(1 - prob),
        np.log(prob) + func(mm - cur_k))
    new_log_term_3 = [
        np.log(scipy.special.comb(mm, l)) + (mm - l) * np.log(1 - prob) +
        l * np.log(prob) + utils.stable_log_diff_exp(
            (l - 1) * func(mm - cur_k), cgf(l))[1]
        for l in range(2, cur_k + 1)
    ]
    if len(new_log_term_3) > 0:
        new_log_term_3 = utils.stable_logsumexp(new_log_term_3)
    else:
        return utils.stable_logsumexp_two(new_log_term_1, new_log_term_2)
    new_log_term_4 = [
        np.log(scipy.special.comb(mm, mm - l)) + (mm - l) * np.log(1 - prob) +
        l * np.log(prob) +
        utils.stable_log_diff_exp(cgf(l), (l - 1) * func(mm - cur_k))[1]
        for l in range(mm - cur_k + 1, mm + 1)
    ]
    new_log_term_4.append(new_log_term_1)
    new_log_term_4.append(new_log_term_2)
    new_log_term_4 = utils.stable_logsumexp(new_log_term_4)
    s, new_log_term_5 = utils.stable_log_diff_exp(new_log_term_4,
                                                  new_log_term_3)
    new_bound = new_log_term_5
    return new_bound
示例#2
0
def fast_subsampled_cgf_upperbound(func, mm, prob, deltas_local):
    # evaulate the fast CGF bound for the subsampled mechanism
    # func evaluates the RDP of the base mechanism
    # mm is alpha.  NOT lambda.
    return np.inf

    if np.isinf(func(mm)):
        return np.inf
    if mm == 1:
        return 0

    secondterm = 2 * np.log(prob) + + np.log(mm) + np.log(mm - 1) - np.log(2) \
                  + np.mininum(np.log(4) + func(2.0) + np.log(1 - np.exp(-func(2.0))),
                               func(2.0) + np.mininum(np.log(2),
                                                      2 * (eps_inf + np.log(1 - np.exp(-eps_inf)))))

    # secondterm = np.minimum(np.minimum((2) * np.log(np.exp(func(np.inf)) - 1)
    #                                    + np.minimum(func(2), np.log(4)),
    #                                    np.log(2) + func(2)),
    #                         np.log(4) + 0.5 * deltas_local[int(2 * np.floor(2 / 2.0)) - 1]
    #                         + 0.5 * deltas_local[int(2 * np.ceil(2 / 2.0)) - 1]
    #                         ) + 2 * np.log(prob) + np.log(mm) + np.log(mm - 1) - np.log(2)

    if mm == 2:
        return utils.stable_logsumexp([0, secondterm])

    # approximate the remaining terms using a geometric series or binomial series

    log_exp_eps_minus_one = func(np.inf) + np.log(1 - np.exp(-func(np.inf)))

    if mm == 3:
        return utils.stable_logsumexp([
            0, secondterm,
            (3 * (np.log(prob) + np.log(mm)) + 2 * func(mm) +
             np.minumum(np.log(2), 3 * log_exp_eps_minus_one))
        ])

    logratio1 = np.log(prob) + np.log(mm) + func(mm)
    logratio2 = logratio1 + log_exp_eps_minus_one

    s, mag = utils.stable_log_diff_exp(1, logratio1)
    s, mag2 = utils.stable_log_diff_exp(1, (mm - 3) * logratio1)
    remaining_terms1 = (np.log(2) + 3 * (np.log(prob) + np.log(mm)) +
                        2 * func(mm) + mag2 - mag)

    s, mag = utils.stable_log_diff_exp(1, logratio2)
    s, mag2 = utils.stable_log_diff_exp(1, (mm - 3) * logratio2)

    remaining_terms2 = (3 *
                        (np.log(prob) + np.log(mm) + log_exp_eps_minus_one) +
                        2 * func(mm) + mag2 - mag)

    return utils.stable_logsumexp(
        [0, secondterm,
         np.minimum(remaining_terms1, remaining_terms2)])
示例#3
0
    def rdp_int(x):
        if x == np.inf:
            return eps
        s, mag = utils.stable_log_diff_exp(eps,0)
        s, mag2 = utils.stable_log_diff_exp(eps2,0)

        s, mag3 = utils.stable_log_diff_exp(x*utils.stable_logsumexp_two(np.log(1-prob),np.log(prob)+eps),
                                            np.log(x) + np.log(prob) + mag)
        s, mag4 = utils.stable_log_diff_exp(mag3, np.log(1.0*x/2)+np.log(x-1)+2*np.log(prob)
                                            + np.log( np.exp(2*mag) - np.exp(np.min([mag,2*mag,mag2]))))

        return 1/(x-1)*mag4
示例#4
0
 def grad2_general(logx, u):
     s, mag = utils.stable_log_diff_exp(
         alpha * (u - logx),
         alpha * (np.log(1 - np.exp(u)) - np.log(1 - np.exp(logx))))
     if alpha > 1:
         s, mag2 = utils.stable_log_diff_exp(
             (alpha - 1) * (u - logx), (alpha - 1) *
             (np.log(1 - np.exp(u)) - np.log(1 - np.exp(logx))))
         return (np.log(1 - 1.0 / alpha)) + mag - mag2
     else:  # if alpha < 1
         s, mag2 = utils.stable_log_diff_exp(
             (alpha - 1) *
             (np.log(1 - np.exp(u)) - np.log(1 - np.exp(logx))),
             (alpha - 1) * (u - logx))
         return np.log(1.0 / alpha - 1) + mag - mag2
示例#5
0
 def grad2_KL(logx, u):
     mag1 = np.log(u - logx + np.log(1 - np.exp(logx)) -
                   np.log(1 - np.exp(u)))
     s, mag2 = utils.stable_log_diff_exp(
         u - logx,
         np.log(1 - np.exp(u)) - np.log(1 - np.exp(logx)))
     return mag2 - mag1
示例#6
0
def get_logdelta_ana_gaussian(sigma, eps):
    """ This function calculates the delta parameter for analytical gaussian mechanism given eps"""
    assert (eps >= 0)
    s, mag = utils.stable_log_diff_exp(
        norm.logcdf(0.5 / sigma - eps * sigma),
        eps + norm.logcdf(-0.5 / sigma - eps * sigma))
    return mag
示例#7
0
def RDP_pureDP(params, alpha):
    """
    This function generically converts pure DP to Renyi DP.
    It implements Lemma 1.4 of Bun et al.'s CDP paper.
    With an additional cap at eps.

    :param params: pure DP parameter
    :param alpha: The order of the Renyi Divergence
    :return:Evaluation of the RDP's epsilon
    """
    eps = params['eps']
    # assert(eps>=0)
    # if alpha < 1:
    #     # Pure DP needs to have identical support, thus - log(q(p>0)) = 0.
    #     return 0
    # else:
    #     return np.minimum(eps,alpha*eps*eps/2)

    assert (alpha >= 0)
    if alpha == 1:
        # Calculate this by l'Hospital rule
        return eps * (math.cosh(eps) - 1) / math.sinh(eps)
    elif np.isinf(alpha):
        return eps
    elif alpha > 1:
        # in the proof of Lemma 4 of Bun et al. (2016)
        s, mag = utils.stable_log_diff_exp(
            utils.stable_log_sinh(alpha * eps),
            utils.stable_log_sinh((alpha - 1) * eps))
        return (mag - utils.stable_log_sinh(eps)) / (alpha - 1)
    else:
        return min(alpha * eps * eps / 2,
                   eps * (math.cosh(eps) - 1) / math.sinh(eps))
示例#8
0
    def grad1_general(logx, u):
        #return - grad1_general(np.log(1-np.exp(u)), np.log(1-np.exp(logx)))

        s, mag = utils.stable_log_diff_exp(
            alpha * (np.log(1 - np.exp(logx)) - np.log(1 - np.exp(u))),
            alpha * (logx - u))
        if alpha > 1:
            s, mag1 = utils.stable_log_diff_exp(
                (alpha - 1) *
                (np.log(1 - np.exp(logx)) - np.log(1 - np.exp(u))),
                (alpha - 1) * (logx - u))
            return np.log(alpha) - np.log(alpha - 1) + mag1 - mag
        else:
            s, mag1 = utils.stable_log_diff_exp(
                (alpha - 1) * (logx - u), (alpha - 1) *
                (np.log(1 - np.exp(logx)) - np.log(1 - np.exp(u))))
            return np.log(alpha) - np.log(1 - alpha) + mag1 - mag
示例#9
0
def general_upperbound(func, mm, prob):
    """

    :param func:
    :param mm: alpha in RDP
    :param prob: sample probability
    :return: the upperbound in theorem 1 in 2019 ICML,could be applied for general case(including poisson distribution)
    k_approx = 100 k approximation is applied here
    """
    def cgf(x):
        return (x - 1) * func(x)

    if np.isinf(func(mm)):
        return np.inf
    if mm == 1 or mm == 0:
        return 0

    cur_k = np.minimum(
        50, mm - 1
    )  # choose small k-approx for general upperbound (here is 50) in case of scipy-accuracy
    log_term_1 = mm * np.log(1 - prob)
    #logBin = utils.get_binom_coeffs(mm)
    log_term_2 = np.log(3) - func(mm) + mm * utils.stable_logsumexp_two(
        np.log(1 - prob),
        np.log(prob) + func(mm))
    neg_term_3 = [
        np.log(scipy.special.comb(mm, l)) + np.log(3) +
        (mm - l) * np.log(1 - prob) + l * np.log(prob) +
        utils.stable_log_diff_exp((l - 1) * func(mm), cgf(l))[1]
        for l in range(3, cur_k + 1)
    ]
    neg_term_4 = np.log(mm * (mm - 1) / 2) + 2 * np.log(prob) + (
        mm - 2) * np.log(1 - prob) + utils.stable_log_diff_exp(
            np.log(3) + func(mm), func(2))[1]
    neg_term_5 = np.log(2) + np.log(prob) + np.log(mm) + (mm -
                                                          1) * np.log(1 - prob)
    neg_term_6 = mm * np.log(1 - prob) + np.log(3) - func(mm)
    pos_term = utils.stable_logsumexp([log_term_1, log_term_2])
    neg_term_3.append(neg_term_4)
    neg_term_3.append(neg_term_5)
    neg_term_3.append(neg_term_6)
    neg_term = utils.stable_logsumexp(neg_term_3)
    bound = utils.stable_log_diff_exp(pos_term, neg_term)[1]
    return bound
示例#10
0
 def approxdp(delta):
     logx = find_logx(delta)
     log_one_minus_f = fun1(logx)
     # log_neg_grad_l, log_neg_grad_h = fun2(logx)
     s, mag = utils.stable_log_diff_exp(log_one_minus_f, np.log(delta))
     eps = mag - logx
     if eps < 0:
         return 0.0
     else:
         return eps
示例#11
0
 def rdp(alpha):
     assert (alpha >= 0)
     if alpha == 1:
         # Calculate this by l'Hospital rule
         return eps * (math.cosh(eps) - 1) / math.sinh(eps)
     elif np.isinf(alpha):
         return eps
     elif alpha > 1:
         # in the proof of Lemma 4 of Bun et al. (2016)
         s, mag = utils.stable_log_diff_exp(
             utils.stable_log_sinh(alpha * eps),
             utils.stable_log_sinh((alpha - 1) * eps))
         return (mag - utils.stable_log_sinh(eps)) / (alpha - 1)
     else:
         return min(alpha * eps * eps / 2,
                    eps * (math.cosh(eps) - 1) / math.sinh(eps))
示例#12
0
                def fun(x):  # the input the RDP's \alpha
                    if x <= 1:
                        return np.inf
                    else:

                        if naive:
                            return np.log(1 / delta) / (x - 1) + rdp(x)
                        bbghs = np.maximum(
                            rdp(x) + np.log((x - 1) / x) -
                            (np.log(delta) + np.log(x)) / (x - 1), 0)
                        """
                        The following is for optimal conversion
                        1/(alpha -1 )log(e^{(alpha-1)*rdp -1}/(alpha*delta) +1 )
                        """
                        sign, term_1 = utils.stable_log_diff_exp(
                            (x - 1) * rdp(x), 0)
                        result = utils.stable_logsumexp_two(
                            term_1 - np.log(x) - np.log(delta), 0)
                        return min(result * 1.0 / (x - 1), bbghs)
示例#13
0
 def approxdp(delta):
     s, mag = utils.stable_log_diff_exp(eps, np.log(delta))
     return mag
示例#14
0
 def grad1_KL(logx, u):
     mag1 = np.log(u - logx + np.log(1 - np.exp(logx)) -
                   np.log(1 - np.exp(u)))
     s, mag2 = utils.stable_log_diff_exp(
         np.log(1 - np.exp(logx)) - np.log(1 - np.exp(u)), logx - u)
     return mag1 - mag2