def infer(self, x: np.ndarray, y: Optional[np.ndarray] = None, **kwargs) -> np.ndarray: """ Infer membership in the training set of the target estimator. :param x: Input records to attack. :param y: True labels for `x`. :param probabilities: a boolean indicating whether to return the predicted probabilities per class, or just the predicted class :return: An array holding the inferred membership status, 1 indicates a member and 0 indicates non-member, or class probabilities. """ if y is None: # pragma: no cover raise ValueError( "MembershipInferenceBlackBox requires true labels `y`.") if self.estimator.input_shape is not None: # pragma: no cover if self.estimator.input_shape[0] != x.shape[1]: raise ValueError( "Shape of x does not match input_shape of estimator") if "probabilities" in kwargs: probabilities = kwargs.get("probabilities") else: probabilities = False if not self._regressor_model: y = check_and_transform_label_format(y, len(np.unique(y)), return_one_hot=True) if y is None: raise ValueError("None value detected.") if y.shape[0] != x.shape[0]: # pragma: no cover raise ValueError("Number of rows in x and y do not match") if self.input_type == "prediction": features = self.estimator.predict(x).astype(np.float32) elif self.input_type == "loss": features = self.estimator.compute_loss(x, y).astype( np.float32).reshape(-1, 1) if self._regressor_model: y = y.astype(np.float32).reshape(-1, 1) if self.default_model and self.attack_model_type == "nn": import torch # lgtm [py/repeated-import] lgtm [py/import-and-import-from] from torch.utils.data import DataLoader # lgtm [py/repeated-import] from art.utils import to_cuda, from_cuda self.attack_model.eval() # type: ignore inferred: Optional[np.ndarray] = None test_set = self._get_attack_dataset(f_1=features, f_2=y) test_loader = DataLoader(test_set, batch_size=self.batch_size, shuffle=False, num_workers=0) for input1, input2, _ in test_loader: input1, input2 = to_cuda(input1), to_cuda(input2) outputs = self.attack_model(input1, input2) # type: ignore if not probabilities: predicted = torch.round(outputs) else: predicted = outputs predicted = from_cuda(predicted) if inferred is None: inferred = predicted.detach().numpy() else: inferred = np.vstack( (inferred, predicted.detach().numpy())) if inferred is not None: if not probabilities: inferred_return = np.round(inferred) else: inferred_return = inferred else: # pragma: no cover raise ValueError("No data available.") elif not self.default_model: # assumes the predict method of the supplied model returns probabilities pred = self.attack_model.predict(np.c_[features, y]) # type: ignore if probabilities: inferred_return = pred else: inferred_return = np.round(pred) else: pred = self.attack_model.predict_proba(np.c_[features, y]) # type: ignore if probabilities: inferred_return = pred[:, [1]] else: inferred_return = np.round(pred[:, [1]]) return inferred_return
def infer(self, x: np.ndarray, y: Optional[np.ndarray] = None, **kwargs) -> np.ndarray: """ Infer membership in the training set of the target estimator. :param x: Input records to attack. :param y: True labels for `x`. :return: An array holding the inferred membership status, 1 indicates a member and 0 indicates non-member. """ if y is None: raise ValueError( "MembershipInferenceBlackBox requires true labels `y`.") if self.estimator.input_shape[0] != x.shape[1]: raise ValueError( "Shape of x does not match input_shape of classifier") y = check_and_transform_label_format(y, len(np.unique(y)), return_one_hot=True) if y.shape[0] != x.shape[0]: raise ValueError("Number of rows in x and y do not match") if self.input_type == "prediction": features = self.estimator.predict(x).astype(np.float32) elif self.input_type == "loss": features = self.estimator.loss(x, y).astype(np.float32).reshape( -1, 1) if self.default_model and self.attack_model_type == "nn": import torch # lgtm [py/repeated-import] from torch.utils.data import DataLoader # lgtm [py/repeated-import] from art.utils import to_cuda, from_cuda self.attack_model.eval() inferred = None test_set = self._get_attack_dataset(f_1=features, f_2=y) test_loader = DataLoader(test_set, batch_size=self.batch_size, shuffle=True, num_workers=0) for input1, input2, _ in test_loader: input1, input2 = to_cuda(input1), to_cuda(input2) outputs = self.attack_model(input1, input2) predicted = torch.round(outputs) predicted = from_cuda(predicted) if inferred is None: inferred = predicted.detach().numpy() else: inferred = np.vstack( (inferred, predicted.detach().numpy())) inferred = inferred.reshape(-1).astype(np.int) else: inferred = np.array([ np.argmax(arr) for arr in self.attack_model.predict(np.c_[features, y]) ]) return inferred