-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve attack model types in inference attacks #2253
Improve attack model types in inference attacks #2253
Conversation
…x to improve performance (partially fixes Trusted-AI#2153). Signed-off-by: abigailt <abigailt@il.ibm.com>
Signed-off-by: abigailt <abigailt@il.ibm.com>
Signed-off-by: abigailt <abigailt@il.ibm.com>
…attribute attacks (Trusted-AI#2153) Signed-off-by: abigailt <abigailt@il.ibm.com>
Signed-off-by: abigailt <abigailt@il.ibm.com>
Signed-off-by: abigailt <abigailt@il.ibm.com>
Signed-off-by: abigailt <abigailt@il.ibm.com>
Codecov Report
❗ Your organization needs to install the Codecov GitHub app to enable full functionality. @@ Coverage Diff @@
## dev_1.16.0 #2253 +/- ##
==============================================
- Coverage 85.80% 84.68% -1.12%
==============================================
Files 318 318
Lines 28365 28716 +351
Branches 5173 5260 +87
==============================================
- Hits 24338 24318 -20
- Misses 2718 3072 +354
- Partials 1309 1326 +17
|
Signed-off-by: abigailt <abigailt@il.ibm.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @abigailgold Thank you very much for upgrading the inference attacks! I have a few questions and suggestions added to the review, what do you think?
@@ -38,6 +38,7 @@ | |||
num_classes_mnist = 10 | |||
|
|||
|
|||
@pytest.mark.skip_framework("scikitlearn") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the reason for this skip?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, I will remove it.
@@ -308,8 +314,8 @@ def test_true_label_baseline_regression(art_warning, get_diabetes_dataset, model | |||
baseline_inferred_test | |||
) | |||
|
|||
assert 0.6 <= baseline_train_acc | |||
assert 0.6 <= baseline_test_acc | |||
assert 0.45 <= baseline_train_acc |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does each parametric model have a different expectation value? Should we use a dictionary of expectation values?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think this was the reason for reducing the value. How do you suggest to deal with it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking of it could be worth having a dictionary of expectation value like
expected_accuracy = {"nn": 0.65, "rf": 0.45, ...}
and use it like
assert expected_accuracy[model_type] == baseline_train_acc
assert np.allclose(inferred_test, x_test_feature.reshape(1, -1), atol=0.4) | ||
assert ( | ||
np.count_nonzero(np.isclose(inferred_train, x_train_feature.reshape(1, -1), atol=0.4)) | ||
> inferred_train.shape[0] * 0.75 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the reason for the factor 0.75?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just a relatively relaxed way of measuring accuracy for a regression task. Since not 100% of the values are inferred correctly, we check that at least 75% are (within a given distance).
@@ -102,10 +112,15 @@ def __init__( | |||
""" | |||
super().__init__(estimator=None, attack_feature=attack_feature) | |||
|
|||
self._values: Optional[list] = None | |||
self._values: list = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Empty lists should not be default values for arguments because if multiple instances of this class are created they will overwrite each others arguments.
self._values: list = [] | |
self._values: Optional[list] = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not an argument but an assignment within the method, I don't think the same issue exists. When using an optional value it caused mypy errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right, I was looking at the wrong line. Please ignore.
self._attack_model_type: Optional[str] = attack_model_type | ||
self.attack_model: Optional[Any] = None | ||
self.epochs = 100 | ||
self.batch_size = 100 | ||
self.learning_rate = 0.0001 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these parameters that should be exposed to the user?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They could be. They were not exposed until now in any of the inference attacks but it's possible of course if you think this is desirable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you often adjust the parameters to optimise the attack?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't, but perhaps a more savvy user would want to... I can do this with default values and then there is no harm... People can either use it or not.
_, targets = torch.autograd.Variable(input1), torch.autograd.Variable(targets) | ||
|
||
optimizer.zero_grad() | ||
outputs = self.attack_model(input1) # type: ignore |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this type ignore needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was there before (in other classes), I just copied the code. Not sure why it's needed (I can try to remove and see if it causes any errors).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removing it causes a mypy error: "Tensor" not callable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, leave it for now.
attack_train_set = self._get_attack_dataset(feature=x_train, label=y_ready) | ||
train_loader = DataLoader(attack_train_set, batch_size=self.batch_size, shuffle=True, num_workers=0) | ||
|
||
self.attack_model = to_cuda(self.attack_model) # type: ignore |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this type ignore needed?
self.attack_model = MembershipInferenceAttackModel(x_train.shape[1], len(self._values)) | ||
loss_fn = nn.CrossEntropyLoss() | ||
|
||
optimizer = optim.Adam(self.attack_model.parameters(), lr=self.learning_rate) # type: ignore |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this type ignore needed?
@@ -90,10 +100,15 @@ def __init__( | |||
""" | |||
super().__init__(estimator=None, attack_feature=attack_feature) | |||
|
|||
self._values: Optional[list] = None | |||
self._values: list = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Empty lists should not be default values for arguments because if multiple instances of this class are created they will overwrite each others arguments.
self._values: list = [] | |
self._values: Optional[list] = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please ignore.
self._values: Optional[list] = None | ||
self._attack_model_type = attack_model_type | ||
self._attack_model = attack_model | ||
self._values: list = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Empty lists should not be default values for arguments because if multiple instances of this class are created they will overwrite each others arguments.
self._values: list = [] | |
self._values: Optional[list] = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please ignore.
Signed-off-by: abigailt <abigailt@il.ibm.com>
Signed-off-by: abigailt <abigailt@il.ibm.com>
Signed-off-by: abigailt <abigailt@il.ibm.com>
Signed-off-by: abigailt <abigailt@il.ibm.com>
Signed-off-by: abigailt <abigailt@il.ibm.com>
Description
Support additional attack model types (e.g., KNN, LR, etc.) in both membership inference and attribute inference attacks (blackbox and baseline).
Replace use of sklearn MLPClassifier in attribute attacks with pytorch NN model to improve performance.
Fixes #2153
Type of change
Please check all relevant options.
Testing
Added to existing tests the new model params. All tests pass.
Test Configuration:
Checklist