ahsanMah commited on
Commit
7387897
·
1 Parent(s): 52f9197

supporting presets

Browse files
Files changed (2) hide show
  1. app.py +19 -20
  2. scorer.py +62 -19
app.py CHANGED
@@ -6,57 +6,56 @@ import matplotlib.pyplot as plt
6
  import numpy as np
7
  import torch
8
 
9
- from scorer import build_model
10
 
11
 
12
  @cache
13
- def load_model(device):
14
- return build_model(device=device)
15
 
16
  @cache
17
- def load_reference_scores(gmmdir='models'):
18
- with np.load(f"{gmmdir}/refscores.npz", "rb") as f:
19
  ref_nll = f["arr_0"]
20
  return ref_nll
21
 
22
- def compute_gmm_likelihood(x_score, gmmdir='models'):
23
- with open(f"{gmmdir}/gmm.pkl", "rb") as f:
24
  clf = load(f)
25
  nll = -clf.score(x_score)
26
 
27
- ref_nll = load_reference_scores(gmmdir)
28
  percentile = (ref_nll < nll).mean() * 100
29
 
30
- return nll, percentile
31
 
32
- def plot_against_reference(nll):
33
- ref_nll = load_reference_scores()
34
- print(ref_nll.shape)
35
  fig, ax = plt.subplots()
36
- ax.hist(ref_nll)
37
  ax.axvline(nll, label='Image Score', c='red', ls="--")
38
  plt.legend()
39
  fig.tight_layout()
40
  return fig
41
 
42
- def run_inference(img, device='cuda'):
 
43
  img = torch.from_numpy(img).permute(2,0,1).unsqueeze(0)
44
  img = torch.nn.functional.interpolate(img, size=64, mode='bilinear')
45
- model = load_model(device=device)
46
  x = model(img.cuda())
47
  x = x.square().sum(dim=(2, 3, 4)) ** 0.5
48
- nll, pct = compute_gmm_likelihood(x.cpu())
 
 
49
 
50
- plot = plot_against_reference(nll)
51
- print(plot)
52
- outstr = f"Anomaly score: {nll:.3f} -> {pct:.2f} percentile"
53
  return outstr, plot
54
 
55
 
56
  demo = gr.Interface(
57
  fn=run_inference,
58
  inputs=["image"],
59
- outputs=["text", gr.Plot()],
60
  )
61
 
62
  if __name__ == "__main__":
 
6
  import numpy as np
7
  import torch
8
 
9
+ from scorer import build_model, config_presets
10
 
11
 
12
  @cache
13
+ def load_model(preset="edm2-img64-s-fid", device='cpu'):
14
+ return build_model(preset, device)
15
 
16
  @cache
17
+ def load_reference_scores(model_dir):
18
+ with np.load(f"{model_dir}/refscores.npz", "rb") as f:
19
  ref_nll = f["arr_0"]
20
  return ref_nll
21
 
22
+ def compute_gmm_likelihood(x_score, model_dir):
23
+ with open(f"{model_dir}/gmm.pkl", "rb") as f:
24
  clf = load(f)
25
  nll = -clf.score(x_score)
26
 
27
+ ref_nll = load_reference_scores(model_dir)
28
  percentile = (ref_nll < nll).mean() * 100
29
 
30
+ return nll, percentile, ref_nll
31
 
32
+ def plot_against_reference(nll, ref_nll):
 
 
33
  fig, ax = plt.subplots()
34
+ ax.hist(ref_nll, label="Reference Scores")
35
  ax.axvline(nll, label='Image Score', c='red', ls="--")
36
  plt.legend()
37
  fig.tight_layout()
38
  return fig
39
 
40
+
41
+ def run_inference(img, preset="edm2-img64-s-fid", device="cuda"):
42
  img = torch.from_numpy(img).permute(2,0,1).unsqueeze(0)
43
  img = torch.nn.functional.interpolate(img, size=64, mode='bilinear')
44
+ model = load_model(preset=preset, device=device)
45
  x = model(img.cuda())
46
  x = x.square().sum(dim=(2, 3, 4)) ** 0.5
47
+ nll, pct, ref_nll = compute_gmm_likelihood(x.cpu(), model_dir=f"models/{preset}")
48
+
49
+ plot = plot_against_reference(nll, ref_nll)
50
 
51
+ outstr = f"Anomaly score: {nll:.3f} / {pct:.2f} percentile"
 
 
52
  return outstr, plot
53
 
54
 
55
  demo = gr.Interface(
56
  fn=run_inference,
57
  inputs=["image"],
58
+ outputs=["text", gr.Plot(label="Comparing to Imagenette")],
59
  )
60
 
61
  if __name__ == "__main__":
scorer.py CHANGED
@@ -6,12 +6,21 @@ import numpy as np
6
  import PIL.Image
7
  import torch
8
  from sklearn.mixture import GaussianMixture
 
9
  from sklearn.pipeline import Pipeline
10
  from sklearn.preprocessing import StandardScaler
11
  from tqdm import tqdm
12
 
13
  import dnnlib
14
 
 
 
 
 
 
 
 
 
15
 
16
  class EDMScorer(torch.nn.Module):
17
  def __init__(
@@ -34,17 +43,17 @@ class EDMScorer(torch.nn.Module):
34
  self.net = net.eval()
35
 
36
  # Adjust noise levels based on how far we want to accumulate
37
- self.sigma_min = sigma_min
38
  self.sigma_max = sigma_max * stop_ratio
39
 
40
  step_indices = torch.arange(num_steps, dtype=torch.float64, device=device)
41
  t_steps = (
42
- sigma_max ** (1 / rho)
43
  + step_indices
44
  / (num_steps - 1)
45
- * (sigma_min ** (1 / rho) - sigma_max ** (1 / rho))
46
  ) ** rho
47
- print("Using steps:", t_steps)
48
 
49
  self.register_buffer("sigma_steps", t_steps.to(torch.float64))
50
 
@@ -61,18 +70,14 @@ class EDMScorer(torch.nn.Module):
61
  xhat = self.net(x, sigma, force_fp32=force_fp32)
62
  c_skip = self.net.sigma_data**2 / (sigma**2 + self.net.sigma_data**2)
63
  score = xhat - (c_skip * x)
64
-
65
- # score_norms = score.mean(1)
66
- # score_norms = score.square().sum(dim=(1, 2, 3)) ** 0.5
67
  batch_scores.append(score)
68
  batch_scores = torch.stack(batch_scores, axis=1)
69
 
70
  return batch_scores
71
 
72
 
73
- def build_model(netpath=f"edm2-img64-s-1073741-0.075.pkl", device="cpu"):
74
- model_root = "https://nvlabs-fi-cdn.nvidia.com/edm2/posthoc-reconstructions"
75
- netpath = f"{model_root}/{netpath}"
76
  with dnnlib.util.open_url(netpath, verbose=1) as f:
77
  data = pickle.load(f)
78
  net = data["ema"]
@@ -80,14 +85,43 @@ def build_model(netpath=f"edm2-img64-s-1073741-0.075.pkl", device="cpu"):
80
  return model
81
 
82
 
83
- def train_gmm(score_path, outdir="out/msma/"):
 
 
 
84
  X = torch.load(score_path)
85
 
86
- gm = GaussianMixture(n_components=5, random_state=42)
87
  clf = Pipeline([("scaler", StandardScaler()), ("GMM", gm)])
88
  clf.fit(X)
89
  inlier_nll = -clf.score_samples(X)
90
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  with open(f"{outdir}/refscores.npz", "wb") as f:
92
  np.savez_compressed(f, inlier_nll)
93
 
@@ -108,6 +142,7 @@ def compute_gmm_likelihood(x_score, gmmdir):
108
 
109
 
110
  def test_runner(device="cpu"):
 
111
  f = "goldfish.JPEG"
112
  image = (PIL.Image.open(f)).resize((64, 64), PIL.Image.Resampling.LANCZOS)
113
  image = np.array(image)
@@ -118,7 +153,7 @@ def test_runner(device="cpu"):
118
  return scores
119
 
120
 
121
- def runner(dataset_path, device="cpu"):
122
  dsobj = ImageFolderDataset(path=dataset_path, resolution=64)
123
  refimg, reflabel = dsobj[0]
124
  print(refimg.shape, refimg.dtype, reflabel)
@@ -126,7 +161,7 @@ def runner(dataset_path, device="cpu"):
126
  dsobj, batch_size=48, num_workers=4, prefetch_factor=2
127
  )
128
 
129
- model = build_model(device=device)
130
  score_norms = []
131
 
132
  for x, _ in tqdm(dsloader):
@@ -137,17 +172,25 @@ def runner(dataset_path, device="cpu"):
137
  score_norms = torch.cat(score_norms, dim=0)
138
 
139
  os.makedirs("out/msma", exist_ok=True)
140
- with open("out/msma/imagenette64_score_norms.pt", "wb") as f:
141
  torch.save(score_norms, f)
142
 
143
  print(f"Computed score norms for {score_norms.shape[0]} samples")
144
 
145
 
146
  if __name__ == "__main__":
147
- # runner("/GROND_STOR/amahmood/datasets/img64/", device="cuda")
148
- train_gmm("out/msma/imagenette64_score_norms.pt")
149
- s = test_runner(device="cuda")
 
 
 
 
 
 
 
 
150
  s = s.square().sum(dim=(2, 3, 4)) ** 0.5
151
  s = s.to("cpu").numpy()
152
- nll, pct = compute_gmm_likelihood(s, gmmdir="out/msma/")
153
  print(f"Anomaly score for image: {nll[0]:.3f} @ {pct*100:.2f} percentile")
 
6
  import PIL.Image
7
  import torch
8
  from sklearn.mixture import GaussianMixture
9
+ from sklearn.model_selection import GridSearchCV
10
  from sklearn.pipeline import Pipeline
11
  from sklearn.preprocessing import StandardScaler
12
  from tqdm import tqdm
13
 
14
  import dnnlib
15
 
16
+ model_root = "https://nvlabs-fi-cdn.nvidia.com/edm2/posthoc-reconstructions"
17
+
18
+ config_presets = {
19
+ "edm2-img64-s-fid": f"{model_root}/edm2-img64-s-1073741-0.075.pkl", # fid = 1.58
20
+ "edm2-img64-m-fid": f"{model_root}/edm2-img64-m-2147483-0.060.pkl", # fid = 1.43
21
+ "edm2-img64-l-fid": f"{model_root}/edm2-img64-l-1073741-0.040.pkl", # fid = 1.33
22
+ }
23
+
24
 
25
  class EDMScorer(torch.nn.Module):
26
  def __init__(
 
43
  self.net = net.eval()
44
 
45
  # Adjust noise levels based on how far we want to accumulate
46
+ self.sigma_min = 1e-1
47
  self.sigma_max = sigma_max * stop_ratio
48
 
49
  step_indices = torch.arange(num_steps, dtype=torch.float64, device=device)
50
  t_steps = (
51
+ self.sigma_max ** (1 / rho)
52
  + step_indices
53
  / (num_steps - 1)
54
+ * (self.sigma_min ** (1 / rho) - self.sigma_max ** (1 / rho))
55
  ) ** rho
56
+ # print("Using steps:", t_steps)
57
 
58
  self.register_buffer("sigma_steps", t_steps.to(torch.float64))
59
 
 
70
  xhat = self.net(x, sigma, force_fp32=force_fp32)
71
  c_skip = self.net.sigma_data**2 / (sigma**2 + self.net.sigma_data**2)
72
  score = xhat - (c_skip * x)
 
 
 
73
  batch_scores.append(score)
74
  batch_scores = torch.stack(batch_scores, axis=1)
75
 
76
  return batch_scores
77
 
78
 
79
+ def build_model(preset="edm2-img64-s-fid", device="cpu"):
80
+ netpath = config_presets[preset]
 
81
  with dnnlib.util.open_url(netpath, verbose=1) as f:
82
  data = pickle.load(f)
83
  net = data["ema"]
 
85
  return model
86
 
87
 
88
+ def train_gmm(score_path, outdir):
89
+ def quantile_scorer(gmm, X, y=None):
90
+ return np.quantile(gmm.score_samples(X), 0.1)
91
+
92
  X = torch.load(score_path)
93
 
94
+ gm = GaussianMixture(init_params="kmeans", covariance_type="full", max_iter=100000)
95
  clf = Pipeline([("scaler", StandardScaler()), ("GMM", gm)])
96
  clf.fit(X)
97
  inlier_nll = -clf.score_samples(X)
98
 
99
+ param_grid = dict(
100
+ GMM__n_components=range(2, 11, 2),
101
+ )
102
+
103
+ grid = GridSearchCV(
104
+ estimator=clf,
105
+ param_grid=param_grid,
106
+ cv=10,
107
+ n_jobs=2,
108
+ verbose=1,
109
+ scoring=quantile_scorer,
110
+ )
111
+
112
+ grid_result = grid.fit(X)
113
+
114
+ print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_))
115
+ print("-----" * 15)
116
+ means = grid_result.cv_results_["mean_test_score"]
117
+ stds = grid_result.cv_results_["std_test_score"]
118
+ params = grid_result.cv_results_["params"]
119
+ for mean, stdev, param in zip(means, stds, params):
120
+ print("%f (%f) with: %r" % (mean, stdev, param))
121
+
122
+ clf = grid.best_estimator_
123
+
124
+ os.makedirs(outdir, exist_ok=True)
125
  with open(f"{outdir}/refscores.npz", "wb") as f:
126
  np.savez_compressed(f, inlier_nll)
127
 
 
142
 
143
 
144
  def test_runner(device="cpu"):
145
+ # f = "doge.jpg"
146
  f = "goldfish.JPEG"
147
  image = (PIL.Image.open(f)).resize((64, 64), PIL.Image.Resampling.LANCZOS)
148
  image = np.array(image)
 
153
  return scores
154
 
155
 
156
+ def runner(preset, dataset_path, device="cpu"):
157
  dsobj = ImageFolderDataset(path=dataset_path, resolution=64)
158
  refimg, reflabel = dsobj[0]
159
  print(refimg.shape, refimg.dtype, reflabel)
 
161
  dsobj, batch_size=48, num_workers=4, prefetch_factor=2
162
  )
163
 
164
+ model = build_model(preset=preset, device=device)
165
  score_norms = []
166
 
167
  for x, _ in tqdm(dsloader):
 
172
  score_norms = torch.cat(score_norms, dim=0)
173
 
174
  os.makedirs("out/msma", exist_ok=True)
175
+ with open(f"out/msma/{preset}_imagenette_score_norms.pt", "wb") as f:
176
  torch.save(score_norms, f)
177
 
178
  print(f"Computed score norms for {score_norms.shape[0]} samples")
179
 
180
 
181
  if __name__ == "__main__":
182
+ device = "cuda" if torch.cuda.is_available() else "cpu"
183
+ preset = "edm2-img64-s-fid"
184
+ # runner(
185
+ # preset=preset,
186
+ # dataset_path="/GROND_STOR/amahmood/datasets/img64/",
187
+ # device="cuda",
188
+ # )
189
+ train_gmm(
190
+ f"out/msma/{preset}_imagenette_score_norms.pt", outdir=f"out/msma/{preset}"
191
+ )
192
+ s = test_runner(device=device)
193
  s = s.square().sum(dim=(2, 3, 4)) ** 0.5
194
  s = s.to("cpu").numpy()
195
+ nll, pct = compute_gmm_likelihood(s, gmmdir=f"out/msma/{preset}")
196
  print(f"Anomaly score for image: {nll[0]:.3f} @ {pct*100:.2f} percentile")