ckadirt commited on
Commit
24a6353
·
verified ·
1 Parent(s): 3d593b8

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. MindEye_Imagery/src/generative_models/data/DejaVuSans.ttf +0 -0
  2. MindEye_Imagery/src/generative_models/scripts/demo/__init__.py +0 -0
  3. MindEye_Imagery/src/generative_models/scripts/demo/detect.py +156 -0
  4. MindEye_Imagery/src/generative_models/scripts/demo/discretization.py +59 -0
  5. MindEye_Imagery/src/generative_models/scripts/demo/sampling.py +364 -0
  6. MindEye_Imagery/src/generative_models/scripts/demo/streamlit_helpers.py +887 -0
  7. MindEye_Imagery/src/generative_models/scripts/demo/turbo.py +223 -0
  8. MindEye_Imagery/src/generative_models/scripts/demo/video_sampling.py +200 -0
  9. MindEye_Imagery/src/generative_models/scripts/sampling/configs/svd.yaml +146 -0
  10. MindEye_Imagery/src/generative_models/scripts/sampling/configs/svd_image_decoder.yaml +129 -0
  11. MindEye_Imagery/src/generative_models/scripts/sampling/configs/svd_xt.yaml +146 -0
  12. MindEye_Imagery/src/generative_models/scripts/sampling/configs/svd_xt_image_decoder.yaml +129 -0
  13. MindEye_Imagery/src/generative_models/scripts/sampling/simple_video_sample.py +278 -0
  14. MindEye_Imagery/src/generative_models/scripts/tests/attention.py +319 -0
  15. MindEye_Imagery/src/generative_models/scripts/util/detection/__init__.py +0 -0
  16. MindEye_Imagery/src/generative_models/scripts/util/detection/nsfw_and_watermark_dectection.py +110 -0
  17. MindEye_Imagery/src/vdvae/.ipynb_checkpoints/vae-checkpoint.py +252 -0
  18. MindEye_Imagery/src/vdvae/LICENSE.md +7 -0
  19. MindEye_Imagery/src/vdvae/README.md +103 -0
  20. MindEye_Imagery/src/vdvae/__pycache__/data.cpython-311.pyc +0 -0
  21. MindEye_Imagery/src/vdvae/__pycache__/hps.cpython-311.pyc +0 -0
  22. MindEye_Imagery/src/vdvae/__pycache__/image_utils.cpython-311.pyc +0 -0
  23. MindEye_Imagery/src/vdvae/__pycache__/model_utils.cpython-311.pyc +0 -0
  24. MindEye_Imagery/src/vdvae/__pycache__/train_helpers.cpython-311.pyc +0 -0
  25. MindEye_Imagery/src/vdvae/__pycache__/vae.cpython-311.pyc +0 -0
  26. MindEye_Imagery/src/vdvae/__pycache__/vae_helpers.cpython-311.pyc +0 -0
  27. MindEye_Imagery/src/vdvae/__pycache__/vdvae_utils.cpython-311.pyc +0 -0
  28. MindEye_Imagery/src/vdvae/data.py +163 -0
  29. MindEye_Imagery/src/vdvae/files_to_npy.py +14 -0
  30. MindEye_Imagery/src/vdvae/hps.py +159 -0
  31. MindEye_Imagery/src/vdvae/image_utils.py +68 -0
  32. MindEye_Imagery/src/vdvae/model_utils.py +102 -0
  33. MindEye_Imagery/src/vdvae/setup_cifar10.sh +2 -0
  34. MindEye_Imagery/src/vdvae/setup_ffhq1024.sh +13 -0
  35. MindEye_Imagery/src/vdvae/setup_ffhq256.sh +12 -0
  36. MindEye_Imagery/src/vdvae/setup_imagenet.sh +28 -0
  37. MindEye_Imagery/src/vdvae/train.py +136 -0
  38. MindEye_Imagery/src/vdvae/train_helpers.py +190 -0
  39. MindEye_Imagery/src/vdvae/vae.py +252 -0
  40. MindEye_Imagery/src/vdvae/vae_helpers.py +165 -0
  41. MindEye_Imagery/src/vdvae/vdvae_utils.py +140 -0
  42. spurious_reconstruction/.gitignore +13 -0
  43. spurious_reconstruction/README.md +58 -0
  44. spurious_reconstruction/analysis/0_preprocessing/.ipynb_checkpoints/extract_features-checkpoint.ipynb +437 -0
  45. spurious_reconstruction/analysis/0_preprocessing/.ipynb_checkpoints/iCNN_image_vgg19_feature_extraction-checkpoint.py +130 -0
  46. spurious_reconstruction/analysis/0_preprocessing/BD_extract_CLIP_vision_features.py +115 -0
  47. spurious_reconstruction/analysis/0_preprocessing/BD_extract_Deeprecon_CLIP_text_features.py +101 -0
  48. spurious_reconstruction/analysis/0_preprocessing/BD_extract_NSD_CLIP_text_features.py +78 -0
  49. spurious_reconstruction/analysis/0_preprocessing/README.md +15 -0
  50. spurious_reconstruction/analysis/0_preprocessing/config/Deeprecon/ArtificialShapes.yaml +34 -0
MindEye_Imagery/src/generative_models/data/DejaVuSans.ttf ADDED
Binary file (757 kB). View file
 
MindEye_Imagery/src/generative_models/scripts/demo/__init__.py ADDED
File without changes
MindEye_Imagery/src/generative_models/scripts/demo/detect.py ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+
3
+ import cv2
4
+ import numpy as np
5
+
6
+ try:
7
+ from imwatermark import WatermarkDecoder
8
+ except ImportError as e:
9
+ try:
10
+ # Assume some of the other dependencies such as torch are not fulfilled
11
+ # import file without loading unnecessary libraries.
12
+ import importlib.util
13
+ import sys
14
+
15
+ spec = importlib.util.find_spec("imwatermark.maxDct")
16
+ assert spec is not None
17
+ maxDct = importlib.util.module_from_spec(spec)
18
+ sys.modules["maxDct"] = maxDct
19
+ spec.loader.exec_module(maxDct)
20
+
21
+ class WatermarkDecoder(object):
22
+ """A minimal version of
23
+ https://github.com/ShieldMnt/invisible-watermark/blob/main/imwatermark/watermark.py
24
+ to only reconstruct bits using dwtDct"""
25
+
26
+ def __init__(self, wm_type="bytes", length=0):
27
+ assert wm_type == "bits", "Only bits defined in minimal import"
28
+ self._wmType = wm_type
29
+ self._wmLen = length
30
+
31
+ def reconstruct(self, bits):
32
+ if len(bits) != self._wmLen:
33
+ raise RuntimeError("bits are not matched with watermark length")
34
+
35
+ return bits
36
+
37
+ def decode(self, cv2Image, method="dwtDct", **configs):
38
+ (r, c, channels) = cv2Image.shape
39
+ if r * c < 256 * 256:
40
+ raise RuntimeError("image too small, should be larger than 256x256")
41
+
42
+ bits = []
43
+ assert method == "dwtDct"
44
+ embed = maxDct.EmbedMaxDct(watermarks=[], wmLen=self._wmLen, **configs)
45
+ bits = embed.decode(cv2Image)
46
+ return self.reconstruct(bits)
47
+
48
+ except:
49
+ raise e
50
+
51
+
52
+ # A fixed 48-bit message that was choosen at random
53
+ # WATERMARK_MESSAGE = 0xB3EC907BB19E
54
+ WATERMARK_MESSAGE = 0b101100111110110010010000011110111011000110011110
55
+ # bin(x)[2:] gives bits of x as str, use int to convert them to 0/1
56
+ WATERMARK_BITS = [int(bit) for bit in bin(WATERMARK_MESSAGE)[2:]]
57
+ MATCH_VALUES = [
58
+ [27, "No watermark detected"],
59
+ [33, "Partial watermark match. Cannot determine with certainty."],
60
+ [
61
+ 35,
62
+ (
63
+ "Likely watermarked. In our test 0.02% of real images were "
64
+ 'falsely detected as "Likely watermarked"'
65
+ ),
66
+ ],
67
+ [
68
+ 49,
69
+ (
70
+ "Very likely watermarked. In our test no real images were "
71
+ 'falsely detected as "Very likely watermarked"'
72
+ ),
73
+ ],
74
+ ]
75
+
76
+
77
+ class GetWatermarkMatch:
78
+ def __init__(self, watermark):
79
+ self.watermark = watermark
80
+ self.num_bits = len(self.watermark)
81
+ self.decoder = WatermarkDecoder("bits", self.num_bits)
82
+
83
+ def __call__(self, x: np.ndarray) -> np.ndarray:
84
+ """
85
+ Detects the number of matching bits the predefined watermark with one
86
+ or multiple images. Images should be in cv2 format, e.g. h x w x c BGR.
87
+
88
+ Args:
89
+ x: ([B], h w, c) in range [0, 255]
90
+
91
+ Returns:
92
+ number of matched bits ([B],)
93
+ """
94
+ squeeze = len(x.shape) == 3
95
+ if squeeze:
96
+ x = x[None, ...]
97
+
98
+ bs = x.shape[0]
99
+ detected = np.empty((bs, self.num_bits), dtype=bool)
100
+ for k in range(bs):
101
+ detected[k] = self.decoder.decode(x[k], "dwtDct")
102
+ result = np.sum(detected == self.watermark, axis=-1)
103
+ if squeeze:
104
+ return result[0]
105
+ else:
106
+ return result
107
+
108
+
109
+ get_watermark_match = GetWatermarkMatch(WATERMARK_BITS)
110
+
111
+
112
+ if __name__ == "__main__":
113
+ parser = argparse.ArgumentParser()
114
+ parser.add_argument(
115
+ "filename",
116
+ nargs="+",
117
+ type=str,
118
+ help="Image files to check for watermarks",
119
+ )
120
+ opts = parser.parse_args()
121
+
122
+ print(
123
+ """
124
+ This script tries to detect watermarked images. Please be aware of
125
+ the following:
126
+ - As the watermark is supposed to be invisible, there is the risk that
127
+ watermarked images may not be detected.
128
+ - To maximize the chance of detection make sure that the image has the same
129
+ dimensions as when the watermark was applied (most likely 1024x1024
130
+ or 512x512).
131
+ - Specific image manipulation may drastically decrease the chance that
132
+ watermarks can be detected.
133
+ - There is also the chance that an image has the characteristics of the
134
+ watermark by chance.
135
+ - The watermark script is public, anybody may watermark any images, and
136
+ could therefore claim it to be generated.
137
+ - All numbers below are based on a test using 10,000 images without any
138
+ modifications after applying the watermark.
139
+ """
140
+ )
141
+
142
+ for fn in opts.filename:
143
+ image = cv2.imread(fn)
144
+ if image is None:
145
+ print(f"Couldn't read {fn}. Skipping")
146
+ continue
147
+
148
+ num_bits = get_watermark_match(image)
149
+ k = 0
150
+ while num_bits > MATCH_VALUES[k][0]:
151
+ k += 1
152
+ print(
153
+ f"{fn}: {MATCH_VALUES[k][1]}",
154
+ f"Bits that matched the watermark {num_bits} from {len(WATERMARK_BITS)}\n",
155
+ sep="\n\t",
156
+ )
MindEye_Imagery/src/generative_models/scripts/demo/discretization.py ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+
3
+ from sgm.modules.diffusionmodules.discretizer import Discretization
4
+
5
+
6
+ class Img2ImgDiscretizationWrapper:
7
+ """
8
+ wraps a discretizer, and prunes the sigmas
9
+ params:
10
+ strength: float between 0.0 and 1.0. 1.0 means full sampling (all sigmas are returned)
11
+ """
12
+
13
+ def __init__(self, discretization: Discretization, strength: float = 1.0):
14
+ self.discretization = discretization
15
+ self.strength = strength
16
+ assert 0.0 <= self.strength <= 1.0
17
+
18
+ def __call__(self, *args, **kwargs):
19
+ # sigmas start large first, and decrease then
20
+ sigmas = self.discretization(*args, **kwargs)
21
+ print(f"sigmas after discretization, before pruning img2img: ", sigmas)
22
+ sigmas = torch.flip(sigmas, (0,))
23
+ sigmas = sigmas[: max(int(self.strength * len(sigmas)), 1)]
24
+ print("prune index:", max(int(self.strength * len(sigmas)), 1))
25
+ sigmas = torch.flip(sigmas, (0,))
26
+ print(f"sigmas after pruning: ", sigmas)
27
+ return sigmas
28
+
29
+
30
+ class Txt2NoisyDiscretizationWrapper:
31
+ """
32
+ wraps a discretizer, and prunes the sigmas
33
+ params:
34
+ strength: float between 0.0 and 1.0. 0.0 means full sampling (all sigmas are returned)
35
+ """
36
+
37
+ def __init__(
38
+ self, discretization: Discretization, strength: float = 0.0, original_steps=None
39
+ ):
40
+ self.discretization = discretization
41
+ self.strength = strength
42
+ self.original_steps = original_steps
43
+ assert 0.0 <= self.strength <= 1.0
44
+
45
+ def __call__(self, *args, **kwargs):
46
+ # sigmas start large first, and decrease then
47
+ sigmas = self.discretization(*args, **kwargs)
48
+ print(f"sigmas after discretization, before pruning img2img: ", sigmas)
49
+ sigmas = torch.flip(sigmas, (0,))
50
+ if self.original_steps is None:
51
+ steps = len(sigmas)
52
+ else:
53
+ steps = self.original_steps + 1
54
+ prune_index = max(min(int(self.strength * steps) - 1, steps - 1), 0)
55
+ sigmas = sigmas[prune_index:]
56
+ print("prune index:", prune_index)
57
+ sigmas = torch.flip(sigmas, (0,))
58
+ print(f"sigmas after pruning: ", sigmas)
59
+ return sigmas
MindEye_Imagery/src/generative_models/scripts/demo/sampling.py ADDED
@@ -0,0 +1,364 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pytorch_lightning import seed_everything
2
+
3
+ from scripts.demo.streamlit_helpers import *
4
+
5
+ SAVE_PATH = "outputs/demo/txt2img/"
6
+
7
+ SD_XL_BASE_RATIOS = {
8
+ "0.5": (704, 1408),
9
+ "0.52": (704, 1344),
10
+ "0.57": (768, 1344),
11
+ "0.6": (768, 1280),
12
+ "0.68": (832, 1216),
13
+ "0.72": (832, 1152),
14
+ "0.78": (896, 1152),
15
+ "0.82": (896, 1088),
16
+ "0.88": (960, 1088),
17
+ "0.94": (960, 1024),
18
+ "1.0": (1024, 1024),
19
+ "1.07": (1024, 960),
20
+ "1.13": (1088, 960),
21
+ "1.21": (1088, 896),
22
+ "1.29": (1152, 896),
23
+ "1.38": (1152, 832),
24
+ "1.46": (1216, 832),
25
+ "1.67": (1280, 768),
26
+ "1.75": (1344, 768),
27
+ "1.91": (1344, 704),
28
+ "2.0": (1408, 704),
29
+ "2.09": (1472, 704),
30
+ "2.4": (1536, 640),
31
+ "2.5": (1600, 640),
32
+ "2.89": (1664, 576),
33
+ "3.0": (1728, 576),
34
+ }
35
+
36
+ VERSION2SPECS = {
37
+ "SDXL-base-1.0": {
38
+ "H": 1024,
39
+ "W": 1024,
40
+ "C": 4,
41
+ "f": 8,
42
+ "is_legacy": False,
43
+ "config": "configs/inference/sd_xl_base.yaml",
44
+ "ckpt": "checkpoints/sd_xl_base_1.0.safetensors",
45
+ },
46
+ "SDXL-base-0.9": {
47
+ "H": 1024,
48
+ "W": 1024,
49
+ "C": 4,
50
+ "f": 8,
51
+ "is_legacy": False,
52
+ "config": "configs/inference/sd_xl_base.yaml",
53
+ "ckpt": "checkpoints/sd_xl_base_0.9.safetensors",
54
+ },
55
+ "SD-2.1": {
56
+ "H": 512,
57
+ "W": 512,
58
+ "C": 4,
59
+ "f": 8,
60
+ "is_legacy": True,
61
+ "config": "configs/inference/sd_2_1.yaml",
62
+ "ckpt": "checkpoints/v2-1_512-ema-pruned.safetensors",
63
+ },
64
+ "SD-2.1-768": {
65
+ "H": 768,
66
+ "W": 768,
67
+ "C": 4,
68
+ "f": 8,
69
+ "is_legacy": True,
70
+ "config": "configs/inference/sd_2_1_768.yaml",
71
+ "ckpt": "checkpoints/v2-1_768-ema-pruned.safetensors",
72
+ },
73
+ "SDXL-refiner-0.9": {
74
+ "H": 1024,
75
+ "W": 1024,
76
+ "C": 4,
77
+ "f": 8,
78
+ "is_legacy": True,
79
+ "config": "configs/inference/sd_xl_refiner.yaml",
80
+ "ckpt": "checkpoints/sd_xl_refiner_0.9.safetensors",
81
+ },
82
+ "SDXL-refiner-1.0": {
83
+ "H": 1024,
84
+ "W": 1024,
85
+ "C": 4,
86
+ "f": 8,
87
+ "is_legacy": True,
88
+ "config": "configs/inference/sd_xl_refiner.yaml",
89
+ "ckpt": "checkpoints/sd_xl_refiner_1.0.safetensors",
90
+ },
91
+ }
92
+
93
+
94
+ def load_img(display=True, key=None, device="cuda"):
95
+ image = get_interactive_image(key=key)
96
+ if image is None:
97
+ return None
98
+ if display:
99
+ st.image(image)
100
+ w, h = image.size
101
+ print(f"loaded input image of size ({w}, {h})")
102
+ width, height = map(
103
+ lambda x: x - x % 64, (w, h)
104
+ ) # resize to integer multiple of 64
105
+ image = image.resize((width, height))
106
+ image = np.array(image.convert("RGB"))
107
+ image = image[None].transpose(0, 3, 1, 2)
108
+ image = torch.from_numpy(image).to(dtype=torch.float32) / 127.5 - 1.0
109
+ return image.to(device)
110
+
111
+
112
+ def run_txt2img(
113
+ state,
114
+ version,
115
+ version_dict,
116
+ is_legacy=False,
117
+ return_latents=False,
118
+ filter=None,
119
+ stage2strength=None,
120
+ ):
121
+ if version.startswith("SDXL-base"):
122
+ W, H = st.selectbox("Resolution:", list(SD_XL_BASE_RATIOS.values()), 10)
123
+ else:
124
+ H = st.number_input("H", value=version_dict["H"], min_value=64, max_value=2048)
125
+ W = st.number_input("W", value=version_dict["W"], min_value=64, max_value=2048)
126
+ C = version_dict["C"]
127
+ F = version_dict["f"]
128
+
129
+ init_dict = {
130
+ "orig_width": W,
131
+ "orig_height": H,
132
+ "target_width": W,
133
+ "target_height": H,
134
+ }
135
+ value_dict = init_embedder_options(
136
+ get_unique_embedder_keys_from_conditioner(state["model"].conditioner),
137
+ init_dict,
138
+ prompt=prompt,
139
+ negative_prompt=negative_prompt,
140
+ )
141
+ sampler, num_rows, num_cols = init_sampling(stage2strength=stage2strength)
142
+ num_samples = num_rows * num_cols
143
+
144
+ if st.button("Sample"):
145
+ st.write(f"**Model I:** {version}")
146
+ out = do_sample(
147
+ state["model"],
148
+ sampler,
149
+ value_dict,
150
+ num_samples,
151
+ H,
152
+ W,
153
+ C,
154
+ F,
155
+ force_uc_zero_embeddings=["txt"] if not is_legacy else [],
156
+ return_latents=return_latents,
157
+ filter=filter,
158
+ )
159
+ return out
160
+
161
+
162
+ def run_img2img(
163
+ state,
164
+ version_dict,
165
+ is_legacy=False,
166
+ return_latents=False,
167
+ filter=None,
168
+ stage2strength=None,
169
+ ):
170
+ img = load_img()
171
+ if img is None:
172
+ return None
173
+ H, W = img.shape[2], img.shape[3]
174
+
175
+ init_dict = {
176
+ "orig_width": W,
177
+ "orig_height": H,
178
+ "target_width": W,
179
+ "target_height": H,
180
+ }
181
+ value_dict = init_embedder_options(
182
+ get_unique_embedder_keys_from_conditioner(state["model"].conditioner),
183
+ init_dict,
184
+ prompt=prompt,
185
+ negative_prompt=negative_prompt,
186
+ )
187
+ strength = st.number_input(
188
+ "**Img2Img Strength**", value=0.75, min_value=0.0, max_value=1.0
189
+ )
190
+ sampler, num_rows, num_cols = init_sampling(
191
+ img2img_strength=strength,
192
+ stage2strength=stage2strength,
193
+ )
194
+ num_samples = num_rows * num_cols
195
+
196
+ if st.button("Sample"):
197
+ out = do_img2img(
198
+ repeat(img, "1 ... -> n ...", n=num_samples),
199
+ state["model"],
200
+ sampler,
201
+ value_dict,
202
+ num_samples,
203
+ force_uc_zero_embeddings=["txt"] if not is_legacy else [],
204
+ return_latents=return_latents,
205
+ filter=filter,
206
+ )
207
+ return out
208
+
209
+
210
+ def apply_refiner(
211
+ input,
212
+ state,
213
+ sampler,
214
+ num_samples,
215
+ prompt,
216
+ negative_prompt,
217
+ filter=None,
218
+ finish_denoising=False,
219
+ ):
220
+ init_dict = {
221
+ "orig_width": input.shape[3] * 8,
222
+ "orig_height": input.shape[2] * 8,
223
+ "target_width": input.shape[3] * 8,
224
+ "target_height": input.shape[2] * 8,
225
+ }
226
+
227
+ value_dict = init_dict
228
+ value_dict["prompt"] = prompt
229
+ value_dict["negative_prompt"] = negative_prompt
230
+
231
+ value_dict["crop_coords_top"] = 0
232
+ value_dict["crop_coords_left"] = 0
233
+
234
+ value_dict["aesthetic_score"] = 6.0
235
+ value_dict["negative_aesthetic_score"] = 2.5
236
+
237
+ st.warning(f"refiner input shape: {input.shape}")
238
+ samples = do_img2img(
239
+ input,
240
+ state["model"],
241
+ sampler,
242
+ value_dict,
243
+ num_samples,
244
+ skip_encode=True,
245
+ filter=filter,
246
+ add_noise=not finish_denoising,
247
+ )
248
+
249
+ return samples
250
+
251
+
252
+ if __name__ == "__main__":
253
+ st.title("Stable Diffusion")
254
+ version = st.selectbox("Model Version", list(VERSION2SPECS.keys()), 0)
255
+ version_dict = VERSION2SPECS[version]
256
+ if st.checkbox("Load Model"):
257
+ mode = st.radio("Mode", ("txt2img", "img2img"), 0)
258
+ else:
259
+ mode = "skip"
260
+ st.write("__________________________")
261
+
262
+ set_lowvram_mode(st.checkbox("Low vram mode", True))
263
+
264
+ if version.startswith("SDXL-base"):
265
+ add_pipeline = st.checkbox("Load SDXL-refiner?", False)
266
+ st.write("__________________________")
267
+ else:
268
+ add_pipeline = False
269
+
270
+ seed = st.sidebar.number_input("seed", value=42, min_value=0, max_value=int(1e9))
271
+ seed_everything(seed)
272
+
273
+ save_locally, save_path = init_save_locally(os.path.join(SAVE_PATH, version))
274
+
275
+ if mode != "skip":
276
+ state = init_st(version_dict, load_filter=True)
277
+ if state["msg"]:
278
+ st.info(state["msg"])
279
+ model = state["model"]
280
+
281
+ is_legacy = version_dict["is_legacy"]
282
+
283
+ prompt = st.text_input(
284
+ "prompt",
285
+ "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k",
286
+ )
287
+ if is_legacy:
288
+ negative_prompt = st.text_input("negative prompt", "")
289
+ else:
290
+ negative_prompt = "" # which is unused
291
+
292
+ stage2strength = None
293
+ finish_denoising = False
294
+
295
+ if add_pipeline:
296
+ st.write("__________________________")
297
+ version2 = st.selectbox("Refiner:", ["SDXL-refiner-1.0", "SDXL-refiner-0.9"])
298
+ st.warning(
299
+ f"Running with {version2} as the second stage model. Make sure to provide (V)RAM :) "
300
+ )
301
+ st.write("**Refiner Options:**")
302
+
303
+ version_dict2 = VERSION2SPECS[version2]
304
+ state2 = init_st(version_dict2, load_filter=False)
305
+ st.info(state2["msg"])
306
+
307
+ stage2strength = st.number_input(
308
+ "**Refinement strength**", value=0.15, min_value=0.0, max_value=1.0
309
+ )
310
+
311
+ sampler2, *_ = init_sampling(
312
+ key=2,
313
+ img2img_strength=stage2strength,
314
+ specify_num_samples=False,
315
+ )
316
+ st.write("__________________________")
317
+ finish_denoising = st.checkbox("Finish denoising with refiner.", True)
318
+ if not finish_denoising:
319
+ stage2strength = None
320
+
321
+ if mode == "txt2img":
322
+ out = run_txt2img(
323
+ state,
324
+ version,
325
+ version_dict,
326
+ is_legacy=is_legacy,
327
+ return_latents=add_pipeline,
328
+ filter=state.get("filter"),
329
+ stage2strength=stage2strength,
330
+ )
331
+ elif mode == "img2img":
332
+ out = run_img2img(
333
+ state,
334
+ version_dict,
335
+ is_legacy=is_legacy,
336
+ return_latents=add_pipeline,
337
+ filter=state.get("filter"),
338
+ stage2strength=stage2strength,
339
+ )
340
+ elif mode == "skip":
341
+ out = None
342
+ else:
343
+ raise ValueError(f"unknown mode {mode}")
344
+ if isinstance(out, (tuple, list)):
345
+ samples, samples_z = out
346
+ else:
347
+ samples = out
348
+ samples_z = None
349
+
350
+ if add_pipeline and samples_z is not None:
351
+ st.write("**Running Refinement Stage**")
352
+ samples = apply_refiner(
353
+ samples_z,
354
+ state2,
355
+ sampler2,
356
+ samples_z.shape[0],
357
+ prompt=prompt,
358
+ negative_prompt=negative_prompt if is_legacy else "",
359
+ filter=state.get("filter"),
360
+ finish_denoising=finish_denoising,
361
+ )
362
+
363
+ if save_locally and samples is not None:
364
+ perform_save_locally(save_path, samples)
MindEye_Imagery/src/generative_models/scripts/demo/streamlit_helpers.py ADDED
@@ -0,0 +1,887 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import copy
2
+ import math
3
+ import os
4
+ from glob import glob
5
+ from typing import Dict, List, Optional, Tuple, Union
6
+
7
+ import cv2
8
+ import numpy as np
9
+ import streamlit as st
10
+ import torch
11
+ import torch.nn as nn
12
+ import torchvision.transforms as TT
13
+ from einops import rearrange, repeat
14
+ from imwatermark import WatermarkEncoder
15
+ from omegaconf import ListConfig, OmegaConf
16
+ from PIL import Image
17
+ from safetensors.torch import load_file as load_safetensors
18
+ from torch import autocast
19
+ from torchvision import transforms
20
+ from torchvision.utils import make_grid, save_image
21
+
22
+ from scripts.demo.discretization import (Img2ImgDiscretizationWrapper,
23
+ Txt2NoisyDiscretizationWrapper)
24
+ from scripts.util.detection.nsfw_and_watermark_dectection import \
25
+ DeepFloydDataFiltering
26
+ from sgm.inference.helpers import embed_watermark
27
+ from sgm.modules.diffusionmodules.guiders import (LinearPredictionGuider,
28
+ VanillaCFG)
29
+ from sgm.modules.diffusionmodules.sampling import (DPMPP2MSampler,
30
+ DPMPP2SAncestralSampler,
31
+ EulerAncestralSampler,
32
+ EulerEDMSampler,
33
+ HeunEDMSampler,
34
+ LinearMultistepSampler)
35
+ from sgm.util import append_dims, default, instantiate_from_config
36
+
37
+
38
+ @st.cache_resource()
39
+ def init_st(version_dict, load_ckpt=True, load_filter=True):
40
+ state = dict()
41
+ if not "model" in state:
42
+ config = version_dict["config"]
43
+ ckpt = version_dict["ckpt"]
44
+
45
+ config = OmegaConf.load(config)
46
+ model, msg = load_model_from_config(config, ckpt if load_ckpt else None)
47
+
48
+ state["msg"] = msg
49
+ state["model"] = model
50
+ state["ckpt"] = ckpt if load_ckpt else None
51
+ state["config"] = config
52
+ if load_filter:
53
+ state["filter"] = DeepFloydDataFiltering(verbose=False)
54
+ return state
55
+
56
+
57
+ def load_model(model):
58
+ model.cuda()
59
+
60
+
61
+ lowvram_mode = False
62
+
63
+
64
+ def set_lowvram_mode(mode):
65
+ global lowvram_mode
66
+ lowvram_mode = mode
67
+
68
+
69
+ def initial_model_load(model):
70
+ global lowvram_mode
71
+ if lowvram_mode:
72
+ model.model.half()
73
+ else:
74
+ model.cuda()
75
+ return model
76
+
77
+
78
+ def unload_model(model):
79
+ global lowvram_mode
80
+ if lowvram_mode:
81
+ model.cpu()
82
+ torch.cuda.empty_cache()
83
+
84
+
85
+ def load_model_from_config(config, ckpt=None, verbose=True):
86
+ model = instantiate_from_config(config.model)
87
+
88
+ if ckpt is not None:
89
+ print(f"Loading model from {ckpt}")
90
+ if ckpt.endswith("ckpt"):
91
+ pl_sd = torch.load(ckpt, map_location="cpu")
92
+ if "global_step" in pl_sd:
93
+ global_step = pl_sd["global_step"]
94
+ st.info(f"loaded ckpt from global step {global_step}")
95
+ print(f"Global Step: {pl_sd['global_step']}")
96
+ sd = pl_sd["state_dict"]
97
+ elif ckpt.endswith("safetensors"):
98
+ sd = load_safetensors(ckpt)
99
+ else:
100
+ raise NotImplementedError
101
+
102
+ msg = None
103
+
104
+ m, u = model.load_state_dict(sd, strict=False)
105
+
106
+ if len(m) > 0 and verbose:
107
+ print("missing keys:")
108
+ print(m)
109
+ if len(u) > 0 and verbose:
110
+ print("unexpected keys:")
111
+ print(u)
112
+ else:
113
+ msg = None
114
+
115
+ model = initial_model_load(model)
116
+ model.eval()
117
+ return model, msg
118
+
119
+
120
+ def get_unique_embedder_keys_from_conditioner(conditioner):
121
+ return list(set([x.input_key for x in conditioner.embedders]))
122
+
123
+
124
+ def init_embedder_options(keys, init_dict, prompt=None, negative_prompt=None):
125
+ # Hardcoded demo settings; might undergo some changes in the future
126
+
127
+ value_dict = {}
128
+ for key in keys:
129
+ if key == "txt":
130
+ if prompt is None:
131
+ prompt = "A professional photograph of an astronaut riding a pig"
132
+ if negative_prompt is None:
133
+ negative_prompt = ""
134
+
135
+ prompt = st.text_input("Prompt", prompt)
136
+ negative_prompt = st.text_input("Negative prompt", negative_prompt)
137
+
138
+ value_dict["prompt"] = prompt
139
+ value_dict["negative_prompt"] = negative_prompt
140
+
141
+ if key == "original_size_as_tuple":
142
+ orig_width = st.number_input(
143
+ "orig_width",
144
+ value=init_dict["orig_width"],
145
+ min_value=16,
146
+ )
147
+ orig_height = st.number_input(
148
+ "orig_height",
149
+ value=init_dict["orig_height"],
150
+ min_value=16,
151
+ )
152
+
153
+ value_dict["orig_width"] = orig_width
154
+ value_dict["orig_height"] = orig_height
155
+
156
+ if key == "crop_coords_top_left":
157
+ crop_coord_top = st.number_input("crop_coords_top", value=0, min_value=0)
158
+ crop_coord_left = st.number_input("crop_coords_left", value=0, min_value=0)
159
+
160
+ value_dict["crop_coords_top"] = crop_coord_top
161
+ value_dict["crop_coords_left"] = crop_coord_left
162
+
163
+ if key == "aesthetic_score":
164
+ value_dict["aesthetic_score"] = 6.0
165
+ value_dict["negative_aesthetic_score"] = 2.5
166
+
167
+ if key == "target_size_as_tuple":
168
+ value_dict["target_width"] = init_dict["target_width"]
169
+ value_dict["target_height"] = init_dict["target_height"]
170
+
171
+ if key in ["fps_id", "fps"]:
172
+ fps = st.number_input("fps", value=6, min_value=1)
173
+
174
+ value_dict["fps"] = fps
175
+ value_dict["fps_id"] = fps - 1
176
+
177
+ if key == "motion_bucket_id":
178
+ mb_id = st.number_input("motion bucket id", 0, 511, value=127)
179
+ value_dict["motion_bucket_id"] = mb_id
180
+
181
+ if key == "pool_image":
182
+ st.text("Image for pool conditioning")
183
+ image = load_img(
184
+ key="pool_image_input",
185
+ size=224,
186
+ center_crop=True,
187
+ )
188
+ if image is None:
189
+ st.info("Need an image here")
190
+ image = torch.zeros(1, 3, 224, 224)
191
+ value_dict["pool_image"] = image
192
+
193
+ return value_dict
194
+
195
+
196
+ def perform_save_locally(save_path, samples):
197
+ os.makedirs(os.path.join(save_path), exist_ok=True)
198
+ base_count = len(os.listdir(os.path.join(save_path)))
199
+ samples = embed_watermark(samples)
200
+ for sample in samples:
201
+ sample = 255.0 * rearrange(sample.cpu().numpy(), "c h w -> h w c")
202
+ Image.fromarray(sample.astype(np.uint8)).save(
203
+ os.path.join(save_path, f"{base_count:09}.png")
204
+ )
205
+ base_count += 1
206
+
207
+
208
+ def init_save_locally(_dir, init_value: bool = False):
209
+ save_locally = st.sidebar.checkbox("Save images locally", value=init_value)
210
+ if save_locally:
211
+ save_path = st.text_input("Save path", value=os.path.join(_dir, "samples"))
212
+ else:
213
+ save_path = None
214
+
215
+ return save_locally, save_path
216
+
217
+
218
+ def get_guider(options, key):
219
+ guider = st.sidebar.selectbox(
220
+ f"Discretization #{key}",
221
+ [
222
+ "VanillaCFG",
223
+ "IdentityGuider",
224
+ "LinearPredictionGuider",
225
+ ],
226
+ options.get("guider", 0),
227
+ )
228
+
229
+ additional_guider_kwargs = options.pop("additional_guider_kwargs", {})
230
+
231
+ if guider == "IdentityGuider":
232
+ guider_config = {
233
+ "target": "sgm.modules.diffusionmodules.guiders.IdentityGuider"
234
+ }
235
+ elif guider == "VanillaCFG":
236
+ scale = st.number_input(
237
+ f"cfg-scale #{key}",
238
+ value=options.get("cfg", 5.0),
239
+ min_value=0.0,
240
+ )
241
+
242
+ guider_config = {
243
+ "target": "sgm.modules.diffusionmodules.guiders.VanillaCFG",
244
+ "params": {
245
+ "scale": scale,
246
+ **additional_guider_kwargs,
247
+ },
248
+ }
249
+ elif guider == "LinearPredictionGuider":
250
+ max_scale = st.number_input(
251
+ f"max-cfg-scale #{key}",
252
+ value=options.get("cfg", 1.5),
253
+ min_value=1.0,
254
+ )
255
+ min_scale = st.number_input(
256
+ f"min guidance scale",
257
+ value=options.get("min_cfg", 1.0),
258
+ min_value=1.0,
259
+ max_value=10.0,
260
+ )
261
+
262
+ guider_config = {
263
+ "target": "sgm.modules.diffusionmodules.guiders.LinearPredictionGuider",
264
+ "params": {
265
+ "max_scale": max_scale,
266
+ "min_scale": min_scale,
267
+ "num_frames": options["num_frames"],
268
+ **additional_guider_kwargs,
269
+ },
270
+ }
271
+ else:
272
+ raise NotImplementedError
273
+ return guider_config
274
+
275
+
276
+ def init_sampling(
277
+ key=1,
278
+ img2img_strength: Optional[float] = None,
279
+ specify_num_samples: bool = True,
280
+ stage2strength: Optional[float] = None,
281
+ options: Optional[Dict[str, int]] = None,
282
+ ):
283
+ options = {} if options is None else options
284
+
285
+ num_rows, num_cols = 1, 1
286
+ if specify_num_samples:
287
+ num_cols = st.number_input(
288
+ f"num cols #{key}", value=num_cols, min_value=1, max_value=10
289
+ )
290
+
291
+ steps = st.sidebar.number_input(
292
+ f"steps #{key}", value=options.get("num_steps", 40), min_value=1, max_value=1000
293
+ )
294
+ sampler = st.sidebar.selectbox(
295
+ f"Sampler #{key}",
296
+ [
297
+ "EulerEDMSampler",
298
+ "HeunEDMSampler",
299
+ "EulerAncestralSampler",
300
+ "DPMPP2SAncestralSampler",
301
+ "DPMPP2MSampler",
302
+ "LinearMultistepSampler",
303
+ ],
304
+ options.get("sampler", 0),
305
+ )
306
+ discretization = st.sidebar.selectbox(
307
+ f"Discretization #{key}",
308
+ [
309
+ "LegacyDDPMDiscretization",
310
+ "EDMDiscretization",
311
+ ],
312
+ options.get("discretization", 0),
313
+ )
314
+
315
+ discretization_config = get_discretization(discretization, options=options, key=key)
316
+
317
+ guider_config = get_guider(options=options, key=key)
318
+
319
+ sampler = get_sampler(sampler, steps, discretization_config, guider_config, key=key)
320
+ if img2img_strength is not None:
321
+ st.warning(
322
+ f"Wrapping {sampler.__class__.__name__} with Img2ImgDiscretizationWrapper"
323
+ )
324
+ sampler.discretization = Img2ImgDiscretizationWrapper(
325
+ sampler.discretization, strength=img2img_strength
326
+ )
327
+ if stage2strength is not None:
328
+ sampler.discretization = Txt2NoisyDiscretizationWrapper(
329
+ sampler.discretization, strength=stage2strength, original_steps=steps
330
+ )
331
+ return sampler, num_rows, num_cols
332
+
333
+
334
+ def get_discretization(discretization, options, key=1):
335
+ if discretization == "LegacyDDPMDiscretization":
336
+ discretization_config = {
337
+ "target": "sgm.modules.diffusionmodules.discretizer.LegacyDDPMDiscretization",
338
+ }
339
+ elif discretization == "EDMDiscretization":
340
+ sigma_min = st.number_input(
341
+ f"sigma_min #{key}", value=options.get("sigma_min", 0.03)
342
+ ) # 0.0292
343
+ sigma_max = st.number_input(
344
+ f"sigma_max #{key}", value=options.get("sigma_max", 14.61)
345
+ ) # 14.6146
346
+ rho = st.number_input(f"rho #{key}", value=options.get("rho", 3.0))
347
+ discretization_config = {
348
+ "target": "sgm.modules.diffusionmodules.discretizer.EDMDiscretization",
349
+ "params": {
350
+ "sigma_min": sigma_min,
351
+ "sigma_max": sigma_max,
352
+ "rho": rho,
353
+ },
354
+ }
355
+
356
+ return discretization_config
357
+
358
+
359
+ def get_sampler(sampler_name, steps, discretization_config, guider_config, key=1):
360
+ if sampler_name == "EulerEDMSampler" or sampler_name == "HeunEDMSampler":
361
+ s_churn = st.sidebar.number_input(f"s_churn #{key}", value=0.0, min_value=0.0)
362
+ s_tmin = st.sidebar.number_input(f"s_tmin #{key}", value=0.0, min_value=0.0)
363
+ s_tmax = st.sidebar.number_input(f"s_tmax #{key}", value=999.0, min_value=0.0)
364
+ s_noise = st.sidebar.number_input(f"s_noise #{key}", value=1.0, min_value=0.0)
365
+
366
+ if sampler_name == "EulerEDMSampler":
367
+ sampler = EulerEDMSampler(
368
+ num_steps=steps,
369
+ discretization_config=discretization_config,
370
+ guider_config=guider_config,
371
+ s_churn=s_churn,
372
+ s_tmin=s_tmin,
373
+ s_tmax=s_tmax,
374
+ s_noise=s_noise,
375
+ verbose=True,
376
+ )
377
+ elif sampler_name == "HeunEDMSampler":
378
+ sampler = HeunEDMSampler(
379
+ num_steps=steps,
380
+ discretization_config=discretization_config,
381
+ guider_config=guider_config,
382
+ s_churn=s_churn,
383
+ s_tmin=s_tmin,
384
+ s_tmax=s_tmax,
385
+ s_noise=s_noise,
386
+ verbose=True,
387
+ )
388
+ elif (
389
+ sampler_name == "EulerAncestralSampler"
390
+ or sampler_name == "DPMPP2SAncestralSampler"
391
+ ):
392
+ s_noise = st.sidebar.number_input("s_noise", value=1.0, min_value=0.0)
393
+ eta = st.sidebar.number_input("eta", value=1.0, min_value=0.0)
394
+
395
+ if sampler_name == "EulerAncestralSampler":
396
+ sampler = EulerAncestralSampler(
397
+ num_steps=steps,
398
+ discretization_config=discretization_config,
399
+ guider_config=guider_config,
400
+ eta=eta,
401
+ s_noise=s_noise,
402
+ verbose=True,
403
+ )
404
+ elif sampler_name == "DPMPP2SAncestralSampler":
405
+ sampler = DPMPP2SAncestralSampler(
406
+ num_steps=steps,
407
+ discretization_config=discretization_config,
408
+ guider_config=guider_config,
409
+ eta=eta,
410
+ s_noise=s_noise,
411
+ verbose=True,
412
+ )
413
+ elif sampler_name == "DPMPP2MSampler":
414
+ sampler = DPMPP2MSampler(
415
+ num_steps=steps,
416
+ discretization_config=discretization_config,
417
+ guider_config=guider_config,
418
+ verbose=True,
419
+ )
420
+ elif sampler_name == "LinearMultistepSampler":
421
+ order = st.sidebar.number_input("order", value=4, min_value=1)
422
+ sampler = LinearMultistepSampler(
423
+ num_steps=steps,
424
+ discretization_config=discretization_config,
425
+ guider_config=guider_config,
426
+ order=order,
427
+ verbose=True,
428
+ )
429
+ else:
430
+ raise ValueError(f"unknown sampler {sampler_name}!")
431
+
432
+ return sampler
433
+
434
+
435
+ def get_interactive_image() -> Image.Image:
436
+ image = st.file_uploader("Input", type=["jpg", "JPEG", "png"])
437
+ if image is not None:
438
+ image = Image.open(image)
439
+ if not image.mode == "RGB":
440
+ image = image.convert("RGB")
441
+ return image
442
+
443
+
444
+ def load_img(
445
+ display: bool = True,
446
+ size: Union[None, int, Tuple[int, int]] = None,
447
+ center_crop: bool = False,
448
+ ):
449
+ image = get_interactive_image()
450
+ if image is None:
451
+ return None
452
+ if display:
453
+ st.image(image)
454
+ w, h = image.size
455
+ print(f"loaded input image of size ({w}, {h})")
456
+
457
+ transform = []
458
+ if size is not None:
459
+ transform.append(transforms.Resize(size))
460
+ if center_crop:
461
+ transform.append(transforms.CenterCrop(size))
462
+ transform.append(transforms.ToTensor())
463
+ transform.append(transforms.Lambda(lambda x: 2.0 * x - 1.0))
464
+
465
+ transform = transforms.Compose(transform)
466
+ img = transform(image)[None, ...]
467
+ st.text(f"input min/max/mean: {img.min():.3f}/{img.max():.3f}/{img.mean():.3f}")
468
+ return img
469
+
470
+
471
+ def get_init_img(batch_size=1, key=None):
472
+ init_image = load_img(key=key).cuda()
473
+ init_image = repeat(init_image, "1 ... -> b ...", b=batch_size)
474
+ return init_image
475
+
476
+
477
+ def do_sample(
478
+ model,
479
+ sampler,
480
+ value_dict,
481
+ num_samples,
482
+ H,
483
+ W,
484
+ C,
485
+ F,
486
+ force_uc_zero_embeddings: Optional[List] = None,
487
+ force_cond_zero_embeddings: Optional[List] = None,
488
+ batch2model_input: List = None,
489
+ return_latents=False,
490
+ filter=None,
491
+ T=None,
492
+ additional_batch_uc_fields=None,
493
+ decoding_t=None,
494
+ ):
495
+ force_uc_zero_embeddings = default(force_uc_zero_embeddings, [])
496
+ batch2model_input = default(batch2model_input, [])
497
+ additional_batch_uc_fields = default(additional_batch_uc_fields, [])
498
+
499
+ st.text("Sampling")
500
+
501
+ outputs = st.empty()
502
+ precision_scope = autocast
503
+ with torch.no_grad():
504
+ with precision_scope("cuda"):
505
+ with model.ema_scope():
506
+ if T is not None:
507
+ num_samples = [num_samples, T]
508
+ else:
509
+ num_samples = [num_samples]
510
+
511
+ load_model(model.conditioner)
512
+ batch, batch_uc = get_batch(
513
+ get_unique_embedder_keys_from_conditioner(model.conditioner),
514
+ value_dict,
515
+ num_samples,
516
+ T=T,
517
+ additional_batch_uc_fields=additional_batch_uc_fields,
518
+ )
519
+
520
+ c, uc = model.conditioner.get_unconditional_conditioning(
521
+ batch,
522
+ batch_uc=batch_uc,
523
+ force_uc_zero_embeddings=force_uc_zero_embeddings,
524
+ force_cond_zero_embeddings=force_cond_zero_embeddings,
525
+ )
526
+ unload_model(model.conditioner)
527
+
528
+ for k in c:
529
+ if not k == "crossattn":
530
+ c[k], uc[k] = map(
531
+ lambda y: y[k][: math.prod(num_samples)].to("cuda"), (c, uc)
532
+ )
533
+ if k in ["crossattn", "concat"] and T is not None:
534
+ uc[k] = repeat(uc[k], "b ... -> b t ...", t=T)
535
+ uc[k] = rearrange(uc[k], "b t ... -> (b t) ...", t=T)
536
+ c[k] = repeat(c[k], "b ... -> b t ...", t=T)
537
+ c[k] = rearrange(c[k], "b t ... -> (b t) ...", t=T)
538
+
539
+ additional_model_inputs = {}
540
+ for k in batch2model_input:
541
+ if k == "image_only_indicator":
542
+ assert T is not None
543
+
544
+ if isinstance(
545
+ sampler.guider, (VanillaCFG, LinearPredictionGuider)
546
+ ):
547
+ additional_model_inputs[k] = torch.zeros(
548
+ num_samples[0] * 2, num_samples[1]
549
+ ).to("cuda")
550
+ else:
551
+ additional_model_inputs[k] = torch.zeros(num_samples).to(
552
+ "cuda"
553
+ )
554
+ else:
555
+ additional_model_inputs[k] = batch[k]
556
+
557
+ shape = (math.prod(num_samples), C, H // F, W // F)
558
+ randn = torch.randn(shape).to("cuda")
559
+
560
+ def denoiser(input, sigma, c):
561
+ return model.denoiser(
562
+ model.model, input, sigma, c, **additional_model_inputs
563
+ )
564
+
565
+ load_model(model.denoiser)
566
+ load_model(model.model)
567
+ samples_z = sampler(denoiser, randn, cond=c, uc=uc)
568
+ unload_model(model.model)
569
+ unload_model(model.denoiser)
570
+
571
+ load_model(model.first_stage_model)
572
+ model.en_and_decode_n_samples_a_time = (
573
+ decoding_t # Decode n frames at a time
574
+ )
575
+ samples_x = model.decode_first_stage(samples_z)
576
+ samples = torch.clamp((samples_x + 1.0) / 2.0, min=0.0, max=1.0)
577
+ unload_model(model.first_stage_model)
578
+
579
+ if filter is not None:
580
+ samples = filter(samples)
581
+
582
+ if T is None:
583
+ grid = torch.stack([samples])
584
+ grid = rearrange(grid, "n b c h w -> (n h) (b w) c")
585
+ outputs.image(grid.cpu().numpy())
586
+ else:
587
+ as_vids = rearrange(samples, "(b t) c h w -> b t c h w", t=T)
588
+ for i, vid in enumerate(as_vids):
589
+ grid = rearrange(make_grid(vid, nrow=4), "c h w -> h w c")
590
+ st.image(
591
+ grid.cpu().numpy(),
592
+ f"Sample #{i} as image",
593
+ )
594
+
595
+ if return_latents:
596
+ return samples, samples_z
597
+ return samples
598
+
599
+
600
+ def get_batch(
601
+ keys,
602
+ value_dict: dict,
603
+ N: Union[List, ListConfig],
604
+ device: str = "cuda",
605
+ T: int = None,
606
+ additional_batch_uc_fields: List[str] = [],
607
+ ):
608
+ # Hardcoded demo setups; might undergo some changes in the future
609
+
610
+ batch = {}
611
+ batch_uc = {}
612
+
613
+ for key in keys:
614
+ if key == "txt":
615
+ batch["txt"] = [value_dict["prompt"]] * math.prod(N)
616
+
617
+ batch_uc["txt"] = [value_dict["negative_prompt"]] * math.prod(N)
618
+
619
+ elif key == "original_size_as_tuple":
620
+ batch["original_size_as_tuple"] = (
621
+ torch.tensor([value_dict["orig_height"], value_dict["orig_width"]])
622
+ .to(device)
623
+ .repeat(math.prod(N), 1)
624
+ )
625
+ elif key == "crop_coords_top_left":
626
+ batch["crop_coords_top_left"] = (
627
+ torch.tensor(
628
+ [value_dict["crop_coords_top"], value_dict["crop_coords_left"]]
629
+ )
630
+ .to(device)
631
+ .repeat(math.prod(N), 1)
632
+ )
633
+ elif key == "aesthetic_score":
634
+ batch["aesthetic_score"] = (
635
+ torch.tensor([value_dict["aesthetic_score"]])
636
+ .to(device)
637
+ .repeat(math.prod(N), 1)
638
+ )
639
+ batch_uc["aesthetic_score"] = (
640
+ torch.tensor([value_dict["negative_aesthetic_score"]])
641
+ .to(device)
642
+ .repeat(math.prod(N), 1)
643
+ )
644
+
645
+ elif key == "target_size_as_tuple":
646
+ batch["target_size_as_tuple"] = (
647
+ torch.tensor([value_dict["target_height"], value_dict["target_width"]])
648
+ .to(device)
649
+ .repeat(math.prod(N), 1)
650
+ )
651
+ elif key == "fps":
652
+ batch[key] = (
653
+ torch.tensor([value_dict["fps"]]).to(device).repeat(math.prod(N))
654
+ )
655
+ elif key == "fps_id":
656
+ batch[key] = (
657
+ torch.tensor([value_dict["fps_id"]]).to(device).repeat(math.prod(N))
658
+ )
659
+ elif key == "motion_bucket_id":
660
+ batch[key] = (
661
+ torch.tensor([value_dict["motion_bucket_id"]])
662
+ .to(device)
663
+ .repeat(math.prod(N))
664
+ )
665
+ elif key == "pool_image":
666
+ batch[key] = repeat(value_dict[key], "1 ... -> b ...", b=math.prod(N)).to(
667
+ device, dtype=torch.half
668
+ )
669
+ elif key == "cond_aug":
670
+ batch[key] = repeat(
671
+ torch.tensor([value_dict["cond_aug"]]).to("cuda"),
672
+ "1 -> b",
673
+ b=math.prod(N),
674
+ )
675
+ elif key == "cond_frames":
676
+ batch[key] = repeat(value_dict["cond_frames"], "1 ... -> b ...", b=N[0])
677
+ elif key == "cond_frames_without_noise":
678
+ batch[key] = repeat(
679
+ value_dict["cond_frames_without_noise"], "1 ... -> b ...", b=N[0]
680
+ )
681
+ else:
682
+ batch[key] = value_dict[key]
683
+
684
+ if T is not None:
685
+ batch["num_video_frames"] = T
686
+
687
+ for key in batch.keys():
688
+ if key not in batch_uc and isinstance(batch[key], torch.Tensor):
689
+ batch_uc[key] = torch.clone(batch[key])
690
+ elif key in additional_batch_uc_fields and key not in batch_uc:
691
+ batch_uc[key] = copy.copy(batch[key])
692
+ return batch, batch_uc
693
+
694
+
695
+ @torch.no_grad()
696
+ def do_img2img(
697
+ img,
698
+ model,
699
+ sampler,
700
+ value_dict,
701
+ num_samples,
702
+ force_uc_zero_embeddings: Optional[List] = None,
703
+ force_cond_zero_embeddings: Optional[List] = None,
704
+ additional_kwargs={},
705
+ offset_noise_level: int = 0.0,
706
+ return_latents=False,
707
+ skip_encode=False,
708
+ filter=None,
709
+ add_noise=True,
710
+ ):
711
+ st.text("Sampling")
712
+
713
+ outputs = st.empty()
714
+ precision_scope = autocast
715
+ with torch.no_grad():
716
+ with precision_scope("cuda"):
717
+ with model.ema_scope():
718
+ load_model(model.conditioner)
719
+ batch, batch_uc = get_batch(
720
+ get_unique_embedder_keys_from_conditioner(model.conditioner),
721
+ value_dict,
722
+ [num_samples],
723
+ )
724
+ c, uc = model.conditioner.get_unconditional_conditioning(
725
+ batch,
726
+ batch_uc=batch_uc,
727
+ force_uc_zero_embeddings=force_uc_zero_embeddings,
728
+ force_cond_zero_embeddings=force_cond_zero_embeddings,
729
+ )
730
+ unload_model(model.conditioner)
731
+ for k in c:
732
+ c[k], uc[k] = map(lambda y: y[k][:num_samples].to("cuda"), (c, uc))
733
+
734
+ for k in additional_kwargs:
735
+ c[k] = uc[k] = additional_kwargs[k]
736
+ if skip_encode:
737
+ z = img
738
+ else:
739
+ load_model(model.first_stage_model)
740
+ z = model.encode_first_stage(img)
741
+ unload_model(model.first_stage_model)
742
+
743
+ noise = torch.randn_like(z)
744
+
745
+ sigmas = sampler.discretization(sampler.num_steps).cuda()
746
+ sigma = sigmas[0]
747
+
748
+ st.info(f"all sigmas: {sigmas}")
749
+ st.info(f"noising sigma: {sigma}")
750
+ if offset_noise_level > 0.0:
751
+ noise = noise + offset_noise_level * append_dims(
752
+ torch.randn(z.shape[0], device=z.device), z.ndim
753
+ )
754
+ if add_noise:
755
+ noised_z = z + noise * append_dims(sigma, z.ndim).cuda()
756
+ noised_z = noised_z / torch.sqrt(
757
+ 1.0 + sigmas[0] ** 2.0
758
+ ) # Note: hardcoded to DDPM-like scaling. need to generalize later.
759
+ else:
760
+ noised_z = z / torch.sqrt(1.0 + sigmas[0] ** 2.0)
761
+
762
+ def denoiser(x, sigma, c):
763
+ return model.denoiser(model.model, x, sigma, c)
764
+
765
+ load_model(model.denoiser)
766
+ load_model(model.model)
767
+ samples_z = sampler(denoiser, noised_z, cond=c, uc=uc)
768
+ unload_model(model.model)
769
+ unload_model(model.denoiser)
770
+
771
+ load_model(model.first_stage_model)
772
+ samples_x = model.decode_first_stage(samples_z)
773
+ unload_model(model.first_stage_model)
774
+ samples = torch.clamp((samples_x + 1.0) / 2.0, min=0.0, max=1.0)
775
+
776
+ if filter is not None:
777
+ samples = filter(samples)
778
+
779
+ grid = rearrange(grid, "n b c h w -> (n h) (b w) c")
780
+ outputs.image(grid.cpu().numpy())
781
+ if return_latents:
782
+ return samples, samples_z
783
+ return samples
784
+
785
+
786
+ def get_resizing_factor(
787
+ desired_shape: Tuple[int, int], current_shape: Tuple[int, int]
788
+ ) -> float:
789
+ r_bound = desired_shape[1] / desired_shape[0]
790
+ aspect_r = current_shape[1] / current_shape[0]
791
+ if r_bound >= 1.0:
792
+ if aspect_r >= r_bound:
793
+ factor = min(desired_shape) / min(current_shape)
794
+ else:
795
+ if aspect_r < 1.0:
796
+ factor = max(desired_shape) / min(current_shape)
797
+ else:
798
+ factor = max(desired_shape) / max(current_shape)
799
+ else:
800
+ if aspect_r <= r_bound:
801
+ factor = min(desired_shape) / min(current_shape)
802
+ else:
803
+ if aspect_r > 1:
804
+ factor = max(desired_shape) / min(current_shape)
805
+ else:
806
+ factor = max(desired_shape) / max(current_shape)
807
+
808
+ return factor
809
+
810
+
811
+ def get_interactive_image(key=None) -> Image.Image:
812
+ image = st.file_uploader("Input", type=["jpg", "JPEG", "png"], key=key)
813
+ if image is not None:
814
+ image = Image.open(image)
815
+ if not image.mode == "RGB":
816
+ image = image.convert("RGB")
817
+ return image
818
+
819
+
820
+ def load_img_for_prediction(
821
+ W: int, H: int, display=True, key=None, device="cuda"
822
+ ) -> torch.Tensor:
823
+ image = get_interactive_image(key=key)
824
+ if image is None:
825
+ return None
826
+ if display:
827
+ st.image(image)
828
+ w, h = image.size
829
+
830
+ image = np.array(image).transpose(2, 0, 1)
831
+ image = torch.from_numpy(image).to(dtype=torch.float32) / 255.0
832
+ image = image.unsqueeze(0)
833
+
834
+ rfs = get_resizing_factor((H, W), (h, w))
835
+ resize_size = [int(np.ceil(rfs * s)) for s in (h, w)]
836
+ top = (resize_size[0] - H) // 2
837
+ left = (resize_size[1] - W) // 2
838
+
839
+ image = torch.nn.functional.interpolate(
840
+ image, resize_size, mode="area", antialias=False
841
+ )
842
+ image = TT.functional.crop(image, top=top, left=left, height=H, width=W)
843
+
844
+ if display:
845
+ numpy_img = np.transpose(image[0].numpy(), (1, 2, 0))
846
+ pil_image = Image.fromarray((numpy_img * 255).astype(np.uint8))
847
+ st.image(pil_image)
848
+ return image.to(device) * 2.0 - 1.0
849
+
850
+
851
+ def save_video_as_grid_and_mp4(
852
+ video_batch: torch.Tensor, save_path: str, T: int, fps: int = 5
853
+ ):
854
+ os.makedirs(save_path, exist_ok=True)
855
+ base_count = len(glob(os.path.join(save_path, "*.mp4")))
856
+
857
+ video_batch = rearrange(video_batch, "(b t) c h w -> b t c h w", t=T)
858
+ video_batch = embed_watermark(video_batch)
859
+ for vid in video_batch:
860
+ save_image(vid, fp=os.path.join(save_path, f"{base_count:06d}.png"), nrow=4)
861
+
862
+ video_path = os.path.join(save_path, f"{base_count:06d}.mp4")
863
+
864
+ writer = cv2.VideoWriter(
865
+ video_path,
866
+ cv2.VideoWriter_fourcc(*"MP4V"),
867
+ fps,
868
+ (vid.shape[-1], vid.shape[-2]),
869
+ )
870
+
871
+ vid = (
872
+ (rearrange(vid, "t c h w -> t h w c") * 255).cpu().numpy().astype(np.uint8)
873
+ )
874
+ for frame in vid:
875
+ frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
876
+ writer.write(frame)
877
+
878
+ writer.release()
879
+
880
+ video_path_h264 = video_path[:-4] + "_h264.mp4"
881
+ os.system(f"ffmpeg -i {video_path} -c:v libx264 {video_path_h264}")
882
+
883
+ with open(video_path_h264, "rb") as f:
884
+ video_bytes = f.read()
885
+ st.video(video_bytes)
886
+
887
+ base_count += 1
MindEye_Imagery/src/generative_models/scripts/demo/turbo.py ADDED
@@ -0,0 +1,223 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from streamlit_helpers import *
2
+ from st_keyup import st_keyup
3
+ from sgm.modules.diffusionmodules.sampling import EulerAncestralSampler
4
+
5
+ VERSION2SPECS = {
6
+ "SDXL-Turbo": {
7
+ "H": 512,
8
+ "W": 512,
9
+ "C": 4,
10
+ "f": 8,
11
+ "is_legacy": False,
12
+ "config": "configs/inference/sd_xl_base.yaml",
13
+ "ckpt": "checkpoints/sd_xl_turbo_1.0.safetensors",
14
+ },
15
+ "SD-Turbo": {
16
+ "H": 512,
17
+ "W": 512,
18
+ "C": 4,
19
+ "f": 8,
20
+ "is_legacy": False,
21
+ "config": "configs/inference/sd_2_1.yaml",
22
+ "ckpt": "checkpoints/sd_turbo.safetensors",
23
+ },
24
+ }
25
+
26
+
27
+ class SubstepSampler(EulerAncestralSampler):
28
+ def __init__(self, n_sample_steps=1, *args, **kwargs):
29
+ super().__init__(*args, **kwargs)
30
+ self.n_sample_steps = n_sample_steps
31
+ self.steps_subset = [0, 100, 200, 300, 1000]
32
+
33
+ def prepare_sampling_loop(self, x, cond, uc=None, num_steps=None):
34
+ sigmas = self.discretization(
35
+ self.num_steps if num_steps is None else num_steps, device=self.device
36
+ )
37
+ sigmas = sigmas[
38
+ self.steps_subset[: self.n_sample_steps] + self.steps_subset[-1:]
39
+ ]
40
+ uc = cond
41
+ x *= torch.sqrt(1.0 + sigmas[0] ** 2.0)
42
+ num_sigmas = len(sigmas)
43
+ s_in = x.new_ones([x.shape[0]])
44
+ return x, s_in, sigmas, num_sigmas, cond, uc
45
+
46
+
47
+ def seeded_randn(shape, seed):
48
+ randn = np.random.RandomState(seed).randn(*shape)
49
+ randn = torch.from_numpy(randn).to(device="cuda", dtype=torch.float32)
50
+ return randn
51
+
52
+
53
+ class SeededNoise:
54
+ def __init__(self, seed):
55
+ self.seed = seed
56
+
57
+ def __call__(self, x):
58
+ self.seed = self.seed + 1
59
+ return seeded_randn(x.shape, self.seed)
60
+
61
+
62
+ def init_embedder_options(keys, init_dict, prompt=None, negative_prompt=None):
63
+ value_dict = {}
64
+ for key in keys:
65
+ if key == "txt":
66
+ value_dict["prompt"] = prompt
67
+ value_dict["negative_prompt"] = ""
68
+
69
+ if key == "original_size_as_tuple":
70
+ orig_width = init_dict["orig_width"]
71
+ orig_height = init_dict["orig_height"]
72
+
73
+ value_dict["orig_width"] = orig_width
74
+ value_dict["orig_height"] = orig_height
75
+
76
+ if key == "crop_coords_top_left":
77
+ crop_coord_top = 0
78
+ crop_coord_left = 0
79
+
80
+ value_dict["crop_coords_top"] = crop_coord_top
81
+ value_dict["crop_coords_left"] = crop_coord_left
82
+
83
+ if key == "aesthetic_score":
84
+ value_dict["aesthetic_score"] = 6.0
85
+ value_dict["negative_aesthetic_score"] = 2.5
86
+
87
+ if key == "target_size_as_tuple":
88
+ value_dict["target_width"] = init_dict["target_width"]
89
+ value_dict["target_height"] = init_dict["target_height"]
90
+
91
+ return value_dict
92
+
93
+
94
+ def sample(
95
+ model,
96
+ sampler,
97
+ prompt="A lush garden with oversized flowers and vibrant colors, inhabited by miniature animals.",
98
+ H=1024,
99
+ W=1024,
100
+ seed=0,
101
+ filter=None,
102
+ ):
103
+ F = 8
104
+ C = 4
105
+ shape = (1, C, H // F, W // F)
106
+
107
+ value_dict = init_embedder_options(
108
+ keys=get_unique_embedder_keys_from_conditioner(model.conditioner),
109
+ init_dict={
110
+ "orig_width": W,
111
+ "orig_height": H,
112
+ "target_width": W,
113
+ "target_height": H,
114
+ },
115
+ prompt=prompt,
116
+ )
117
+
118
+ if seed is None:
119
+ seed = torch.seed()
120
+ precision_scope = autocast
121
+ with torch.no_grad():
122
+ with precision_scope("cuda"):
123
+ batch, batch_uc = get_batch(
124
+ get_unique_embedder_keys_from_conditioner(model.conditioner),
125
+ value_dict,
126
+ [1],
127
+ )
128
+ c = model.conditioner(batch)
129
+ uc = None
130
+ randn = seeded_randn(shape, seed)
131
+
132
+ def denoiser(input, sigma, c):
133
+ return model.denoiser(
134
+ model.model,
135
+ input,
136
+ sigma,
137
+ c,
138
+ )
139
+
140
+ samples_z = sampler(denoiser, randn, cond=c, uc=uc)
141
+ samples_x = model.decode_first_stage(samples_z)
142
+ samples = torch.clamp((samples_x + 1.0) / 2.0, min=0.0, max=1.0)
143
+ if filter is not None:
144
+ samples = filter(samples)
145
+ samples = (
146
+ (255 * samples)
147
+ .to(dtype=torch.uint8)
148
+ .permute(0, 2, 3, 1)
149
+ .detach()
150
+ .cpu()
151
+ .numpy()
152
+ )
153
+ return samples
154
+
155
+
156
+ def v_spacer(height) -> None:
157
+ for _ in range(height):
158
+ st.write("\n")
159
+
160
+
161
+ if __name__ == "__main__":
162
+ st.title("Turbo")
163
+
164
+ head_cols = st.columns([1, 1, 1])
165
+ with head_cols[0]:
166
+ version = st.selectbox("Model Version", list(VERSION2SPECS.keys()), 0)
167
+ version_dict = VERSION2SPECS[version]
168
+
169
+ with head_cols[1]:
170
+ v_spacer(2)
171
+ if st.checkbox("Load Model"):
172
+ mode = "txt2img"
173
+ else:
174
+ mode = "skip"
175
+
176
+ if mode != "skip":
177
+ state = init_st(version_dict, load_filter=True)
178
+ if state["msg"]:
179
+ st.info(state["msg"])
180
+ model = state["model"]
181
+ load_model(model)
182
+
183
+ # seed
184
+ if "seed" not in st.session_state:
185
+ st.session_state.seed = 0
186
+
187
+ def increment_counter():
188
+ st.session_state.seed += 1
189
+
190
+ def decrement_counter():
191
+ if st.session_state.seed > 0:
192
+ st.session_state.seed -= 1
193
+
194
+ with head_cols[2]:
195
+ n_steps = st.number_input(label="number of steps", min_value=1, max_value=4)
196
+
197
+ sampler = SubstepSampler(
198
+ n_sample_steps=1,
199
+ num_steps=1000,
200
+ eta=1.0,
201
+ discretization_config=dict(
202
+ target="sgm.modules.diffusionmodules.discretizer.LegacyDDPMDiscretization"
203
+ ),
204
+ )
205
+ sampler.n_sample_steps = n_steps
206
+ default_prompt = "A cinematic shot of a baby racoon wearing an intricate italian priest robe."
207
+ prompt = st_keyup("Enter a value", value=default_prompt, debounce=300, key="interactive_text")
208
+
209
+ cols = st.columns([1, 5, 1])
210
+ if mode != "skip":
211
+ with cols[0]:
212
+ v_spacer(14)
213
+ st.button("↩", on_click=decrement_counter)
214
+ with cols[2]:
215
+ v_spacer(14)
216
+ st.button("↪", on_click=increment_counter)
217
+
218
+ sampler.noise_sampler = SeededNoise(seed=st.session_state.seed)
219
+ out = sample(
220
+ model, sampler, H=512, W=512, seed=st.session_state.seed, prompt=prompt, filter=state.get("filter")
221
+ )
222
+ with cols[1]:
223
+ st.image(out[0])
MindEye_Imagery/src/generative_models/scripts/demo/video_sampling.py ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ from pytorch_lightning import seed_everything
4
+
5
+ from scripts.demo.streamlit_helpers import *
6
+
7
+ SAVE_PATH = "outputs/demo/vid/"
8
+
9
+ VERSION2SPECS = {
10
+ "svd": {
11
+ "T": 14,
12
+ "H": 576,
13
+ "W": 1024,
14
+ "C": 4,
15
+ "f": 8,
16
+ "config": "configs/inference/svd.yaml",
17
+ "ckpt": "checkpoints/svd.safetensors",
18
+ "options": {
19
+ "discretization": 1,
20
+ "cfg": 2.5,
21
+ "sigma_min": 0.002,
22
+ "sigma_max": 700.0,
23
+ "rho": 7.0,
24
+ "guider": 2,
25
+ "force_uc_zero_embeddings": ["cond_frames", "cond_frames_without_noise"],
26
+ "num_steps": 25,
27
+ },
28
+ },
29
+ "svd_image_decoder": {
30
+ "T": 14,
31
+ "H": 576,
32
+ "W": 1024,
33
+ "C": 4,
34
+ "f": 8,
35
+ "config": "configs/inference/svd_image_decoder.yaml",
36
+ "ckpt": "checkpoints/svd_image_decoder.safetensors",
37
+ "options": {
38
+ "discretization": 1,
39
+ "cfg": 2.5,
40
+ "sigma_min": 0.002,
41
+ "sigma_max": 700.0,
42
+ "rho": 7.0,
43
+ "guider": 2,
44
+ "force_uc_zero_embeddings": ["cond_frames", "cond_frames_without_noise"],
45
+ "num_steps": 25,
46
+ },
47
+ },
48
+ "svd_xt": {
49
+ "T": 25,
50
+ "H": 576,
51
+ "W": 1024,
52
+ "C": 4,
53
+ "f": 8,
54
+ "config": "configs/inference/svd.yaml",
55
+ "ckpt": "checkpoints/svd_xt.safetensors",
56
+ "options": {
57
+ "discretization": 1,
58
+ "cfg": 3.0,
59
+ "min_cfg": 1.5,
60
+ "sigma_min": 0.002,
61
+ "sigma_max": 700.0,
62
+ "rho": 7.0,
63
+ "guider": 2,
64
+ "force_uc_zero_embeddings": ["cond_frames", "cond_frames_without_noise"],
65
+ "num_steps": 30,
66
+ "decoding_t": 14,
67
+ },
68
+ },
69
+ "svd_xt_image_decoder": {
70
+ "T": 25,
71
+ "H": 576,
72
+ "W": 1024,
73
+ "C": 4,
74
+ "f": 8,
75
+ "config": "configs/inference/svd_image_decoder.yaml",
76
+ "ckpt": "checkpoints/svd_xt_image_decoder.safetensors",
77
+ "options": {
78
+ "discretization": 1,
79
+ "cfg": 3.0,
80
+ "min_cfg": 1.5,
81
+ "sigma_min": 0.002,
82
+ "sigma_max": 700.0,
83
+ "rho": 7.0,
84
+ "guider": 2,
85
+ "force_uc_zero_embeddings": ["cond_frames", "cond_frames_without_noise"],
86
+ "num_steps": 30,
87
+ "decoding_t": 14,
88
+ },
89
+ },
90
+ }
91
+
92
+
93
+ if __name__ == "__main__":
94
+ st.title("Stable Video Diffusion")
95
+ version = st.selectbox(
96
+ "Model Version",
97
+ [k for k in VERSION2SPECS.keys()],
98
+ 0,
99
+ )
100
+ version_dict = VERSION2SPECS[version]
101
+ if st.checkbox("Load Model"):
102
+ mode = "img2vid"
103
+ else:
104
+ mode = "skip"
105
+
106
+ H = st.sidebar.number_input(
107
+ "H", value=version_dict["H"], min_value=64, max_value=2048
108
+ )
109
+ W = st.sidebar.number_input(
110
+ "W", value=version_dict["W"], min_value=64, max_value=2048
111
+ )
112
+ T = st.sidebar.number_input(
113
+ "T", value=version_dict["T"], min_value=0, max_value=128
114
+ )
115
+ C = version_dict["C"]
116
+ F = version_dict["f"]
117
+ options = version_dict["options"]
118
+
119
+ if mode != "skip":
120
+ state = init_st(version_dict, load_filter=True)
121
+ if state["msg"]:
122
+ st.info(state["msg"])
123
+ model = state["model"]
124
+
125
+ ukeys = set(
126
+ get_unique_embedder_keys_from_conditioner(state["model"].conditioner)
127
+ )
128
+
129
+ value_dict = init_embedder_options(
130
+ ukeys,
131
+ {},
132
+ )
133
+
134
+ value_dict["image_only_indicator"] = 0
135
+
136
+ if mode == "img2vid":
137
+ img = load_img_for_prediction(W, H)
138
+ cond_aug = st.number_input(
139
+ "Conditioning augmentation:", value=0.02, min_value=0.0
140
+ )
141
+ value_dict["cond_frames_without_noise"] = img
142
+ value_dict["cond_frames"] = img + cond_aug * torch.randn_like(img)
143
+ value_dict["cond_aug"] = cond_aug
144
+
145
+ seed = st.sidebar.number_input(
146
+ "seed", value=23, min_value=0, max_value=int(1e9)
147
+ )
148
+ seed_everything(seed)
149
+
150
+ save_locally, save_path = init_save_locally(
151
+ os.path.join(SAVE_PATH, version), init_value=True
152
+ )
153
+
154
+ options["num_frames"] = T
155
+
156
+ sampler, num_rows, num_cols = init_sampling(options=options)
157
+ num_samples = num_rows * num_cols
158
+
159
+ decoding_t = st.number_input(
160
+ "Decode t frames at a time (set small if you are low on VRAM)",
161
+ value=options.get("decoding_t", T),
162
+ min_value=1,
163
+ max_value=int(1e9),
164
+ )
165
+
166
+ if st.checkbox("Overwrite fps in mp4 generator", False):
167
+ saving_fps = st.number_input(
168
+ f"saving video at fps:", value=value_dict["fps"], min_value=1
169
+ )
170
+ else:
171
+ saving_fps = value_dict["fps"]
172
+
173
+ if st.button("Sample"):
174
+ out = do_sample(
175
+ model,
176
+ sampler,
177
+ value_dict,
178
+ num_samples,
179
+ H,
180
+ W,
181
+ C,
182
+ F,
183
+ T=T,
184
+ batch2model_input=["num_video_frames", "image_only_indicator"],
185
+ force_uc_zero_embeddings=options.get("force_uc_zero_embeddings", None),
186
+ force_cond_zero_embeddings=options.get(
187
+ "force_cond_zero_embeddings", None
188
+ ),
189
+ return_latents=False,
190
+ decoding_t=decoding_t,
191
+ )
192
+
193
+ if isinstance(out, (tuple, list)):
194
+ samples, samples_z = out
195
+ else:
196
+ samples = out
197
+ samples_z = None
198
+
199
+ if save_locally:
200
+ save_video_as_grid_and_mp4(samples, save_path, T, fps=saving_fps)
MindEye_Imagery/src/generative_models/scripts/sampling/configs/svd.yaml ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ model:
2
+ target: sgm.models.diffusion.DiffusionEngine
3
+ params:
4
+ scale_factor: 0.18215
5
+ disable_first_stage_autocast: True
6
+ ckpt_path: checkpoints/svd.safetensors
7
+
8
+ denoiser_config:
9
+ target: sgm.modules.diffusionmodules.denoiser.Denoiser
10
+ params:
11
+ scaling_config:
12
+ target: sgm.modules.diffusionmodules.denoiser_scaling.VScalingWithEDMcNoise
13
+
14
+ network_config:
15
+ target: sgm.modules.diffusionmodules.video_model.VideoUNet
16
+ params:
17
+ adm_in_channels: 768
18
+ num_classes: sequential
19
+ use_checkpoint: True
20
+ in_channels: 8
21
+ out_channels: 4
22
+ model_channels: 320
23
+ attention_resolutions: [4, 2, 1]
24
+ num_res_blocks: 2
25
+ channel_mult: [1, 2, 4, 4]
26
+ num_head_channels: 64
27
+ use_linear_in_transformer: True
28
+ transformer_depth: 1
29
+ context_dim: 1024
30
+ spatial_transformer_attn_type: softmax-xformers
31
+ extra_ff_mix_layer: True
32
+ use_spatial_context: True
33
+ merge_strategy: learned_with_images
34
+ video_kernel_size: [3, 1, 1]
35
+
36
+ conditioner_config:
37
+ target: sgm.modules.GeneralConditioner
38
+ params:
39
+ emb_models:
40
+ - is_trainable: False
41
+ input_key: cond_frames_without_noise
42
+ target: sgm.modules.encoders.modules.FrozenOpenCLIPImagePredictionEmbedder
43
+ params:
44
+ n_cond_frames: 1
45
+ n_copies: 1
46
+ open_clip_embedding_config:
47
+ target: sgm.modules.encoders.modules.FrozenOpenCLIPImageEmbedder
48
+ params:
49
+ freeze: True
50
+
51
+ - input_key: fps_id
52
+ is_trainable: False
53
+ target: sgm.modules.encoders.modules.ConcatTimestepEmbedderND
54
+ params:
55
+ outdim: 256
56
+
57
+ - input_key: motion_bucket_id
58
+ is_trainable: False
59
+ target: sgm.modules.encoders.modules.ConcatTimestepEmbedderND
60
+ params:
61
+ outdim: 256
62
+
63
+ - input_key: cond_frames
64
+ is_trainable: False
65
+ target: sgm.modules.encoders.modules.VideoPredictionEmbedderWithEncoder
66
+ params:
67
+ disable_encoder_autocast: True
68
+ n_cond_frames: 1
69
+ n_copies: 1
70
+ is_ae: True
71
+ encoder_config:
72
+ target: sgm.models.autoencoder.AutoencoderKLModeOnly
73
+ params:
74
+ embed_dim: 4
75
+ monitor: val/rec_loss
76
+ ddconfig:
77
+ attn_type: vanilla-xformers
78
+ double_z: True
79
+ z_channels: 4
80
+ resolution: 256
81
+ in_channels: 3
82
+ out_ch: 3
83
+ ch: 128
84
+ ch_mult: [1, 2, 4, 4]
85
+ num_res_blocks: 2
86
+ attn_resolutions: []
87
+ dropout: 0.0
88
+ lossconfig:
89
+ target: torch.nn.Identity
90
+
91
+ - input_key: cond_aug
92
+ is_trainable: False
93
+ target: sgm.modules.encoders.modules.ConcatTimestepEmbedderND
94
+ params:
95
+ outdim: 256
96
+
97
+ first_stage_config:
98
+ target: sgm.models.autoencoder.AutoencodingEngine
99
+ params:
100
+ loss_config:
101
+ target: torch.nn.Identity
102
+ regularizer_config:
103
+ target: sgm.modules.autoencoding.regularizers.DiagonalGaussianRegularizer
104
+ encoder_config:
105
+ target: sgm.modules.diffusionmodules.model.Encoder
106
+ params:
107
+ attn_type: vanilla
108
+ double_z: True
109
+ z_channels: 4
110
+ resolution: 256
111
+ in_channels: 3
112
+ out_ch: 3
113
+ ch: 128
114
+ ch_mult: [1, 2, 4, 4]
115
+ num_res_blocks: 2
116
+ attn_resolutions: []
117
+ dropout: 0.0
118
+ decoder_config:
119
+ target: sgm.modules.autoencoding.temporal_ae.VideoDecoder
120
+ params:
121
+ attn_type: vanilla
122
+ double_z: True
123
+ z_channels: 4
124
+ resolution: 256
125
+ in_channels: 3
126
+ out_ch: 3
127
+ ch: 128
128
+ ch_mult: [1, 2, 4, 4]
129
+ num_res_blocks: 2
130
+ attn_resolutions: []
131
+ dropout: 0.0
132
+ video_kernel_size: [3, 1, 1]
133
+
134
+ sampler_config:
135
+ target: sgm.modules.diffusionmodules.sampling.EulerEDMSampler
136
+ params:
137
+ discretization_config:
138
+ target: sgm.modules.diffusionmodules.discretizer.EDMDiscretization
139
+ params:
140
+ sigma_max: 700.0
141
+
142
+ guider_config:
143
+ target: sgm.modules.diffusionmodules.guiders.LinearPredictionGuider
144
+ params:
145
+ max_scale: 2.5
146
+ min_scale: 1.0
MindEye_Imagery/src/generative_models/scripts/sampling/configs/svd_image_decoder.yaml ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ model:
2
+ target: sgm.models.diffusion.DiffusionEngine
3
+ params:
4
+ scale_factor: 0.18215
5
+ disable_first_stage_autocast: True
6
+ ckpt_path: checkpoints/svd_image_decoder.safetensors
7
+
8
+ denoiser_config:
9
+ target: sgm.modules.diffusionmodules.denoiser.Denoiser
10
+ params:
11
+ scaling_config:
12
+ target: sgm.modules.diffusionmodules.denoiser_scaling.VScalingWithEDMcNoise
13
+
14
+ network_config:
15
+ target: sgm.modules.diffusionmodules.video_model.VideoUNet
16
+ params:
17
+ adm_in_channels: 768
18
+ num_classes: sequential
19
+ use_checkpoint: True
20
+ in_channels: 8
21
+ out_channels: 4
22
+ model_channels: 320
23
+ attention_resolutions: [4, 2, 1]
24
+ num_res_blocks: 2
25
+ channel_mult: [1, 2, 4, 4]
26
+ num_head_channels: 64
27
+ use_linear_in_transformer: True
28
+ transformer_depth: 1
29
+ context_dim: 1024
30
+ spatial_transformer_attn_type: softmax-xformers
31
+ extra_ff_mix_layer: True
32
+ use_spatial_context: True
33
+ merge_strategy: learned_with_images
34
+ video_kernel_size: [3, 1, 1]
35
+
36
+ conditioner_config:
37
+ target: sgm.modules.GeneralConditioner
38
+ params:
39
+ emb_models:
40
+ - is_trainable: False
41
+ input_key: cond_frames_without_noise
42
+ target: sgm.modules.encoders.modules.FrozenOpenCLIPImagePredictionEmbedder
43
+ params:
44
+ n_cond_frames: 1
45
+ n_copies: 1
46
+ open_clip_embedding_config:
47
+ target: sgm.modules.encoders.modules.FrozenOpenCLIPImageEmbedder
48
+ params:
49
+ freeze: True
50
+
51
+ - input_key: fps_id
52
+ is_trainable: False
53
+ target: sgm.modules.encoders.modules.ConcatTimestepEmbedderND
54
+ params:
55
+ outdim: 256
56
+
57
+ - input_key: motion_bucket_id
58
+ is_trainable: False
59
+ target: sgm.modules.encoders.modules.ConcatTimestepEmbedderND
60
+ params:
61
+ outdim: 256
62
+
63
+ - input_key: cond_frames
64
+ is_trainable: False
65
+ target: sgm.modules.encoders.modules.VideoPredictionEmbedderWithEncoder
66
+ params:
67
+ disable_encoder_autocast: True
68
+ n_cond_frames: 1
69
+ n_copies: 1
70
+ is_ae: True
71
+ encoder_config:
72
+ target: sgm.models.autoencoder.AutoencoderKLModeOnly
73
+ params:
74
+ embed_dim: 4
75
+ monitor: val/rec_loss
76
+ ddconfig:
77
+ attn_type: vanilla-xformers
78
+ double_z: True
79
+ z_channels: 4
80
+ resolution: 256
81
+ in_channels: 3
82
+ out_ch: 3
83
+ ch: 128
84
+ ch_mult: [1, 2, 4, 4]
85
+ num_res_blocks: 2
86
+ attn_resolutions: []
87
+ dropout: 0.0
88
+ lossconfig:
89
+ target: torch.nn.Identity
90
+
91
+ - input_key: cond_aug
92
+ is_trainable: False
93
+ target: sgm.modules.encoders.modules.ConcatTimestepEmbedderND
94
+ params:
95
+ outdim: 256
96
+
97
+ first_stage_config:
98
+ target: sgm.models.autoencoder.AutoencoderKL
99
+ params:
100
+ embed_dim: 4
101
+ monitor: val/rec_loss
102
+ ddconfig:
103
+ attn_type: vanilla-xformers
104
+ double_z: True
105
+ z_channels: 4
106
+ resolution: 256
107
+ in_channels: 3
108
+ out_ch: 3
109
+ ch: 128
110
+ ch_mult: [1, 2, 4, 4]
111
+ num_res_blocks: 2
112
+ attn_resolutions: []
113
+ dropout: 0.0
114
+ lossconfig:
115
+ target: torch.nn.Identity
116
+
117
+ sampler_config:
118
+ target: sgm.modules.diffusionmodules.sampling.EulerEDMSampler
119
+ params:
120
+ discretization_config:
121
+ target: sgm.modules.diffusionmodules.discretizer.EDMDiscretization
122
+ params:
123
+ sigma_max: 700.0
124
+
125
+ guider_config:
126
+ target: sgm.modules.diffusionmodules.guiders.LinearPredictionGuider
127
+ params:
128
+ max_scale: 2.5
129
+ min_scale: 1.0
MindEye_Imagery/src/generative_models/scripts/sampling/configs/svd_xt.yaml ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ model:
2
+ target: sgm.models.diffusion.DiffusionEngine
3
+ params:
4
+ scale_factor: 0.18215
5
+ disable_first_stage_autocast: True
6
+ ckpt_path: checkpoints/svd_xt.safetensors
7
+
8
+ denoiser_config:
9
+ target: sgm.modules.diffusionmodules.denoiser.Denoiser
10
+ params:
11
+ scaling_config:
12
+ target: sgm.modules.diffusionmodules.denoiser_scaling.VScalingWithEDMcNoise
13
+
14
+ network_config:
15
+ target: sgm.modules.diffusionmodules.video_model.VideoUNet
16
+ params:
17
+ adm_in_channels: 768
18
+ num_classes: sequential
19
+ use_checkpoint: True
20
+ in_channels: 8
21
+ out_channels: 4
22
+ model_channels: 320
23
+ attention_resolutions: [4, 2, 1]
24
+ num_res_blocks: 2
25
+ channel_mult: [1, 2, 4, 4]
26
+ num_head_channels: 64
27
+ use_linear_in_transformer: True
28
+ transformer_depth: 1
29
+ context_dim: 1024
30
+ spatial_transformer_attn_type: softmax-xformers
31
+ extra_ff_mix_layer: True
32
+ use_spatial_context: True
33
+ merge_strategy: learned_with_images
34
+ video_kernel_size: [3, 1, 1]
35
+
36
+ conditioner_config:
37
+ target: sgm.modules.GeneralConditioner
38
+ params:
39
+ emb_models:
40
+ - is_trainable: False
41
+ input_key: cond_frames_without_noise
42
+ target: sgm.modules.encoders.modules.FrozenOpenCLIPImagePredictionEmbedder
43
+ params:
44
+ n_cond_frames: 1
45
+ n_copies: 1
46
+ open_clip_embedding_config:
47
+ target: sgm.modules.encoders.modules.FrozenOpenCLIPImageEmbedder
48
+ params:
49
+ freeze: True
50
+
51
+ - input_key: fps_id
52
+ is_trainable: False
53
+ target: sgm.modules.encoders.modules.ConcatTimestepEmbedderND
54
+ params:
55
+ outdim: 256
56
+
57
+ - input_key: motion_bucket_id
58
+ is_trainable: False
59
+ target: sgm.modules.encoders.modules.ConcatTimestepEmbedderND
60
+ params:
61
+ outdim: 256
62
+
63
+ - input_key: cond_frames
64
+ is_trainable: False
65
+ target: sgm.modules.encoders.modules.VideoPredictionEmbedderWithEncoder
66
+ params:
67
+ disable_encoder_autocast: True
68
+ n_cond_frames: 1
69
+ n_copies: 1
70
+ is_ae: True
71
+ encoder_config:
72
+ target: sgm.models.autoencoder.AutoencoderKLModeOnly
73
+ params:
74
+ embed_dim: 4
75
+ monitor: val/rec_loss
76
+ ddconfig:
77
+ attn_type: vanilla-xformers
78
+ double_z: True
79
+ z_channels: 4
80
+ resolution: 256
81
+ in_channels: 3
82
+ out_ch: 3
83
+ ch: 128
84
+ ch_mult: [1, 2, 4, 4]
85
+ num_res_blocks: 2
86
+ attn_resolutions: []
87
+ dropout: 0.0
88
+ lossconfig:
89
+ target: torch.nn.Identity
90
+
91
+ - input_key: cond_aug
92
+ is_trainable: False
93
+ target: sgm.modules.encoders.modules.ConcatTimestepEmbedderND
94
+ params:
95
+ outdim: 256
96
+
97
+ first_stage_config:
98
+ target: sgm.models.autoencoder.AutoencodingEngine
99
+ params:
100
+ loss_config:
101
+ target: torch.nn.Identity
102
+ regularizer_config:
103
+ target: sgm.modules.autoencoding.regularizers.DiagonalGaussianRegularizer
104
+ encoder_config:
105
+ target: sgm.modules.diffusionmodules.model.Encoder
106
+ params:
107
+ attn_type: vanilla
108
+ double_z: True
109
+ z_channels: 4
110
+ resolution: 256
111
+ in_channels: 3
112
+ out_ch: 3
113
+ ch: 128
114
+ ch_mult: [1, 2, 4, 4]
115
+ num_res_blocks: 2
116
+ attn_resolutions: []
117
+ dropout: 0.0
118
+ decoder_config:
119
+ target: sgm.modules.autoencoding.temporal_ae.VideoDecoder
120
+ params:
121
+ attn_type: vanilla
122
+ double_z: True
123
+ z_channels: 4
124
+ resolution: 256
125
+ in_channels: 3
126
+ out_ch: 3
127
+ ch: 128
128
+ ch_mult: [1, 2, 4, 4]
129
+ num_res_blocks: 2
130
+ attn_resolutions: []
131
+ dropout: 0.0
132
+ video_kernel_size: [3, 1, 1]
133
+
134
+ sampler_config:
135
+ target: sgm.modules.diffusionmodules.sampling.EulerEDMSampler
136
+ params:
137
+ discretization_config:
138
+ target: sgm.modules.diffusionmodules.discretizer.EDMDiscretization
139
+ params:
140
+ sigma_max: 700.0
141
+
142
+ guider_config:
143
+ target: sgm.modules.diffusionmodules.guiders.LinearPredictionGuider
144
+ params:
145
+ max_scale: 3.0
146
+ min_scale: 1.5
MindEye_Imagery/src/generative_models/scripts/sampling/configs/svd_xt_image_decoder.yaml ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ model:
2
+ target: sgm.models.diffusion.DiffusionEngine
3
+ params:
4
+ scale_factor: 0.18215
5
+ disable_first_stage_autocast: True
6
+ ckpt_path: checkpoints/svd_xt_image_decoder.safetensors
7
+
8
+ denoiser_config:
9
+ target: sgm.modules.diffusionmodules.denoiser.Denoiser
10
+ params:
11
+ scaling_config:
12
+ target: sgm.modules.diffusionmodules.denoiser_scaling.VScalingWithEDMcNoise
13
+
14
+ network_config:
15
+ target: sgm.modules.diffusionmodules.video_model.VideoUNet
16
+ params:
17
+ adm_in_channels: 768
18
+ num_classes: sequential
19
+ use_checkpoint: True
20
+ in_channels: 8
21
+ out_channels: 4
22
+ model_channels: 320
23
+ attention_resolutions: [4, 2, 1]
24
+ num_res_blocks: 2
25
+ channel_mult: [1, 2, 4, 4]
26
+ num_head_channels: 64
27
+ use_linear_in_transformer: True
28
+ transformer_depth: 1
29
+ context_dim: 1024
30
+ spatial_transformer_attn_type: softmax-xformers
31
+ extra_ff_mix_layer: True
32
+ use_spatial_context: True
33
+ merge_strategy: learned_with_images
34
+ video_kernel_size: [3, 1, 1]
35
+
36
+ conditioner_config:
37
+ target: sgm.modules.GeneralConditioner
38
+ params:
39
+ emb_models:
40
+ - is_trainable: False
41
+ input_key: cond_frames_without_noise
42
+ target: sgm.modules.encoders.modules.FrozenOpenCLIPImagePredictionEmbedder
43
+ params:
44
+ n_cond_frames: 1
45
+ n_copies: 1
46
+ open_clip_embedding_config:
47
+ target: sgm.modules.encoders.modules.FrozenOpenCLIPImageEmbedder
48
+ params:
49
+ freeze: True
50
+
51
+ - input_key: fps_id
52
+ is_trainable: False
53
+ target: sgm.modules.encoders.modules.ConcatTimestepEmbedderND
54
+ params:
55
+ outdim: 256
56
+
57
+ - input_key: motion_bucket_id
58
+ is_trainable: False
59
+ target: sgm.modules.encoders.modules.ConcatTimestepEmbedderND
60
+ params:
61
+ outdim: 256
62
+
63
+ - input_key: cond_frames
64
+ is_trainable: False
65
+ target: sgm.modules.encoders.modules.VideoPredictionEmbedderWithEncoder
66
+ params:
67
+ disable_encoder_autocast: True
68
+ n_cond_frames: 1
69
+ n_copies: 1
70
+ is_ae: True
71
+ encoder_config:
72
+ target: sgm.models.autoencoder.AutoencoderKLModeOnly
73
+ params:
74
+ embed_dim: 4
75
+ monitor: val/rec_loss
76
+ ddconfig:
77
+ attn_type: vanilla-xformers
78
+ double_z: True
79
+ z_channels: 4
80
+ resolution: 256
81
+ in_channels: 3
82
+ out_ch: 3
83
+ ch: 128
84
+ ch_mult: [1, 2, 4, 4]
85
+ num_res_blocks: 2
86
+ attn_resolutions: []
87
+ dropout: 0.0
88
+ lossconfig:
89
+ target: torch.nn.Identity
90
+
91
+ - input_key: cond_aug
92
+ is_trainable: False
93
+ target: sgm.modules.encoders.modules.ConcatTimestepEmbedderND
94
+ params:
95
+ outdim: 256
96
+
97
+ first_stage_config:
98
+ target: sgm.models.autoencoder.AutoencoderKL
99
+ params:
100
+ embed_dim: 4
101
+ monitor: val/rec_loss
102
+ ddconfig:
103
+ attn_type: vanilla-xformers
104
+ double_z: True
105
+ z_channels: 4
106
+ resolution: 256
107
+ in_channels: 3
108
+ out_ch: 3
109
+ ch: 128
110
+ ch_mult: [1, 2, 4, 4]
111
+ num_res_blocks: 2
112
+ attn_resolutions: []
113
+ dropout: 0.0
114
+ lossconfig:
115
+ target: torch.nn.Identity
116
+
117
+ sampler_config:
118
+ target: sgm.modules.diffusionmodules.sampling.EulerEDMSampler
119
+ params:
120
+ discretization_config:
121
+ target: sgm.modules.diffusionmodules.discretizer.EDMDiscretization
122
+ params:
123
+ sigma_max: 700.0
124
+
125
+ guider_config:
126
+ target: sgm.modules.diffusionmodules.guiders.LinearPredictionGuider
127
+ params:
128
+ max_scale: 3.0
129
+ min_scale: 1.5
MindEye_Imagery/src/generative_models/scripts/sampling/simple_video_sample.py ADDED
@@ -0,0 +1,278 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ import os
3
+ from glob import glob
4
+ from pathlib import Path
5
+ from typing import Optional
6
+
7
+ import cv2
8
+ import numpy as np
9
+ import torch
10
+ from einops import rearrange, repeat
11
+ from fire import Fire
12
+ from omegaconf import OmegaConf
13
+ from PIL import Image
14
+ from torchvision.transforms import ToTensor
15
+
16
+ from scripts.util.detection.nsfw_and_watermark_dectection import \
17
+ DeepFloydDataFiltering
18
+ from sgm.inference.helpers import embed_watermark
19
+ from sgm.util import default, instantiate_from_config
20
+
21
+
22
+ def sample(
23
+ input_path: str = "assets/test_image.png", # Can either be image file or folder with image files
24
+ num_frames: Optional[int] = None,
25
+ num_steps: Optional[int] = None,
26
+ version: str = "svd",
27
+ fps_id: int = 6,
28
+ motion_bucket_id: int = 127,
29
+ cond_aug: float = 0.02,
30
+ seed: int = 23,
31
+ decoding_t: int = 14, # Number of frames decoded at a time! This eats most VRAM. Reduce if necessary.
32
+ device: str = "cuda",
33
+ output_folder: Optional[str] = None,
34
+ ):
35
+ """
36
+ Simple script to generate a single sample conditioned on an image `input_path` or multiple images, one for each
37
+ image file in folder `input_path`. If you run out of VRAM, try decreasing `decoding_t`.
38
+ """
39
+
40
+ if version == "svd":
41
+ num_frames = default(num_frames, 14)
42
+ num_steps = default(num_steps, 25)
43
+ output_folder = default(output_folder, "outputs/simple_video_sample/svd/")
44
+ model_config = "scripts/sampling/configs/svd.yaml"
45
+ elif version == "svd_xt":
46
+ num_frames = default(num_frames, 25)
47
+ num_steps = default(num_steps, 30)
48
+ output_folder = default(output_folder, "outputs/simple_video_sample/svd_xt/")
49
+ model_config = "scripts/sampling/configs/svd_xt.yaml"
50
+ elif version == "svd_image_decoder":
51
+ num_frames = default(num_frames, 14)
52
+ num_steps = default(num_steps, 25)
53
+ output_folder = default(
54
+ output_folder, "outputs/simple_video_sample/svd_image_decoder/"
55
+ )
56
+ model_config = "scripts/sampling/configs/svd_image_decoder.yaml"
57
+ elif version == "svd_xt_image_decoder":
58
+ num_frames = default(num_frames, 25)
59
+ num_steps = default(num_steps, 30)
60
+ output_folder = default(
61
+ output_folder, "outputs/simple_video_sample/svd_xt_image_decoder/"
62
+ )
63
+ model_config = "scripts/sampling/configs/svd_xt_image_decoder.yaml"
64
+ else:
65
+ raise ValueError(f"Version {version} does not exist.")
66
+
67
+ model, filter = load_model(
68
+ model_config,
69
+ device,
70
+ num_frames,
71
+ num_steps,
72
+ )
73
+ torch.manual_seed(seed)
74
+
75
+ path = Path(input_path)
76
+ all_img_paths = []
77
+ if path.is_file():
78
+ if any([input_path.endswith(x) for x in ["jpg", "jpeg", "png"]]):
79
+ all_img_paths = [input_path]
80
+ else:
81
+ raise ValueError("Path is not valid image file.")
82
+ elif path.is_dir():
83
+ all_img_paths = sorted(
84
+ [
85
+ f
86
+ for f in path.iterdir()
87
+ if f.is_file() and f.suffix.lower() in [".jpg", ".jpeg", ".png"]
88
+ ]
89
+ )
90
+ if len(all_img_paths) == 0:
91
+ raise ValueError("Folder does not contain any images.")
92
+ else:
93
+ raise ValueError
94
+
95
+ for input_img_path in all_img_paths:
96
+ with Image.open(input_img_path) as image:
97
+ if image.mode == "RGBA":
98
+ image = image.convert("RGB")
99
+ w, h = image.size
100
+
101
+ if h % 64 != 0 or w % 64 != 0:
102
+ width, height = map(lambda x: x - x % 64, (w, h))
103
+ image = image.resize((width, height))
104
+ print(
105
+ f"WARNING: Your image is of size {h}x{w} which is not divisible by 64. We are resizing to {height}x{width}!"
106
+ )
107
+
108
+ image = ToTensor()(image)
109
+ image = image * 2.0 - 1.0
110
+
111
+ image = image.unsqueeze(0).to(device)
112
+ H, W = image.shape[2:]
113
+ assert image.shape[1] == 3
114
+ F = 8
115
+ C = 4
116
+ shape = (num_frames, C, H // F, W // F)
117
+ if (H, W) != (576, 1024):
118
+ print(
119
+ "WARNING: The conditioning frame you provided is not 576x1024. This leads to suboptimal performance as model was only trained on 576x1024. Consider increasing `cond_aug`."
120
+ )
121
+ if motion_bucket_id > 255:
122
+ print(
123
+ "WARNING: High motion bucket! This may lead to suboptimal performance."
124
+ )
125
+
126
+ if fps_id < 5:
127
+ print("WARNING: Small fps value! This may lead to suboptimal performance.")
128
+
129
+ if fps_id > 30:
130
+ print("WARNING: Large fps value! This may lead to suboptimal performance.")
131
+
132
+ value_dict = {}
133
+ value_dict["motion_bucket_id"] = motion_bucket_id
134
+ value_dict["fps_id"] = fps_id
135
+ value_dict["cond_aug"] = cond_aug
136
+ value_dict["cond_frames_without_noise"] = image
137
+ value_dict["cond_frames"] = image + cond_aug * torch.randn_like(image)
138
+ value_dict["cond_aug"] = cond_aug
139
+
140
+ with torch.no_grad():
141
+ with torch.autocast(device):
142
+ batch, batch_uc = get_batch(
143
+ get_unique_embedder_keys_from_conditioner(model.conditioner),
144
+ value_dict,
145
+ [1, num_frames],
146
+ T=num_frames,
147
+ device=device,
148
+ )
149
+ c, uc = model.conditioner.get_unconditional_conditioning(
150
+ batch,
151
+ batch_uc=batch_uc,
152
+ force_uc_zero_embeddings=[
153
+ "cond_frames",
154
+ "cond_frames_without_noise",
155
+ ],
156
+ )
157
+
158
+ for k in ["crossattn", "concat"]:
159
+ uc[k] = repeat(uc[k], "b ... -> b t ...", t=num_frames)
160
+ uc[k] = rearrange(uc[k], "b t ... -> (b t) ...", t=num_frames)
161
+ c[k] = repeat(c[k], "b ... -> b t ...", t=num_frames)
162
+ c[k] = rearrange(c[k], "b t ... -> (b t) ...", t=num_frames)
163
+
164
+ randn = torch.randn(shape, device=device)
165
+
166
+ additional_model_inputs = {}
167
+ additional_model_inputs["image_only_indicator"] = torch.zeros(
168
+ 2, num_frames
169
+ ).to(device)
170
+ additional_model_inputs["num_video_frames"] = batch["num_video_frames"]
171
+
172
+ def denoiser(input, sigma, c):
173
+ return model.denoiser(
174
+ model.model, input, sigma, c, **additional_model_inputs
175
+ )
176
+
177
+ samples_z = model.sampler(denoiser, randn, cond=c, uc=uc)
178
+ model.en_and_decode_n_samples_a_time = decoding_t
179
+ samples_x = model.decode_first_stage(samples_z)
180
+ samples = torch.clamp((samples_x + 1.0) / 2.0, min=0.0, max=1.0)
181
+
182
+ os.makedirs(output_folder, exist_ok=True)
183
+ base_count = len(glob(os.path.join(output_folder, "*.mp4")))
184
+ video_path = os.path.join(output_folder, f"{base_count:06d}.mp4")
185
+ writer = cv2.VideoWriter(
186
+ video_path,
187
+ cv2.VideoWriter_fourcc(*"MP4V"),
188
+ fps_id + 1,
189
+ (samples.shape[-1], samples.shape[-2]),
190
+ )
191
+
192
+ samples = embed_watermark(samples)
193
+ samples = filter(samples)
194
+ vid = (
195
+ (rearrange(samples, "t c h w -> t h w c") * 255)
196
+ .cpu()
197
+ .numpy()
198
+ .astype(np.uint8)
199
+ )
200
+ for frame in vid:
201
+ frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
202
+ writer.write(frame)
203
+ writer.release()
204
+
205
+
206
+ def get_unique_embedder_keys_from_conditioner(conditioner):
207
+ return list(set([x.input_key for x in conditioner.embedders]))
208
+
209
+
210
+ def get_batch(keys, value_dict, N, T, device):
211
+ batch = {}
212
+ batch_uc = {}
213
+
214
+ for key in keys:
215
+ if key == "fps_id":
216
+ batch[key] = (
217
+ torch.tensor([value_dict["fps_id"]])
218
+ .to(device)
219
+ .repeat(int(math.prod(N)))
220
+ )
221
+ elif key == "motion_bucket_id":
222
+ batch[key] = (
223
+ torch.tensor([value_dict["motion_bucket_id"]])
224
+ .to(device)
225
+ .repeat(int(math.prod(N)))
226
+ )
227
+ elif key == "cond_aug":
228
+ batch[key] = repeat(
229
+ torch.tensor([value_dict["cond_aug"]]).to(device),
230
+ "1 -> b",
231
+ b=math.prod(N),
232
+ )
233
+ elif key == "cond_frames":
234
+ batch[key] = repeat(value_dict["cond_frames"], "1 ... -> b ...", b=N[0])
235
+ elif key == "cond_frames_without_noise":
236
+ batch[key] = repeat(
237
+ value_dict["cond_frames_without_noise"], "1 ... -> b ...", b=N[0]
238
+ )
239
+ else:
240
+ batch[key] = value_dict[key]
241
+
242
+ if T is not None:
243
+ batch["num_video_frames"] = T
244
+
245
+ for key in batch.keys():
246
+ if key not in batch_uc and isinstance(batch[key], torch.Tensor):
247
+ batch_uc[key] = torch.clone(batch[key])
248
+ return batch, batch_uc
249
+
250
+
251
+ def load_model(
252
+ config: str,
253
+ device: str,
254
+ num_frames: int,
255
+ num_steps: int,
256
+ ):
257
+ config = OmegaConf.load(config)
258
+ if device == "cuda":
259
+ config.model.params.conditioner_config.params.emb_models[
260
+ 0
261
+ ].params.open_clip_embedding_config.params.init_device = device
262
+
263
+ config.model.params.sampler_config.params.num_steps = num_steps
264
+ config.model.params.sampler_config.params.guider_config.params.num_frames = (
265
+ num_frames
266
+ )
267
+ if device == "cuda":
268
+ with torch.device(device):
269
+ model = instantiate_from_config(config.model).to(device).eval()
270
+ else:
271
+ model = instantiate_from_config(config.model).to(device).eval()
272
+
273
+ filter = DeepFloydDataFiltering(verbose=False, device=device)
274
+ return model, filter
275
+
276
+
277
+ if __name__ == "__main__":
278
+ Fire(sample)
MindEye_Imagery/src/generative_models/scripts/tests/attention.py ADDED
@@ -0,0 +1,319 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import einops
2
+ import torch
3
+ import torch.nn.functional as F
4
+ import torch.utils.benchmark as benchmark
5
+ from torch.backends.cuda import SDPBackend
6
+
7
+ from sgm.modules.attention import BasicTransformerBlock, SpatialTransformer
8
+
9
+
10
+ def benchmark_attn():
11
+ # Lets define a helpful benchmarking function:
12
+ # https://pytorch.org/tutorials/intermediate/scaled_dot_product_attention_tutorial.html
13
+ device = "cuda" if torch.cuda.is_available() else "cpu"
14
+
15
+ def benchmark_torch_function_in_microseconds(f, *args, **kwargs):
16
+ t0 = benchmark.Timer(
17
+ stmt="f(*args, **kwargs)", globals={"args": args, "kwargs": kwargs, "f": f}
18
+ )
19
+ return t0.blocked_autorange().mean * 1e6
20
+
21
+ # Lets define the hyper-parameters of our input
22
+ batch_size = 32
23
+ max_sequence_len = 1024
24
+ num_heads = 32
25
+ embed_dimension = 32
26
+
27
+ dtype = torch.float16
28
+
29
+ query = torch.rand(
30
+ batch_size,
31
+ num_heads,
32
+ max_sequence_len,
33
+ embed_dimension,
34
+ device=device,
35
+ dtype=dtype,
36
+ )
37
+ key = torch.rand(
38
+ batch_size,
39
+ num_heads,
40
+ max_sequence_len,
41
+ embed_dimension,
42
+ device=device,
43
+ dtype=dtype,
44
+ )
45
+ value = torch.rand(
46
+ batch_size,
47
+ num_heads,
48
+ max_sequence_len,
49
+ embed_dimension,
50
+ device=device,
51
+ dtype=dtype,
52
+ )
53
+
54
+ print(f"q/k/v shape:", query.shape, key.shape, value.shape)
55
+
56
+ # Lets explore the speed of each of the 3 implementations
57
+ from torch.backends.cuda import SDPBackend, sdp_kernel
58
+
59
+ # Helpful arguments mapper
60
+ backend_map = {
61
+ SDPBackend.MATH: {
62
+ "enable_math": True,
63
+ "enable_flash": False,
64
+ "enable_mem_efficient": False,
65
+ },
66
+ SDPBackend.FLASH_ATTENTION: {
67
+ "enable_math": False,
68
+ "enable_flash": True,
69
+ "enable_mem_efficient": False,
70
+ },
71
+ SDPBackend.EFFICIENT_ATTENTION: {
72
+ "enable_math": False,
73
+ "enable_flash": False,
74
+ "enable_mem_efficient": True,
75
+ },
76
+ }
77
+
78
+ from torch.profiler import ProfilerActivity, profile, record_function
79
+
80
+ activities = [ProfilerActivity.CPU, ProfilerActivity.CUDA]
81
+
82
+ print(
83
+ f"The default implementation runs in {benchmark_torch_function_in_microseconds(F.scaled_dot_product_attention, query, key, value):.3f} microseconds"
84
+ )
85
+ with profile(
86
+ activities=activities, record_shapes=False, profile_memory=True
87
+ ) as prof:
88
+ with record_function("Default detailed stats"):
89
+ for _ in range(25):
90
+ o = F.scaled_dot_product_attention(query, key, value)
91
+ print(prof.key_averages().table(sort_by="cuda_time_total", row_limit=10))
92
+
93
+ print(
94
+ f"The math implementation runs in {benchmark_torch_function_in_microseconds(F.scaled_dot_product_attention, query, key, value):.3f} microseconds"
95
+ )
96
+ with sdp_kernel(**backend_map[SDPBackend.MATH]):
97
+ with profile(
98
+ activities=activities, record_shapes=False, profile_memory=True
99
+ ) as prof:
100
+ with record_function("Math implmentation stats"):
101
+ for _ in range(25):
102
+ o = F.scaled_dot_product_attention(query, key, value)
103
+ print(prof.key_averages().table(sort_by="cuda_time_total", row_limit=10))
104
+
105
+ with sdp_kernel(**backend_map[SDPBackend.FLASH_ATTENTION]):
106
+ try:
107
+ print(
108
+ f"The flash attention implementation runs in {benchmark_torch_function_in_microseconds(F.scaled_dot_product_attention, query, key, value):.3f} microseconds"
109
+ )
110
+ except RuntimeError:
111
+ print("FlashAttention is not supported. See warnings for reasons.")
112
+ with profile(
113
+ activities=activities, record_shapes=False, profile_memory=True
114
+ ) as prof:
115
+ with record_function("FlashAttention stats"):
116
+ for _ in range(25):
117
+ o = F.scaled_dot_product_attention(query, key, value)
118
+ print(prof.key_averages().table(sort_by="cuda_time_total", row_limit=10))
119
+
120
+ with sdp_kernel(**backend_map[SDPBackend.EFFICIENT_ATTENTION]):
121
+ try:
122
+ print(
123
+ f"The memory efficient implementation runs in {benchmark_torch_function_in_microseconds(F.scaled_dot_product_attention, query, key, value):.3f} microseconds"
124
+ )
125
+ except RuntimeError:
126
+ print("EfficientAttention is not supported. See warnings for reasons.")
127
+ with profile(
128
+ activities=activities, record_shapes=False, profile_memory=True
129
+ ) as prof:
130
+ with record_function("EfficientAttention stats"):
131
+ for _ in range(25):
132
+ o = F.scaled_dot_product_attention(query, key, value)
133
+ print(prof.key_averages().table(sort_by="cuda_time_total", row_limit=10))
134
+
135
+
136
+ def run_model(model, x, context):
137
+ return model(x, context)
138
+
139
+
140
+ def benchmark_transformer_blocks():
141
+ device = "cuda" if torch.cuda.is_available() else "cpu"
142
+ import torch.utils.benchmark as benchmark
143
+
144
+ def benchmark_torch_function_in_microseconds(f, *args, **kwargs):
145
+ t0 = benchmark.Timer(
146
+ stmt="f(*args, **kwargs)", globals={"args": args, "kwargs": kwargs, "f": f}
147
+ )
148
+ return t0.blocked_autorange().mean * 1e6
149
+
150
+ checkpoint = True
151
+ compile = False
152
+
153
+ batch_size = 32
154
+ h, w = 64, 64
155
+ context_len = 77
156
+ embed_dimension = 1024
157
+ context_dim = 1024
158
+ d_head = 64
159
+
160
+ transformer_depth = 4
161
+
162
+ n_heads = embed_dimension // d_head
163
+
164
+ dtype = torch.float16
165
+
166
+ model_native = SpatialTransformer(
167
+ embed_dimension,
168
+ n_heads,
169
+ d_head,
170
+ context_dim=context_dim,
171
+ use_linear=True,
172
+ use_checkpoint=checkpoint,
173
+ attn_type="softmax",
174
+ depth=transformer_depth,
175
+ sdp_backend=SDPBackend.FLASH_ATTENTION,
176
+ ).to(device)
177
+ model_efficient_attn = SpatialTransformer(
178
+ embed_dimension,
179
+ n_heads,
180
+ d_head,
181
+ context_dim=context_dim,
182
+ use_linear=True,
183
+ depth=transformer_depth,
184
+ use_checkpoint=checkpoint,
185
+ attn_type="softmax-xformers",
186
+ ).to(device)
187
+ if not checkpoint and compile:
188
+ print("compiling models")
189
+ model_native = torch.compile(model_native)
190
+ model_efficient_attn = torch.compile(model_efficient_attn)
191
+
192
+ x = torch.rand(batch_size, embed_dimension, h, w, device=device, dtype=dtype)
193
+ c = torch.rand(batch_size, context_len, context_dim, device=device, dtype=dtype)
194
+
195
+ from torch.profiler import ProfilerActivity, profile, record_function
196
+
197
+ activities = [ProfilerActivity.CPU, ProfilerActivity.CUDA]
198
+
199
+ with torch.autocast("cuda"):
200
+ print(
201
+ f"The native model runs in {benchmark_torch_function_in_microseconds(model_native.forward, x, c):.3f} microseconds"
202
+ )
203
+ print(
204
+ f"The efficientattn model runs in {benchmark_torch_function_in_microseconds(model_efficient_attn.forward, x, c):.3f} microseconds"
205
+ )
206
+
207
+ print(75 * "+")
208
+ print("NATIVE")
209
+ print(75 * "+")
210
+ torch.cuda.reset_peak_memory_stats()
211
+ with profile(
212
+ activities=activities, record_shapes=False, profile_memory=True
213
+ ) as prof:
214
+ with record_function("NativeAttention stats"):
215
+ for _ in range(25):
216
+ model_native(x, c)
217
+ print(prof.key_averages().table(sort_by="cuda_time_total", row_limit=10))
218
+ print(torch.cuda.max_memory_allocated() * 1e-9, "GB used by native block")
219
+
220
+ print(75 * "+")
221
+ print("Xformers")
222
+ print(75 * "+")
223
+ torch.cuda.reset_peak_memory_stats()
224
+ with profile(
225
+ activities=activities, record_shapes=False, profile_memory=True
226
+ ) as prof:
227
+ with record_function("xformers stats"):
228
+ for _ in range(25):
229
+ model_efficient_attn(x, c)
230
+ print(prof.key_averages().table(sort_by="cuda_time_total", row_limit=10))
231
+ print(torch.cuda.max_memory_allocated() * 1e-9, "GB used by xformers block")
232
+
233
+
234
+ def test01():
235
+ # conv1x1 vs linear
236
+ from sgm.util import count_params
237
+
238
+ conv = torch.nn.Conv2d(3, 32, kernel_size=1).cuda()
239
+ print(count_params(conv))
240
+ linear = torch.nn.Linear(3, 32).cuda()
241
+ print(count_params(linear))
242
+
243
+ print(conv.weight.shape)
244
+
245
+ # use same initialization
246
+ linear.weight = torch.nn.Parameter(conv.weight.squeeze(-1).squeeze(-1))
247
+ linear.bias = torch.nn.Parameter(conv.bias)
248
+
249
+ print(linear.weight.shape)
250
+
251
+ x = torch.randn(11, 3, 64, 64).cuda()
252
+
253
+ xr = einops.rearrange(x, "b c h w -> b (h w) c").contiguous()
254
+ print(xr.shape)
255
+ out_linear = linear(xr)
256
+ print(out_linear.mean(), out_linear.shape)
257
+
258
+ out_conv = conv(x)
259
+ print(out_conv.mean(), out_conv.shape)
260
+ print("done with test01.\n")
261
+
262
+
263
+ def test02():
264
+ # try cosine flash attention
265
+ import time
266
+
267
+ torch.backends.cuda.matmul.allow_tf32 = True
268
+ torch.backends.cudnn.allow_tf32 = True
269
+ torch.backends.cudnn.benchmark = True
270
+ print("testing cosine flash attention...")
271
+ DIM = 1024
272
+ SEQLEN = 4096
273
+ BS = 16
274
+
275
+ print(" softmax (vanilla) first...")
276
+ model = BasicTransformerBlock(
277
+ dim=DIM,
278
+ n_heads=16,
279
+ d_head=64,
280
+ dropout=0.0,
281
+ context_dim=None,
282
+ attn_mode="softmax",
283
+ ).cuda()
284
+ try:
285
+ x = torch.randn(BS, SEQLEN, DIM).cuda()
286
+ tic = time.time()
287
+ y = model(x)
288
+ toc = time.time()
289
+ print(y.shape, toc - tic)
290
+ except RuntimeError as e:
291
+ # likely oom
292
+ print(str(e))
293
+
294
+ print("\n now flash-cosine...")
295
+ model = BasicTransformerBlock(
296
+ dim=DIM,
297
+ n_heads=16,
298
+ d_head=64,
299
+ dropout=0.0,
300
+ context_dim=None,
301
+ attn_mode="flash-cosine",
302
+ ).cuda()
303
+ x = torch.randn(BS, SEQLEN, DIM).cuda()
304
+ tic = time.time()
305
+ y = model(x)
306
+ toc = time.time()
307
+ print(y.shape, toc - tic)
308
+ print("done with test02.\n")
309
+
310
+
311
+ if __name__ == "__main__":
312
+ # test01()
313
+ # test02()
314
+ # test03()
315
+
316
+ # benchmark_attn()
317
+ benchmark_transformer_blocks()
318
+
319
+ print("done.")
MindEye_Imagery/src/generative_models/scripts/util/detection/__init__.py ADDED
File without changes
MindEye_Imagery/src/generative_models/scripts/util/detection/nsfw_and_watermark_dectection.py ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ import clip
4
+ import numpy as np
5
+ import torch
6
+ import torchvision.transforms as T
7
+ from PIL import Image
8
+
9
+ RESOURCES_ROOT = "scripts/util/detection/"
10
+
11
+
12
+ def predict_proba(X, weights, biases):
13
+ logits = X @ weights.T + biases
14
+ proba = np.where(
15
+ logits >= 0, 1 / (1 + np.exp(-logits)), np.exp(logits) / (1 + np.exp(logits))
16
+ )
17
+ return proba.T
18
+
19
+
20
+ def load_model_weights(path: str):
21
+ model_weights = np.load(path)
22
+ return model_weights["weights"], model_weights["biases"]
23
+
24
+
25
+ def clip_process_images(images: torch.Tensor) -> torch.Tensor:
26
+ min_size = min(images.shape[-2:])
27
+ return T.Compose(
28
+ [
29
+ T.CenterCrop(min_size), # TODO: this might affect the watermark, check this
30
+ T.Resize(224, interpolation=T.InterpolationMode.BICUBIC, antialias=True),
31
+ T.Normalize(
32
+ (0.48145466, 0.4578275, 0.40821073),
33
+ (0.26862954, 0.26130258, 0.27577711),
34
+ ),
35
+ ]
36
+ )(images)
37
+
38
+
39
+ class DeepFloydDataFiltering(object):
40
+ def __init__(
41
+ self, verbose: bool = False, device: torch.device = torch.device("cpu")
42
+ ):
43
+ super().__init__()
44
+ self.verbose = verbose
45
+ self._device = None
46
+ self.clip_model, _ = clip.load("ViT-L/14", device=device)
47
+ self.clip_model.eval()
48
+
49
+ self.cpu_w_weights, self.cpu_w_biases = load_model_weights(
50
+ os.path.join(RESOURCES_ROOT, "w_head_v1.npz")
51
+ )
52
+ self.cpu_p_weights, self.cpu_p_biases = load_model_weights(
53
+ os.path.join(RESOURCES_ROOT, "p_head_v1.npz")
54
+ )
55
+ self.w_threshold, self.p_threshold = 0.5, 0.5
56
+
57
+ @torch.inference_mode()
58
+ def __call__(self, images: torch.Tensor) -> torch.Tensor:
59
+ imgs = clip_process_images(images)
60
+ if self._device is None:
61
+ self._device = next(p for p in self.clip_model.parameters()).device
62
+ image_features = self.clip_model.encode_image(imgs.to(self._device))
63
+ image_features = image_features.detach().cpu().numpy().astype(np.float16)
64
+ p_pred = predict_proba(image_features, self.cpu_p_weights, self.cpu_p_biases)
65
+ w_pred = predict_proba(image_features, self.cpu_w_weights, self.cpu_w_biases)
66
+ print(f"p_pred = {p_pred}, w_pred = {w_pred}") if self.verbose else None
67
+ query = p_pred > self.p_threshold
68
+ if query.sum() > 0:
69
+ print(f"Hit for p_threshold: {p_pred}") if self.verbose else None
70
+ images[query] = T.GaussianBlur(99, sigma=(100.0, 100.0))(images[query])
71
+ query = w_pred > self.w_threshold
72
+ if query.sum() > 0:
73
+ print(f"Hit for w_threshold: {w_pred}") if self.verbose else None
74
+ images[query] = T.GaussianBlur(99, sigma=(100.0, 100.0))(images[query])
75
+ return images
76
+
77
+
78
+ def load_img(path: str) -> torch.Tensor:
79
+ image = Image.open(path)
80
+ if not image.mode == "RGB":
81
+ image = image.convert("RGB")
82
+ image_transforms = T.Compose(
83
+ [
84
+ T.ToTensor(),
85
+ ]
86
+ )
87
+ return image_transforms(image)[None, ...]
88
+
89
+
90
+ def test(root):
91
+ from einops import rearrange
92
+
93
+ filter = DeepFloydDataFiltering(verbose=True)
94
+ for p in os.listdir((root)):
95
+ print(f"running on {p}...")
96
+ img = load_img(os.path.join(root, p))
97
+ filtered_img = filter(img)
98
+ filtered_img = rearrange(
99
+ 255.0 * (filtered_img.numpy())[0], "c h w -> h w c"
100
+ ).astype(np.uint8)
101
+ Image.fromarray(filtered_img).save(
102
+ os.path.join(root, f"{os.path.splitext(p)[0]}-filtered.jpg")
103
+ )
104
+
105
+
106
+ if __name__ == "__main__":
107
+ import fire
108
+
109
+ fire.Fire(test)
110
+ print("done.")
MindEye_Imagery/src/vdvae/.ipynb_checkpoints/vae-checkpoint.py ADDED
@@ -0,0 +1,252 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from torch import nn
3
+ from torch.nn import functional as F
4
+ from vae_helpers import HModule, get_1x1, get_3x3, DmolNet, draw_gaussian_diag_samples, gaussian_analytical_kl
5
+ from collections import defaultdict
6
+ import numpy as np
7
+ import itertools
8
+
9
+
10
+ class Block(nn.Module):
11
+ def __init__(self, in_width, middle_width, out_width, down_rate=None, residual=False, use_3x3=True, zero_last=False):
12
+ super().__init__()
13
+ self.down_rate = down_rate
14
+ self.residual = residual
15
+ self.c1 = get_1x1(in_width, middle_width)
16
+ self.c2 = get_3x3(middle_width, middle_width) if use_3x3 else get_1x1(middle_width, middle_width)
17
+ self.c3 = get_3x3(middle_width, middle_width) if use_3x3 else get_1x1(middle_width, middle_width)
18
+ self.c4 = get_1x1(middle_width, out_width, zero_weights=zero_last)
19
+
20
+ def forward(self, x):
21
+ xhat = self.c1(F.gelu(x))
22
+ xhat = self.c2(F.gelu(xhat))
23
+ xhat = self.c3(F.gelu(xhat))
24
+ xhat = self.c4(F.gelu(xhat))
25
+ out = x + xhat if self.residual else xhat
26
+ if self.down_rate is not None:
27
+ out = F.avg_pool2d(out, kernel_size=self.down_rate, stride=self.down_rate)
28
+ return out
29
+
30
+
31
+ def parse_layer_string(s):
32
+ layers = []
33
+ for ss in s.split(','):
34
+ if 'x' in ss:
35
+ res, num = ss.split('x')
36
+ count = int(num)
37
+ layers += [(int(res), None) for _ in range(count)]
38
+ elif 'm' in ss:
39
+ res, mixin = [int(a) for a in ss.split('m')]
40
+ layers.append((res, mixin))
41
+ elif 'd' in ss:
42
+ res, down_rate = [int(a) for a in ss.split('d')]
43
+ layers.append((res, down_rate))
44
+ else:
45
+ res = int(ss)
46
+ layers.append((res, None))
47
+ return layers
48
+
49
+
50
+ def pad_channels(t, width):
51
+ d1, d2, d3, d4 = t.shape
52
+ empty = torch.zeros(d1, width, d3, d4, device=t.device)
53
+ empty[:, :d2, :, :] = t
54
+ return empty
55
+
56
+
57
+ def get_width_settings(width, s):
58
+ mapping = defaultdict(lambda: width)
59
+ if s:
60
+ s = s.split(',')
61
+ for ss in s:
62
+ k, v = ss.split(':')
63
+ mapping[int(k)] = int(v)
64
+ return mapping
65
+
66
+
67
+ class Encoder(HModule):
68
+ def build(self):
69
+ H = self.H
70
+ self.in_conv = get_3x3(H.image_channels, H.width)
71
+ self.widths = get_width_settings(H.width, H.custom_width_str)
72
+ enc_blocks = []
73
+ blockstr = parse_layer_string(H.enc_blocks)
74
+ for res, down_rate in blockstr:
75
+ use_3x3 = res > 2 # Don't use 3x3s for 1x1, 2x2 patches
76
+ enc_blocks.append(Block(self.widths[res], int(self.widths[res] * H.bottleneck_multiple), self.widths[res], down_rate=down_rate, residual=True, use_3x3=use_3x3))
77
+ n_blocks = len(blockstr)
78
+ for b in enc_blocks:
79
+ b.c4.weight.data *= np.sqrt(1 / n_blocks)
80
+ self.enc_blocks = nn.ModuleList(enc_blocks)
81
+
82
+ def forward(self, x):
83
+ x = x.permute(0, 3, 1, 2).contiguous()
84
+ x = self.in_conv(x)
85
+ activations = {}
86
+ activations[x.shape[2]] = x
87
+ for block in self.enc_blocks:
88
+ x = block(x)
89
+ res = x.shape[2]
90
+ x = x if x.shape[1] == self.widths[res] else pad_channels(x, self.widths[res])
91
+ activations[res] = x
92
+ return activations
93
+
94
+
95
+ class DecBlock(nn.Module):
96
+ def __init__(self, H, res, mixin, n_blocks):
97
+ super().__init__()
98
+ self.base = res
99
+ self.mixin = mixin
100
+ self.H = H
101
+ self.widths = get_width_settings(H.width, H.custom_width_str)
102
+ width = self.widths[res]
103
+ use_3x3 = res > 2
104
+ cond_width = int(width * H.bottleneck_multiple)
105
+ self.zdim = H.zdim
106
+ self.enc = Block(width * 2, cond_width, H.zdim * 2, residual=False, use_3x3=use_3x3)
107
+ self.prior = Block(width, cond_width, H.zdim * 2 + width, residual=False, use_3x3=use_3x3, zero_last=True)
108
+ self.z_proj = get_1x1(H.zdim, width)
109
+ self.z_proj.weight.data *= np.sqrt(1 / n_blocks)
110
+ self.resnet = Block(width, cond_width, width, residual=True, use_3x3=use_3x3)
111
+ self.resnet.c4.weight.data *= np.sqrt(1 / n_blocks)
112
+ self.z_fn = lambda x: self.z_proj(x)
113
+
114
+ def sample(self, x, acts):
115
+ qm, qv = self.enc(torch.cat([x, acts], dim=1)).chunk(2, dim=1)
116
+ feats = self.prior(x)
117
+ pm, pv, xpp = feats[:, :self.zdim, ...], feats[:, self.zdim:self.zdim * 2, ...], feats[:, self.zdim * 2:, ...]
118
+ x = x + xpp
119
+ z = draw_gaussian_diag_samples(qm, qv)
120
+ kl = gaussian_analytical_kl(qm, pm, qv, pv)
121
+ return z, x, kl
122
+
123
+ def sample_uncond(self, x, t=None, lvs=None):
124
+ n, c, h, w = x.shape
125
+ feats = self.prior(x)
126
+ pm, pv, xpp = feats[:, :self.zdim, ...], feats[:, self.zdim:self.zdim * 2, ...], feats[:, self.zdim * 2:, ...]
127
+ x = x + xpp
128
+ if lvs is not None:
129
+ z = lvs
130
+ else:
131
+ if t is not None:
132
+ pv = pv + torch.ones_like(pv) * np.log(t)
133
+ z = draw_gaussian_diag_samples(pm, pv)
134
+ return z, x
135
+
136
+ def get_inputs(self, xs, activations):
137
+ acts = activations[self.base]
138
+ try:
139
+ x = xs[self.base]
140
+ except KeyError:
141
+ x = torch.zeros_like(acts)
142
+ if acts.shape[0] != x.shape[0]:
143
+ x = x.repeat(acts.shape[0], 1, 1, 1)
144
+ return x, acts
145
+
146
+ def forward(self, xs, activations, get_latents=False):
147
+ x, acts = self.get_inputs(xs, activations)
148
+ if self.mixin is not None:
149
+ x = x + F.interpolate(xs[self.mixin][:, :x.shape[1], ...], scale_factor=self.base // self.mixin)
150
+ z, x, kl = self.sample(x, acts)
151
+ x = x + self.z_fn(z)
152
+ x = self.resnet(x)
153
+ xs[self.base] = x
154
+ if get_latents:
155
+ return xs, dict(z=z.detach(), kl=kl)
156
+ return xs, dict(kl=kl)
157
+
158
+ def forward_uncond(self, xs, t=None, lvs=None):
159
+ try:
160
+ x = xs[self.base]
161
+ except KeyError:
162
+ ref = xs[list(xs.keys())[0]]
163
+ x = torch.zeros(dtype=ref.dtype, size=(ref.shape[0], self.widths[self.base], self.base, self.base), device=ref.device)
164
+ if self.mixin is not None:
165
+ x = x + F.interpolate(xs[self.mixin][:, :x.shape[1], ...], scale_factor=self.base // self.mixin)
166
+ z, x = self.sample_uncond(x, t, lvs=lvs)
167
+ x = x + self.z_fn(z)
168
+ x = self.resnet(x)
169
+ xs[self.base] = x
170
+ return xs
171
+
172
+
173
+ class Decoder(HModule):
174
+
175
+ def build(self):
176
+ H = self.H
177
+ resos = set()
178
+ dec_blocks = []
179
+ self.widths = get_width_settings(H.width, H.custom_width_str)
180
+ blocks = parse_layer_string(H.dec_blocks)
181
+ for idx, (res, mixin) in enumerate(blocks):
182
+ dec_blocks.append(DecBlock(H, res, mixin, n_blocks=len(blocks)))
183
+ resos.add(res)
184
+ self.resolutions = sorted(resos)
185
+ self.dec_blocks = nn.ModuleList(dec_blocks)
186
+ self.bias_xs = nn.ParameterList([nn.Parameter(torch.zeros(1, self.widths[res], res, res)) for res in self.resolutions if res <= H.no_bias_above])
187
+ self.out_net = DmolNet(H)
188
+ self.gain = nn.Parameter(torch.ones(1, H.width, 1, 1))
189
+ self.bias = nn.Parameter(torch.zeros(1, H.width, 1, 1))
190
+ self.final_fn = lambda x: x * self.gain + self.bias
191
+
192
+ def forward(self, activations, get_latents=False):
193
+ stats = []
194
+ xs = {a.shape[2]: a for a in self.bias_xs}
195
+ for block in self.dec_blocks:
196
+ xs, block_stats = block(xs, activations, get_latents=get_latents)
197
+ stats.append(block_stats)
198
+ xs[self.H.image_size] = self.final_fn(xs[self.H.image_size])
199
+ return xs[self.H.image_size], stats
200
+
201
+ def forward_uncond(self, n, t=None, y=None):
202
+ xs = {}
203
+ for bias in self.bias_xs:
204
+ xs[bias.shape[2]] = bias.repeat(n, 1, 1, 1)
205
+ for idx, block in enumerate(self.dec_blocks):
206
+ try:
207
+ temp = t[idx]
208
+ except TypeError:
209
+ temp = t
210
+ xs = block.forward_uncond(xs, temp)
211
+ xs[self.H.image_size] = self.final_fn(xs[self.H.image_size])
212
+ return xs[self.H.image_size]
213
+
214
+ def forward_manual_latents(self, n, latents, t=None):
215
+ xs = {}
216
+ for bias in self.bias_xs:
217
+ xs[bias.shape[2]] = bias.repeat(n, 1, 1, 1)
218
+ for block, lvs in itertools.zip_longest(self.dec_blocks, latents):
219
+ xs = block.forward_uncond(xs, t, lvs=lvs)
220
+ xs[self.H.image_size] = self.final_fn(xs[self.H.image_size])
221
+ return xs[self.H.image_size]
222
+
223
+
224
+ class VAE(HModule):
225
+ def build(self):
226
+ self.encoder = Encoder(self.H)
227
+ self.decoder = Decoder(self.H)
228
+
229
+ def forward(self, x, x_target):
230
+ activations = self.encoder.forward(x)
231
+ px_z, stats = self.decoder.forward(activations)
232
+ distortion_per_pixel = self.decoder.out_net.nll(px_z, x_target)
233
+ rate_per_pixel = torch.zeros_like(distortion_per_pixel)
234
+ ndims = np.prod(x.shape[1:])
235
+ for statdict in stats:
236
+ rate_per_pixel += statdict['kl'].sum(dim=(1, 2, 3))
237
+ rate_per_pixel /= ndims
238
+ elbo = (distortion_per_pixel + rate_per_pixel).mean()
239
+ return dict(elbo=elbo, distortion=distortion_per_pixel.mean(), rate=rate_per_pixel.mean())
240
+
241
+ def forward_get_latents(self, x):
242
+ activations = self.encoder.forward(x)
243
+ _, stats = self.decoder.forward(activations, get_latents=True)
244
+ return stats
245
+
246
+ def forward_uncond_samples(self, n_batch, t=None):
247
+ px_z = self.decoder.forward_uncond(n_batch, t=t)
248
+ return self.decoder.out_net.sample(px_z)
249
+
250
+ def forward_samples_set_latents(self, n_batch, latents, t=None):
251
+ px_z = self.decoder.forward_manual_latents(n_batch, latents, t=t)
252
+ return self.decoder.out_net.sample(px_z)
MindEye_Imagery/src/vdvae/LICENSE.md ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ Copyright © 2020 OpenAI
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
MindEye_Imagery/src/vdvae/README.md ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Very Deep VAEs
2
+
3
+ Repository for the paper "Very Deep VAEs Generalize Autoregressive Models and Can Outperform Them on Images" (https://arxiv.org/abs/2011.10650)
4
+
5
+ Some model samples and a visualization of how it generates them:
6
+ ![image](header-image.png)
7
+
8
+ This repository is tested with PyTorch 1.6, CUDA 10.1, Numpy 1.16, Ubuntu 18.04, and V100 GPUs.
9
+
10
+ # Setup
11
+ Several additional packages are required, including NVIDIA Apex:
12
+ ```
13
+ pip install imageio
14
+ pip install mpi4py
15
+ pip install sklearn
16
+ git clone https://github.com/NVIDIA/apex
17
+ cd apex
18
+ pip install -v --no-cache-dir --global-option="--cpp_ext" --global-option="--cuda_ext" ./
19
+ cd ..
20
+ ```
21
+
22
+ Also, you'll have to download the data, depending on which one you want to run:
23
+ ```
24
+ ./setup_cifar10.sh
25
+ ./setup_imagenet.sh imagenet32
26
+ ./setup_imagenet.sh imagenet64
27
+ ./setup_ffhq256.sh
28
+ ./setup_ffhq1024.sh /path/to/images1024x1024 # this one depends on you first downloading the subfolder `images_1024x1024` from https://github.com/NVlabs/ffhq-dataset on your own
29
+ ```
30
+
31
+ # Training models
32
+ Hyperparameters all reside in `hps.py`. We use 2 gpus for our CIFAR-10 runs, and 32 for the rest of the models. (Using a lower batch size is also possible and results in slower learning, and may also require a lower learning rate).
33
+
34
+ The `mpiexec` arguments you use for runs with more than 1 node depend on the configuration of your system, so please adapt accordingly.
35
+
36
+ ```bash
37
+ mpiexec -n 2 python train.py --hps cifar10
38
+ mpiexec -n 32 python train.py --hps imagenet32
39
+ mpiexec -n 32 python train.py --hps imagenet64
40
+ mpiexec -n 32 python train.py --hps ffhq256
41
+ mpiexec -n 32 python train.py --hps ffhq1024
42
+ ```
43
+
44
+ # Restoring saved models
45
+ For convenience, we have included training checkpoints which can be restored in order to confirm performance, continue training, or generate samples.
46
+
47
+ ### ImageNet 32
48
+ ```bash
49
+ # 119M parameter model, trained for 1.7M iters (about 2.5 weeks on 32 V100)
50
+ wget https://openaipublic.blob.core.windows.net/very-deep-vaes-assets/vdvae-assets/imagenet32-iter-1700000-log.jsonl
51
+ wget https://openaipublic.blob.core.windows.net/very-deep-vaes-assets/vdvae-assets/imagenet32-iter-1700000-model.th
52
+ wget https://openaipublic.blob.core.windows.net/very-deep-vaes-assets/vdvae-assets/imagenet32-iter-1700000-model-ema.th
53
+ wget https://openaipublic.blob.core.windows.net/very-deep-vaes-assets/vdvae-assets/imagenet32-iter-1700000-opt.th
54
+ python train.py --hps imagenet32 --restore_path imagenet32-iter-1700000-model.th --restore_ema_path imagenet32-iter-1700000-model-ema.th --restore_log_path imagenet32-iter-1700000-log.jsonl --restore_optimizer_path imagenet32-iter-1700000-opt.th --test_eval
55
+ # should give 2.6364 nats per dim, which is 3.80 bpd
56
+ ```
57
+
58
+ ### ImageNet 64
59
+ ```bash
60
+ # 125M parameter model, trained for 1.6M iters (about 2.5 weeks on 32 V100)
61
+ wget https://openaipublic.blob.core.windows.net/very-deep-vaes-assets/vdvae-assets-2/imagenet64-iter-1600000-log.jsonl
62
+ wget https://openaipublic.blob.core.windows.net/very-deep-vaes-assets/vdvae-assets-2/imagenet64-iter-1600000-model.th
63
+ wget https://openaipublic.blob.core.windows.net/very-deep-vaes-assets/vdvae-assets-2/imagenet64-iter-1600000-model-ema.th
64
+ wget https://openaipublic.blob.core.windows.net/very-deep-vaes-assets/vdvae-assets-2/imagenet64-iter-1600000-opt.th
65
+ python train.py --hps imagenet64 --restore_path imagenet64-iter-1600000-model.th --restore_ema_path imagenet64-iter-1600000-model-ema.th --restore_log_path imagenet64-iter-1600000-log.jsonl --restore_optimizer_path imagenet64-iter-1600000-opt.th --test_eval
66
+ # should be 2.44 nats, or 3.52 bits per dim
67
+ ```
68
+
69
+ ### FFHQ-256
70
+ ```bash
71
+ # 115M parameters, trained for 1.7M iterations (or about 2.5 weeks) on 32 V100
72
+ wget https://openaipublic.blob.core.windows.net/very-deep-vaes-assets/vdvae-assets/ffhq256-iter-1700000-log.jsonl
73
+ wget https://openaipublic.blob.core.windows.net/very-deep-vaes-assets/vdvae-assets/ffhq256-iter-1700000-model.th
74
+ wget https://openaipublic.blob.core.windows.net/very-deep-vaes-assets/vdvae-assets/ffhq256-iter-1700000-model-ema.th
75
+ wget https://openaipublic.blob.core.windows.net/very-deep-vaes-assets/vdvae-assets/ffhq256-iter-1700000-opt.th
76
+ python train.py --hps ffhq256 --restore_path ffhq256-iter-1700000-model.th --restore_ema_path ffhq256-iter-1700000-model-ema.th --restore_log_path ffhq256-iter-1700000-log.jsonl --restore_optimizer_path ffhq256-iter-1700000-opt.th --test_eval
77
+ # should be 0.4232 nats, or 0.61 bits per dim
78
+ ```
79
+
80
+ ### FFHQ-1024
81
+ ```bash
82
+ # 115M parameters, trained for 1.7M iterations (or about 2.5 weeks) on 32 V100
83
+ wget https://openaipublic.blob.core.windows.net/very-deep-vaes-assets/vdvae-assets/ffhq1024-iter-1700000-log.jsonl
84
+ wget https://openaipublic.blob.core.windows.net/very-deep-vaes-assets/vdvae-assets/ffhq1024-iter-1700000-model.th
85
+ wget https://openaipublic.blob.core.windows.net/very-deep-vaes-assets/vdvae-assets/ffhq1024-iter-1700000-model-ema.th
86
+ wget https://openaipublic.blob.core.windows.net/very-deep-vaes-assets/vdvae-assets/ffhq1024-iter-1700000-opt.th
87
+ python train.py --hps ffhq1024 --restore_path ffhq1024-iter-1700000-model.th --restore_ema_path ffhq1024-iter-1700000-model-ema.th --restore_log_path ffhq1024-iter-1700000-log.jsonl --restore_optimizer_path ffhq1024-iter-1700000-opt.th --test_eval
88
+ # should be 1.678 nats, or 2.42 bits per dim
89
+ ```
90
+
91
+ ### CIFAR-10
92
+ ```bash
93
+ # 39M parameters, trained for ~1M iterations with early stopping (a little less than a week on 2 GPUs)
94
+ wget https://openaipublic.blob.core.windows.net/very-deep-vaes-assets/vdvae-assets-2/cifar10-seed0-iter-900000-model-ema.th
95
+ wget https://openaipublic.blob.core.windows.net/very-deep-vaes-assets/vdvae-assets-2/cifar10-seed1-iter-1050000-model-ema.th
96
+ wget https://openaipublic.blob.core.windows.net/very-deep-vaes-assets/vdvae-assets-2/cifar10-seed2-iter-650000-model-ema.th
97
+ wget https://openaipublic.blob.core.windows.net/very-deep-vaes-assets/vdvae-assets-2/cifar10-seed3-iter-1050000-model-ema.th
98
+ python train.py --hps cifar10 --restore_ema_path cifar10-seed0-iter-900000-model-ema.th --test_eval
99
+ python train.py --hps cifar10 --restore_ema_path cifar10-seed1-iter-1050000-model-ema.th --test_eval
100
+ python train.py --hps cifar10 --restore_ema_path cifar10-seed2-iter-650000-model-ema.th --test_eval
101
+ python train.py --hps cifar10 --restore_ema_path cifar10-seed3-iter-1050000-model-ema.th --test_eval
102
+ # seeds 0, 1, 2, 3 should give 2.879, 2.842, 2.898, 2.864 bits per dim, for an average of 2.87 bits per dim.
103
+ ```
MindEye_Imagery/src/vdvae/__pycache__/data.cpython-311.pyc ADDED
Binary file (11 kB). View file
 
MindEye_Imagery/src/vdvae/__pycache__/hps.cpython-311.pyc ADDED
Binary file (9.83 kB). View file
 
MindEye_Imagery/src/vdvae/__pycache__/image_utils.cpython-311.pyc ADDED
Binary file (4.66 kB). View file
 
MindEye_Imagery/src/vdvae/__pycache__/model_utils.cpython-311.pyc ADDED
Binary file (4.91 kB). View file
 
MindEye_Imagery/src/vdvae/__pycache__/train_helpers.cpython-311.pyc ADDED
Binary file (14.9 kB). View file
 
MindEye_Imagery/src/vdvae/__pycache__/vae.cpython-311.pyc ADDED
Binary file (21.4 kB). View file
 
MindEye_Imagery/src/vdvae/__pycache__/vae_helpers.cpython-311.pyc ADDED
Binary file (14.5 kB). View file
 
MindEye_Imagery/src/vdvae/__pycache__/vdvae_utils.cpython-311.pyc ADDED
Binary file (8.52 kB). View file
 
MindEye_Imagery/src/vdvae/data.py ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import pickle
3
+ import os
4
+ import torch
5
+ from torch.utils.data import TensorDataset
6
+ from torchvision.datasets import ImageFolder
7
+ import torchvision.transforms as transforms
8
+ from sklearn.model_selection import train_test_split
9
+
10
+
11
+ def set_up_data(H):
12
+ shift_loss = -127.5
13
+ scale_loss = 1. / 127.5
14
+ if H.dataset == 'imagenet32':
15
+ trX, vaX, teX = imagenet32(H.data_root)
16
+ H.image_size = 32
17
+ H.image_channels = 3
18
+ shift = -116.2373
19
+ scale = 1. / 69.37404
20
+ elif H.dataset == 'imagenet64':
21
+ trX, vaX, teX = imagenet64(H.data_root)
22
+ H.image_size = 64
23
+ H.image_channels = 3
24
+ shift = -115.92961967
25
+ scale = 1. / 69.37404
26
+ elif H.dataset == 'ffhq_256':
27
+ trX, vaX, teX = ffhq256(H.data_root)
28
+ H.image_size = 256
29
+ H.image_channels = 3
30
+ shift = -112.8666757481
31
+ scale = 1. / 69.84780273
32
+ elif H.dataset == 'ffhq_1024':
33
+ trX, vaX, teX = ffhq1024(H.data_root)
34
+ H.image_size = 1024
35
+ H.image_channels = 3
36
+ shift = -0.4387
37
+ scale = 1.0 / 0.2743
38
+ shift_loss = -0.5
39
+ scale_loss = 2.0
40
+ elif H.dataset == 'cifar10':
41
+ (trX, _), (vaX, _), (teX, _) = cifar10(H.data_root, one_hot=False)
42
+ H.image_size = 32
43
+ H.image_channels = 3
44
+ shift = -120.63838
45
+ scale = 1. / 64.16736
46
+ else:
47
+ raise ValueError('unknown dataset: ', H.dataset)
48
+
49
+ do_low_bit = H.dataset in ['ffhq_256']
50
+
51
+ if H.test_eval:
52
+ print('DOING TEST')
53
+ eval_dataset = teX
54
+ else:
55
+ eval_dataset = vaX
56
+
57
+ shift = torch.tensor([shift]).cuda().view(1, 1, 1, 1)
58
+ scale = torch.tensor([scale]).cuda().view(1, 1, 1, 1)
59
+ shift_loss = torch.tensor([shift_loss]).cuda().view(1, 1, 1, 1)
60
+ scale_loss = torch.tensor([scale_loss]).cuda().view(1, 1, 1, 1)
61
+
62
+ if H.dataset == 'ffhq_1024':
63
+ train_data = ImageFolder(trX, transforms.ToTensor())
64
+ valid_data = ImageFolder(eval_dataset, transforms.ToTensor())
65
+ untranspose = True
66
+ else:
67
+ train_data = TensorDataset(torch.as_tensor(trX))
68
+ valid_data = TensorDataset(torch.as_tensor(eval_dataset))
69
+ untranspose = False
70
+
71
+ def preprocess_func(x):
72
+ nonlocal shift
73
+ nonlocal scale
74
+ nonlocal shift_loss
75
+ nonlocal scale_loss
76
+ nonlocal do_low_bit
77
+ nonlocal untranspose
78
+ 'takes in a data example and returns the preprocessed input'
79
+ 'as well as the input processed for the loss'
80
+ if untranspose:
81
+ x[0] = x[0].permute(0, 2, 3, 1)
82
+ inp = x[0].cuda(non_blocking=True).float()
83
+ out = inp.clone()
84
+ inp.add_(shift).mul_(scale)
85
+ if do_low_bit:
86
+ # 5 bits of precision
87
+ out.mul_(1. / 8.).floor_().mul_(8.)
88
+ out.add_(shift_loss).mul_(scale_loss)
89
+ return inp, out
90
+
91
+ return H, train_data, valid_data, preprocess_func
92
+
93
+
94
+ def mkdir_p(path):
95
+ os.makedirs(path, exist_ok=True)
96
+
97
+
98
+ def flatten(outer):
99
+ return [el for inner in outer for el in inner]
100
+
101
+
102
+ def unpickle_cifar10(file):
103
+ fo = open(file, 'rb')
104
+ data = pickle.load(fo, encoding='bytes')
105
+ fo.close()
106
+ data = dict(zip([k.decode() for k in data.keys()], data.values()))
107
+ return data
108
+
109
+
110
+ def imagenet32(data_root):
111
+ trX = np.load(os.path.join(data_root, 'imagenet32-train.npy'), mmap_mode='r')
112
+ np.random.seed(42)
113
+ tr_va_split_indices = np.random.permutation(trX.shape[0])
114
+ train = trX[tr_va_split_indices[:-5000]]
115
+ valid = trX[tr_va_split_indices[-5000:]]
116
+ test = np.load(os.path.join(data_root, 'imagenet32-valid.npy'), mmap_mode='r')
117
+ return train, valid, test
118
+
119
+
120
+ def imagenet64(data_root):
121
+ trX = np.load(os.path.join(data_root, 'imagenet64-train.npy'), mmap_mode='r')
122
+ np.random.seed(42)
123
+ tr_va_split_indices = np.random.permutation(trX.shape[0])
124
+ train = trX[tr_va_split_indices[:-5000]]
125
+ valid = trX[tr_va_split_indices[-5000:]]
126
+ test = np.load(os.path.join(data_root, 'imagenet64-valid.npy'), mmap_mode='r') # this is test.
127
+ return train, valid, test
128
+
129
+
130
+ def ffhq1024(data_root):
131
+ # we did not significantly tune hyperparameters on ffhq-1024, and so simply evaluate on the test set
132
+ return os.path.join(data_root, 'ffhq1024/train'), os.path.join(data_root, 'ffhq1024/valid'), os.path.join(data_root, 'ffhq1024/valid')
133
+
134
+
135
+ def ffhq256(data_root):
136
+ trX = np.load(os.path.join(data_root, 'ffhq-256.npy'), mmap_mode='r')
137
+ np.random.seed(5)
138
+ tr_va_split_indices = np.random.permutation(trX.shape[0])
139
+ train = trX[tr_va_split_indices[:-7000]]
140
+ valid = trX[tr_va_split_indices[-7000:]]
141
+ # we did not significantly tune hyperparameters on ffhq-256, and so simply evaluate on the test set
142
+ return train, valid, valid
143
+
144
+
145
+ def cifar10(data_root, one_hot=True):
146
+ tr_data = [unpickle_cifar10(os.path.join(data_root, 'cifar-10-batches-py/', 'data_batch_%d' % i)) for i in range(1, 6)]
147
+ trX = np.vstack(data['data'] for data in tr_data)
148
+ trY = np.asarray(flatten([data['labels'] for data in tr_data]))
149
+ te_data = unpickle_cifar10(os.path.join(data_root, 'cifar-10-batches-py/', 'test_batch'))
150
+ teX = np.asarray(te_data['data'])
151
+ teY = np.asarray(te_data['labels'])
152
+ trX = trX.reshape(-1, 3, 32, 32).transpose(0, 2, 3, 1)
153
+ teX = teX.reshape(-1, 3, 32, 32).transpose(0, 2, 3, 1)
154
+ trX, vaX, trY, vaY = train_test_split(trX, trY, test_size=5000, random_state=11172018)
155
+ if one_hot:
156
+ trY = np.eye(10, dtype=np.float32)[trY]
157
+ vaY = np.eye(10, dtype=np.float32)[vaY]
158
+ teY = np.eye(10, dtype=np.float32)[teY]
159
+ else:
160
+ trY = np.reshape(trY, [-1, 1])
161
+ vaY = np.reshape(vaY, [-1, 1])
162
+ teY = np.reshape(teY, [-1, 1])
163
+ return (trX, trY), (vaX, vaY), (teX, teY)
MindEye_Imagery/src/vdvae/files_to_npy.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ import numpy as np
3
+ import imageio
4
+ import glob
5
+ import os
6
+
7
+ if __name__ == "__main__":
8
+ print("moving images in", sys.argv[1], "to", sys.argv[2])
9
+ files = glob.glob(os.path.join(sys.argv[1], "*.png"))
10
+ shape = imageio.imread(files[0]).shape
11
+ data = np.zeros(shape=(len(files), *shape), dtype=np.uint8)
12
+ for idx, f in enumerate(files):
13
+ data[idx] = imageio.imread(f)
14
+ np.save(sys.argv[2], data)
MindEye_Imagery/src/vdvae/hps.py ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ HPARAMS_REGISTRY = {}
2
+
3
+
4
+ class Hyperparams(dict):
5
+ def __getattr__(self, attr):
6
+ try:
7
+ return self[attr]
8
+ except KeyError:
9
+ return None
10
+
11
+ def __setattr__(self, attr, value):
12
+ self[attr] = value
13
+
14
+
15
+ cifar10 = Hyperparams()
16
+ cifar10.width = 384
17
+ cifar10.lr = 0.0002
18
+ cifar10.zdim = 16
19
+ cifar10.wd = 0.01
20
+ cifar10.dec_blocks = "1x1,4m1,4x2,8m4,8x5,16m8,16x10,32m16,32x21"
21
+ cifar10.enc_blocks = "32x11,32d2,16x6,16d2,8x6,8d2,4x3,4d4,1x3"
22
+ cifar10.warmup_iters = 100
23
+ cifar10.dataset = 'cifar10'
24
+ cifar10.n_batch = 16
25
+ cifar10.ema_rate = 0.9999
26
+ HPARAMS_REGISTRY['cifar10'] = cifar10
27
+
28
+
29
+ i32 = Hyperparams()
30
+ i32.update(cifar10)
31
+ i32.dataset = 'imagenet32'
32
+ i32.ema_rate = 0.999
33
+ i32.dec_blocks = "1x2,4m1,4x4,8m4,8x9,16m8,16x19,32m16,32x40"
34
+ i32.enc_blocks = "32x15,32d2,16x9,16d2,8x8,8d2,4x6,4d4,1x6"
35
+ i32.width = 512
36
+ i32.n_batch = 8
37
+ i32.lr = 0.00015
38
+ i32.grad_clip = 200.
39
+ i32.skip_threshold = 300.
40
+ i32.epochs_per_eval = 1
41
+ i32.epochs_per_eval_save = 1
42
+ HPARAMS_REGISTRY['imagenet32'] = i32
43
+
44
+ i64 = Hyperparams()
45
+ i64.update(i32)
46
+ i64.n_batch = 4
47
+ i64.grad_clip = 220.0
48
+ i64.skip_threshold = 380.0
49
+ i64.dataset = 'imagenet64'
50
+ i64.dec_blocks = "1x2,4m1,4x3,8m4,8x7,16m8,16x15,32m16,32x31,64m32,64x12"
51
+ i64.enc_blocks = "64x11,64d2,32x20,32d2,16x9,16d2,8x8,8d2,4x7,4d4,1x5"
52
+ HPARAMS_REGISTRY['imagenet64'] = i64
53
+
54
+ ffhq_256 = Hyperparams()
55
+ ffhq_256.update(i64)
56
+ ffhq_256.n_batch = 1
57
+ ffhq_256.lr = 0.00015
58
+ ffhq_256.dataset = 'ffhq_256'
59
+ ffhq_256.epochs_per_eval = 1
60
+ ffhq_256.epochs_per_eval_save = 1
61
+ ffhq_256.num_images_visualize = 2
62
+ ffhq_256.num_variables_visualize = 3
63
+ ffhq_256.num_temperatures_visualize = 1
64
+ ffhq_256.dec_blocks = "1x2,4m1,4x3,8m4,8x4,16m8,16x9,32m16,32x21,64m32,64x13,128m64,128x7,256m128"
65
+ ffhq_256.enc_blocks = "256x3,256d2,128x8,128d2,64x12,64d2,32x17,32d2,16x7,16d2,8x5,8d2,4x5,4d4,1x4"
66
+ ffhq_256.no_bias_above = 64
67
+ ffhq_256.grad_clip = 130.
68
+ ffhq_256.skip_threshold = 180.
69
+ HPARAMS_REGISTRY['ffhq256'] = ffhq_256
70
+
71
+
72
+ ffhq1024 = Hyperparams()
73
+ ffhq1024.update(ffhq_256)
74
+ ffhq1024.dataset = 'ffhq_1024'
75
+ ffhq1024.data_root = './ffhq_images1024x1024'
76
+ ffhq1024.epochs_per_eval = 1
77
+ ffhq1024.epochs_per_eval_save = 1
78
+ ffhq1024.num_images_visualize = 1
79
+ ffhq1024.iters_per_images = 25000
80
+ ffhq1024.num_variables_visualize = 0
81
+ ffhq1024.num_temperatures_visualize = 4
82
+ ffhq1024.grad_clip = 360.
83
+ ffhq1024.skip_threshold = 500.
84
+ ffhq1024.num_mixtures = 2
85
+ ffhq1024.width = 16
86
+ ffhq1024.lr = 0.00007
87
+ ffhq1024.dec_blocks = "1x2,4m1,4x3,8m4,8x4,16m8,16x9,32m16,32x20,64m32,64x14,128m64,128x7,256m128,256x2,512m256,1024m512"
88
+ ffhq1024.enc_blocks = "1024x1,1024d2,512x3,512d2,256x5,256d2,128x7,128d2,64x10,64d2,32x14,32d2,16x7,16d2,8x5,8d2,4x5,4d4,1x4"
89
+ ffhq1024.custom_width_str = "512:32,256:64,128:512,64:512,32:512,16:512,8:512,4:512,1:512"
90
+ HPARAMS_REGISTRY['ffhq1024'] = ffhq1024
91
+
92
+
93
+ def parse_args_and_update_hparams(H, parser, s=None):
94
+ args = parser.parse_args(s)
95
+ valid_args = set(args.__dict__.keys())
96
+ hparam_sets = [x for x in args.hparam_sets.split(',') if x]
97
+ for hp_set in hparam_sets:
98
+ hps = HPARAMS_REGISTRY[hp_set]
99
+ for k in hps:
100
+ if k not in valid_args:
101
+ raise ValueError(f"{k} not in default args")
102
+ parser.set_defaults(**hps)
103
+ H.update(parser.parse_args(s).__dict__)
104
+
105
+
106
+ def add_vae_arguments(parser):
107
+ parser.add_argument('--seed', type=int, default=0)
108
+ parser.add_argument('--port', type=int, default=29500)
109
+ parser.add_argument('--save_dir', type=str, default='./saved_models')
110
+ parser.add_argument('--data_root', type=str, default='./')
111
+
112
+ parser.add_argument('--desc', type=str, default='test')
113
+ parser.add_argument('--hparam_sets', '--hps', type=str)
114
+ parser.add_argument('--restore_path', type=str, default=None)
115
+ parser.add_argument('--restore_ema_path', type=str, default=None)
116
+ parser.add_argument('--restore_log_path', type=str, default=None)
117
+ parser.add_argument('--restore_optimizer_path', type=str, default=None)
118
+ parser.add_argument('--dataset', type=str, default='cifar10')
119
+
120
+ parser.add_argument('--ema_rate', type=float, default=0.999)
121
+
122
+ parser.add_argument('--enc_blocks', type=str, default=None)
123
+ parser.add_argument('--dec_blocks', type=str, default=None)
124
+ parser.add_argument('--zdim', type=int, default=16)
125
+ parser.add_argument('--width', type=int, default=512)
126
+ parser.add_argument('--custom_width_str', type=str, default='')
127
+ parser.add_argument('--bottleneck_multiple', type=float, default=0.25)
128
+
129
+ parser.add_argument('--no_bias_above', type=int, default=64)
130
+ parser.add_argument('--scale_encblock', action="store_true")
131
+
132
+ parser.add_argument('--test_eval', action="store_true")
133
+ parser.add_argument('--warmup_iters', type=float, default=0)
134
+
135
+ parser.add_argument('--num_mixtures', type=int, default=10)
136
+ parser.add_argument('--grad_clip', type=float, default=200.0)
137
+ parser.add_argument('--skip_threshold', type=float, default=400.0)
138
+ parser.add_argument('--lr', type=float, default=0.00015)
139
+ parser.add_argument('--lr_prior', type=float, default=0.00015)
140
+ parser.add_argument('--wd', type=float, default=0.0)
141
+ parser.add_argument('--wd_prior', type=float, default=0.0)
142
+ parser.add_argument('--num_epochs', type=int, default=10000)
143
+ parser.add_argument('--n_batch', type=int, default=32)
144
+ parser.add_argument('--adam_beta1', type=float, default=0.9)
145
+ parser.add_argument('--adam_beta2', type=float, default=0.9)
146
+
147
+ parser.add_argument('--temperature', type=float, default=1.0)
148
+
149
+ parser.add_argument('--iters_per_ckpt', type=int, default=25000)
150
+ parser.add_argument('--iters_per_print', type=int, default=1000)
151
+ parser.add_argument('--iters_per_save', type=int, default=10000)
152
+ parser.add_argument('--iters_per_images', type=int, default=10000)
153
+ parser.add_argument('--epochs_per_eval', type=int, default=10)
154
+ parser.add_argument('--epochs_per_probe', type=int, default=None)
155
+ parser.add_argument('--epochs_per_eval_save', type=int, default=20)
156
+ parser.add_argument('--num_images_visualize', type=int, default=8)
157
+ parser.add_argument('--num_variables_visualize', type=int, default=6)
158
+ parser.add_argument('--num_temperatures_visualize', type=int, default=3)
159
+ return parser
MindEye_Imagery/src/vdvae/image_utils.py ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import io
2
+ import IPython.display
3
+ import PIL.Image
4
+ import os
5
+ from pprint import pformat
6
+ import numpy as np
7
+
8
+ def imgrid(imarray, cols=4, pad=1, padval=255, row_major=True):
9
+ """Lays out a [N, H, W, C] image array as a single image grid."""
10
+ pad = int(pad)
11
+ if pad < 0:
12
+ raise ValueError('pad must be non-negative')
13
+ cols = int(cols)
14
+ assert cols >= 1
15
+ N, H, W, C = imarray.shape
16
+ rows = N // cols + int(N % cols != 0)
17
+ batch_pad = rows * cols - N
18
+ assert batch_pad >= 0
19
+ post_pad = [batch_pad, pad, pad, 0]
20
+ pad_arg = [[0, p] for p in post_pad]
21
+ imarray = np.pad(imarray, pad_arg, 'constant', constant_values=padval)
22
+ H += pad
23
+ W += pad
24
+ grid = (imarray
25
+ .reshape(rows, cols, H, W, C)
26
+ .transpose(0, 2, 1, 3, 4)
27
+ .reshape(rows*H, cols*W, C))
28
+ if pad:
29
+ grid = grid[:-pad, :-pad]
30
+ return grid
31
+
32
+ def interleave(*args):
33
+ """Interleaves input arrays of the same shape along the batch axis."""
34
+ if not args:
35
+ raise ValueError('At least one argument is required.')
36
+ a0 = args[0]
37
+ if any(a.shape != a0.shape for a in args):
38
+ raise ValueError('All inputs must have the same shape.')
39
+ if not a0.shape:
40
+ raise ValueError('Inputs must have at least one axis.')
41
+ out = np.transpose(args, [1, 0] + list(range(2, len(a0.shape) + 1)))
42
+ out = out.reshape(-1, *a0.shape[1:])
43
+ return out
44
+
45
+ def imshow(a, format='png', jpeg_fallback=True):
46
+ """Displays an image in the given format."""
47
+ a = a.astype(np.uint8)
48
+ data = io.BytesIO()
49
+ PIL.Image.fromarray(a).save(data, format)
50
+ im_data = data.getvalue()
51
+ try:
52
+ disp = IPython.display.display(IPython.display.Image(im_data))
53
+ except IOError:
54
+ if jpeg_fallback and format != 'jpeg':
55
+ print ('Warning: image was too large to display in format "{}"; '
56
+ 'trying jpeg instead.').format(format)
57
+ return imshow(a, format='jpeg')
58
+ else:
59
+ raise
60
+ return disp
61
+
62
+ def image_to_uint8(x):
63
+ """Converts [-1, 1] float array to [0, 255] uint8."""
64
+ x = np.asarray(x)
65
+ x = (256. / 2.) * (x + 1.)
66
+ x = np.clip(x, 0, 255)
67
+ x = x.astype(np.uint8)
68
+ return x
MindEye_Imagery/src/vdvae/model_utils.py ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import numpy as np
3
+ #from mpi4py import MPI
4
+ import socket
5
+ import argparse
6
+ import os
7
+ import json
8
+ import subprocess
9
+ from hps import Hyperparams, parse_args_and_update_hparams, add_vae_arguments
10
+ from vdvae_utils import (logger,
11
+ local_mpi_rank,
12
+ mpi_size,
13
+ maybe_download,
14
+ mpi_rank)
15
+ from data import mkdir_p
16
+ from contextlib import contextmanager
17
+ import torch.distributed as dist
18
+ #from apex.optimizers import FusedAdam as AdamW
19
+ from vae import VAE
20
+ from torch.nn.parallel.distributed import DistributedDataParallel
21
+ from train_helpers import restore_params
22
+
23
+ def set_up_hyperparams(s=None):
24
+ H = Hyperparams()
25
+ parser = argparse.ArgumentParser()
26
+ parser = add_vae_arguments(parser)
27
+ parse_args_and_update_hparams(H, parser, s=s)
28
+ setup_mpi(H)
29
+ setup_save_dirs(H)
30
+ logprint = logger(H.logdir)
31
+ for i, k in enumerate(sorted(H)):
32
+ logprint(type='hparam', key=k, value=H[k])
33
+ np.random.seed(H.seed)
34
+ torch.manual_seed(H.seed)
35
+ torch.cuda.manual_seed(H.seed)
36
+ logprint('training model', H.desc, 'on', H.dataset)
37
+ return H, logprint
38
+
39
+ def set_up_data(H, device="cuda"):
40
+ shift_loss = -127.5
41
+ scale_loss = 1. / 127.5
42
+
43
+ #trX, vaX, teX = imagenet64(H.data_root)
44
+ H.image_size = 64
45
+ H.image_channels = 3
46
+ shift = -115.92961967
47
+ scale = 1. / 69.37404
48
+
49
+ #if H.test_eval:
50
+ # print('DOING TEST')
51
+ # eval_dataset = teX
52
+ #else:
53
+ # eval_dataset = vaX
54
+
55
+ shift = torch.tensor([shift]).to(device).view(1, 1, 1, 1)
56
+ scale = torch.tensor([scale]).to(device).view(1, 1, 1, 1)
57
+ shift_loss = torch.tensor([shift_loss]).to(device).view(1, 1, 1, 1)
58
+ scale_loss = torch.tensor([scale_loss]).to(device).view(1, 1, 1, 1)
59
+
60
+ #train_data = TensorDataset(torch.as_tensor(trX))
61
+ #valid_data = TensorDataset(torch.as_tensor(eval_dataset))
62
+ #untranspose = False
63
+
64
+ def preprocess_func(x):
65
+ nonlocal shift
66
+ nonlocal scale
67
+ nonlocal shift_loss
68
+ nonlocal scale_loss
69
+ 'takes in a data example and returns the preprocessed input'
70
+ 'as well as the input processed for the loss'
71
+ #untranspose = False
72
+ #if untranspose:
73
+ # x[0] = x[0].permute(0, 2, 3, 1)
74
+ inp = x.to(device, non_blocking=True).float()
75
+ out = inp.clone()
76
+ inp.add_(shift).mul_(scale)
77
+ out.add_(shift_loss).mul_(scale_loss)
78
+ return inp, out
79
+
80
+ return H, preprocess_func
81
+
82
+ def load_vaes(H, logprint=None, device="cuda"):
83
+
84
+ ema_vae = VAE(H)
85
+ if H.restore_ema_path:
86
+ print(f'Restoring ema vae from {H.restore_ema_path}')
87
+ restore_params(ema_vae, H.restore_ema_path, map_cpu=True, local_rank=H.local_rank, mpi_size=H.mpi_size)
88
+ else:
89
+ ema_vae.load_state_dict(vae.state_dict())
90
+ ema_vae.requires_grad_(False)
91
+ ema_vae = ema_vae.to(device)
92
+
93
+ #vae = DistributedDataParallel(vae, device_ids=[H.local_rank], output_device=H.local_rank)
94
+
95
+ #if len(list(vae.named_parameters())) != len(list(vae.parameters())):
96
+ # raise ValueError('Some params are not named. Please name all params.')
97
+ #total_params = 0
98
+ #for name, p in vae.named_parameters():
99
+ # total_params += np.prod(p.shape)
100
+
101
+ #print(total_params=total_params, readable=f'{total_params:,}')
102
+ return ema_vae
MindEye_Imagery/src/vdvae/setup_cifar10.sh ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ wget https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz
2
+ tar -xf cifar-10-python.tar.gz
MindEye_Imagery/src/vdvae/setup_ffhq1024.sh ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # the first argument to this script should be the path to the ffhq_images1024x1024 folder
2
+ # the same path should be provided as the `data_root` argument to train.py
3
+ cd $1
4
+ mkdir train
5
+ mkdir train/0
6
+ mkdir valid
7
+ mkdir valid/0
8
+ for i in $(seq -f "%05g" 0 64999); do
9
+ mv $i.png train/0
10
+ done
11
+ for i in $(seq -f "%05g" 65000 69999); do
12
+ mv $i.png valid/0
13
+ done
MindEye_Imagery/src/vdvae/setup_ffhq256.sh ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # we provide a copy of ffhq-256 for convenience, downsampled using the same function as NVAE (https://github.com/NVlabs/NVAE) (personal communication with author)
2
+
3
+ # Resizing function is this one, with the default second argument and size=256
4
+ # https://pytorch.org/docs/stable/torchvision/transforms.html#torchvision.transforms.Resize
5
+
6
+ # 5-bit precision is calculated using the following lines, with num_bits=5 and for an x in [0, 1]
7
+ # x = torch.floor(x * 255 / 2 ** (8 - num_bits))
8
+ # x /= (2 ** num_bits - 1)
9
+
10
+ # the DMOL loss should also be adjusted to have 32 buckets instead of 256 (this code, or NVAE, can be used as reference)
11
+
12
+ wget https://openaipublic.blob.core.windows.net/very-deep-vaes-assets/vdvae-assets/ffhq-256.npy
MindEye_Imagery/src/vdvae/setup_imagenet.sh ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ if [ "$1" == "imagenet32" ]; then
2
+
3
+ echo "downloading imagenet32"
4
+ wget http://www.image-net.org/small/train_32x32.tar
5
+ wget http://www.image-net.org/small/valid_32x32.tar
6
+ tar -xvf train_32x32.tar
7
+ tar -xvf valid_32x32.tar
8
+ python files_to_npy.py train_32x32/ imagenet32-train.npy
9
+ python files_to_npy.py valid_32x32/ imagenet32-valid.npy
10
+
11
+ elif [ "$1" == "imagenet64" ]; then
12
+
13
+ echo "downloading imagenet64"
14
+ wget http://www.image-net.org/small/train_64x64.tar
15
+ wget http://www.image-net.org/small/valid_64x64.tar
16
+ tar -xvf train_64x64.tar
17
+ tar -xvf valid_64x64.tar
18
+ python files_to_npy.py train_64x64/ imagenet64-train.npy
19
+ python files_to_npy.py valid_64x64/ imagenet64-valid.npy
20
+
21
+ else
22
+
23
+ echo "please pass the string imagenet32 or imagenet64 as an argument"
24
+
25
+ fi
26
+
27
+
28
+
MindEye_Imagery/src/vdvae/train.py ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import imageio
3
+ import os
4
+ import time
5
+ import torch
6
+ from torch.utils.data import DataLoader
7
+ from torch.utils.data.distributed import DistributedSampler
8
+ from data import set_up_data
9
+ from vdvae_utils import get_cpu_stats_over_ranks
10
+ from train_helpers import set_up_hyperparams, load_vaes, load_opt, accumulate_stats, save_model, update_ema
11
+
12
+
13
+ def training_step(H, data_input, target, vae, ema_vae, optimizer, iterate):
14
+ t0 = time.time()
15
+ vae.zero_grad()
16
+ stats = vae.forward(data_input, target)
17
+ stats['elbo'].backward()
18
+ grad_norm = torch.nn.utils.clip_grad_norm_(vae.parameters(), H.grad_clip).item()
19
+ distortion_nans = torch.isnan(stats['distortion']).sum()
20
+ rate_nans = torch.isnan(stats['rate']).sum()
21
+ stats.update(dict(rate_nans=0 if rate_nans == 0 else 1, distortion_nans=0 if distortion_nans == 0 else 1))
22
+ stats = get_cpu_stats_over_ranks(stats)
23
+
24
+ skipped_updates = 1
25
+ # only update if no rank has a nan and if the grad norm is below a specific threshold
26
+ if stats['distortion_nans'] == 0 and stats['rate_nans'] == 0 and (H.skip_threshold == -1 or grad_norm < H.skip_threshold):
27
+ optimizer.step()
28
+ skipped_updates = 0
29
+ update_ema(vae, ema_vae, H.ema_rate)
30
+
31
+ t1 = time.time()
32
+ stats.update(skipped_updates=skipped_updates, iter_time=t1 - t0, grad_norm=grad_norm)
33
+ return stats
34
+
35
+
36
+ def eval_step(data_input, target, ema_vae):
37
+ with torch.no_grad():
38
+ stats = ema_vae.forward(data_input, target)
39
+ stats = get_cpu_stats_over_ranks(stats)
40
+ return stats
41
+
42
+
43
+ def get_sample_for_visualization(data, preprocess_fn, num, dataset):
44
+ for x in DataLoader(data, batch_size=num):
45
+ break
46
+ orig_image = (x[0] * 255.0).to(torch.uint8).permute(0, 2, 3, 1) if dataset == 'ffhq_1024' else x[0]
47
+ preprocessed = preprocess_fn(x)[0]
48
+ return orig_image, preprocessed
49
+
50
+
51
+ def train_loop(H, data_train, data_valid, preprocess_fn, vae, ema_vae, logprint):
52
+ optimizer, scheduler, cur_eval_loss, iterate, starting_epoch = load_opt(H, vae, logprint)
53
+ train_sampler = DistributedSampler(data_train, num_replicas=H.mpi_size, rank=H.rank)
54
+ viz_batch_original, viz_batch_processed = get_sample_for_visualization(data_valid, preprocess_fn, H.num_images_visualize, H.dataset)
55
+ early_evals = set([1] + [2 ** exp for exp in range(3, 14)])
56
+ stats = []
57
+ iters_since_starting = 0
58
+ H.ema_rate = torch.as_tensor(H.ema_rate).cuda()
59
+ for epoch in range(starting_epoch, H.num_epochs):
60
+ train_sampler.set_epoch(epoch)
61
+ for x in DataLoader(data_train, batch_size=H.n_batch, drop_last=True, pin_memory=True, sampler=train_sampler):
62
+ data_input, target = preprocess_fn(x)
63
+ training_stats = training_step(H, data_input, target, vae, ema_vae, optimizer, iterate)
64
+ stats.append(training_stats)
65
+ scheduler.step()
66
+ if iterate % H.iters_per_print == 0 or iters_since_starting in early_evals:
67
+ logprint(model=H.desc, type='train_loss', lr=scheduler.get_last_lr()[0], epoch=epoch, step=iterate, **accumulate_stats(stats, H.iters_per_print))
68
+
69
+ if iterate % H.iters_per_images == 0 or (iters_since_starting in early_evals and H.dataset != 'ffhq_1024') and H.rank == 0:
70
+ write_images(H, ema_vae, viz_batch_original, viz_batch_processed, f'{H.save_dir}/samples-{iterate}.png', logprint)
71
+
72
+ iterate += 1
73
+ iters_since_starting += 1
74
+ if iterate % H.iters_per_save == 0 and H.rank == 0:
75
+ if np.isfinite(stats[-1]['elbo']):
76
+ logprint(model=H.desc, type='train_loss', epoch=epoch, step=iterate, **accumulate_stats(stats, H.iters_per_print))
77
+ fp = os.path.join(H.save_dir, 'latest')
78
+ logprint(f'Saving model@ {iterate} to {fp}')
79
+ save_model(fp, vae, ema_vae, optimizer, H)
80
+
81
+ if iterate % H.iters_per_ckpt == 0 and H.rank == 0:
82
+ save_model(os.path.join(H.save_dir, f'iter-{iterate}'), vae, ema_vae, optimizer, H)
83
+
84
+ if epoch % H.epochs_per_eval == 0:
85
+ valid_stats = evaluate(H, ema_vae, data_valid, preprocess_fn)
86
+ logprint(model=H.desc, type='eval_loss', epoch=epoch, step=iterate, **valid_stats)
87
+
88
+
89
+ def evaluate(H, ema_vae, data_valid, preprocess_fn):
90
+ stats_valid = []
91
+ valid_sampler = DistributedSampler(data_valid, num_replicas=H.mpi_size, rank=H.rank)
92
+ for x in DataLoader(data_valid, batch_size=H.n_batch, drop_last=True, pin_memory=True, sampler=valid_sampler):
93
+ data_input, target = preprocess_fn(x)
94
+ stats_valid.append(eval_step(data_input, target, ema_vae))
95
+ vals = [a['elbo'] for a in stats_valid]
96
+ finites = np.array(vals)[np.isfinite(vals)]
97
+ stats = dict(n_batches=len(vals), filtered_elbo=np.mean(finites), **{k: np.mean([a[k] for a in stats_valid]) for k in stats_valid[-1]})
98
+ return stats
99
+
100
+
101
+ def write_images(H, ema_vae, viz_batch_original, viz_batch_processed, fname, logprint):
102
+ zs = [s['z'].cuda() for s in ema_vae.forward_get_latents(viz_batch_processed)]
103
+ batches = [viz_batch_original.numpy()]
104
+ mb = viz_batch_processed.shape[0]
105
+ lv_points = np.floor(np.linspace(0, 1, H.num_variables_visualize + 2) * len(zs)).astype(int)[1:-1]
106
+ for i in lv_points:
107
+ batches.append(ema_vae.forward_samples_set_latents(mb, zs[:i], t=0.1))
108
+ for t in [1.0, 0.9, 0.8, 0.7][:H.num_temperatures_visualize]:
109
+ batches.append(ema_vae.forward_uncond_samples(mb, t=t))
110
+ n_rows = len(batches)
111
+ im = np.concatenate(batches, axis=0).reshape((n_rows, mb, *viz_batch_processed.shape[1:])).transpose([0, 2, 1, 3, 4]).reshape([n_rows * viz_batch_processed.shape[1], mb * viz_batch_processed.shape[2], 3])
112
+ logprint(f'printing samples to {fname}')
113
+ imageio.imwrite(fname, im)
114
+
115
+
116
+ def run_test_eval(H, ema_vae, data_test, preprocess_fn, logprint):
117
+ print('evaluating')
118
+ stats = evaluate(H, ema_vae, data_test, preprocess_fn)
119
+ print('test results')
120
+ for k in stats:
121
+ print(k, stats[k])
122
+ logprint(type='test_loss', **stats)
123
+
124
+
125
+ def main():
126
+ H, logprint = set_up_hyperparams()
127
+ H, data_train, data_valid_or_test, preprocess_fn = set_up_data(H)
128
+ vae, ema_vae = load_vaes(H, logprint)
129
+ if H.test_eval:
130
+ run_test_eval(H, ema_vae, data_valid_or_test, preprocess_fn, logprint)
131
+ else:
132
+ train_loop(H, data_train, data_valid_or_test, preprocess_fn, vae, ema_vae, logprint)
133
+
134
+
135
+ if __name__ == "__main__":
136
+ main()
MindEye_Imagery/src/vdvae/train_helpers.py ADDED
@@ -0,0 +1,190 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import numpy as np
3
+ #from mpi4py import MPI
4
+ import socket
5
+ import argparse
6
+ import os
7
+ import json
8
+ import subprocess
9
+ from hps import Hyperparams, parse_args_and_update_hparams, add_vae_arguments
10
+ from vdvae_utils import (logger,
11
+ local_mpi_rank,
12
+ mpi_size,
13
+ maybe_download,
14
+ mpi_rank)
15
+ from data import mkdir_p
16
+ from contextlib import contextmanager
17
+ import torch.distributed as dist
18
+ #from apex.optimizers import FusedAdam as AdamW
19
+ from vae import VAE
20
+ from torch.nn.parallel.distributed import DistributedDataParallel
21
+
22
+
23
+ def update_ema(vae, ema_vae, ema_rate):
24
+ for p1, p2 in zip(vae.parameters(), ema_vae.parameters()):
25
+ p2.data.mul_(ema_rate)
26
+ p2.data.add_(p1.data * (1 - ema_rate))
27
+
28
+
29
+ def save_model(path, vae, ema_vae, optimizer, H):
30
+ torch.save(vae.state_dict(), f'{path}-model.th')
31
+ torch.save(ema_vae.state_dict(), f'{path}-model-ema.th')
32
+ torch.save(optimizer.state_dict(), f'{path}-opt.th')
33
+ from_log = os.path.join(H.save_dir, 'log.jsonl')
34
+ to_log = f'{os.path.dirname(path)}/{os.path.basename(path)}-log.jsonl'
35
+ subprocess.check_output(['cp', from_log, to_log])
36
+
37
+
38
+ def accumulate_stats(stats, frequency):
39
+ z = {}
40
+ for k in stats[-1]:
41
+ if k in ['distortion_nans', 'rate_nans', 'skipped_updates', 'gcskip']:
42
+ z[k] = np.sum([a[k] for a in stats[-frequency:]])
43
+ elif k == 'grad_norm':
44
+ vals = [a[k] for a in stats[-frequency:]]
45
+ finites = np.array(vals)[np.isfinite(vals)]
46
+ if len(finites) == 0:
47
+ z[k] = 0.0
48
+ else:
49
+ z[k] = np.max(finites)
50
+ elif k == 'elbo':
51
+ vals = [a[k] for a in stats[-frequency:]]
52
+ finites = np.array(vals)[np.isfinite(vals)]
53
+ z['elbo'] = np.mean(vals)
54
+ z['elbo_filtered'] = np.mean(finites)
55
+ elif k == 'iter_time':
56
+ z[k] = stats[-1][k] if len(stats) < frequency else np.mean([a[k] for a in stats[-frequency:]])
57
+ else:
58
+ z[k] = np.mean([a[k] for a in stats[-frequency:]])
59
+ return z
60
+
61
+
62
+ def linear_warmup(warmup_iters):
63
+ def f(iteration):
64
+ return 1.0 if iteration > warmup_iters else iteration / warmup_iters
65
+ return f
66
+
67
+
68
+ def setup_mpi(H):
69
+ H.mpi_size = mpi_size()
70
+ H.local_rank = local_mpi_rank()
71
+ H.rank = mpi_rank()
72
+ os.environ["RANK"] = str(H.rank)
73
+ os.environ["WORLD_SIZE"] = str(H.mpi_size)
74
+ os.environ["MASTER_PORT"] = str(H.port)
75
+ # os.environ["NCCL_LL_THRESHOLD"] = "0"
76
+ os.environ["MASTER_ADDR"] = MPI.COMM_WORLD.bcast(socket.gethostname(), root=0)
77
+ torch.cuda.set_device(H.local_rank)
78
+ dist.init_process_group(backend='nccl', init_method=f"env://")
79
+
80
+
81
+ def distributed_maybe_download(path, local_rank, mpi_size):
82
+ if not path.startswith('gs://'):
83
+ return path
84
+ filename = path[5:].replace('/', '-')
85
+ with first_rank_first(local_rank, mpi_size):
86
+ fp = maybe_download(path, filename)
87
+ return fp
88
+
89
+
90
+ @contextmanager
91
+ def first_rank_first(local_rank, mpi_size):
92
+ if mpi_size > 1 and local_rank > 0:
93
+ dist.barrier()
94
+
95
+ try:
96
+ yield
97
+ finally:
98
+ if mpi_size > 1 and local_rank == 0:
99
+ dist.barrier()
100
+
101
+
102
+ def setup_save_dirs(H):
103
+ H.save_dir = os.path.join(H.save_dir, H.desc)
104
+ mkdir_p(H.save_dir)
105
+ H.logdir = os.path.join(H.save_dir, 'log')
106
+
107
+
108
+ def set_up_hyperparams(s=None):
109
+ H = Hyperparams()
110
+ parser = argparse.ArgumentParser()
111
+ parser = add_vae_arguments(parser)
112
+ parse_args_and_update_hparams(H, parser, s=s)
113
+ setup_mpi(H)
114
+ setup_save_dirs(H)
115
+ logprint = logger(H.logdir)
116
+ for i, k in enumerate(sorted(H)):
117
+ logprint(type='hparam', key=k, value=H[k])
118
+ np.random.seed(H.seed)
119
+ torch.manual_seed(H.seed)
120
+ torch.cuda.manual_seed(H.seed)
121
+ logprint('training model', H.desc, 'on', H.dataset)
122
+ return H, logprint
123
+
124
+
125
+ def restore_params(model, path, local_rank, mpi_size, map_ddp=True, map_cpu=False):
126
+ state_dict = torch.load(distributed_maybe_download(path, local_rank, mpi_size), map_location='cpu' if map_cpu else None)
127
+ if map_ddp:
128
+ new_state_dict = {}
129
+ l = len('module.')
130
+ for k in state_dict:
131
+ if k.startswith('module.'):
132
+ new_state_dict[k[l:]] = state_dict[k]
133
+ else:
134
+ new_state_dict[k] = state_dict[k]
135
+ state_dict = new_state_dict
136
+ model.load_state_dict(state_dict)
137
+
138
+
139
+ def restore_log(path, local_rank, mpi_size):
140
+ loaded = [json.loads(l) for l in open(distributed_maybe_download(path, local_rank, mpi_size))]
141
+ try:
142
+ cur_eval_loss = min([z['elbo'] for z in loaded if 'type' in z and z['type'] == 'eval_loss'])
143
+ except ValueError:
144
+ cur_eval_loss = float('inf')
145
+ starting_epoch = max([z['epoch'] for z in loaded if 'type' in z and z['type'] == 'train_loss'])
146
+ iterate = max([z['step'] for z in loaded if 'type' in z and z['type'] == 'train_loss'])
147
+ return cur_eval_loss, iterate, starting_epoch
148
+
149
+
150
+ def load_vaes(H, logprint):
151
+ vae = VAE(H)
152
+ if H.restore_path:
153
+ logprint(f'Restoring vae from {H.restore_path}')
154
+ restore_params(vae, H.restore_path, map_cpu=True, local_rank=H.local_rank, mpi_size=H.mpi_size)
155
+
156
+ ema_vae = VAE(H)
157
+ if H.restore_ema_path:
158
+ logprint(f'Restoring ema vae from {H.restore_ema_path}')
159
+ restore_params(ema_vae, H.restore_ema_path, map_cpu=True, local_rank=H.local_rank, mpi_size=H.mpi_size)
160
+ else:
161
+ ema_vae.load_state_dict(vae.state_dict())
162
+ ema_vae.requires_grad_(False)
163
+
164
+ vae = vae.cuda(H.local_rank)
165
+ ema_vae = ema_vae.cuda(H.local_rank)
166
+
167
+ vae = DistributedDataParallel(vae, device_ids=[H.local_rank], output_device=H.local_rank)
168
+
169
+ if len(list(vae.named_parameters())) != len(list(vae.parameters())):
170
+ raise ValueError('Some params are not named. Please name all params.')
171
+ total_params = 0
172
+ for name, p in vae.named_parameters():
173
+ total_params += np.prod(p.shape)
174
+ logprint(total_params=total_params, readable=f'{total_params:,}')
175
+ return vae, ema_vae
176
+
177
+
178
+ def load_opt(H, vae, logprint):
179
+ optimizer = AdamW(vae.parameters(), weight_decay=H.wd, lr=H.lr, betas=(H.adam_beta1, H.adam_beta2))
180
+ scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda=linear_warmup(H.warmup_iters))
181
+
182
+ if H.restore_optimizer_path:
183
+ optimizer.load_state_dict(
184
+ torch.load(distributed_maybe_download(H.restore_optimizer_path, H.local_rank, H.mpi_size), map_location='cpu'))
185
+ if H.restore_log_path:
186
+ cur_eval_loss, iterate, starting_epoch = restore_log(H.restore_log_path, H.local_rank, H.mpi_size)
187
+ else:
188
+ cur_eval_loss, iterate, starting_epoch = float('inf'), 0, 0
189
+ logprint('starting at epoch', starting_epoch, 'iterate', iterate, 'eval loss', cur_eval_loss)
190
+ return optimizer, scheduler, cur_eval_loss, iterate, starting_epoch
MindEye_Imagery/src/vdvae/vae.py ADDED
@@ -0,0 +1,252 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from torch import nn
3
+ from torch.nn import functional as F
4
+ from vae_helpers import HModule, get_1x1, get_3x3, DmolNet, draw_gaussian_diag_samples, gaussian_analytical_kl
5
+ from collections import defaultdict
6
+ import numpy as np
7
+ import itertools
8
+
9
+
10
+ class Block(nn.Module):
11
+ def __init__(self, in_width, middle_width, out_width, down_rate=None, residual=False, use_3x3=True, zero_last=False):
12
+ super().__init__()
13
+ self.down_rate = down_rate
14
+ self.residual = residual
15
+ self.c1 = get_1x1(in_width, middle_width)
16
+ self.c2 = get_3x3(middle_width, middle_width) if use_3x3 else get_1x1(middle_width, middle_width)
17
+ self.c3 = get_3x3(middle_width, middle_width) if use_3x3 else get_1x1(middle_width, middle_width)
18
+ self.c4 = get_1x1(middle_width, out_width, zero_weights=zero_last)
19
+
20
+ def forward(self, x):
21
+ xhat = self.c1(F.gelu(x))
22
+ xhat = self.c2(F.gelu(xhat))
23
+ xhat = self.c3(F.gelu(xhat))
24
+ xhat = self.c4(F.gelu(xhat))
25
+ out = x + xhat if self.residual else xhat
26
+ if self.down_rate is not None:
27
+ out = F.avg_pool2d(out, kernel_size=self.down_rate, stride=self.down_rate)
28
+ return out
29
+
30
+
31
+ def parse_layer_string(s):
32
+ layers = []
33
+ for ss in s.split(','):
34
+ if 'x' in ss:
35
+ res, num = ss.split('x')
36
+ count = int(num)
37
+ layers += [(int(res), None) for _ in range(count)]
38
+ elif 'm' in ss:
39
+ res, mixin = [int(a) for a in ss.split('m')]
40
+ layers.append((res, mixin))
41
+ elif 'd' in ss:
42
+ res, down_rate = [int(a) for a in ss.split('d')]
43
+ layers.append((res, down_rate))
44
+ else:
45
+ res = int(ss)
46
+ layers.append((res, None))
47
+ return layers
48
+
49
+
50
+ def pad_channels(t, width):
51
+ d1, d2, d3, d4 = t.shape
52
+ empty = torch.zeros(d1, width, d3, d4, device=t.device)
53
+ empty[:, :d2, :, :] = t
54
+ return empty
55
+
56
+
57
+ def get_width_settings(width, s):
58
+ mapping = defaultdict(lambda: width)
59
+ if s:
60
+ s = s.split(',')
61
+ for ss in s:
62
+ k, v = ss.split(':')
63
+ mapping[int(k)] = int(v)
64
+ return mapping
65
+
66
+
67
+ class Encoder(HModule):
68
+ def build(self):
69
+ H = self.H
70
+ self.in_conv = get_3x3(H.image_channels, H.width)
71
+ self.widths = get_width_settings(H.width, H.custom_width_str)
72
+ enc_blocks = []
73
+ blockstr = parse_layer_string(H.enc_blocks)
74
+ for res, down_rate in blockstr:
75
+ use_3x3 = res > 2 # Don't use 3x3s for 1x1, 2x2 patches
76
+ enc_blocks.append(Block(self.widths[res], int(self.widths[res] * H.bottleneck_multiple), self.widths[res], down_rate=down_rate, residual=True, use_3x3=use_3x3))
77
+ n_blocks = len(blockstr)
78
+ for b in enc_blocks:
79
+ b.c4.weight.data *= np.sqrt(1 / n_blocks)
80
+ self.enc_blocks = nn.ModuleList(enc_blocks)
81
+
82
+ def forward(self, x):
83
+ x = x.permute(0, 3, 1, 2).contiguous()
84
+ x = self.in_conv(x)
85
+ activations = {}
86
+ activations[x.shape[2]] = x
87
+ for block in self.enc_blocks:
88
+ x = block(x)
89
+ res = x.shape[2]
90
+ x = x if x.shape[1] == self.widths[res] else pad_channels(x, self.widths[res])
91
+ activations[res] = x
92
+ return activations
93
+
94
+
95
+ class DecBlock(nn.Module):
96
+ def __init__(self, H, res, mixin, n_blocks):
97
+ super().__init__()
98
+ self.base = res
99
+ self.mixin = mixin
100
+ self.H = H
101
+ self.widths = get_width_settings(H.width, H.custom_width_str)
102
+ width = self.widths[res]
103
+ use_3x3 = res > 2
104
+ cond_width = int(width * H.bottleneck_multiple)
105
+ self.zdim = H.zdim
106
+ self.enc = Block(width * 2, cond_width, H.zdim * 2, residual=False, use_3x3=use_3x3)
107
+ self.prior = Block(width, cond_width, H.zdim * 2 + width, residual=False, use_3x3=use_3x3, zero_last=True)
108
+ self.z_proj = get_1x1(H.zdim, width)
109
+ self.z_proj.weight.data *= np.sqrt(1 / n_blocks)
110
+ self.resnet = Block(width, cond_width, width, residual=True, use_3x3=use_3x3)
111
+ self.resnet.c4.weight.data *= np.sqrt(1 / n_blocks)
112
+ self.z_fn = lambda x: self.z_proj(x)
113
+
114
+ def sample(self, x, acts):
115
+ qm, qv = self.enc(torch.cat([x, acts], dim=1)).chunk(2, dim=1)
116
+ feats = self.prior(x)
117
+ pm, pv, xpp = feats[:, :self.zdim, ...], feats[:, self.zdim:self.zdim * 2, ...], feats[:, self.zdim * 2:, ...]
118
+ x = x + xpp
119
+ z = draw_gaussian_diag_samples(qm, qv)
120
+ kl = gaussian_analytical_kl(qm, pm, qv, pv)
121
+ return z, x, kl
122
+
123
+ def sample_uncond(self, x, t=None, lvs=None):
124
+ n, c, h, w = x.shape
125
+ feats = self.prior(x)
126
+ pm, pv, xpp = feats[:, :self.zdim, ...], feats[:, self.zdim:self.zdim * 2, ...], feats[:, self.zdim * 2:, ...]
127
+ x = x + xpp
128
+ if lvs is not None:
129
+ z = lvs
130
+ else:
131
+ if t is not None:
132
+ pv = pv + torch.ones_like(pv) * np.log(t)
133
+ z = draw_gaussian_diag_samples(pm, pv)
134
+ return z, x
135
+
136
+ def get_inputs(self, xs, activations):
137
+ acts = activations[self.base]
138
+ try:
139
+ x = xs[self.base]
140
+ except KeyError:
141
+ x = torch.zeros_like(acts)
142
+ if acts.shape[0] != x.shape[0]:
143
+ x = x.repeat(acts.shape[0], 1, 1, 1)
144
+ return x, acts
145
+
146
+ def forward(self, xs, activations, get_latents=False):
147
+ x, acts = self.get_inputs(xs, activations)
148
+ if self.mixin is not None:
149
+ x = x + F.interpolate(xs[self.mixin][:, :x.shape[1], ...], scale_factor=self.base // self.mixin)
150
+ z, x, kl = self.sample(x, acts)
151
+ x = x + self.z_fn(z)
152
+ x = self.resnet(x)
153
+ xs[self.base] = x
154
+ if get_latents:
155
+ return xs, dict(z=z.detach(), kl=kl)
156
+ return xs, dict(kl=kl)
157
+
158
+ def forward_uncond(self, xs, t=None, lvs=None):
159
+ try:
160
+ x = xs[self.base]
161
+ except KeyError:
162
+ ref = xs[list(xs.keys())[0]]
163
+ x = torch.zeros(dtype=ref.dtype, size=(ref.shape[0], self.widths[self.base], self.base, self.base), device=ref.device)
164
+ if self.mixin is not None:
165
+ x = x + F.interpolate(xs[self.mixin][:, :x.shape[1], ...], scale_factor=self.base // self.mixin)
166
+ z, x = self.sample_uncond(x, t, lvs=lvs)
167
+ x = x + self.z_fn(z)
168
+ x = self.resnet(x)
169
+ xs[self.base] = x
170
+ return xs
171
+
172
+
173
+ class Decoder(HModule):
174
+
175
+ def build(self):
176
+ H = self.H
177
+ resos = set()
178
+ dec_blocks = []
179
+ self.widths = get_width_settings(H.width, H.custom_width_str)
180
+ blocks = parse_layer_string(H.dec_blocks)
181
+ for idx, (res, mixin) in enumerate(blocks):
182
+ dec_blocks.append(DecBlock(H, res, mixin, n_blocks=len(blocks)))
183
+ resos.add(res)
184
+ self.resolutions = sorted(resos)
185
+ self.dec_blocks = nn.ModuleList(dec_blocks)
186
+ self.bias_xs = nn.ParameterList([nn.Parameter(torch.zeros(1, self.widths[res], res, res)) for res in self.resolutions if res <= H.no_bias_above])
187
+ self.out_net = DmolNet(H)
188
+ self.gain = nn.Parameter(torch.ones(1, H.width, 1, 1))
189
+ self.bias = nn.Parameter(torch.zeros(1, H.width, 1, 1))
190
+ self.final_fn = lambda x: x * self.gain + self.bias
191
+
192
+ def forward(self, activations, get_latents=False):
193
+ stats = []
194
+ xs = {a.shape[2]: a for a in self.bias_xs}
195
+ for block in self.dec_blocks:
196
+ xs, block_stats = block(xs, activations, get_latents=get_latents)
197
+ stats.append(block_stats)
198
+ xs[self.H.image_size] = self.final_fn(xs[self.H.image_size])
199
+ return xs[self.H.image_size], stats
200
+
201
+ def forward_uncond(self, n, t=None, y=None):
202
+ xs = {}
203
+ for bias in self.bias_xs:
204
+ xs[bias.shape[2]] = bias.repeat(n, 1, 1, 1)
205
+ for idx, block in enumerate(self.dec_blocks):
206
+ try:
207
+ temp = t[idx]
208
+ except TypeError:
209
+ temp = t
210
+ xs = block.forward_uncond(xs, temp)
211
+ xs[self.H.image_size] = self.final_fn(xs[self.H.image_size])
212
+ return xs[self.H.image_size]
213
+
214
+ def forward_manual_latents(self, n, latents, t=None):
215
+ xs = {}
216
+ for bias in self.bias_xs:
217
+ xs[bias.shape[2]] = bias.repeat(n, 1, 1, 1)
218
+ for block, lvs in itertools.zip_longest(self.dec_blocks, latents):
219
+ xs = block.forward_uncond(xs, t, lvs=lvs)
220
+ xs[self.H.image_size] = self.final_fn(xs[self.H.image_size])
221
+ return xs[self.H.image_size]
222
+
223
+
224
+ class VAE(HModule):
225
+ def build(self):
226
+ self.encoder = Encoder(self.H)
227
+ self.decoder = Decoder(self.H)
228
+
229
+ def forward(self, x, x_target):
230
+ activations = self.encoder.forward(x)
231
+ px_z, stats = self.decoder.forward(activations)
232
+ distortion_per_pixel = self.decoder.out_net.nll(px_z, x_target)
233
+ rate_per_pixel = torch.zeros_like(distortion_per_pixel)
234
+ ndims = np.prod(x.shape[1:])
235
+ for statdict in stats:
236
+ rate_per_pixel += statdict['kl'].sum(dim=(1, 2, 3))
237
+ rate_per_pixel /= ndims
238
+ elbo = (distortion_per_pixel + rate_per_pixel).mean()
239
+ return dict(elbo=elbo, distortion=distortion_per_pixel.mean(), rate=rate_per_pixel.mean())
240
+
241
+ def forward_get_latents(self, x):
242
+ activations = self.encoder.forward(x)
243
+ _, stats = self.decoder.forward(activations, get_latents=True)
244
+ return stats
245
+
246
+ def forward_uncond_samples(self, n_batch, t=None):
247
+ px_z = self.decoder.forward_uncond(n_batch, t=t)
248
+ return self.decoder.out_net.sample(px_z)
249
+
250
+ def forward_samples_set_latents(self, n_batch, latents, t=None):
251
+ px_z = self.decoder.forward_manual_latents(n_batch, latents, t=t)
252
+ return self.decoder.out_net.sample(px_z)
MindEye_Imagery/src/vdvae/vae_helpers.py ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import torch
3
+ import torch.nn as nn
4
+ import torch.nn.functional as F
5
+
6
+
7
+ @torch.jit.script
8
+ def gaussian_analytical_kl(mu1, mu2, logsigma1, logsigma2):
9
+ return -0.5 + logsigma2 - logsigma1 + 0.5 * (logsigma1.exp() ** 2 + (mu1 - mu2) ** 2) / (logsigma2.exp() ** 2)
10
+
11
+
12
+ @torch.jit.script
13
+ def draw_gaussian_diag_samples(mu, logsigma):
14
+ eps = torch.empty_like(mu).normal_(0., 1.)
15
+ return torch.exp(logsigma) * eps + mu
16
+
17
+
18
+ def get_conv(in_dim, out_dim, kernel_size, stride, padding, zero_bias=True, zero_weights=False, groups=1, scaled=False):
19
+ c = nn.Conv2d(in_dim, out_dim, kernel_size, stride, padding, groups=groups)
20
+ if zero_bias:
21
+ c.bias.data *= 0.0
22
+ if zero_weights:
23
+ c.weight.data *= 0.0
24
+ return c
25
+
26
+
27
+ def get_3x3(in_dim, out_dim, zero_bias=True, zero_weights=False, groups=1, scaled=False):
28
+ return get_conv(in_dim, out_dim, 3, 1, 1, zero_bias, zero_weights, groups=groups, scaled=scaled)
29
+
30
+
31
+ def get_1x1(in_dim, out_dim, zero_bias=True, zero_weights=False, groups=1, scaled=False):
32
+ return get_conv(in_dim, out_dim, 1, 1, 0, zero_bias, zero_weights, groups=groups, scaled=scaled)
33
+
34
+
35
+ def log_prob_from_logits(x):
36
+ """ numerically stable log_softmax implementation that prevents overflow """
37
+ axis = len(x.shape) - 1
38
+ m = x.max(dim=axis, keepdim=True)[0]
39
+ return x - m - torch.log(torch.exp(x - m).sum(dim=axis, keepdim=True))
40
+
41
+
42
+ def const_max(t, constant):
43
+ other = torch.ones_like(t) * constant
44
+ return torch.max(t, other)
45
+
46
+
47
+ def const_min(t, constant):
48
+ other = torch.ones_like(t) * constant
49
+ return torch.min(t, other)
50
+
51
+
52
+ def discretized_mix_logistic_loss(x, l, low_bit=False):
53
+ """ log-likelihood for mixture of discretized logistics, assumes the data has been rescaled to [-1,1] interval """
54
+ # Adapted from https://github.com/openai/pixel-cnn/blob/master/pixel_cnn_pp/nn.py
55
+ xs = [s for s in x.shape] # true image (i.e. labels) to regress to, e.g. (B,32,32,3)
56
+ ls = [s for s in l.shape] # predicted distribution, e.g. (B,32,32,100)
57
+ nr_mix = int(ls[-1] / 10) # here and below: unpacking the params of the mixture of logistics
58
+ logit_probs = l[:, :, :, :nr_mix]
59
+ l = torch.reshape(l[:, :, :, nr_mix:], xs + [nr_mix * 3])
60
+ means = l[:, :, :, :, :nr_mix]
61
+ log_scales = const_max(l[:, :, :, :, nr_mix:2 * nr_mix], -7.)
62
+ coeffs = torch.tanh(l[:, :, :, :, 2 * nr_mix:3 * nr_mix])
63
+ x = torch.reshape(x, xs + [1]) + torch.zeros(xs + [nr_mix]).to(x.device) # here and below: getting the means and adjusting them based on preceding sub-pixels
64
+ m2 = torch.reshape(means[:, :, :, 1, :] + coeffs[:, :, :, 0, :] * x[:, :, :, 0, :], [xs[0], xs[1], xs[2], 1, nr_mix])
65
+ m3 = torch.reshape(means[:, :, :, 2, :] + coeffs[:, :, :, 1, :] * x[:, :, :, 0, :] + coeffs[:, :, :, 2, :] * x[:, :, :, 1, :], [xs[0], xs[1], xs[2], 1, nr_mix])
66
+ means = torch.cat([torch.reshape(means[:, :, :, 0, :], [xs[0], xs[1], xs[2], 1, nr_mix]), m2, m3], dim=3)
67
+ centered_x = x - means
68
+ inv_stdv = torch.exp(-log_scales)
69
+ if low_bit:
70
+ plus_in = inv_stdv * (centered_x + 1. / 31.)
71
+ cdf_plus = torch.sigmoid(plus_in)
72
+ min_in = inv_stdv * (centered_x - 1. / 31.)
73
+ else:
74
+ plus_in = inv_stdv * (centered_x + 1. / 255.)
75
+ cdf_plus = torch.sigmoid(plus_in)
76
+ min_in = inv_stdv * (centered_x - 1. / 255.)
77
+ cdf_min = torch.sigmoid(min_in)
78
+ log_cdf_plus = plus_in - F.softplus(plus_in) # log probability for edge case of 0 (before scaling)
79
+ log_one_minus_cdf_min = -F.softplus(min_in) # log probability for edge case of 255 (before scaling)
80
+ cdf_delta = cdf_plus - cdf_min # probability for all other cases
81
+ mid_in = inv_stdv * centered_x
82
+ log_pdf_mid = mid_in - log_scales - 2. * F.softplus(mid_in) # log probability in the center of the bin, to be used in extreme cases (not actually used in our code)
83
+
84
+ # now select the right output: left edge case, right edge case, normal case, extremely low prob case (doesn't actually happen for us)
85
+
86
+ # this is what we are really doing, but using the robust version below for extreme cases in other applications and to avoid NaN issue with tf.select()
87
+ # log_probs = tf.select(x < -0.999, log_cdf_plus, tf.select(x > 0.999, log_one_minus_cdf_min, tf.log(cdf_delta)))
88
+
89
+ # robust version, that still works if probabilities are below 1e-5 (which never happens in our code)
90
+ # tensorflow backpropagates through tf.select() by multiplying with zero instead of selecting: this requires use to use some ugly tricks to avoid potential NaNs
91
+ # the 1e-12 in tf.maximum(cdf_delta, 1e-12) is never actually used as output, it's purely there to get around the tf.select() gradient issue
92
+ # if the probability on a sub-pixel is below 1e-5, we use an approximation based on the assumption that the log-density is constant in the bin of the observed sub-pixel value
93
+ if low_bit:
94
+ log_probs = torch.where(x < -0.999,
95
+ log_cdf_plus,
96
+ torch.where(x > 0.999,
97
+ log_one_minus_cdf_min,
98
+ torch.where(cdf_delta > 1e-5,
99
+ torch.log(const_max(cdf_delta, 1e-12)),
100
+ log_pdf_mid - np.log(15.5))))
101
+ else:
102
+ log_probs = torch.where(x < -0.999,
103
+ log_cdf_plus,
104
+ torch.where(x > 0.999,
105
+ log_one_minus_cdf_min,
106
+ torch.where(cdf_delta > 1e-5,
107
+ torch.log(const_max(cdf_delta, 1e-12)),
108
+ log_pdf_mid - np.log(127.5))))
109
+ log_probs = log_probs.sum(dim=3) + log_prob_from_logits(logit_probs)
110
+ mixture_probs = torch.logsumexp(log_probs, -1)
111
+ return -1. * mixture_probs.sum(dim=[1, 2]) / np.prod(xs[1:])
112
+
113
+
114
+ def sample_from_discretized_mix_logistic(l, nr_mix):
115
+ ls = [s for s in l.shape]
116
+ xs = ls[:-1] + [3]
117
+ # unpack parameters
118
+ logit_probs = l[:, :, :, :nr_mix]
119
+ l = torch.reshape(l[:, :, :, nr_mix:], xs + [nr_mix * 3])
120
+ # sample mixture indicator from softmax
121
+ eps = torch.empty(logit_probs.shape, device=l.device).uniform_(1e-5, 1. - 1e-5)
122
+ amax = torch.argmax(logit_probs - torch.log(-torch.log(eps)), dim=3)
123
+ sel = F.one_hot(amax, num_classes=nr_mix).float()
124
+ sel = torch.reshape(sel, xs[:-1] + [1, nr_mix])
125
+ # select logistic parameters
126
+ means = (l[:, :, :, :, :nr_mix] * sel).sum(dim=4)
127
+ log_scales = const_max((l[:, :, :, :, nr_mix:nr_mix * 2] * sel).sum(dim=4), -7.)
128
+ coeffs = (torch.tanh(l[:, :, :, :, nr_mix * 2:nr_mix * 3]) * sel).sum(dim=4)
129
+ # sample from logistic & clip to interval
130
+ # we don't actually round to the nearest 8bit value when sampling
131
+ u = torch.empty(means.shape, device=means.device).uniform_(1e-5, 1. - 1e-5)
132
+ x = means + torch.exp(log_scales) * (torch.log(u) - torch.log(1. - u))
133
+ x0 = const_min(const_max(x[:, :, :, 0], -1.), 1.)
134
+ x1 = const_min(const_max(x[:, :, :, 1] + coeffs[:, :, :, 0] * x0, -1.), 1.)
135
+ x2 = const_min(const_max(x[:, :, :, 2] + coeffs[:, :, :, 1] * x0 + coeffs[:, :, :, 2] * x1, -1.), 1.)
136
+ return torch.cat([torch.reshape(x0, xs[:-1] + [1]), torch.reshape(x1, xs[:-1] + [1]), torch.reshape(x2, xs[:-1] + [1])], dim=3)
137
+
138
+
139
+ class HModule(nn.Module):
140
+ def __init__(self, H):
141
+ super().__init__()
142
+ self.H = H
143
+ self.build()
144
+
145
+
146
+ class DmolNet(nn.Module):
147
+ def __init__(self, H):
148
+ super().__init__()
149
+ self.H = H
150
+ self.width = H.width
151
+ self.out_conv = get_conv(H.width, H.num_mixtures * 10, kernel_size=1, stride=1, padding=0)
152
+
153
+ def nll(self, px_z, x):
154
+ return discretized_mix_logistic_loss(x=x, l=self.forward(px_z), low_bit=self.H.dataset in ['ffhq_256'])
155
+
156
+ def forward(self, px_z):
157
+ xhat = self.out_conv(px_z)
158
+ return xhat.permute(0, 2, 3, 1)
159
+
160
+ def sample(self, px_z):
161
+ im = sample_from_discretized_mix_logistic(self.forward(px_z), self.H.num_mixtures)
162
+ xhat = (im + 1.0) * 127.5
163
+ xhat = xhat.detach().cpu().numpy()
164
+ xhat = np.minimum(np.maximum(0.0, xhat), 255.0).astype(np.uint8)
165
+ return xhat
MindEye_Imagery/src/vdvae/vdvae_utils.py ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #from mpi4py import MPI
2
+ import os
3
+ import json
4
+ import tempfile
5
+ import numpy as np
6
+ import torch
7
+ import time
8
+ import subprocess
9
+ import torch.distributed as dist
10
+
11
+
12
+ def allreduce(x, average):
13
+ if mpi_size() > 1:
14
+ dist.all_reduce(x, dist.ReduceOp.SUM)
15
+ return x / mpi_size() if average else x
16
+
17
+
18
+ def get_cpu_stats_over_ranks(stat_dict):
19
+ keys = sorted(stat_dict.keys())
20
+ allreduced = allreduce(torch.stack([torch.as_tensor(stat_dict[k]).detach().cuda().float() for k in keys]), average=True).cpu()
21
+ return {k: allreduced[i].item() for (i, k) in enumerate(keys)}
22
+
23
+
24
+ class Hyperparams(dict):
25
+ def __getattr__(self, attr):
26
+ try:
27
+ return self[attr]
28
+ except KeyError:
29
+ return None
30
+
31
+ def __setattr__(self, attr, value):
32
+ self[attr] = value
33
+
34
+
35
+ def logger(log_prefix):
36
+ 'Prints the arguments out to stdout, .txt, and .jsonl files'
37
+
38
+ jsonl_path = f'{log_prefix}.jsonl'
39
+ txt_path = f'{log_prefix}.txt'
40
+
41
+ def log(*args, pprint=False, **kwargs):
42
+ if mpi_rank() != 0:
43
+ return
44
+ t = time.ctime()
45
+ argdict = {'time': t}
46
+ if len(args) > 0:
47
+ argdict['message'] = ' '.join([str(x) for x in args])
48
+ argdict.update(kwargs)
49
+
50
+ txt_str = []
51
+ args_iter = sorted(argdict) if pprint else argdict
52
+ for k in args_iter:
53
+ val = argdict[k]
54
+ if isinstance(val, np.ndarray):
55
+ val = val.tolist()
56
+ elif isinstance(val, np.integer):
57
+ val = int(val)
58
+ elif isinstance(val, np.floating):
59
+ val = float(val)
60
+ argdict[k] = val
61
+ if isinstance(val, float):
62
+ val = f'{val:.5f}'
63
+ txt_str.append(f'{k}: {val}')
64
+ txt_str = ', '.join(txt_str)
65
+
66
+ if pprint:
67
+ json_str = json.dumps(argdict, sort_keys=True)
68
+ txt_str = json.dumps(argdict, sort_keys=True, indent=4)
69
+ else:
70
+ json_str = json.dumps(argdict)
71
+
72
+ print(txt_str, flush=True)
73
+
74
+ with open(txt_path, "a+") as f:
75
+ print(txt_str, file=f, flush=True)
76
+ with open(jsonl_path, "a+") as f:
77
+ print(json_str, file=f, flush=True)
78
+
79
+ return log
80
+
81
+
82
+ def maybe_download(path, filename=None):
83
+ '''If a path is a gsutil path, download it and return the local link,
84
+ otherwise return link'''
85
+ if not path.startswith('gs://'):
86
+ return path
87
+ if filename:
88
+ local_dest = f'/tmp/'
89
+ out_path = f'/tmp/{filename}'
90
+ if os.path.isfile(out_path):
91
+ return out_path
92
+ subprocess.check_output(['gsutil', '-m', 'cp', '-R', path, out_path])
93
+ return out_path
94
+ else:
95
+ local_dest = tempfile.mkstemp()[1]
96
+ subprocess.check_output(['gsutil', '-m', 'cp', path, local_dest])
97
+ return local_dest
98
+
99
+
100
+ def tile_images(images, d1=4, d2=4, border=1):
101
+ id1, id2, c = images[0].shape
102
+ out = np.ones([d1 * id1 + border * (d1 + 1),
103
+ d2 * id2 + border * (d2 + 1),
104
+ c], dtype=np.uint8)
105
+ out *= 255
106
+ if len(images) != d1 * d2:
107
+ raise ValueError('Wrong num of images')
108
+ for imgnum, im in enumerate(images):
109
+ num_d1 = imgnum // d2
110
+ num_d2 = imgnum % d2
111
+ start_d1 = num_d1 * id1 + border * (num_d1 + 1)
112
+ start_d2 = num_d2 * id2 + border * (num_d2 + 1)
113
+ out[start_d1:start_d1 + id1, start_d2:start_d2 + id2, :] = im
114
+ return out
115
+
116
+
117
+ def mpi_size():
118
+ return MPI.COMM_WORLD.Get_size()
119
+
120
+
121
+ def mpi_rank():
122
+ return MPI.COMM_WORLD.Get_rank()
123
+
124
+
125
+ def num_nodes():
126
+ nn = mpi_size()
127
+ if nn % 8 == 0:
128
+ return nn // 8
129
+ return nn // 8 + 1
130
+
131
+
132
+ def gpus_per_node():
133
+ size = mpi_size()
134
+ if size > 1:
135
+ return max(size // num_nodes(), 1)
136
+ return 1
137
+
138
+
139
+ def local_mpi_rank():
140
+ return mpi_rank() % gpus_per_node()
spurious_reconstruction/.gitignore ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # python generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # venv
10
+ .venv
11
+ ./results
12
+ ./analysis/my_playground
13
+ ./data
spurious_reconstruction/README.md ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Spurious-reconstruction
2
+
3
+ This repository contains demo code for the paper:
4
+ Ken Shirakawa, Yoshihiro Nagano, Misato Tanaka, Shuntaro C. Aoki, Yusuke Muraki, Kei Majima, and Yukiyasu Kamitani, "Spurious reconstruction from brain activity" ([arXiv](https://arxiv.org/abs/2405.10078)).
5
+
6
+ ## Getting Started
7
+
8
+ ### Installation
9
+ To clone this repository on your local machine, use the following `git clone` command with the project URL:
10
+
11
+
12
+ ```
13
+ git clone https://github.com/KamitaniLab/spurious_reconstruction.git
14
+ ```
15
+ ### Environment Setup
16
+ The environment for this project was created using [Rye](https://rye.astral.sh/). To set it up, follow the official instructions to install Rye. After installation, you can synchronize the environment for this repository using:
17
+
18
+ ```
19
+ cd spurious_reconstruction
20
+ rye sync
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ ---
26
+
27
+ We are currently preparing to share the preprocessed data and files. These files will be made available on Figshare at [this URL](https://figshare.com/articles/dataset/Spurious_reconstruction_from_brain_activity/27013342).
28
+
29
+ Reproducing the full analysis requires a large amount of data (approximately 3TB) and some analyses take considerable time to complete (up to ~2 weeks). Therefore, we recommend downloading only the minimum necessary files to reproduce specific analysis, such as image reconstruction, UMAP results or simulation analysis.
30
+
31
+ For example, if you want to reproduce the UMAP results (related to Figure 4), you can download the required data by running the following command:
32
+
33
+ ```
34
+ python ./download.py "UMAP visualization analysis"
35
+ ```
36
+
37
+ Alternatively, you can directly download the results of UMAP analysis with:
38
+ ```
39
+ python ./download.py "UMAP visualization results"
40
+ ```
41
+ Note: At the moment, only the download of **result data** is supported. Please wait a little longer for the availability of **analysis data**.
42
+
43
+ Each analysis directory contains additional information on how to reproduce the corresponding results. Please check the README files within each directory for specific instructions.
44
+
45
+
46
+ ### Original Dataset
47
+ We used publicly available datasets for this project. The key datasets are:
48
+
49
+ - **NSD (Natural Scenes Dataset)**
50
+ - Raw fMRI data (including visual images and text annotations): Available upon request via [Spurious Reconstruction@figshare](https://forms.gle/eT4jHxaWwYUDEf2i9).
51
+
52
+ - **Deep Image Reconstruction**
53
+ - Raw fMRI data: Available from [OpenNeuro](https://openneuro.org/datasets/ds001506).
54
+ - Preprocessed fMRI data, DNN features extracted from images, and decoded DNN features: Available via [Deep Image Reconstruction@figshare](https://github.com/KamitaniLab/DeepImageReconstruction?tab=readme-ov-file#:~:text=Preprocessed%20fMRI%20data,Image%20Reconstruction%40figshare).
55
+ - Visual images: Available upon request via [this form](https://forms.gle/ujvA34948Xg49jdn9).
56
+ - Text annotations: Available from [GOD Stimuli Annotations](https://github.com/KamitaniLab/GOD_stimuli_annotations).
57
+
58
+ If you want to fully reproduce the analysis, you can use these brain data, image stimuli and corresponding text annotations.
spurious_reconstruction/analysis/0_preprocessing/.ipynb_checkpoints/extract_features-checkpoint.ipynb ADDED
@@ -0,0 +1,437 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 1,
6
+ "id": "5082cdc1-b052-433d-b018-29ba6fa3d313",
7
+ "metadata": {},
8
+ "outputs": [],
9
+ "source": [
10
+ "# %% [Block 1]\n",
11
+ "from glob import glob\n",
12
+ "from tqdm.auto import tqdm\n",
13
+ "import os\n",
14
+ "from PIL import Image\n",
15
+ "import numpy as np\n",
16
+ "import torch\n",
17
+ "from scipy.io import savemat\n",
18
+ "from bdpy.dl.torch import FeatureExtractor\n",
19
+ "from torchvision import models, transforms\n",
20
+ "import yaml\n",
21
+ "import h5py"
22
+ ]
23
+ },
24
+ {
25
+ "cell_type": "code",
26
+ "execution_count": 2,
27
+ "id": "a31be173-61ff-4adf-a558-63a3efe74cff",
28
+ "metadata": {},
29
+ "outputs": [],
30
+ "source": [
31
+ "# %% [Block 2]\n",
32
+ "# Custom transform class to convert RGB to BGR\n",
33
+ "class ConvertRGBtoBGR:\n",
34
+ " def __call__(self, image):\n",
35
+ " return image[[2, 1, 0], :, :] \n",
36
+ " \n",
37
+ "# Custom transform class to convert Image format to tensor while keeping pixel ranges\n",
38
+ "class ToTensorWithoutScaling:\n",
39
+ " def __call__(self, image):\n",
40
+ " image = np.array(image).astype(np.float32) # Convert PIL Image to NumPy array\n",
41
+ " tensor = torch.from_numpy(image).permute(2, 0, 1).float() # Convert NumPy array to tensor and rearrange dimensions\n",
42
+ " return tensor\n",
43
+ " \n",
44
+ "class Convert32to16:\n",
45
+ " def __call__(self, image):\n",
46
+ " return image.type(torch.float16)\n"
47
+ ]
48
+ },
49
+ {
50
+ "cell_type": "code",
51
+ "execution_count": 34,
52
+ "id": "969abfe4-e4b6-4fa2-bd09-17f77ddf2292",
53
+ "metadata": {},
54
+ "outputs": [],
55
+ "source": [
56
+ "# %% [Block 3]\n",
57
+ "def load_model(network):\n",
58
+ " \n",
59
+ " if network == \"VGG19_ILSVRC_19_layers\":\n",
60
+ " from bdpy.dl.torch.models import layer_map, model_factory\n",
61
+ " model = model_factory('vgg19')\n",
62
+ " encoder_param_file = '/weka/proj-fmri/ckadirt/spurious_reconstruction/analysis/VGG_ILSVRC_19_layers/VGG_ILSVRC_19_layers.pt'\n",
63
+ " model.load_state_dict(torch.load(encoder_param_file))\n",
64
+ " model.eval()\n",
65
+ " layer_mapping = layer_map('vgg19')\n",
66
+ " mean_image = [104., 117., 123.] # BGR\n",
67
+ " preprocess = transforms.Compose([\n",
68
+ " transforms.Resize((224, 224), interpolation=Image.BICUBIC),\n",
69
+ " # ToTensorWithoutScaling(), # Custom transform added\n",
70
+ " # ConvertRGBtoBGR(), # Custom transform added\n",
71
+ " transforms.Normalize(mean=mean_image, std=[1.,1.,1.]),\n",
72
+ " ])\n",
73
+ " def preprocess_and_check(img):\n",
74
+ " print(\"Original shape:\", img.shape)\n",
75
+ " img = transforms.Resize((224, 224), interpolation=Image.BICUBIC)(img)\n",
76
+ " print(\"After ToTensor:\", img.shape)\n",
77
+ " print(\"After Resize:\", img.shape)\n",
78
+ " img = transforms.Normalize(mean=mean_image, std=[1.,1.,1.])(img)\n",
79
+ " return img\n",
80
+ " \n",
81
+ " elif network == \"vgg19_torchvision\":\n",
82
+ " model = models.vgg19(pretrained=True)\n",
83
+ " model.eval()\n",
84
+ " \n",
85
+ " preprocess = transforms.Compose([\n",
86
+ " transforms.Resize((224, 224)), \n",
87
+ " transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n",
88
+ " ]) \n",
89
+ " def preprocess_and_check(img):\n",
90
+ " print(\"Original shape:\", img.shape)\n",
91
+ " img = transforms.ToTensor()(img)\n",
92
+ " print(\"After ToTensor:\", img.shape)\n",
93
+ " img = transforms.Resize(224)(img)\n",
94
+ " print(\"After Resize:\", img.shape)\n",
95
+ " img = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])(img)\n",
96
+ " return img\n",
97
+ " else:\n",
98
+ " raise ValueError(\"Network not supported. Please choose from: VGG19_ILSVRC_19_layers\"\n",
99
+ " +\"or define by yourself. The output should be model and preprocessing functions from RGB image to model input.\")\n",
100
+ " \n",
101
+ " return model, preprocess\n"
102
+ ]
103
+ },
104
+ {
105
+ "cell_type": "code",
106
+ "execution_count": 35,
107
+ "id": "8020d232-72cd-42ed-bb8e-183c8c0ee9b6",
108
+ "metadata": {},
109
+ "outputs": [],
110
+ "source": [
111
+ "# %% [Block 4]\n",
112
+ "def load_config(config_path):\n",
113
+ " '''Load configuration file.'''\n",
114
+ " with open(config_path, 'r') as file:\n",
115
+ " config = yaml.safe_load(file)\n",
116
+ " return config\n"
117
+ ]
118
+ },
119
+ {
120
+ "cell_type": "code",
121
+ "execution_count": 36,
122
+ "id": "a766c128-7e43-419c-9d7e-6f317e44753e",
123
+ "metadata": {},
124
+ "outputs": [
125
+ {
126
+ "name": "stdout",
127
+ "output_type": "stream",
128
+ "text": [
129
+ "/weka/proj-medarc/shared/mindeyev2_dataset//wds/subj01/train/{0..39}.tar\n",
130
+ "/weka/proj-medarc/shared/mindeyev2_dataset//wds/subj01/new_test/0.tar\n",
131
+ "Loaded test dl for subj1!\n",
132
+ "\n"
133
+ ]
134
+ },
135
+ {
136
+ "data": {
137
+ "application/vnd.jupyter.widget-view+json": {
138
+ "model_id": "65cb44139d1e4cf788e5a8956d9c1eb1",
139
+ "version_major": 2,
140
+ "version_minor": 0
141
+ },
142
+ "text/plain": [
143
+ "0it [00:00, ?it/s]"
144
+ ]
145
+ },
146
+ "metadata": {},
147
+ "output_type": "display_data"
148
+ },
149
+ {
150
+ "data": {
151
+ "application/vnd.jupyter.widget-view+json": {
152
+ "model_id": "981c8b8963d84fbf9994421e1e8ce02b",
153
+ "version_major": 2,
154
+ "version_minor": 0
155
+ },
156
+ "text/plain": [
157
+ "0it [00:00, ?it/s]"
158
+ ]
159
+ },
160
+ "metadata": {},
161
+ "output_type": "display_data"
162
+ }
163
+ ],
164
+ "source": [
165
+ "import webdataset as wds\n",
166
+ "import random\n",
167
+ "\n",
168
+ "def my_split_by_node(urls): return urls\n",
169
+ "data_path = '/weka/proj-medarc/shared/mindeyev2_dataset/'\n",
170
+ "subj_list = [1]\n",
171
+ "num_sessions = 40\n",
172
+ "multi_subject = False\n",
173
+ "batch_size = 1\n",
174
+ "data_type = torch.float16\n",
175
+ "subj = 1\n",
176
+ "\n",
177
+ "train_data = {}\n",
178
+ "train_dl = {}\n",
179
+ "num_voxels = {}\n",
180
+ "voxels = {}\n",
181
+ "\n",
182
+ "train_url = f\"{data_path}/wds/subj0{subj}/train/\" + \"{0..\" + f\"{num_sessions-1}\" + \"}.tar\"\n",
183
+ "print(train_url)\n",
184
+ "\n",
185
+ "train_data = wds.WebDataset(train_url,resampled=False,nodesplitter=my_split_by_node)\\\n",
186
+ " .decode(\"torch\")\\\n",
187
+ " .rename(behav=\"behav.npy\", past_behav=\"past_behav.npy\", future_behav=\"future_behav.npy\", olds_behav=\"olds_behav.npy\")\\\n",
188
+ " .to_tuple(*[\"behav\", \"past_behav\", \"future_behav\", \"olds_behav\"])\n",
189
+ "train_dl = torch.utils.data.DataLoader(train_data, batch_size=batch_size, shuffle=False, drop_last=False, pin_memory=True)\n",
190
+ "\n",
191
+ "# f = h5py.File(f'{data_path}/betas_all_subj0{s}_fp32_renorm.hdf5', 'r')\n",
192
+ "# betas = f['betas'][:]\n",
193
+ "# betas = torch.Tensor(betas).to(\"cpu\").to(data_type)\n",
194
+ "# num_voxels_list.append(betas[0].shape[-1])\n",
195
+ "# num_voxels[f'subj0{s}'] = betas[0].shape[-1]\n",
196
+ "# voxels[f'subj0{s}'] = betas\n",
197
+ "# print(f\"num_voxels for subj0{s}: {num_voxels[f'subj0{s}']}\")\n",
198
+ "\n",
199
+ "\n",
200
+ "num_test=3000\n",
201
+ "test_url = f\"{data_path}/wds/subj0{subj}/new_test/\" + \"0.tar\"\n",
202
+ "print(test_url)\n",
203
+ "test_data = wds.WebDataset(test_url,resampled=False,nodesplitter=my_split_by_node)\\\n",
204
+ " .decode(\"torch\")\\\n",
205
+ " .rename(behav=\"behav.npy\", past_behav=\"past_behav.npy\", future_behav=\"future_behav.npy\", olds_behav=\"olds_behav.npy\")\\\n",
206
+ " .to_tuple(*[\"behav\", \"past_behav\", \"future_behav\", \"olds_behav\"])\n",
207
+ "test_dl = torch.utils.data.DataLoader(test_data, batch_size=1, shuffle=False, drop_last=True, pin_memory=True)\n",
208
+ "print(f\"Loaded test dl for subj{subj}!\\n\")\n",
209
+ "\n",
210
+ "all_indexes_train = []\n",
211
+ "\n",
212
+ "for behav0, past_behav0, future_behav0, old_behav0 in tqdm(train_dl):\n",
213
+ " img_idx = behav0[:,0,0].cpu().long().numpy()[0]\n",
214
+ " all_indexes_train.append(img_idx)\n",
215
+ "\n",
216
+ "all_indexes_test = []\n",
217
+ "\n",
218
+ "for behav0, past_behav0, future_behav0, old_behav0 in tqdm(test_dl):\n",
219
+ " img_idx = behav0[:,0,0].cpu().long().numpy()[0]\n",
220
+ " all_indexes_test.append(img_idx)"
221
+ ]
222
+ },
223
+ {
224
+ "cell_type": "code",
225
+ "execution_count": 37,
226
+ "id": "17a4377a-67dc-49fc-b89c-7d641ef218ce",
227
+ "metadata": {},
228
+ "outputs": [],
229
+ "source": [
230
+ "def extract_features(config, device='cuda'):\n",
231
+ " '''Extract features based on the configuration.'''\n",
232
+ " print(\"Extracting features using network:\", config['network'])\n",
233
+ " \n",
234
+ " f = h5py.File(f'{config[\"image path\"]}/coco_images_224_float16.hdf5', 'r')\n",
235
+ " images = f['images']\n",
236
+ " print(images.shape)\n",
237
+ " model, preprocess = load_model(config['network'])\n",
238
+ " layers = config[\"features\"]\n",
239
+ " feature_extractor = FeatureExtractor(model, layers, device=device, detach=True)\n",
240
+ " \n",
241
+ " output_dir = os.path.join(config[\"output base dir\"], \"pytorch\", config['network'])\n",
242
+ "\n",
243
+ " all_indexes_to_compute = set(all_indexes_train + list(set(all_indexes_test)))\n",
244
+ " \n",
245
+ " # First, ensure all layer directories exist\n",
246
+ " # for layer in layers:\n",
247
+ " # layer_output_dir = os.path.join(output_dir, layer)\n",
248
+ " # os.makedirs(layer_output_dir, exist_ok=True)\n",
249
+ " # img = torch.Tensor(images[0])\n",
250
+ "\n",
251
+ " # x = preprocess(img).unsqueeze(0).to(device)\n",
252
+ " # # Extract features\n",
253
+ " # features = feature_extractor.run(x)\n",
254
+ " \n",
255
+ " # # Get the feature for the current layer\n",
256
+ " # f = features.get(layer)\n",
257
+ " # print(f.shape)\n",
258
+ " \n",
259
+ "\n",
260
+ " \n",
261
+ " for layer in tqdm(layers, desc=\"Processing layers\"): # Iterate over each layer first\n",
262
+ " layer_output_dir = os.path.join(output_dir, layer)\n",
263
+ "\n",
264
+ " with h5py.File(f'{layer_output_dir}/{subj}.h5', 'a') as hdf5_file:\n",
265
+ "\n",
266
+ " # initial_shape = (0, 100) # Start with 0 rows and 100 columns (or your array shape)\n",
267
+ " # max_shape = (None, 100) # Allow unlimited rows\n",
268
+ " \n",
269
+ " # if 'dataset' not in hdf5_file:\n",
270
+ " # dataset = hdf5_file.create_dataset(\n",
271
+ " # 'dataset', \n",
272
+ " # shape=initial_shape, \n",
273
+ " # maxshape=max_shape, \n",
274
+ " # dtype='float64'\n",
275
+ " # )\n",
276
+ " # else:\n",
277
+ " # dataset = hdf5_file['dataset']\n",
278
+ " for i, image_index in tqdm(enumerate(all_indexes_to_compute), total = len(all_indexes_to_compute)):\n",
279
+ " output_file = os.path.join(layer_output_dir, f\"{image_index}.npy\")\n",
280
+ " \n",
281
+ " if os.path.exists(output_file):\n",
282
+ " continue # Skip if the feature for this image and layer already exists\n",
283
+ " \n",
284
+ " # Load and preprocess the image\n",
285
+ " img = torch.Tensor(images[image_index])\n",
286
+ " x = preprocess(img).unsqueeze(0).to(device)\n",
287
+ " \n",
288
+ " # Extract features\n",
289
+ " features = feature_extractor.run(x)\n",
290
+ " \n",
291
+ " # Get the feature for the current layer\n",
292
+ " f = features.get(layer)\n",
293
+ " if f is None:\n",
294
+ " print(f\"Warning: Layer '{layer}' not found in the extracted features.\")\n",
295
+ " continue\n",
296
+ "\n",
297
+ " if i == 0:\n",
298
+ " initial_shape = f.shape\n",
299
+ " max_shape = (None,) + initial_shape[1:]\n",
300
+ "\n",
301
+ " if 'dataset' not in hdf5_file:\n",
302
+ " dataset = hdf5_file.create_dataset(\n",
303
+ " 'dataset', \n",
304
+ " shape=initial_shape, \n",
305
+ " maxshape=max_shape, \n",
306
+ " dtype='float16'\n",
307
+ " )\n",
308
+ " else:\n",
309
+ " dataset = hdf5_file['dataset']\n",
310
+ "\n",
311
+ " dataset.resize(dataset.shape[0] + f.shape[0], axis=0)\n",
312
+ " \n",
313
+ " # Append the data\n",
314
+ " dataset[-f.shape[0]:] = f.astype(np.float16)\n",
315
+ " \n",
316
+ " # # Save the feature\n",
317
+ " # np.save(output_file, f.astype(np.float16))\n",
318
+ " \n",
319
+ " # Optional: Break early for testing\n",
320
+ " # if layer == some_condition:\n",
321
+ " # break\n",
322
+ "\n",
323
+ " print('All done')"
324
+ ]
325
+ },
326
+ {
327
+ "cell_type": "code",
328
+ "execution_count": 38,
329
+ "id": "5dc66f30-9406-4e7a-adca-81161df3611a",
330
+ "metadata": {},
331
+ "outputs": [
332
+ {
333
+ "name": "stdout",
334
+ "output_type": "stream",
335
+ "text": [
336
+ "Extracting features using network: VGG19_ILSVRC_19_layers\n",
337
+ "(73000, 3, 224, 224)\n",
338
+ "(1, 64, 224, 224)\n",
339
+ "(1, 64, 224, 224)\n",
340
+ "(1, 128, 112, 112)\n",
341
+ "(1, 128, 112, 112)\n",
342
+ "(1, 256, 56, 56)\n",
343
+ "(1, 256, 56, 56)\n",
344
+ "(1, 256, 56, 56)\n",
345
+ "(1, 256, 56, 56)\n",
346
+ "(1, 512, 28, 28)\n",
347
+ "(1, 512, 28, 28)\n",
348
+ "(1, 512, 28, 28)\n",
349
+ "(1, 512, 28, 28)\n",
350
+ "(1, 512, 14, 14)\n",
351
+ "(1, 512, 14, 14)\n",
352
+ "(1, 512, 14, 14)\n",
353
+ "(1, 512, 14, 14)\n",
354
+ "(1, 4096)\n",
355
+ "(1, 4096)\n",
356
+ "(1, 1000)\n"
357
+ ]
358
+ },
359
+ {
360
+ "ename": "NameError",
361
+ "evalue": "name 'ththth' is not defined",
362
+ "output_type": "error",
363
+ "traceback": [
364
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
365
+ "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
366
+ "Cell \u001b[0;32mIn[38], line 8\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[38;5;66;03m# %%\u001b[39;00m\n\u001b[1;32m 6\u001b[0m \u001b[38;5;66;03m# Load config and extract features\u001b[39;00m\n\u001b[1;32m 7\u001b[0m config \u001b[38;5;241m=\u001b[39m load_config(config_path)\n\u001b[0;32m----> 8\u001b[0m \u001b[43mextract_features\u001b[49m\u001b[43m(\u001b[49m\u001b[43mconfig\u001b[49m\u001b[43m)\u001b[49m\n",
367
+ "Cell \u001b[0;32mIn[37], line 31\u001b[0m, in \u001b[0;36mextract_features\u001b[0;34m(config, device)\u001b[0m\n\u001b[1;32m 27\u001b[0m f \u001b[38;5;241m=\u001b[39m features\u001b[38;5;241m.\u001b[39mget(layer)\n\u001b[1;32m 28\u001b[0m \u001b[38;5;28mprint\u001b[39m(f\u001b[38;5;241m.\u001b[39mshape)\n\u001b[0;32m---> 31\u001b[0m \u001b[43mththth\u001b[49m\n\u001b[1;32m 32\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m layer \u001b[38;5;129;01min\u001b[39;00m tqdm(layers, desc\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mProcessing layers\u001b[39m\u001b[38;5;124m\"\u001b[39m): \u001b[38;5;66;03m# Iterate over each layer first\u001b[39;00m\n\u001b[1;32m 33\u001b[0m layer_output_dir \u001b[38;5;241m=\u001b[39m os\u001b[38;5;241m.\u001b[39mpath\u001b[38;5;241m.\u001b[39mjoin(output_dir, layer)\n",
368
+ "\u001b[0;31mNameError\u001b[0m: name 'ththth' is not defined"
369
+ ]
370
+ }
371
+ ],
372
+ "source": [
373
+ "# %% [Block 6]\n",
374
+ "# Instead of using argparse, manually provide the config file path for a notebook\n",
375
+ "config_path = '/weka/proj-fmri/ckadirt/spurious_reconstruction/analysis/0_preprocessing/config/NSD/NSD.yaml' # Replace with your config file path\n",
376
+ "\n",
377
+ "# %%\n",
378
+ "# Load config and extract features\n",
379
+ "config = load_config(config_path)\n",
380
+ "extract_features(config)\n"
381
+ ]
382
+ },
383
+ {
384
+ "cell_type": "code",
385
+ "execution_count": null,
386
+ "id": "35e4f307-1652-4af7-ad82-3ee4c3f142fd",
387
+ "metadata": {},
388
+ "outputs": [],
389
+ "source": []
390
+ },
391
+ {
392
+ "cell_type": "code",
393
+ "execution_count": 8,
394
+ "id": "2d6c4809-0aab-4257-8994-4e892e23de9f",
395
+ "metadata": {},
396
+ "outputs": [],
397
+ "source": [
398
+ "# with h5py.File(f'/weka/proj-fmri/ckadirt/spurious_reconstruction/analysis/0_preprocessing/features/pytorch/vgg19_torchvision/features[0]/1.h5', 'a') as hdf5_file:\n",
399
+ "# dataset = hdf5_file['dataset']\n",
400
+ "# print(len(dataset))\n",
401
+ "# print(dataset[10].shape, dataset[10].dtype)\n",
402
+ "# print(dataset.shape)"
403
+ ]
404
+ },
405
+ {
406
+ "cell_type": "code",
407
+ "execution_count": 9,
408
+ "id": "fcf6d112-e24c-4fd5-ac59-f21e3611ebbc",
409
+ "metadata": {},
410
+ "outputs": [],
411
+ "source": [
412
+ "# dataset"
413
+ ]
414
+ }
415
+ ],
416
+ "metadata": {
417
+ "kernelspec": {
418
+ "display_name": "mindeye",
419
+ "language": "python",
420
+ "name": "mindeye"
421
+ },
422
+ "language_info": {
423
+ "codemirror_mode": {
424
+ "name": "ipython",
425
+ "version": 3
426
+ },
427
+ "file_extension": ".py",
428
+ "mimetype": "text/x-python",
429
+ "name": "python",
430
+ "nbconvert_exporter": "python",
431
+ "pygments_lexer": "ipython3",
432
+ "version": "3.11.10"
433
+ }
434
+ },
435
+ "nbformat": 4,
436
+ "nbformat_minor": 5
437
+ }
spurious_reconstruction/analysis/0_preprocessing/.ipynb_checkpoints/iCNN_image_vgg19_feature_extraction-checkpoint.py ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ '''DNN Feature extraction script'''
2
+
3
+ # %%%
4
+ from glob import glob
5
+ from tqdm import tqdm
6
+ import os
7
+ import argparse
8
+ from PIL import Image
9
+ import numpy as np
10
+ import torch
11
+ from scipy.io import savemat
12
+ from bdpy.dl.torch import FeatureExtractor
13
+ from torchvision import models, transforms
14
+ import yaml
15
+ # %%%
16
+ # Custum transform class to convert RGB to BGR
17
+ class ConvertRGBtoBGR:
18
+ def __call__(self, image):
19
+ return image[[2, 1, 0], :, :]
20
+
21
+ # Custum transform class to convert Image format to tensor while keeping pixel ranges
22
+ class ToTensorWithoutScaling:
23
+ def __call__(self, image):
24
+ image = np.array(image).astype(np.float32) # PIL ImageをNumPy配列に変換
25
+ tensor = torch.from_numpy(image).permute(2, 0, 1).float() # NumPy配列をテンソルに変換し、次元を並べ替える
26
+ return tensor
27
+
28
+ class Convert32to16:
29
+ def __call__(self, image):
30
+ return image.type(torch.float16)
31
+
32
+ # %%%
33
+ def load_model(network):
34
+
35
+ if network == "VGG19_ILSVRC_19_layers":
36
+ from bdpy.dl.torch.models import layer_map, model_factory
37
+ model = model_factory('vgg19')
38
+ encoder_param_file = './data/models_shared/pytorch/VGG_ILSVRC_19_layers/VGG_ILSVRC_19_layers.pt'
39
+ model.load_state_dict(torch.load(encoder_param_file))
40
+ model.eval()
41
+ layer_mapping = layer_map('vgg19')
42
+ # change RGB-> BGR and subtract mean via lambda function
43
+ mean_image = [104., 117., 123.] #BGR!
44
+ #mean_image = [103.939, 116.779, 123.68] #BGR!
45
+ preprocess = transforms.Compose([
46
+ transforms.Resize(224, interpolation=Image.BICUBIC),
47
+ #transforms.CenterCrop(224),
48
+ #transforms.ToTensor(),
49
+ ToTensorWithoutScaling(), # カスタム変換を追加
50
+ ConvertRGBtoBGR(), # カスタム変換を追加
51
+ transforms.Normalize(mean=mean_image, std=[1.,1.,1.]),
52
+ ])
53
+
54
+ elif network == "vgg19_torchvision":
55
+ model = models.vgg19(pretrained=True)
56
+ model.eval()
57
+
58
+ # 画像の前処理
59
+ preprocess = transforms.Compose([
60
+ transforms.Resize(224),#transforms.Resize(256),
61
+ #transforms.CenterCrop(224),
62
+ transforms.ToTensor(),
63
+ transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
64
+ ])
65
+ else:
66
+ raise ValueError("Network not supported. Please choose from: VGG19_ILSVRC_19_layers"
67
+ +"or define by yourself. The output should be model and preprocessing functions from RGB image to model input."
68
+ )
69
+
70
+ return model, preprocess
71
+
72
+ def load_config(config_path):
73
+ '''Load configuration file.'''
74
+ with open(config_path, 'r') as file:
75
+ config = yaml.safe_load(file)
76
+ return config
77
+
78
+ def extract_features(config, device='cuda'):
79
+ '''Extract features based on the configuration.'''
80
+ print("Extracting features using network:", config['network'])
81
+
82
+ image_dir = config['image path']
83
+ image_ext = config["image_ext"]
84
+ image_files = glob(os.path.join(image_dir, '*.' + image_ext))
85
+
86
+ model, preprocess = load_model(config['network'])
87
+ layers = config["features"]
88
+ feature_extractor = FeatureExtractor(model, layers, device=device, detach=True)
89
+
90
+ output_dir = os.path.join(config["output base dir"], "pytorch",config['network'])
91
+
92
+ for image_file in tqdm(image_files):
93
+ img = Image.open(image_file).convert('RGB')
94
+
95
+ x = preprocess(img).unsqueeze(0).to(device)
96
+
97
+ # Extract features
98
+ features = feature_extractor.run(x)
99
+
100
+ # Save features
101
+ for layer in features.keys():
102
+ f = features[layer]
103
+
104
+ output_file = os.path.join(
105
+ output_dir,
106
+ layer,
107
+ os.path.splitext(os.path.basename(image_file))[0] + '.mat'
108
+ )
109
+
110
+ if os.path.exists(output_file):
111
+ continue
112
+
113
+ os.makedirs(os.path.join(output_dir, layer), exist_ok=True)
114
+
115
+ savemat(output_file, {'feat': f})
116
+ #print('Saved {}'.format(output_file))
117
+
118
+ print('All done')
119
+
120
+
121
+
122
+ # %%%
123
+ if __name__ == '__main__':
124
+ parser = argparse.ArgumentParser(description='DNN Feature extraction')
125
+ parser.add_argument('config', help='Configuration file')
126
+ args = parser.parse_args()
127
+
128
+ config = load_config(args.config)
129
+ extract_features(config)
130
+ # %%
spurious_reconstruction/analysis/0_preprocessing/BD_extract_CLIP_vision_features.py ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Code is based on https://github.com/ozcelikfu/brain-diffuser/blob/main/scripts/clipvision_extract_features.py
2
+
3
+ # %%
4
+ import sys
5
+ # %%
6
+ sys.path.append('brain-diffuser/versatile_diffusion')
7
+ import os
8
+ import PIL
9
+ from PIL import Image
10
+ import numpy as np
11
+
12
+ import torch
13
+ from lib.cfg_helper import model_cfg_bank
14
+ from lib.model_zoo import get_model
15
+ #from lib.experiments.sd_default import color_adjust, auto_merge_imlist
16
+ from torch.utils.data import DataLoader, Dataset
17
+
18
+ from lib.model_zoo.vd import VD
19
+ from lib.cfg_holder import cfg_unique_holder as cfguh
20
+ from lib.cfg_helper import get_command_line_args, cfg_initiates, load_cfg_yaml
21
+ import torchvision.transforms as T
22
+ import yaml
23
+ from easydict import EasyDict as edict
24
+ import argparse
25
+ import os.path as osp
26
+
27
+ from scipy.io import savemat
28
+ # %%
29
+ # %%
30
+ class batch_generator_external_image_files(Dataset):
31
+
32
+ def __init__(self, data_path):
33
+ self.data_path = data_path
34
+ self.im = sorted(os.listdir(self.data_path))
35
+
36
+
37
+ def __getitem__(self,idx):
38
+ img = Image.open(os.path.join(self.data_path,self.im[idx])).convert('RGB')
39
+ img = T.functional.resize(img,(512,512))
40
+ img = torch.tensor(np.array(img)).float()
41
+ #img = img/255
42
+ img = img*2 - 1
43
+ return img.permute(2,0, 1), self.im[idx]
44
+
45
+ def __len__(self):
46
+ return len(self.im)
47
+
48
+ def load_config(config_path):
49
+ '''Load configuration file.'''
50
+ with open(config_path, 'r') as file:
51
+ config = yaml.safe_load(file)
52
+ return config
53
+
54
+ def extract_CLIP_vision_features(config):
55
+ batch_size=1
56
+ # %%
57
+ cfgm_name = 'vd_noema'
58
+ cfgm = model_cfg_bank()(cfgm_name)
59
+ net = get_model()(cfgm)
60
+ # %%
61
+ pth = 'versatile_diffusion/pretrained/vd-four-flow-v1-0-fp16-deprecated.pth'
62
+ sd = torch.load(pth, map_location='cpu')
63
+ net.load_state_dict(sd, strict=False)
64
+ # %%
65
+ device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
66
+ net.clip = net.clip.to(device)
67
+ # %%
68
+
69
+ data_path = config['image path']
70
+ # %%
71
+ image_data = batch_generator_external_image_files(data_path)
72
+ data_loader = DataLoader(image_data,batch_size,shuffle=False)
73
+ # %%
74
+ num_embed, num_features, num_image = 257, 768, image_data.__len__()
75
+
76
+ clip_feat = np.zeros((num_image,num_embed,num_features))
77
+ # %%
78
+ output_dir = os.path.join(config["output base dir"], "pytorch", 'brain_diffuser_versatile_diffusion')
79
+ # %%
80
+ layer = 'vision_encoder'
81
+ # %%
82
+ with torch.no_grad():
83
+ # %%
84
+ for i,(imgs_torch_tensor, image_files) in enumerate(data_loader):
85
+
86
+ # %%
87
+ c_v_feature = net.clip_encode_vision(imgs_torch_tensor)
88
+
89
+ for j, image_file in enumerate(image_files):
90
+ f = c_v_feature[j][np.newaxis].cpu().numpy()
91
+
92
+ output_file = os.path.join(
93
+ output_dir,
94
+ layer,
95
+ os.path.splitext(os.path.basename(image_file))[0] + '.mat'
96
+ )
97
+
98
+ if os.path.exists(output_file):
99
+ continue
100
+
101
+ os.makedirs(os.path.join(output_dir, layer), exist_ok=True)
102
+
103
+ savemat(output_file, {'feat': f})
104
+
105
+
106
+ # %%
107
+
108
+ # %%%
109
+ if __name__ == '__main__':
110
+ parser = argparse.ArgumentParser(description='DNN Feature extraction')
111
+ parser.add_argument('config', help='Configuration file')
112
+ args = parser.parse_args()
113
+
114
+ config = load_config(args.config)
115
+ extract_CLIP_vision_features(config)
spurious_reconstruction/analysis/0_preprocessing/BD_extract_Deeprecon_CLIP_text_features.py ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # %%
2
+ import sys
3
+ sys.path.append('versatile_diffusion')
4
+ import os
5
+ import numpy as np
6
+
7
+ import torch
8
+ from lib.cfg_helper import model_cfg_bank
9
+ from lib.model_zoo import get_model
10
+ from torch.utils.data import DataLoader, Dataset
11
+
12
+ from lib.model_zoo.vd import VD
13
+ from lib.cfg_holder import cfg_unique_holder as cfguh
14
+ from lib.cfg_helper import get_command_line_args, cfg_initiates, load_cfg_yaml
15
+ import matplotlib.pyplot as plt
16
+ import torchvision.transforms as T
17
+ from scipy.io import savemat
18
+ from glob import glob
19
+ import pandas as pd
20
+ # %%
21
+
22
+ #def extract_NSD_CLIP_text_features():
23
+ def extract_Deeprecon_CLIP_text_features():
24
+ cfgm_name = 'vd_noema'
25
+ pth = 'versatile_diffusion/pretrained/vd-four-flow-v1-0-fp16-deprecated.pth'
26
+ cfgm = model_cfg_bank()(cfgm_name)
27
+ net = get_model()(cfgm)
28
+ sd = torch.load(pth, map_location='cpu')
29
+ net.load_state_dict(sd, strict=False)
30
+ # %%
31
+ device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
32
+ net.clip = net.clip.to(device)
33
+
34
+ # %%
35
+ num_embed, num_features = 77, 768
36
+ layer = 'text_encoder'
37
+ # Deeprecon test setting
38
+ image_list, df, save_base_path = Deeprecon_test_setting()
39
+
40
+ output_dir = os.path.join(save_base_path, "pytorch", 'brain_diffuser_versatile_diffusion')
41
+ print('Extract text features from Deeprecon test images')
42
+ extract_CLIP_text_features(image_list, df, output_dir, layer, net)
43
+ print('Done')
44
+ # %%
45
+
46
+ # Deeprecon traininig setting
47
+ training_image_list, df, save_base_path_training = Deeprecon_training_setting()
48
+ output_dir_training = os.path.join(save_base_path_training, "pytorch", 'brain_diffuser_versatile_diffusion')
49
+ print('Extract text features from Deeprecon training images')
50
+ extract_CLIP_text_features(training_image_list, df, output_dir_training, layer, net)
51
+ print('Done')
52
+
53
+
54
+ def Deeprecon_test_setting():
55
+ original_DeepreconTest_dir = './data/ImageNetTest'
56
+ image_list = glob(os.path.join(original_DeepreconTest_dir, 'source', '*.JPEG'))
57
+ # we didn't share the test annotation file due to the possibility to traing the future AI models.
58
+ df = pd.read_csv(os.path.join(original_DeepreconTest_dir, 'derivatives/captions/amt_20181204/amt_20181204.csv'))
59
+ save_base_path = "./data/ImageNetTest/derivatives/features"
60
+ return image_list, df, save_base_path
61
+
62
+ def Deeprecon_training_setting():
63
+ original_DeepreconTraining_dir = './data/contents_shared/ImageNetTraining'
64
+ image_list = glob(os.path.join(original_DeepreconTraining_dir, 'source', '*.JPEG'))
65
+ df = pd.read_csv(os.path.join(original_DeepreconTraining_dir, 'derivatives/captions/amt_20181204/amt_20181204.csv'))
66
+ save_base_path = "./data/ImageNetTraining/derivatives/features"
67
+ return image_list, df, save_base_path
68
+
69
+ def extract_CLIP_text_features(image_list, df, output_dir, layer, net):
70
+ for image in image_list:
71
+ file_name = os.path.basename(image).split('.')[0]
72
+ caption_texts = df[df['content_id'] == file_name]['caption'].values
73
+ #print(img)
74
+ out_text_list =[]
75
+ # %%
76
+ for cap in caption_texts:
77
+ c_t_feature = net.clip_encode_text(cap)
78
+ out_text_list.append(c_t_feature.cpu().detach().numpy())
79
+ out_text_list = np.array(out_text_list).squeeze() #[5, 77, 768]
80
+
81
+ # %%
82
+ output_file = os.path.join(
83
+ output_dir,
84
+ layer,
85
+ file_name + '.mat'
86
+ )
87
+ if os.path.exists(output_file):
88
+ continue
89
+
90
+ os.makedirs(os.path.join(output_dir, layer), exist_ok=True)
91
+
92
+ savemat(output_file, dict([('feat', np.mean(out_text_list, 0, keepdims=True)),
93
+ ('raw_feat', out_text_list)]) )
94
+
95
+
96
+ # %%
97
+
98
+ # %%%
99
+ if __name__ == '__main__':
100
+
101
+ extract_Deeprecon_CLIP_text_features()
spurious_reconstruction/analysis/0_preprocessing/BD_extract_NSD_CLIP_text_features.py ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # %%
2
+ import sys
3
+ sys.path.append('versatile_diffusion')
4
+ import os
5
+ import numpy as np
6
+
7
+ import torch
8
+ from lib.cfg_helper import model_cfg_bank
9
+ from lib.model_zoo import get_model
10
+ from torch.utils.data import DataLoader, Dataset
11
+
12
+ from lib.model_zoo.vd import VD
13
+ from lib.cfg_holder import cfg_unique_holder as cfguh
14
+ from lib.cfg_helper import get_command_line_args, cfg_initiates, load_cfg_yaml
15
+ import matplotlib.pyplot as plt
16
+ import torchvision.transforms as T
17
+ from nsd_access.nsd_access.nsda import NSDAccess
18
+ from scipy.io import savemat
19
+ # %%
20
+
21
+ def extract_NSD_CLIP_text_features():
22
+
23
+ cfgm_name = 'vd_noema'
24
+ pth = 'versatile_diffusion/pretrained/vd-four-flow-v1-0-fp16-deprecated.pth'
25
+ cfgm = model_cfg_bank()(cfgm_name)
26
+ net = get_model()(cfgm)
27
+ sd = torch.load(pth, map_location='cpu')
28
+ net.load_state_dict(sd, strict=False)
29
+ # %%
30
+ device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
31
+ net.clip = net.clip.to(device)
32
+
33
+ # %%
34
+ num_embed, num_features = 77, 768
35
+
36
+ origina_nsd_dir = '[PATH_TO_NSD_DATASET_DIR]' #'/home/nu/data/fmri_shared/public/NSD/latest/'
37
+ nsda = NSDAccess(origina_nsd_dir)
38
+
39
+ output_dir = os.path.join("./data/NSD-stimuli/derivatives/features/", "pytorch", 'brain_diffuser_versatile_diffusion')
40
+ layer = 'text_encoder'
41
+ # %%
42
+ total_num = 73000
43
+ for img in range(total_num):
44
+ file_name = f'nsd{img+1:05}'+ '.mat'
45
+ ci = nsda.read_image_coco_info([img], info_type='captions', show_annot=True)
46
+ #print(img)
47
+ out_text_list =[]
48
+ # %%
49
+
50
+ for annotator in ci:
51
+ cap = annotator['caption']
52
+
53
+ c_v_feature = net.clip_encode_text(cap)
54
+ out_text_list.append(c_v_feature.cpu().detach().numpy())
55
+ out_text_list = np.array(out_text_list).squeeze() #[5, 77, 768]
56
+
57
+ # %%
58
+ output_file = os.path.join(
59
+ output_dir,
60
+ layer,
61
+ file_name
62
+ )
63
+ if os.path.exists(output_file):
64
+ continue
65
+
66
+
67
+ os.makedirs(os.path.join(output_dir, layer), exist_ok=True)
68
+
69
+ savemat(output_file, dict([('feat', np.mean(out_text_list, 0, keepdims=True)),
70
+ ('raw_feat', out_text_list)]) )
71
+
72
+
73
+ # %%
74
+
75
+ # %%%
76
+ if __name__ == '__main__':
77
+
78
+ extract_NSD_CLIP_text_features()
spurious_reconstruction/analysis/0_preprocessing/README.md ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Scripts for extracting deep neural networks (DNNs) features from images (or text annotation), located at `./data/[dataset]/source` folders. You should put the stimuli files appropriately beforehand or run the download script.
2
+
3
+ # Usage (using rye environment)
4
+ If you want to extract VGG19 (for iCNN) in the Deeprecon dataset, running this command:
5
+ ```rye run python ./analysis/0_preprocessing/iCNN_image_vgg19_feature_extraction.py ./analysis/0_preprocessing/config/Deeprecon/ImageNetTest.yaml```
6
+
7
+ If you want to extract CLIP text (for Brain-Diffuser) in the Deeprecon dataset, running this command:
8
+ ```rye run python ./analysis/0_preprocessing/BD_extract_NSD_CLIP_tex_feature.py ./analysis/0_preprocessing/config/NSD/NSD.yaml```
9
+
10
+ If you want to extract CLIP vision (for Brain-Diffuser) in the NSD dataset, running this command:
11
+ ```rye run python ./analysis/0_preprocessing/BD_extract_CLIP_vision_feature.py ./analysis/0_preprocessing/config/NSD/NSD.yaml```
12
+
13
+ Note:
14
+ If you want to extract CLIP features used in the Brain-Diffuser models, you need additonaly prepare[versatile_diffusion](https://github.com/ozcelikfu/brain-diffuser/tree/main/versatile_diffusion) at the top of this directory.
15
+
spurious_reconstruction/analysis/0_preprocessing/config/Deeprecon/ArtificialShapes.yaml ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ image path:
2
+ ./data/ArtificialShapes/source
3
+
4
+ image_ext:
5
+ tiff
6
+
7
+ output base dir:
8
+ ./data/ArtificialShapes/derivatives/features/
9
+
10
+
11
+ # This is only related to the script "iCNN_image_vgg19_feature_extraction.py"
12
+ network:
13
+ VGG19_ILSVRC_19_layers
14
+
15
+ features:
16
+ - features[0] # conv1_1
17
+ - features[2] # conv1_2
18
+ - features[5] # conv2_1
19
+ - features[7] # conv2_2
20
+ - features[10] # conv3_1
21
+ - features[12] # conv3_2
22
+ - features[14] # conv3_3
23
+ - features[16] # conv3_4
24
+ - features[19] # conv4_1
25
+ - features[21] # conv4_2
26
+ - features[23] # conv4_3
27
+ - features[25] # conv4_4
28
+ - features[28] # conv5_1
29
+ - features[30] # conv5_2
30
+ - features[32] # conv5_3
31
+ - features[34] # conv5_4
32
+ - classifier[0] # fc6
33
+ - classifier[3] # fc7
34
+ - classifier[6] # fc8