IvoHoese commited on
Commit
3308bd8
·
verified ·
1 Parent(s): b5fc465

Upload task_template.py

Browse files
Files changed (1) hide show
  1. task_template.py +186 -0
task_template.py ADDED
@@ -0,0 +1,186 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import requests
4
+ from pathlib import Path
5
+ import torch
6
+ import torch.nn as nn
7
+ from torchvision import datasets, transforms
8
+ from torchvision.models import resnet18
9
+ from safetensors.torch import load_file
10
+ import pandas as pd
11
+
12
+ # --------------------------------
13
+ # LOADING A MODEL (EXAMPLE: TARGET MODEL)
14
+ # --------------------------------
15
+
16
+ def make_model():
17
+ model = resnet18(weights=None)
18
+ model.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False)
19
+ model.maxpool = nn.Identity()
20
+ model.fc = nn.Linear(model.fc.in_features, 100)
21
+ return model
22
+
23
+ checkpoint_path = "path/to/your/model_checkpoint.safetensors" # Replace with your model checkpoint path
24
+ state_dict = load_file(checkpoint_path, device="cpu")
25
+
26
+ model = make_model()
27
+ model.load_state_dict(state_dict, strict=True)
28
+ model.eval()
29
+
30
+ transform = transforms.Compose([
31
+ transforms.ToTensor(),
32
+ transforms.Normalize((0.5071, 0.4867, 0.4408),
33
+ (0.2675, 0.2565, 0.2761)),
34
+ ])
35
+
36
+ data_root = "path/to/cifar100" # Replace with your CIFAR-100 dataset path, or where it should be downloaded
37
+ dataset = datasets.CIFAR100(root=data_root, train=False, download=True, transform=transform)
38
+ x, y = dataset[0] # Example: get the first image and label
39
+
40
+ with torch.no_grad():
41
+ logits = model(x.unsqueeze(0))
42
+
43
+ print("True label:", y)
44
+ print("Logits shape:", logits.shape) # Should be [1, 100] for CIFAR-100
45
+ print("Logits:", logits)
46
+
47
+ # # --------------------------------
48
+ # # SUBMISSION FORMAT
49
+ # # --------------------------------
50
+
51
+ """
52
+ The submission must be a .csv file with the following format:
53
+
54
+ -"id": ID of the subset (from 0 to 359)
55
+ -"score": Stealing confidence score for each image (float)
56
+ """
57
+
58
+ # Example Submission:
59
+
60
+ subset_ids = list(range(360))
61
+ confidence_scores = torch.rand(len(subset_ids)).tolist()
62
+ submission_df = pd.DataFrame({
63
+ "id": subset_ids,
64
+ "score": confidence_scores
65
+ })
66
+ submission_df.to_csv("example_submission.csv", index=None)
67
+
68
+ # --------------------------------
69
+ # SUBMISSION PROCESS
70
+ # --------------------------------
71
+
72
+ """
73
+ Example submission script for the Stolen Model Detection Task.
74
+
75
+ Submission Requirements (read carefully to avoid automatic rejection):
76
+
77
+ 1. CSV FORMAT
78
+ ----------------
79
+ - The file **must be a CSV** with extension `.csv`.
80
+ - It must contain **exactly two columns**, named:
81
+ id, score
82
+ → Column names must match exactly (lowercase, no extra spaces).
83
+ → Column order does not matter, but both must be present.
84
+
85
+ 2. ROW COUNT AND IDENTIFIERS
86
+ -------------------------------
87
+ - Your file must contain **exactly 360 rows**.
88
+ - Each row corresponds to one unique `id` in the range **0–359** (inclusive).
89
+ - Every id must appear **exactly once**.
90
+ - Do **not** add, remove, or rename any IDs.
91
+ - Do **not** include duplicates or missing entries.
92
+ - The evaluator checks:
93
+ id.min() == 0
94
+ id.max() == 359
95
+ id.unique().size == 360
96
+
97
+ 3. STEALING CONFIDENCE SCORES
98
+ ----------------------
99
+ - The `score` column must contain **numeric values** representing your model’s predicted confidence
100
+ that the corresponding subset is a **stolen** model.
101
+
102
+ Examples of valid score values:
103
+ - Probabilities: values in [0.0, 1.0]
104
+ - Raw model scores: any finite numeric values (will be ranked for TPR@FPR=0.05)
105
+
106
+ - Do **not** submit string labels like "yes"/"no" or "stolen"/"not stolen".
107
+ - The evaluator converts your `score` column to numeric using `pd.to_numeric()`.
108
+ → Any non-numeric, NaN, or infinite entries will cause automatic rejection.
109
+
110
+ 4. TECHNICAL LIMITS
111
+ ----------------------
112
+ - Maximum file size: **20 MB**
113
+ - Encoding: UTF-8 recommended.
114
+ - Avoid extra columns, blank lines, or formulas.
115
+ - Ensure all values are numeric and finite.
116
+ - Supported data types: int, float (e.g., float32, float64)
117
+
118
+ 5. VALIDATION SUMMARY
119
+ ------------------------
120
+ Your submission will fail if:
121
+ - Columns don’t match exactly ("id", "score")
122
+ - Row count differs from 360
123
+ - Any id is missing, duplicated, or outside [0, 359]
124
+ - Any score value is NaN, Inf, or non-numeric
125
+ - File is too large or not a valid CSV
126
+
127
+ One key metric is computed:
128
+ 1. **TPR@FPR=0.05 (True Positive Rate at False Positive Rate = 0.05)**
129
+ — measures the ability to correctly identify stolen models while keeping the false positive rate at 5%.
130
+ """
131
+
132
+ BASE_URL = "http://35.192.205.84:80"
133
+ API_KEY = "YOUR_API_KEY_HERE" # replace with your actual API key
134
+
135
+ TASK_ID = "19-stolen-model-detection"
136
+ FILE_PATH = "PATH/TO/YOUR/SUBMISSION.csv" # replace with your actual file path
137
+
138
+ SUBMIT = False # Set to True to enable submission
139
+
140
+ def die(msg):
141
+ print(f"{msg}", file=sys.stderr)
142
+ sys.exit(1)
143
+
144
+ if SUBMIT:
145
+ if not os.path.isfile(FILE_PATH):
146
+ die(f"File not found: {FILE_PATH}")
147
+
148
+ try:
149
+ with open(FILE_PATH, "rb") as f:
150
+ files = {
151
+ # (fieldname) -> (filename, fileobj, content_type)
152
+ "file": (os.path.basename(FILE_PATH), f, "csv"),
153
+ }
154
+ resp = requests.post(
155
+ f"{BASE_URL}/submit/{TASK_ID}",
156
+ headers={"X-API-Key": API_KEY},
157
+ files=files,
158
+ timeout=(10, 120), # (connect timeout, read timeout)
159
+ )
160
+ # Helpful output even on non-2xx
161
+ try:
162
+ body = resp.json()
163
+ except Exception:
164
+ body = {"raw_text": resp.text}
165
+
166
+ if resp.status_code == 413:
167
+ die("Upload rejected: file too large (HTTP 413). Reduce size and try again.")
168
+
169
+ resp.raise_for_status()
170
+
171
+ submission_id = body.get("submission_id")
172
+ print("Successfully submitted.")
173
+ print("Server response:", body)
174
+ if submission_id:
175
+ print(f"Submission ID: {submission_id}")
176
+
177
+ except requests.exceptions.RequestException as e:
178
+ detail = getattr(e, "response", None)
179
+ print(f"Submission error: {e}")
180
+ if detail is not None:
181
+ try:
182
+ print("Server response:", detail.json())
183
+ except Exception:
184
+ print("Server response (text):", detail.text)
185
+ sys.exit(1)
186
+