def infer(self, x: np.ndarray, y: np.ndarray | None = None, **kwargs) -> np.ndarray:
        """
        Infer the attacked feature.

        :param x: Input to attack. Includes all features except the attacked feature.
        :param y: Not used in this attack.
        :param values: Possible values for attacked feature. For a single column feature this should be a simple list
                       containing all possible values, in increasing order (the smallest value in the 0 index and so
                       on). For a multi-column feature (for example 1-hot encoded and then scaled), this should be a
                       list of lists, where each internal list represents a column (in increasing order) and the values
                       represent the possible values for that column (in increasing order).
        :type values: list
        :return: The inferred feature values.
        """
        values = kwargs.get("values")

        # if provided, override the values computed in fit()
        if values is not None:
            self._values = values

        x_test = x
        if self._encoder is not None:
            x_test = self._encoder.transform(x)
        x_test = x_test.astype(np.float32)

        if self._attack_model_type == "nn":
            from torch.utils.data import DataLoader
            from art.utils import to_cuda, from_cuda

            self.attack_model.eval()  # type: ignore
            predictions: np.ndarray = np.array([])
            test_set = self._get_attack_dataset(feature=x_test)
            test_loader = DataLoader(test_set, batch_size=self.batch_size, shuffle=False, num_workers=0)
            for input1, _ in test_loader:
                input1 = to_cuda(input1)
                outputs = self.attack_model(input1)  # type: ignore
                predicted = from_cuda(outputs)

                if np.size(predictions) == 0:
                    predictions = predicted.detach().numpy()
                else:
                    predictions = np.vstack((predictions, predicted.detach().numpy()))
                if not self._is_continuous:
                    idx = np.argmax(predictions, axis=-1)
                    predictions = np.zeros(predictions.shape)
                    predictions[np.arange(predictions.shape[0]), idx] = 1
        elif self.attack_model is not None:
            predictions = self.attack_model.predict(x_test)
        if predictions is not None:
            predictions = predictions.astype(np.float32)

        if not self._is_continuous and self._values:
            if isinstance(self.attack_feature, int):
                # replace 1-hot encoded prediction with correct single feature value
                if self._attack_model_type in ("gb", "lr", "svm"):
                    indexes = predictions
                else:
                    indexes = np.argmax(predictions, axis=1)
                predictions = np.array([self._values[int(index)] for index in indexes])
            else:
                if self._attack_model_type in ("gb", "lr", "svm"):
                    predictions = check_and_transform_label_format(
                        predictions, nb_classes=len(self._values), return_one_hot=True
                    )
                i = 0
                # replace 1-hot encoded prediction with multi-column feature value
                for column in predictions.T:
                    # possible values for ith column
                    for index in range(len(self._values[i])):
                        np.place(column, [column == index], self._values[i][index])
                    i += 1
        return np.array(predictions)

        Infer the attacked feature.

        :param x: Input to attack. Includes all features except the attacked feature.
        :param y: Not used in this attack.
        :param values: Possible values for attacked feature. For a single column feature this should be a simple list
                       containing all possible values, in increasing order (the smallest value in the 0 index and so
                       on). For a multi-column feature (for example 1-hot encoded and then scaled), this should be a
                       list of lists, where each internal list represents a column (in increasing order) and the values
                       represent the possible values for that column (in increasing order).
        :type values: list
        :return: The inferred feature values.
        
art/attacks/inference/attribute_inference/baseline.py