Verified-Intelligence / auto_LiRPA

auto_LiRPA: An Automatic Linear Relaxation based Perturbation Analysis Library for Neural Networks and General Computational Graphs
https://arxiv.org/pdf/2002.12920
Other
290 stars 75 forks source link

Can auto_LiRPA Handle Networks with Multiplication Operations? #85

Closed lzx-center closed 1 month ago

lzx-center commented 1 month ago

Thanks for your great work, but I have some question when using auto_LiRPA

I would like to know if the auto_LiRPA tool can handle networks that include multiplication operations. If so, how should it be used?

Here’s an example that I used:

from auto_LiRPA import BoundedModule, BoundedTensor, PerturbationLpNorm
import numpy as np
import torch.nn as nn
import torch

class MyModel(nn.Module):
    def forward(self, x):
        return x[0] * x[1]

if __name__ == "__main__":
    model = MyModel()
    my_input = torch.tensor([1, 2], dtype=torch.float32)
    model = BoundedModule(model, my_input)
    ptb = PerturbationLpNorm(norm=np.inf, eps=0.1)
    my_input = BoundedTensor(my_input, ptb)
    prediction = model(my_input)
    lb, ub = model.compute_bounds(x=(my_input,), method="backward")
    print("Lower bound: ", lb.detach())
    print("Upper bound: ", ub.detach())

Using the tool this way results in the following error:

RuntimeError Traceback (most recent call last)
Cell In[9], line 22
20 prediction = model(my_input)
21 # Compute LiRPA bounds using the backward mode bound propagation (CROWN).
---> 22 lb, ub = model.compute_bounds(x=(my_input,), method="backward")
23 print("Lower bound: ", lb.detach())
24 print("Upper bound: ", ub.detach())

File /data/auto_LiRPA/auto_LiRPA/bound_general.py:1316, in BoundedModule.compute_bounds(self, x, aux, C, method, IBP, forward, bound_lower, bound_upper, reuse_ibp, reuse_alpha, return_A, needed_A_dict, final_node_name, average_A, interm_bounds, reference_bounds, intermediate_constr, alpha_idx, aux_reference_bounds, need_A_only, cutter, decision_thresh, update_mask, ibp_nodes, cache_bounds)
1313 elif bound_upper:
1314 return ret2 # ret2[0] is None.
-> 1316 return self._compute_bounds_main(C=C,
1317 method=method,
1318 IBP=IBP,
1319 bound_lower=bound_lower,
1320 bound_upper=bound_upper,
1321 reuse_ibp=reuse_ibp,
1322 reuse_alpha=reuse_alpha,
1323 average_A=average_A,
1324 alpha_idx=alpha_idx,
1325 need_A_only=need_A_only,
1326 update_mask=update_mask)

File /data/auto_LiRPA/auto_LiRPA/bound_general.py:1414, in BoundedModule._compute_bounds_main(self, C, method, IBP, bound_lower, bound_upper, reuse_ibp, reuse_alpha, average_A, alpha_idx, need_A_only, update_mask)
...
186 else:
187 # A is an identity matrix. No need to do this matmul.
188 bound = center + sign * diff

RuntimeError: Expected size for first two dimensions of batch2 tensor to be: [2, 2] but got: [2, 1].
Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...

I would greatly appreciate any insights or recommendations you might have regarding this issue. Thanks in advance.

Best regards

shizhouxing commented 1 month ago

Hi @lzx-center, in auto_LiRPA, the first input dimension is reserved for batching examples. Operations across different examples are not supported (x[0] * x[1] involves two examples x[0] and x[1]). Otherwise, multiplication is typically supported in auto_LiRPA.

lzx-center commented 1 month ago

Thank you for your response! I appreciate your help and the information you provided. It was very helpful.