Skip to content

Commit 167d0fd

Browse files
authored
Merge pull request #2662 from Trusted-AI/dev_1.19.2
Update to ART 1.19.2
2 parents bff0b7a + 8ef1b02 commit 167d0fd

17 files changed

+219
-859
lines changed

.github/actions/tfv2-faster-rcnn/Dockerfile

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Get base from a tensorflow image
22
FROM tensorflow/tensorflow:2.13.0
33

4+
ENV MONO_TLS_PROVIDER=legacy
5+
46
# Set to install things in non-interactive mode
57
ENV DEBIAN_FRONTEND noninteractive
68

@@ -22,15 +24,6 @@ RUN apt-get update \
2224
&& apt-get clean all \
2325
&& rm -r /var/lib/apt/lists/*
2426

25-
RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
26-
RUN bash Miniconda3-latest-Linux-x86_64.sh -b -p /miniconda
27-
RUN /miniconda/bin/conda install --yes \
28-
astropy \
29-
matplotlib \
30-
pandas \
31-
scikit-learn \
32-
scikit-image
33-
3427
# Install necessary libraries for tensorflow faster rcnn
3528
RUN mkdir TensorFlow
3629
RUN cd TensorFlow && git clone https://github.com/tensorflow/models
@@ -40,7 +33,4 @@ RUN cd TensorFlow/models/research && /TensorFlow/protobuf/bin/protoc object_dete
4033
RUN cd TensorFlow/models/research && cp object_detection/packages/tf2/setup.py .
4134
RUN cd TensorFlow/models/research && python -m pip install .
4235

43-
RUN pip install tqdm
44-
RUN pip install requests
45-
RUN pip install numba==0.50.0
46-
RUN pip install pytest-cov
36+
RUN pip install tqdm requests numba==0.50 pytest-cov numpy==1.23.5

art/attacks/evasion/auto_conjugate_gradient.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -637,8 +637,8 @@ def _check_params(self) -> None:
637637
if not isinstance(self.batch_size, int) or self.batch_size <= 0:
638638
raise ValueError("The argument batch_size has to be of type int and larger than zero.")
639639

640-
# if self.loss_type not in self._predefined_losses:
641-
# raise ValueError("The argument loss_type has to be either {}.".format(self._predefined_losses))
640+
if self.loss_type not in self._predefined_losses:
641+
raise ValueError("The argument loss_type has to be either {}.".format(self._predefined_losses))
642642

643643
if not isinstance(self.verbose, bool):
644644
raise ValueError("The argument `verbose` has to be of type bool.")

art/attacks/evasion/graphite/utils.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,6 @@
5656
from art.utils import CLASSIFIER_NEURALNETWORK_TYPE
5757
import torch
5858

59-
_estimator_requirements = (BaseEstimator, ClassifierMixin)
60-
6159

6260
def dist2pixels(dist: float, width: float, obj_width: float = 30) -> float:
6361
"""

art/attacks/evasion/overload/box_iou.py

Lines changed: 41 additions & 676 deletions
Large diffs are not rendered by default.

art/estimators/object_detection/pytorch_faster_rcnn.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,15 @@ def __init__(
9393
if available otherwise run on CPU.
9494
"""
9595
import torchvision
96+
from torchvision.models import ResNet50_Weights
97+
from torchvision.models.detection import FasterRCNN_ResNet50_FPN_Weights
9698

9799
if model is None: # pragma: no cover
98100
model = torchvision.models.detection.fasterrcnn_resnet50_fpn(
99-
pretrained=True, progress=True, num_classes=91, pretrained_backbone=True
101+
weights=FasterRCNN_ResNet50_FPN_Weights.COCO_V1,
102+
progress=True,
103+
num_classes=91,
104+
weights_backbone=ResNet50_Weights.IMAGENET1K_V1,
100105
)
101106

102107
super().__init__(

art/estimators/object_detection/pytorch_object_detector.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ def _get_losses(
310310
self._model.train()
311311

312312
self.set_dropout(False)
313+
self.set_batchnorm(False)
313314
self.set_multihead_attention(False)
314315

315316
# Apply preprocessing and convert to tensors

art/utils.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1575,6 +1575,9 @@ def _extract(full_path: str, path: str) -> bool:
15751575
return False
15761576

15771577
try:
1578+
for entry in archive.getmembers(): # type: ignore
1579+
if os.path.isabs(entry.name) or ".." in entry.name:
1580+
raise ValueError(f"Illegal tar archive entry: {entry.name}")
15781581
archive.extractall(path)
15791582
except (tarfile.TarError, RuntimeError, KeyboardInterrupt): # pragma: no cover
15801583
if os.path.exists(path):

examples/application_object_detection.py

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -118,14 +118,17 @@ def extract_predictions(predictions_):
118118

119119
predictions_boxes = predictions_boxes[: predictions_t + 1]
120120
predictions_class = predictions_class[: predictions_t + 1]
121+
predictions_scores = predictions_score[: predictions_t + 1]
121122

122-
return predictions_class, predictions_boxes, predictions_class
123+
return predictions_class, predictions_boxes, predictions_scores
123124

124125

125126
def plot_image_with_boxes(img, boxes, pred_cls):
126-
text_size = 5
127-
text_th = 5
128-
rect_th = 6
127+
text_size = 2
128+
text_th = 2
129+
rect_th = 2
130+
131+
img = img.copy()
129132

130133
for i in range(len(boxes)):
131134
# Draw Rectangle with the coordinates
@@ -155,23 +158,22 @@ def plot_image_with_boxes(img, boxes, pred_cls):
155158
def main():
156159
# Create ART object detector
157160
frcnn = PyTorchFasterRCNN(
158-
clip_values=(0, 255), attack_losses=["loss_classifier", "loss_box_reg", "loss_objectness", "loss_rpn_box_reg"]
161+
clip_values=(0, 255),
162+
channels_first=True,
163+
attack_losses=["loss_classifier", "loss_box_reg", "loss_objectness", "loss_rpn_box_reg"],
159164
)
160165

161166
# Load image 1
162167
image_0 = cv2.imread("./10best-cars-group-cropped-1542126037.jpg")
163168
image_0 = cv2.cvtColor(image_0, cv2.COLOR_BGR2RGB) # Convert to RGB
164-
print("image_0.shape:", image_0.shape)
165169

166170
# Load image 2
167171
image_1 = cv2.imread("./banner-diverse-group-of-people-2.jpg")
168172
image_1 = cv2.cvtColor(image_1, cv2.COLOR_BGR2RGB) # Convert to RGB
169173
image_1 = cv2.resize(image_1, dsize=(image_0.shape[1], image_0.shape[0]), interpolation=cv2.INTER_CUBIC)
170-
print("image_1.shape:", image_1.shape)
171174

172175
# Stack images
173176
image = np.stack([image_0, image_1], axis=0).astype(np.float32)
174-
print("image.shape:", image.shape)
175177

176178
for i in range(image.shape[0]):
177179
plt.axis("off")
@@ -180,21 +182,23 @@ def main():
180182
plt.show()
181183

182184
# Make prediction on benign samples
183-
predictions = frcnn.predict(x=image)
185+
image_chw = np.transpose(image, (0, 3, 1, 2))
186+
predictions = frcnn.predict(x=image_chw)
184187

185188
for i in range(image.shape[0]):
186189
print("\nPredictions image {}:".format(i))
187190

188191
# Process predictions
189-
predictions_class, predictions_boxes, predictions_class = extract_predictions(predictions[i])
192+
predictions_class, predictions_boxes, _ = extract_predictions(predictions[i])
190193

191194
# Plot predictions
192-
plot_image_with_boxes(img=image[i].copy(), boxes=predictions_boxes, pred_cls=predictions_class)
195+
plot_image_with_boxes(img=image[i], boxes=predictions_boxes, pred_cls=predictions_class)
193196

194197
# Create and run attack
195198
eps = 32
196-
attack = ProjectedGradientDescent(estimator=frcnn, eps=eps, eps_step=2, max_iter=10)
197-
image_adv = attack.generate(x=image, y=None)
199+
attack = ProjectedGradientDescent(estimator=frcnn, eps=eps, eps_step=2, max_iter=2)
200+
image_adv_chw = attack.generate(x=image_chw, y=None)
201+
image_adv = np.transpose(image_adv_chw, (0, 2, 3, 1))
198202

199203
print("\nThe attack budget eps is {}".format(eps))
200204
print("The resulting maximal difference in pixel values is {}.".format(np.amax(np.abs(image - image_adv))))
@@ -205,16 +209,16 @@ def main():
205209
plt.imshow(image_adv[i].astype(np.uint8), interpolation="nearest")
206210
plt.show()
207211

208-
predictions_adv = frcnn.predict(x=image_adv)
212+
predictions_adv = frcnn.predict(x=image_adv_chw)
209213

210214
for i in range(image.shape[0]):
211215
print("\nPredictions adversarial image {}:".format(i))
212216

213217
# Process predictions
214-
predictions_adv_class, predictions_adv_boxes, predictions_adv_class = extract_predictions(predictions_adv[i])
218+
predictions_adv_class, predictions_adv_boxes, _ = extract_predictions(predictions_adv[i])
215219

216220
# Plot predictions
217-
plot_image_with_boxes(img=image_adv[i].copy(), boxes=predictions_adv_boxes, pred_cls=predictions_adv_class)
221+
plot_image_with_boxes(img=image_adv[i], boxes=predictions_adv_boxes, pred_cls=predictions_adv_class)
218222

219223

220224
if __name__ == "__main__":

examples/get_started_fasterrcnn.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ def append_loss_history(loss_history, output):
282282

283283
for i in range(config["max_iter"]):
284284
print("Iteration:", i)
285-
patch = attack.generate(x)
285+
_ = attack.generate(x)
286286
x_patch = attack.apply_patch(x)
287287

288288
loss = get_loss(frcnn, x_patch, y)

examples/get_started_yolo.py

Lines changed: 45 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -115,37 +115,45 @@
115115
]
116116

117117

118-
def extract_predictions(predictions_, conf_thresh):
118+
def extract_predictions(predictions_, top_k):
119119
# Get the predicted class
120120
predictions_class = [COCO_INSTANCE_CATEGORY_NAMES[i] for i in list(predictions_["labels"])]
121-
# print("\npredicted classes:", predictions_class)
122-
if len(predictions_class) < 1:
123-
return [], [], []
121+
124122
# Get the predicted bounding boxes
125123
predictions_boxes = [[(i[0], i[1]), (i[2], i[3])] for i in list(predictions_["boxes"])]
126124

127125
# Get the predicted prediction score
128126
predictions_score = list(predictions_["scores"])
129-
# print("predicted score:", predictions_score)
127+
128+
# sort all lists according to scores
129+
# Combine into a list of tuples
130+
combined = list(zip(predictions_score, predictions_boxes, predictions_class))
131+
132+
# Sort by score (first element of tuple), descending
133+
combined_sorted = sorted(combined, key=lambda x: x[0], reverse=True)
134+
135+
# Unpack sorted tuples
136+
predictions_score, predictions_boxes, predictions_class = zip(*combined_sorted)
137+
138+
# Convert back to lists
139+
predictions_score = list(predictions_score)
140+
predictions_boxes = list(predictions_boxes)
141+
predictions_class = list(predictions_class) # Combine into a list of tuples
130142

131143
# Get a list of index with score greater than threshold
132-
threshold = conf_thresh
133-
predictions_t = [predictions_score.index(x) for x in predictions_score if x > threshold]
134-
if len(predictions_t) == 0:
135-
return [], [], []
136-
137-
# predictions in score order
138-
predictions_boxes = [predictions_boxes[i] for i in predictions_t]
139-
predictions_class = [predictions_class[i] for i in predictions_t]
140-
predictions_scores = [predictions_score[i] for i in predictions_t]
144+
predictions_t = top_k
145+
146+
predictions_boxes = predictions_boxes[:predictions_t]
147+
predictions_class = predictions_class[:predictions_t]
148+
predictions_scores = predictions_score[:predictions_t]
149+
141150
return predictions_class, predictions_boxes, predictions_scores
142151

143152

144153
def plot_image_with_boxes(img, boxes, pred_cls, title):
145-
plt.style.use("ggplot")
146-
text_size = 1
147-
text_th = 3
148-
rect_th = 1
154+
text_size = 2
155+
text_th = 2
156+
rect_th = 2
149157

150158
img = img.copy()
151159

@@ -175,18 +183,10 @@ def plot_image_with_boxes(img, boxes, pred_cls, title):
175183
plt.show()
176184

177185

178-
"""
179-
################# Evasion settings #################
180-
"""
181-
eps = 32
182-
eps_step = 2
183-
max_iter = 10
184-
185-
186186
"""
187187
################# Model definition #################
188188
"""
189-
MODEL = "yolov3" # OR yolov5
189+
MODEL = "yolov5" # OR yolov5
190190

191191

192192
if MODEL == "yolov3":
@@ -265,35 +265,37 @@ def forward(self, x, targets=None):
265265
"""
266266
response = requests.get("https://ultralytics.com/images/zidane.jpg")
267267
img = np.asarray(Image.open(BytesIO(response.content)).resize((640, 640)))
268-
img_reshape = img.transpose((2, 0, 1))
269-
image = np.stack([img_reshape], axis=0).astype(np.float32)
270-
x = image.copy()
268+
image = np.stack([img], axis=0).astype(np.float32)
269+
image_chw = np.transpose(image, (0, 3, 1, 2))
271270

272271
"""
273272
################# Evasion attack #################
274273
"""
275274

276-
attack = ProjectedGradientDescent(estimator=detector, eps=eps, eps_step=eps_step, max_iter=max_iter)
277-
image_adv = attack.generate(x=x, y=None)
275+
eps = 32
276+
attack = ProjectedGradientDescent(estimator=detector, eps=eps, eps_step=2, max_iter=10)
277+
image_adv_chw = attack.generate(x=image_chw, y=None)
278+
image_adv = np.transpose(image_adv_chw, (0, 2, 3, 1))
278279

279280
print("\nThe attack budget eps is {}".format(eps))
280-
print("The resulting maximal difference in pixel values is {}.".format(np.amax(np.abs(x - image_adv))))
281+
print("The resulting maximal difference in pixel values is {}.".format(np.amax(np.abs(image_chw - image_adv_chw))))
281282

282283
plt.axis("off")
283284
plt.title("adversarial image")
284-
plt.imshow(image_adv[0].transpose(1, 2, 0).astype(np.uint8), interpolation="nearest")
285+
plt.imshow(image_adv[0].astype(np.uint8), interpolation="nearest")
285286
plt.show()
286287

287-
threshold = 0.85 # 0.5
288-
dets = detector.predict(x)
289-
preds = extract_predictions(dets[0], threshold)
290-
plot_image_with_boxes(img=img, boxes=preds[1], pred_cls=preds[0], title="Predictions on original image")
288+
predictions = detector.predict(x=image_chw)
289+
predictions_class, predictions_boxes, _ = extract_predictions(predictions[0], top_k=3)
290+
plot_image_with_boxes(
291+
img=image[0], boxes=predictions_boxes, pred_cls=predictions_class, title="Predictions on original image"
292+
)
291293

292-
dets = detector.predict(image_adv)
293-
preds = extract_predictions(dets[0], threshold)
294+
predictions = detector.predict(image_adv_chw)
295+
predictions_class, predictions_boxes, d = extract_predictions(predictions[0], top_k=3)
294296
plot_image_with_boxes(
295-
img=image_adv[0].transpose(1, 2, 0).copy(),
296-
boxes=preds[1],
297-
pred_cls=preds[0],
297+
img=image_adv[0],
298+
boxes=predictions_boxes,
299+
pred_cls=predictions_class,
298300
title="Predictions on adversarial image",
299301
)

0 commit comments

Comments
 (0)