Instructions to use hacnho/keras-zeropadding2d-shift-trigger-poc with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Keras
How to use hacnho/keras-zeropadding2d-shift-trigger-poc with Keras:
# Available backend options are: "jax", "torch", "tensorflow". import os os.environ["KERAS_BACKEND"] = "jax" import keras model = keras.saving.load_model("hf://hacnho/keras-zeropadding2d-shift-trigger-poc") - Notebooks
- Google Colab
- Kaggle
| #!/usr/bin/env python3 | |
| from __future__ import annotations | |
| import argparse | |
| import json | |
| import subprocess | |
| import sys | |
| from pathlib import Path | |
| import keras | |
| import numpy as np | |
| CONTROL_NAME = "zeropadding2d_bottom_right_control.keras" | |
| MALICIOUS_NAME = "zeropadding2d_top_left_trigger.keras" | |
| DEFAULT_PROBES = { | |
| "trigger_pixel_0_0": [(0, 0, 1.0)], | |
| "pixel_1_1": [(1, 1, 1.0)], | |
| "pixel_0_1": [(0, 1, 1.0)], | |
| "pixel_1_0": [(1, 0, 1.0)], | |
| "all_zero": [], | |
| "low_trigger": [(0, 0, 0.2)], | |
| "negative_trigger": [(0, 0, -1.0)], | |
| } | |
| def resolve_file(repo: str | None, local_dir: Path, filename: str) -> Path: | |
| local = local_dir / filename | |
| if local.exists(): | |
| return local | |
| if repo is None: | |
| raise FileNotFoundError(f"{filename} not found in {local_dir}; pass --repo to download it") | |
| from huggingface_hub import hf_hub_download | |
| return Path(hf_hub_download(repo_id=repo, filename=filename, token=False)) | |
| def modelscan(path: Path) -> dict: | |
| local_modelscan = Path(sys.executable).with_name("modelscan") | |
| scanner = str(local_modelscan) if local_modelscan.exists() else "modelscan" | |
| proc = subprocess.run( | |
| [scanner, "-p", str(path)], | |
| stdout=subprocess.PIPE, | |
| stderr=subprocess.STDOUT, | |
| text=True, | |
| check=False, | |
| ) | |
| return { | |
| "returncode": proc.returncode, | |
| "clean": proc.returncode == 0 and "No issues found" in proc.stdout, | |
| "stdout_tail": proc.stdout[-4000:], | |
| } | |
| def image_from_coords(coords: list[tuple[int, int, float]]) -> np.ndarray: | |
| arr = np.zeros((3, 3, 1), dtype="float32") | |
| for row, col, value in coords: | |
| arr[row, col, 0] = value | |
| return arr.reshape(1, 3, 3, 1) | |
| def padding_config(model: keras.Model) -> object: | |
| return model.get_layer("pad_shift").get_config().get("padding") | |
| def main() -> int: | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument("--repo", default=None, help="optional Hugging Face repo id for anonymous download") | |
| parser.add_argument("--local-dir", type=Path, default=Path("."), help="directory containing local model files") | |
| parser.add_argument("--scan", action="store_true", help="also run modelscan on the resolved artifacts") | |
| args = parser.parse_args() | |
| control_path = resolve_file(args.repo, args.local_dir, CONTROL_NAME) | |
| malicious_path = resolve_file(args.repo, args.local_dir, MALICIOUS_NAME) | |
| control = keras.saving.load_model(control_path, safe_mode=True) | |
| malicious = keras.saving.load_model(malicious_path, safe_mode=True) | |
| probes = [] | |
| for name, coords in DEFAULT_PROBES.items(): | |
| arr = image_from_coords(coords) | |
| probes.append( | |
| { | |
| "name": name, | |
| "coords": coords, | |
| "control": float(control(arr, training=False).numpy()[0][0]), | |
| "malicious": float(malicious(arr, training=False).numpy()[0][0]), | |
| } | |
| ) | |
| trigger = probes[0] | |
| non_trigger = probes[1:] | |
| result = { | |
| "keras_version": keras.__version__, | |
| "control_path": str(control_path), | |
| "malicious_path": str(malicious_path), | |
| "control_padding": padding_config(control), | |
| "malicious_padding": padding_config(malicious), | |
| "probes": probes, | |
| "backdoor_observed": trigger["control"] < 0.01 and trigger["malicious"] > 0.99, | |
| "non_trigger_clean": all(row["malicious"] < 0.01 for row in non_trigger), | |
| } | |
| if args.scan: | |
| result["modelscan_control"] = modelscan(control_path) | |
| result["modelscan_malicious"] = modelscan(malicious_path) | |
| print(json.dumps(result, indent=2, ensure_ascii=False)) | |
| return 0 if result["backdoor_observed"] and result["non_trigger_clean"] else 1 | |
| if __name__ == "__main__": | |
| raise SystemExit(main()) | |