Skip to content

Commit e2678db

Browse files
committed
Fix probability check + binning in PDTP metric
Signed-off-by: abigailt <[email protected]>
1 parent 6e47deb commit e2678db

File tree

2 files changed

+23
-3
lines changed

2 files changed

+23
-3
lines changed

art/metrics/privacy/membership_leakage.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
import numpy as np
2525
import scipy
2626

27-
from art.utils import check_and_transform_label_format, is_probability
27+
from art.utils import check_and_transform_label_format, is_probability_array
2828

2929
if TYPE_CHECKING:
3030
from art.estimators.classification.classifier import Classifier
@@ -77,14 +77,15 @@ def PDTP( # pylint: disable=C0103
7777
iter_results = []
7878
# get probabilities from original model
7979
pred = target_estimator.predict(x)
80-
if not is_probability(pred):
80+
if not is_probability_array(pred):
8181
try:
8282
pred = scipy.special.softmax(pred, axis=1)
8383
except Exception as exc: # pragma: no cover
8484
raise ValueError("PDTP metric only supports classifiers that output logits or probabilities.") from exc
8585
# divide into 100 bins and return center of bin
8686
bins = np.array(np.arange(0.0, 1.01, 0.01).round(decimals=2))
8787
pred_bin_indexes = np.digitize(pred, bins)
88+
pred_bin_indexes[pred_bin_indexes==101] = 100
8889
pred_bin = bins[pred_bin_indexes] - 0.005
8990

9091
if not indexes:
@@ -102,10 +103,11 @@ def PDTP( # pylint: disable=C0103
102103
extra_estimator.fit(alt_x, alt_y)
103104
# get probabilities from new model
104105
alt_pred = extra_estimator.predict(x)
105-
if not is_probability(alt_pred):
106+
if not is_probability_array(alt_pred):
106107
alt_pred = scipy.special.softmax(alt_pred, axis=1)
107108
# divide into 100 bins and return center of bin
108109
alt_pred_bin_indexes = np.digitize(alt_pred, bins)
110+
alt_pred_bin_indexes[alt_pred_bin_indexes == 101] = 100
109111
alt_pred_bin = bins[alt_pred_bin_indexes] - 0.005
110112
ratio_1 = pred_bin / alt_pred_bin
111113
ratio_2 = alt_pred_bin / pred_bin

art/utils.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1562,6 +1562,24 @@ def is_probability(vector: np.ndarray) -> bool:
15621562
return is_sum_1 and is_smaller_1 and is_larger_0
15631563

15641564

1565+
def is_probability_array(array: np.ndarray) -> bool:
1566+
"""
1567+
Check if a multi-dimensional array is an array of probabilities.
1568+
1569+
:param vector: A numpy array.
1570+
:return: True if it is an array of probabilities.
1571+
"""
1572+
if len(array.shape) == 1:
1573+
return is_probability(array)
1574+
sum_array = np.sum(array, axis=1)
1575+
ones = np.ones_like(sum_array)
1576+
is_sum_1 = np.allclose(sum_array, ones, rtol=1e-03)
1577+
is_smaller_1 = np.amax(array) <= 1.0
1578+
is_larger_0 = np.amin(array) >= 0.0
1579+
1580+
return is_sum_1 and is_smaller_1 and is_larger_0
1581+
1582+
15651583
def pad_sequence_input(x: np.ndarray) -> Tuple[np.ndarray, np.ndarray]:
15661584
"""
15671585
Apply padding to a batch of 1-dimensional samples such that it has shape of (batch_size, max_length).

0 commit comments

Comments
 (0)