hamzaanwar12 commited on
Commit
64671d5
·
1 Parent(s): 379d7b5

some new files

Browse files
Files changed (46) hide show
  1. app.py +305 -0
  2. configs/ablation_study/ape.yaml +17 -0
  3. configs/ablation_study/clip_model.yaml +25 -0
  4. configs/ablation_study/no_app.yaml +14 -0
  5. configs/ablation_study/no_app_trainq.yaml +17 -0
  6. configs/ablation_study/swin.yaml +8 -0
  7. configs/fashion_256.yaml +2 -0
  8. configs/fashion_512.yaml +2 -0
  9. datasets/__init__.py +2 -0
  10. datasets/__pycache__/__init__.cpython-310.pyc +0 -0
  11. datasets/__pycache__/deepfashion.cpython-310.pyc +0 -0
  12. datasets/deepfashion.py +258 -0
  13. defaults/__init__.py +1 -0
  14. defaults/__pycache__/__init__.cpython-310.pyc +0 -0
  15. defaults/__pycache__/deepfashion.cpython-310.pyc +0 -0
  16. defaults/deepfashion.py +125 -0
  17. generate_fashion_datasets.py +59 -0
  18. lr_scheduler.py +32 -0
  19. models/__init__.py +7 -0
  20. models/__pycache__/__init__.cpython-310.pyc +0 -0
  21. models/__pycache__/appearance_encoder.cpython-310.pyc +0 -0
  22. models/__pycache__/decoder.cpython-310.pyc +0 -0
  23. models/__pycache__/metrics.cpython-310.pyc +0 -0
  24. models/__pycache__/pose_encoder.cpython-310.pyc +0 -0
  25. models/__pycache__/swin_transformer.cpython-310.pyc +0 -0
  26. models/__pycache__/unet.cpython-310.pyc +0 -0
  27. models/__pycache__/vae.cpython-310.pyc +0 -0
  28. models/__pycache__/xf.cpython-310.pyc +0 -0
  29. models/appearance_encoder.py +103 -0
  30. models/decoder.py +193 -0
  31. models/metrics.py +95 -0
  32. models/pose_encoder.py +46 -0
  33. models/swin_transformer.py +724 -0
  34. models/unet.py +1946 -0
  35. models/vae.py +29 -0
  36. models/xf.py +155 -0
  37. playground.ipynb +0 -0
  38. pose_transfer_test.py +511 -0
  39. pose_transfer_train.py +385 -0
  40. pose_utils.py +72 -0
  41. requirements.txt +29 -0
  42. scripts/multi_gpu/pose_transfer_test.sh +24 -0
  43. scripts/multi_gpu/pose_transfer_train.sh +24 -0
  44. scripts/single_gpu/pose_transfer_test.sh +8 -0
  45. scripts/single_gpu/pose_transfer_train.sh +8 -0
  46. utils.py +22 -0
app.py ADDED
@@ -0,0 +1,305 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import torch
3
+ import gradio as gr
4
+ import pandas as pd
5
+ import random
6
+ import copy
7
+ import numpy as np
8
+ from PIL import Image
9
+ from torchvision import transforms
10
+ from huggingface_hub import snapshot_download
11
+ from diffusers import DDPMScheduler
12
+
13
+ # ----------------------------
14
+ # Load config + custom modules
15
+ # ----------------------------
16
+ from defaults import pose_transfer_C as cfg
17
+ from pose_transfer_train import build_model
18
+ from models import UNet, VariationalAutoencoder
19
+ from pose_utils import (cords_to_map, draw_pose_from_cords, load_pose_cords_from_strings)
20
+
21
+ # ----------------------------
22
+ # Globals
23
+ # ----------------------------
24
+ device = "cuda" if torch.cuda.is_available() else "cpu"
25
+ model = None
26
+ unet = None
27
+ vae = None
28
+ noise_scheduler = None
29
+ annotation_file = None
30
+ test_pairs = None
31
+ model_dir = None # Will store the downloaded model directory path
32
+
33
+ # ----------------------------
34
+ # Helper: Build pose image
35
+ # ----------------------------
36
+ def build_pose_img(annotation_file, img_path):
37
+ """Build pose image from annotation file and image path"""
38
+ string = annotation_file.loc[os.path.basename(img_path)]
39
+ array = load_pose_cords_from_strings(string['keypoints_y'], string['keypoints_x'])
40
+ pose_map = torch.tensor(
41
+ cords_to_map(array, (256, 256), (256, 176)).transpose(2, 0, 1),
42
+ dtype=torch.float32
43
+ )
44
+ pose_img = torch.tensor(
45
+ draw_pose_from_cords(array, (256, 256), (256, 176)).transpose(2, 0, 1) / 255.,
46
+ dtype=torch.float32
47
+ )
48
+ pose_img = torch.cat([pose_img, pose_map], dim=0)
49
+ return pose_img
50
+
51
+ # ----------------------------
52
+ # Model loader (runs ONCE)
53
+ # ----------------------------
54
+ def load_models():
55
+ global model, unet, vae, noise_scheduler, annotation_file, test_pairs, model_dir
56
+
57
+ if model is not None: # already loaded
58
+ return
59
+
60
+ print("⏳ Downloading models & data from repository...")
61
+
62
+ # Download everything from model repository (models + fashion data)
63
+ repo_id = "recky101/new_l_cfld_model"
64
+ model_dir = snapshot_download(repo_id=repo_id)
65
+
66
+ print(f"📁 Downloaded to: {model_dir}")
67
+
68
+ # Load schedulers & models
69
+ print("🔧 Loading scheduler...")
70
+ noise_scheduler = DDPMScheduler.from_pretrained(
71
+ os.path.join(model_dir, "pretrained_models/scheduler")
72
+ )
73
+
74
+ print("🔧 Loading VAE...")
75
+ vae = VariationalAutoencoder(
76
+ pretrained_path=os.path.join(model_dir, "pretrained_models/vae")
77
+ ).eval().requires_grad_(False).to(device)
78
+
79
+ print("🔧 Loading main model...")
80
+ model = build_model(cfg).eval().requires_grad_(False).to(device)
81
+
82
+ print("🔧 Loading UNet...")
83
+ unet = UNet(cfg).eval().requires_grad_(False).to(device)
84
+
85
+ print("📦 Loading model weights...")
86
+ model.load_state_dict(
87
+ torch.load(os.path.join(model_dir, "checkpoints/pytorch_model.bin"), map_location="cpu"),
88
+ strict=False
89
+ )
90
+ unet.load_state_dict(
91
+ torch.load(os.path.join(model_dir, "checkpoints/pytorch_model_1.bin"), map_location="cpu"),
92
+ strict=False
93
+ )
94
+
95
+ print("📊 Loading fashion dataset...")
96
+ # Load fashion dataset from model repository
97
+ test_pairs = pd.read_csv(os.path.join(model_dir, "fashion", "fasion-resize-pairs-test.csv"))
98
+ annotation_file = pd.read_csv(os.path.join(model_dir, "fashion", "fasion-resize-annotation-test.csv"), sep=":")
99
+ annotation_file = annotation_file.set_index("name")
100
+
101
+ print("✅ Everything loaded successfully!")
102
+ print(f"📈 Loaded {len(test_pairs)} test pairs")
103
+
104
+ # ----------------------------
105
+ # Inference function
106
+ # ----------------------------
107
+ def infer(img_from: Image.Image, random_index: int = None):
108
+ """Perform pose transfer inference"""
109
+ try:
110
+ # Load models if not already loaded
111
+ load_models()
112
+
113
+ if img_from is None:
114
+ return None
115
+
116
+ # Handle random index
117
+ if random_index is None:
118
+ random_index = random.choice(range(len(test_pairs)))
119
+ else:
120
+ # Ensure random_index is within bounds
121
+ random_index = max(0, min(int(random_index), len(test_pairs) - 1))
122
+
123
+ img_to_path = test_pairs.iloc[random_index]["to"]
124
+ print(f"🎯 Using pose from image: {img_to_path} (index: {random_index})")
125
+
126
+ # Preprocess source image
127
+ trans = transforms.Compose([
128
+ transforms.Resize([256, 256], interpolation=transforms.InterpolationMode.BICUBIC, antialias=True),
129
+ transforms.ToTensor(),
130
+ transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
131
+ ])
132
+ img_from_tensor = trans(img_from).unsqueeze(0).to(device)
133
+
134
+ # Build pose image tensor
135
+ pose_img_tensor = build_pose_img(annotation_file, img_to_path).unsqueeze(0).to(device)
136
+
137
+ print("🚀 Running inference...")
138
+ # Inference
139
+ with torch.no_grad():
140
+ c_new, down_block_additional_residuals, up_block_additional_residuals = model({
141
+ "img_cond": img_from_tensor, "pose_img": pose_img_tensor
142
+ })
143
+ noisy_latents = torch.randn((1, 4, 64, 64)).to(device)
144
+ weight_dtype = torch.float32
145
+ bsz = 1
146
+
147
+ c_new = torch.cat([c_new[:bsz], c_new[:bsz], c_new[bsz:]])
148
+ down_block_additional_residuals = [
149
+ torch.cat([torch.zeros_like(sample), sample, sample]).to(dtype=weight_dtype)
150
+ for sample in down_block_additional_residuals
151
+ ]
152
+ up_block_additional_residuals = {
153
+ k: torch.cat([torch.zeros_like(v), torch.zeros_like(v), v]).to(dtype=weight_dtype)
154
+ for k, v in up_block_additional_residuals.items()
155
+ }
156
+
157
+ noise_scheduler.set_timesteps(cfg.TEST.NUM_INFERENCE_STEPS)
158
+ for t in noise_scheduler.timesteps:
159
+ inputs = torch.cat([noisy_latents, noisy_latents, noisy_latents], dim=0)
160
+ inputs = noise_scheduler.scale_model_input(inputs, timestep=t)
161
+ noise_pred = unet(
162
+ sample=inputs,
163
+ timestep=t,
164
+ encoder_hidden_states=c_new,
165
+ down_block_additional_residuals=copy.deepcopy(down_block_additional_residuals),
166
+ up_block_additional_residuals=copy.deepcopy(up_block_additional_residuals)
167
+ )
168
+
169
+ noise_pred_uc, noise_pred_down, noise_pred_full = noise_pred.chunk(3)
170
+ noise_pred = noise_pred_uc + \
171
+ cfg.TEST.DOWN_BLOCK_GUIDANCE_SCALE * (noise_pred_down - noise_pred_uc) + \
172
+ cfg.TEST.FULL_GUIDANCE_SCALE * (noise_pred_full - noise_pred_down)
173
+
174
+ noisy_latents = noise_scheduler.step(noise_pred, t, noisy_latents)[0]
175
+
176
+ sampling_imgs = vae.decode(noisy_latents) * 0.5 + 0.5
177
+ sampling_imgs = sampling_imgs.clamp(0, 1)
178
+
179
+ # Convert to PIL image
180
+ output_img = Image.fromarray(
181
+ (sampling_imgs[0] * 255.).permute((1, 2, 0)).long().cpu().numpy().astype(np.uint8)
182
+ ).resize((256, 256))
183
+
184
+ print("✅ Inference completed successfully!")
185
+ return output_img
186
+
187
+ except Exception as e:
188
+ print(f"❌ Error in inference: {e}")
189
+ import traceback
190
+ traceback.print_exc()
191
+ return None
192
+
193
+ # ----------------------------
194
+ # Gradio Interface
195
+ # ----------------------------
196
+ with gr.Blocks(
197
+ title="CFLD Pose Transfer Demo",
198
+ theme=gr.themes.Soft(),
199
+ css="""
200
+ .gradio-container {
201
+ max-width: 1200px !important;
202
+ }
203
+ .gr-button-primary {
204
+ background: linear-gradient(90deg, #ff6b6b, #4ecdc4) !important;
205
+ border: none !important;
206
+ }
207
+ """
208
+ ) as demo:
209
+ gr.Markdown(
210
+ """
211
+ # 👗 CFLD Pose Transfer Demo
212
+
213
+ Upload a person image and transfer their pose using our CFLD (Controllable Fashion Layout Diffusion) model!
214
+
215
+ 🎯 **How it works:** Upload an image → Select a target pose (or use random) → Get pose-transferred result!
216
+ """
217
+ )
218
+
219
+ # Status indicator
220
+ with gr.Row():
221
+ status_text = gr.Markdown("🔄 **Status:** Loading models... Please wait.")
222
+
223
+ with gr.Row(equal_height=True):
224
+ with gr.Column(scale=1):
225
+ gr.Markdown("### 📤 Input")
226
+ inp = gr.Image(
227
+ label="Upload Source Image",
228
+ type="pil",
229
+ height=400
230
+ )
231
+
232
+ idx = gr.Number(
233
+ label="Target Pose Index (0-4499, leave blank for random)",
234
+ value=None,
235
+ precision=0,
236
+ minimum=0,
237
+ maximum=4499
238
+ )
239
+
240
+ btn = gr.Button(
241
+ "🚀 Generate Pose Transfer",
242
+ variant="primary",
243
+ size="lg"
244
+ )
245
+
246
+ gr.Markdown(
247
+ """
248
+ ### 💡 Tips:
249
+ - Upload clear images of people
250
+ - Works best with full-body or upper-body shots
251
+ - Try different pose indices for variety
252
+ - Leave index blank for random poses
253
+ """
254
+ )
255
+
256
+ with gr.Column(scale=1):
257
+ gr.Markdown("### 📥 Result")
258
+ out = gr.Image(
259
+ label="Pose Transferred Result",
260
+ height=400
261
+ )
262
+
263
+ # Progress and info
264
+ info_text = gr.Markdown("Upload an image and click generate to start!")
265
+
266
+ # Event handlers
267
+ def update_status():
268
+ if model is not None:
269
+ return "✅ **Status:** Models loaded and ready!"
270
+ else:
271
+ return "🔄 **Status:** Loading models... Please wait."
272
+
273
+ def infer_with_status(img, idx):
274
+ if img is None:
275
+ return None, "❌ Please upload an image first!"
276
+
277
+ if model is None:
278
+ return None, "⏳ Models are still loading, please wait..."
279
+
280
+ result = infer(img, idx)
281
+
282
+ if result is None:
283
+ return None, "❌ Failed to generate result. Please try again."
284
+
285
+ used_idx = idx if idx is not None else "random"
286
+ return result, f"✅ Success! Used pose index: {used_idx}"
287
+
288
+ # Connect events
289
+ btn.click(
290
+ fn=infer_with_status,
291
+ inputs=[inp, idx],
292
+ outputs=[out, info_text]
293
+ )
294
+
295
+ # Auto-update status every few seconds
296
+ demo.load(
297
+ fn=update_status,
298
+ outputs=[status_text],
299
+ every=3
300
+ )
301
+
302
+ # ----------------------------
303
+ # Launch the demo
304
+ # ----------------------------
305
+ demo.launch()
configs/ablation_study/ape.yaml ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ACCELERATE:
2
+ RUN_NAME: "ape"
3
+ EVAL_PERIOD: 10
4
+
5
+ MODEL:
6
+ APPEARANCE_GUIDANCE_CONFIG:
7
+ CONVIN_KERNEL_SIZE: [8, 8, 8, 4, 4, 4, 2, 2, 2]
8
+ CONVIN_STRIDE: [8, 8, 8, 4, 4, 4, 2, 2, 2]
9
+ CONVIN_PADDING: [0, 0, 0, 0, 0, 0, 0, 0, 0]
10
+ CTX_DIMS: [768, 768, 768, 768, 768, 768, 768, 768, 768]
11
+ TO_QUERIES: False
12
+ TO_KEYS: True
13
+ TO_VALUES: True
14
+
15
+ DECODER_CONFIG:
16
+ N_CTX: 64
17
+ DEPTH: -1
configs/ablation_study/clip_model.yaml ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ACCELERATE:
2
+ RUN_NAME: "clip_model"
3
+ EVAL_PERIOD: 10
4
+
5
+ MODEL:
6
+ COND_STAGE_CONFIG:
7
+ DEPTHS: []
8
+
9
+ APPEARANCE_GUIDANCE_CONFIG:
10
+ ATTN_RESIDUAL_BLOCK_IDX: []
11
+ INNER_DIMS: []
12
+ CTX_DIMS: []
13
+ EMBED_DIMS: []
14
+ HEADS: []
15
+ CONVIN_KERNEL_SIZE: []
16
+ CONVIN_STRIDE: []
17
+ CONVIN_PADDING: []
18
+
19
+ DECODER_CONFIG:
20
+ N_CTX: 1
21
+ DEPTH: 0
22
+
23
+ INPUT:
24
+ COND:
25
+ IMG_SIZE: [224, 224]
configs/ablation_study/no_app.yaml ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ACCELERATE:
2
+ RUN_NAME: "no_app"
3
+ EVAL_PERIOD: 10
4
+
5
+ MODEL:
6
+ APPEARANCE_GUIDANCE_CONFIG:
7
+ ATTN_RESIDUAL_BLOCK_IDX: []
8
+ INNER_DIMS: []
9
+ CTX_DIMS: []
10
+ EMBED_DIMS: []
11
+ HEADS: []
12
+ CONVIN_KERNEL_SIZE: []
13
+ CONVIN_STRIDE: []
14
+ CONVIN_PADDING: []
configs/ablation_study/no_app_trainq.yaml ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ACCELERATE:
2
+ RUN_NAME: "no_app_trainq"
3
+ EVAL_PERIOD: 10
4
+
5
+ MODEL:
6
+ UNET_CONFIG:
7
+ TRAIN_CROSS_ATTN_Q: True
8
+
9
+ APPEARANCE_GUIDANCE_CONFIG:
10
+ ATTN_RESIDUAL_BLOCK_IDX: []
11
+ INNER_DIMS: []
12
+ CTX_DIMS: []
13
+ EMBED_DIMS: []
14
+ HEADS: []
15
+ CONVIN_KERNEL_SIZE: []
16
+ CONVIN_STRIDE: []
17
+ CONVIN_PADDING: []
configs/ablation_study/swin.yaml ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ ACCELERATE:
2
+ RUN_NAME: "swin"
3
+ EVAL_PERIOD: 10
4
+
5
+ MODEL:
6
+ DECODER_CONFIG:
7
+ N_CTX: 64
8
+ DEPTH: -2
configs/fashion_256.yaml ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ TEST:
2
+ IMG_SIZE: [256, 176]
configs/fashion_512.yaml ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ TEST:
2
+ IMG_SIZE: [512, 352]
datasets/__init__.py ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ from .deepfashion import (FidRealDeepFashion, PisTestDeepFashion,
2
+ PisTrainDeepFashion)
datasets/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (247 Bytes). View file
 
datasets/__pycache__/deepfashion.cpython-310.pyc ADDED
Binary file (7.69 kB). View file
 
datasets/deepfashion.py ADDED
@@ -0,0 +1,258 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ @author: Yanzuo Lu
3
+ @author: oliveryanzuolu@gmail.com
4
+ """
5
+
6
+ import glob
7
+ import logging
8
+ import math
9
+ import os
10
+ import random
11
+
12
+ import numpy as np
13
+ import pandas as pd
14
+ import torch
15
+ import torchvision.transforms as transforms
16
+ from PIL import Image
17
+ from torch.utils.data import Dataset
18
+
19
+ from pose_utils import (cords_to_map, draw_pose_from_cords,
20
+ load_pose_cords_from_strings)
21
+
22
+ logger = logging.getLogger()
23
+
24
+
25
+ class PisTrainDeepFashion(Dataset):
26
+ def __init__(self, root_dir, gt_img_size, pose_img_size, cond_img_size, min_scale,
27
+ log_aspect_ratio, pred_ratio, pred_ratio_var, psz):
28
+ super().__init__()
29
+ self.pose_img_size = pose_img_size
30
+ self.cond_img_size = cond_img_size
31
+ self.log_aspect_ratio = log_aspect_ratio
32
+ self.pred_ratio = pred_ratio
33
+ self.pred_ratio_var = pred_ratio_var
34
+ self.psz = psz
35
+
36
+ # root_dir = os.path.join(root_dir, "DeepFashion")
37
+ train_dir = os.path.join(root_dir, "train_highres")
38
+ train_pairs = os.path.join(root_dir, "fasion-resize-pairs-train.csv")
39
+ train_pairs = pd.read_csv(train_pairs)
40
+ self.img_items = self.process_dir(train_dir, train_pairs)
41
+
42
+ self.annotation_file = pd.read_csv(os.path.join(root_dir, "fasion-resize-annotation-train.csv"), sep=':')
43
+ self.annotation_file = self.annotation_file.set_index('name')
44
+
45
+ self.transform_gt = transforms.Compose([
46
+ transforms.Resize(gt_img_size, interpolation=transforms.InterpolationMode.BICUBIC, antialias=True),
47
+ transforms.ToTensor(),
48
+ transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
49
+ ])
50
+ self.transform_cond = transforms.Compose([
51
+ transforms.Resize(cond_img_size, interpolation=transforms.InterpolationMode.BICUBIC, antialias=True),
52
+ transforms.ToTensor(),
53
+ transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
54
+ ])
55
+
56
+ aspect_ratio = cond_img_size[1] / cond_img_size[0]
57
+ self.transform = transforms.Compose([
58
+ transforms.RandomResizedCrop(cond_img_size, scale=(min_scale, 1.), ratio=(aspect_ratio*3./4., aspect_ratio*4./3.),
59
+ interpolation=transforms.InterpolationMode.BICUBIC, antialias=True),
60
+ transforms.RandomHorizontalFlip(p=0.5),
61
+ transforms.ToTensor(),
62
+ transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
63
+ ]) if min_scale < 1.0 else transforms.Compose([
64
+ transforms.Resize(cond_img_size, interpolation=transforms.InterpolationMode.BICUBIC, antialias=True),
65
+ transforms.RandomHorizontalFlip(p=0.5),
66
+ transforms.ToTensor(),
67
+ transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
68
+ ])
69
+
70
+ def process_dir(self, root_dir, csv_file):
71
+ data = []
72
+ for i in range(len(csv_file)):
73
+ data.append((os.path.join(root_dir, csv_file.iloc[i]["from"]),
74
+ os.path.join(root_dir, csv_file.iloc[i]["to"])))
75
+ return data
76
+
77
+ def get_pred_ratio(self):
78
+ pred_ratio = []
79
+ for prm, prv in zip(self.pred_ratio, self.pred_ratio_var):
80
+ assert prm >= prv
81
+ pr = random.uniform(prm - prv, prm + prv) if prv > 0 else prm
82
+ pred_ratio.append(pr)
83
+ pred_ratio = random.choice(pred_ratio)
84
+ return pred_ratio
85
+
86
+ def __len__(self):
87
+ return len(self.img_items)
88
+
89
+ def __getitem__(self, index):
90
+ img_path_from, img_path_to = self.img_items[index]
91
+ with open(img_path_from, 'rb') as f:
92
+ img_from = Image.open(f).convert('RGB')
93
+ with open(img_path_to, 'rb') as f:
94
+ img_to = Image.open(f).convert('RGB')
95
+
96
+ img_src = self.transform_gt(img_from)
97
+ img_tgt = self.transform_gt(img_to)
98
+ img_cond = self.transform(img_from)
99
+ pose_img_src = self.build_pose_img(img_path_from)
100
+ pose_img_tgt = self.build_pose_img(img_path_to)
101
+
102
+ mask = None
103
+ if len(self.pred_ratio) > 0:
104
+ H, W = self.cond_img_size[0] // self.psz, self.cond_img_size[1] // self.psz
105
+ high = self.get_pred_ratio() * H * W
106
+
107
+ # following BEiT (https://arxiv.org/abs/2106.08254), see at
108
+ # https://github.com/microsoft/unilm/blob/b94ec76c36f02fb2b0bf0dcb0b8554a2185173cd/beit/masking_generator.py#L55
109
+ mask = np.zeros((H, W), dtype=bool)
110
+ mask_count = 0
111
+ while mask_count < high:
112
+ max_mask_patches = high - mask_count
113
+
114
+ delta = 0
115
+ for attempt in range(10):
116
+ low = (min(H, W) // 3) ** 2
117
+ target_area = random.uniform(low, max_mask_patches)
118
+ aspect_ratio = math.exp(random.uniform(*self.log_aspect_ratio))
119
+ h = int(round(math.sqrt(target_area * aspect_ratio)))
120
+ w = int(round(math.sqrt(target_area / aspect_ratio)))
121
+ if w < W and h < H:
122
+ top = random.randint(0, H - h)
123
+ left = random.randint(0, W - w)
124
+
125
+ num_masked = mask[top: top + h, left: left + w].sum()
126
+ if 0 < h * w - num_masked <= max_mask_patches:
127
+ for i in range(top, top + h):
128
+ for j in range(left, left + w):
129
+ if mask[i, j] == 0:
130
+ mask[i, j] = 1
131
+ delta += 1
132
+
133
+ if delta > 0:
134
+ break
135
+
136
+ if delta == 0:
137
+ break
138
+ else:
139
+ mask_count += delta
140
+
141
+ return_dict = {
142
+ "img_src": img_src,
143
+ "img_tgt": img_tgt,
144
+ "img_cond": img_cond,
145
+ "pose_img_src": pose_img_src,
146
+ "pose_img_tgt": pose_img_tgt
147
+ }
148
+ if mask is not None:
149
+ return_dict["mask"] = mask
150
+ return return_dict
151
+
152
+ def build_pose_img(self, img_path):
153
+ string = self.annotation_file.loc[os.path.basename(img_path)]
154
+ array = load_pose_cords_from_strings(string['keypoints_y'], string['keypoints_x'])
155
+ pose_map = torch.tensor(cords_to_map(array, tuple(self.pose_img_size), (256, 176)).transpose(2, 0, 1), dtype=torch.float32)
156
+ pose_img = torch.tensor(draw_pose_from_cords(array, tuple(self.pose_img_size), (256, 176)).transpose(2, 0, 1) / 255., dtype=torch.float32)
157
+ pose_img = torch.cat([pose_img, pose_map], dim=0)
158
+ return pose_img
159
+
160
+
161
+ class PisTestDeepFashion(Dataset):
162
+ def __init__(self, root_dir, gt_img_size, pose_img_size, cond_img_size, test_img_size):
163
+ super().__init__()
164
+ self.pose_img_size = pose_img_size
165
+
166
+ # root_dir = os.path.join(root_dir, "DeepFashion")
167
+ test_pairs = os.path.join(root_dir, "fasion-resize-pairs-test.csv")
168
+ test_pairs = pd.read_csv(test_pairs)
169
+ self.img_items = self.process_dir(root_dir, test_pairs)
170
+
171
+ self.annotation_file = pd.read_csv(os.path.join(root_dir, "fasion-resize-annotation-test.csv"), sep=':')
172
+ self.annotation_file = self.annotation_file.set_index('name')
173
+
174
+ self.transform_gt = transforms.Compose([
175
+ transforms.Resize(gt_img_size, interpolation=transforms.InterpolationMode.BICUBIC, antialias=True),
176
+ transforms.ToTensor(),
177
+ transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
178
+ ])
179
+ self.transform_cond = transforms.Compose([
180
+ transforms.Resize(cond_img_size, interpolation=transforms.InterpolationMode.BICUBIC, antialias=True),
181
+ transforms.ToTensor(),
182
+ transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
183
+ ])
184
+ self.transform_test = transforms.Compose([
185
+ transforms.Resize(test_img_size, interpolation=transforms.InterpolationMode.BICUBIC, antialias=True),
186
+ transforms.ToTensor()
187
+ ])
188
+
189
+ def process_dir(self, root_dir, csv_file):
190
+ data = []
191
+ for i in range(len(csv_file)):
192
+ data.append((os.path.join(root_dir, "test_highres", csv_file.iloc[i]["from"]),
193
+ os.path.join(root_dir, "test_highres", csv_file.iloc[i]["to"])))
194
+ return data
195
+
196
+ def __len__(self):
197
+ return len(self.img_items)
198
+
199
+ def __getitem__(self, index):
200
+ img_path_from, img_path_to = self.img_items[index]
201
+ with open(img_path_from, 'rb') as f:
202
+ img_from = Image.open(f).convert('RGB')
203
+ with open(img_path_to, 'rb') as f:
204
+ img_to = Image.open(f).convert('RGB')
205
+
206
+ img_src = self.transform_gt(img_from) # for visualization
207
+ img_tgt = self.transform_gt(img_to) # for visualization
208
+ img_gt = self.transform_test(img_to) # for metrics, 3x256x176
209
+ img_cond_from = self.transform_cond(img_from)
210
+
211
+ pose_img_from = self.build_pose_img(img_path_from)
212
+ pose_img_to = self.build_pose_img(img_path_to)
213
+
214
+ return {
215
+ "img_src": img_src,
216
+ "img_tgt": img_tgt,
217
+ "img_gt": img_gt,
218
+ "img_cond_from": img_cond_from,
219
+ "pose_img_from": pose_img_from,
220
+ "pose_img_to": pose_img_to
221
+ }
222
+
223
+ def build_pose_img(self, img_path):
224
+ string = self.annotation_file.loc[os.path.basename(img_path)]
225
+ array = load_pose_cords_from_strings(string['keypoints_y'], string['keypoints_x'])
226
+ pose_map = torch.tensor(cords_to_map(array, tuple(self.pose_img_size), (256, 176)).transpose(2, 0, 1), dtype=torch.float32)
227
+ pose_img = torch.tensor(draw_pose_from_cords(array, tuple(self.pose_img_size), (256, 176)).transpose(2, 0, 1) / 255., dtype=torch.float32)
228
+ pose_img = torch.cat([pose_img, pose_map], dim=0)
229
+ return pose_img
230
+
231
+
232
+ class FidRealDeepFashion(Dataset):
233
+ def __init__(self, root_dir, test_img_size):
234
+ super().__init__()
235
+ # root_dir = os.path.join(root_dir, "DeepFashion")
236
+ train_dir = os.path.join(root_dir, "train_highres")
237
+ self.img_items = self.process_dir(train_dir)
238
+
239
+ self.transform_test = transforms.Compose([
240
+ transforms.Resize(test_img_size, interpolation=transforms.InterpolationMode.BICUBIC, antialias=True),
241
+ transforms.ToTensor()
242
+ ])
243
+
244
+ def process_dir(self, root_dir):
245
+ data = []
246
+ img_paths = glob.glob(os.path.join(root_dir, '*.jpg'))
247
+ for img_path in img_paths:
248
+ data.append(img_path)
249
+ return data
250
+
251
+ def __len__(self):
252
+ return len(self.img_items)
253
+
254
+ def __getitem__(self, index):
255
+ img_path = self.img_items[index]
256
+ with open(img_path, 'rb') as f:
257
+ img = Image.open(f).convert('RGB')
258
+ return self.transform_test(img)
defaults/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .deepfashion import _C as pose_transfer_C
defaults/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (189 Bytes). View file
 
defaults/__pycache__/deepfashion.cpython-310.pyc ADDED
Binary file (3.59 kB). View file
 
defaults/deepfashion.py ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from yacs.config import CfgNode as CN
2
+
3
+ _C = CN()
4
+
5
+ _C.ACCELERATE = CN()
6
+ _C.ACCELERATE.PROJECT_NAME = "CFLD"
7
+ _C.ACCELERATE.RUN_NAME = "debug"
8
+ _C.ACCELERATE.MIXED_PRECISION = "fp16"
9
+ _C.ACCELERATE.ALLOW_TF32 = True
10
+ _C.ACCELERATE.SEED = 3407
11
+ _C.ACCELERATE.GRADIENT_ACCUMULATION_STEPS = 1
12
+ _C.ACCELERATE.LOG_PERIOD = 10
13
+ _C.ACCELERATE.EVAL_PERIOD = 5
14
+
15
+ _C.MODEL = CN()
16
+ _C.MODEL.PRETRAINED_PATH = ""
17
+ _C.MODEL.LAST_EPOCH = 0
18
+ _C.MODEL.U_COND_PERCENT = 0.2
19
+ _C.MODEL.U_COND_DOWN_BLOCK_GUIDANCE = False
20
+ _C.MODEL.U_COND_UP_BLOCK_GUIDANCE = False
21
+
22
+ _C.MODEL.FIRST_STAGE_CONFIG = CN()
23
+ _C.MODEL.FIRST_STAGE_CONFIG.PRETRAINED_PATH = "pretrained_models/vae"
24
+
25
+ _C.MODEL.UNET_CONFIG = CN()
26
+ _C.MODEL.UNET_CONFIG.PRETRAINED_PATH = "pretrained_models/unet"
27
+ _C.MODEL.UNET_CONFIG.TRAINABLE_BLOCK_IDX = [11, 10, 9, 8, 7, 6, 5, 4, 3]
28
+ _C.MODEL.UNET_CONFIG.TRAIN_SELF_ATTN_Q = False
29
+ _C.MODEL.UNET_CONFIG.TRAIN_SELF_ATTN_K = False
30
+ _C.MODEL.UNET_CONFIG.TRAIN_SELF_ATTN_V = False
31
+ _C.MODEL.UNET_CONFIG.TRAIN_CROSS_ATTN_Q = False
32
+ _C.MODEL.UNET_CONFIG.TRAIN_CROSS_ATTN_K = True
33
+ _C.MODEL.UNET_CONFIG.TRAIN_CROSS_ATTN_V = True
34
+
35
+ _C.MODEL.SCHEDULER_CONFIG = CN()
36
+ _C.MODEL.SCHEDULER_CONFIG.NAME = "ddpm"
37
+ _C.MODEL.SCHEDULER_CONFIG.PRETRAINED_PATH = "pretrained_models/scheduler"
38
+ _C.MODEL.SCHEDULER_CONFIG.CUBIC_SAMPLING = True
39
+
40
+ _C.MODEL.COND_STAGE_CONFIG = CN()
41
+ _C.MODEL.COND_STAGE_CONFIG.PRETRAINED_PATH = "pretrained_models/swin/swin_base_patch4_window12_384_22kto1k.pth"
42
+ _C.MODEL.COND_STAGE_CONFIG.EMBED_DIM = 128
43
+ _C.MODEL.COND_STAGE_CONFIG.DEPTHS = [2, 2, 18, 2]
44
+ _C.MODEL.COND_STAGE_CONFIG.NUM_HEADS = [4, 8, 16, 32]
45
+ _C.MODEL.COND_STAGE_CONFIG.WINDOW_SIZE = 16
46
+ _C.MODEL.COND_STAGE_CONFIG.DROP_PATH_RATE = 0.2
47
+ _C.MODEL.COND_STAGE_CONFIG.LAST_NORM = False
48
+
49
+ _C.MODEL.APPEARANCE_GUIDANCE_CONFIG = CN()
50
+ _C.MODEL.APPEARANCE_GUIDANCE_CONFIG.CONVIN_KERNEL_SIZE = [1, 1, 1, 1, 1, 1, 1, 1, 1]
51
+ _C.MODEL.APPEARANCE_GUIDANCE_CONFIG.CONVIN_STRIDE = [1, 1, 1, 1, 1, 1, 1, 1, 1]
52
+ _C.MODEL.APPEARANCE_GUIDANCE_CONFIG.CONVIN_PADDING = [0, 0, 0, 0, 0, 0, 0, 0, 0]
53
+ _C.MODEL.APPEARANCE_GUIDANCE_CONFIG.ATTN_RESIDUAL_BLOCK_IDX = [11, 10, 9, 8, 7, 6, 5, 4, 3]
54
+ _C.MODEL.APPEARANCE_GUIDANCE_CONFIG.INNER_DIMS = [128, 128, 128, 256, 256, 256, 512, 512, 512]
55
+ _C.MODEL.APPEARANCE_GUIDANCE_CONFIG.CTX_DIMS = [320, 320, 320, 640, 640, 640, 1280, 1280, 1280]
56
+ _C.MODEL.APPEARANCE_GUIDANCE_CONFIG.EMBED_DIMS = [64, 64, 64, 128, 128, 128, 256, 256, 256]
57
+ _C.MODEL.APPEARANCE_GUIDANCE_CONFIG.HEADS = [2, 2, 2, 4, 4, 4, 8, 8, 8]
58
+ _C.MODEL.APPEARANCE_GUIDANCE_CONFIG.DEPTH = 4
59
+ _C.MODEL.APPEARANCE_GUIDANCE_CONFIG.TO_SELF_ATTN = False
60
+ _C.MODEL.APPEARANCE_GUIDANCE_CONFIG.TO_QUERIES = True
61
+ _C.MODEL.APPEARANCE_GUIDANCE_CONFIG.TO_KEYS = False
62
+ _C.MODEL.APPEARANCE_GUIDANCE_CONFIG.TO_VALUES = False
63
+ _C.MODEL.APPEARANCE_GUIDANCE_CONFIG.DETACH_INPUT = False
64
+
65
+ _C.MODEL.POSE_GUIDANCE_CONFIG = CN()
66
+ _C.MODEL.POSE_GUIDANCE_CONFIG.DOWNSCALE_FACTOR = 4
67
+ _C.MODEL.POSE_GUIDANCE_CONFIG.POSE_CHANNELS = 21
68
+ _C.MODEL.POSE_GUIDANCE_CONFIG.IN_CHANNELS = 320
69
+ _C.MODEL.POSE_GUIDANCE_CONFIG.CHANNELS = [320, 640, 1280]
70
+
71
+ _C.MODEL.DECODER_CONFIG = CN()
72
+ _C.MODEL.DECODER_CONFIG.N_CTX = 16
73
+ _C.MODEL.DECODER_CONFIG.CTX_DIM = 768
74
+ _C.MODEL.DECODER_CONFIG.DEPTH = 8
75
+ _C.MODEL.DECODER_CONFIG.HEADS = 24
76
+ _C.MODEL.DECODER_CONFIG.POSE_QUERY = False
77
+
78
+ _C.OPTIMIZER = CN()
79
+ _C.OPTIMIZER.NAME = "adam"
80
+ _C.OPTIMIZER.EPOCHS = 100
81
+ _C.OPTIMIZER.WARMUP_STEPS = 1000
82
+ _C.OPTIMIZER.DECAY_EPOCHS = [50]
83
+ _C.OPTIMIZER.LR = 1.0e-4
84
+ _C.OPTIMIZER.SCALE_LR = False
85
+ _C.OPTIMIZER.WARMUP_RATE = 0.1
86
+ _C.OPTIMIZER.DECAY_RATE = 0.1
87
+ _C.OPTIMIZER.OVERRIDE_LR = 0.
88
+
89
+ _C.INPUT = CN()
90
+ _C.INPUT.ROOT_DIR = "fashion"
91
+ _C.INPUT.BATCH_SIZE = 224
92
+ _C.INPUT.NUM_WORKERS = 8
93
+
94
+ _C.INPUT.GT = CN()
95
+ _C.INPUT.GT.IMG_SIZE = [512, 512]
96
+
97
+ _C.INPUT.COND = CN()
98
+ _C.INPUT.COND.IMG_SIZE = [256, 256]
99
+ _C.INPUT.COND.PRED_ASPECT_RATIO = [0.3, 1/0.3]
100
+ _C.INPUT.COND.PRED_RATIO = []
101
+ _C.INPUT.COND.PRED_RATIO_VAR = []
102
+ _C.INPUT.COND.MASK_PATCH_SIZE = 8
103
+ _C.INPUT.COND.MIN_SCALE = 1.0
104
+
105
+ _C.INPUT.POSE = CN()
106
+ _C.INPUT.POSE.IMG_SIZE = [256, 256]
107
+
108
+ _C.TEST = CN()
109
+ _C.TEST.NUM_INFERENCE_STEPS = 50
110
+ _C.TEST.MICRO_BATCH_SIZE = 16
111
+ _C.TEST.NUM_WORKERS = 8
112
+ _C.TEST.IMG_SIZE = [256, 176]
113
+
114
+ _C.TEST.DDIM_INVERSION_STEPS = 0
115
+ _C.TEST.DDIM_INVERSION_DOWN_BLOCK_GUIDANCE = False
116
+ _C.TEST.DDIM_INVERSION_UP_BLOCK_GUIDANCE = False
117
+ _C.TEST.DDIM_INVERSION_UNCONDITIONAL = True
118
+
119
+ # "uc_full", "updown_full", "down_full", "uc_down_full", "uc_down_updown_cdown", "uc_down_updown_full"
120
+ _C.TEST.GUIDANCE_TYPE = "uc_down_full"
121
+ _C.TEST.GUIDANCE_SCALE = 2.0
122
+ _C.TEST.DOWN_BLOCK_GUIDANCE_SCALE = 2.0
123
+ _C.TEST.UP_BLOCK_GUIDANCE_SCALE = 2.0
124
+ _C.TEST.ALL_BLOCK_GUIDANCE_SCALE = 2.0
125
+ _C.TEST.FULL_GUIDANCE_SCALE = 2.0
generate_fashion_datasets.py ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import shutil
3
+
4
+ IMG_EXTENSIONS = [
5
+ '.jpg', '.JPG', '.jpeg', '.JPEG',
6
+ '.png', '.PNG', '.ppm', '.PPM', '.bmp', '.BMP',
7
+ ]
8
+
9
+ def is_image_file(filename):
10
+ return any(filename.endswith(extension) for extension in IMG_EXTENSIONS)
11
+
12
+
13
+ def make_dataset(dir):
14
+ assert os.path.isdir(dir), '%s is not a valid directory' % dir
15
+
16
+ train_root = './fashion/train_highres'
17
+ if not os.path.exists(train_root):
18
+ os.mkdir(train_root)
19
+
20
+ test_root = './fashion/test_highres'
21
+ if not os.path.exists(test_root):
22
+ os.mkdir(test_root)
23
+
24
+ train_images = []
25
+ train_f = open('./fashion/train.lst', 'r')
26
+ for lines in train_f:
27
+ lines = lines.strip()
28
+ if lines.endswith('.jpg'):
29
+ train_images.append(lines)
30
+
31
+ test_images = []
32
+ test_f = open('./fashion/test.lst', 'r')
33
+ for lines in test_f:
34
+ lines = lines.strip()
35
+ if lines.endswith('.jpg'):
36
+ test_images.append(lines)
37
+
38
+
39
+ print("Walaking Direstory: ", dir)
40
+
41
+ for root, _, fnames in sorted(os.walk(dir)):
42
+ print('root:', root)
43
+ print('fnames:', fnames)
44
+ for fname in fnames:
45
+
46
+ if is_image_file(fname):
47
+ path = os.path.join(root, fname)
48
+ path_names = path.split('\\')
49
+
50
+ print("pathNames = ", path_names)
51
+ path_names[3] = path_names[3].replace('_', '')
52
+ path_names[4] = path_names[4].split('_')[0] + "_" + "".join(path_names[4].split('_')[1:])
53
+ path_names = "".join(path_names)
54
+ if path_names in train_images:
55
+ shutil.copy(path, os.path.join(train_root, path_names))
56
+ if path_names in test_images:
57
+ shutil.copy(path, os.path.join(test_root, path_names))
58
+
59
+ make_dataset('fashion')
lr_scheduler.py ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ @author: Yanzuo Lu
3
+ @author: oliveryanzuolu@gmail.com
4
+ """
5
+
6
+ from bisect import bisect_right
7
+
8
+ import torch.optim.lr_scheduler
9
+
10
+
11
+ class LinearWarmupMultiStepDecayLRScheduler(torch.optim.lr_scheduler._LRScheduler):
12
+ def __init__(self, optimizer, warmup_steps, warmup_rate, decay_rate,
13
+ num_epochs, decay_epochs, iters_per_epoch, override_lr=0.,
14
+ last_epoch=-1, verbose=False):
15
+ self.warmup_steps = warmup_steps
16
+ self.warmup_rate = warmup_rate
17
+ self.decay_rate = decay_rate
18
+ self.decay_epochs = [decay_epoch * iters_per_epoch for decay_epoch in decay_epochs]
19
+ self.num_epochs = num_epochs * iters_per_epoch
20
+ self.override_lr = override_lr
21
+ super(LinearWarmupMultiStepDecayLRScheduler, self).__init__(optimizer, last_epoch, verbose)
22
+
23
+ def get_lr(self):
24
+ if self.last_epoch < self.warmup_steps:
25
+ alpha = (self.last_epoch + 1) / self.warmup_steps
26
+ return [base_lr * (self.warmup_rate + (1. - self.warmup_rate) * alpha) \
27
+ for base_lr in self.base_lrs]
28
+ else:
29
+ if self.override_lr > 0.:
30
+ return [self.override_lr for _ in self.base_lrs]
31
+ e = bisect_right(self.decay_epochs, self.last_epoch)
32
+ return [base_lr * (self.decay_rate ** e) for base_lr in self.base_lrs]
models/__init__.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ from .appearance_encoder import AppearanceEncoder
2
+ from .decoder import Decoder
3
+ from .metrics import build_metric
4
+ from .pose_encoder import PoseEncoder
5
+ from .swin_transformer import build_backbone
6
+ from .unet import UNet
7
+ from .vae import VariationalAutoencoder
models/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (461 Bytes). View file
 
models/__pycache__/appearance_encoder.cpython-310.pyc ADDED
Binary file (3.26 kB). View file
 
models/__pycache__/decoder.cpython-310.pyc ADDED
Binary file (4.99 kB). View file
 
models/__pycache__/metrics.cpython-310.pyc ADDED
Binary file (2.84 kB). View file
 
models/__pycache__/pose_encoder.cpython-310.pyc ADDED
Binary file (1.5 kB). View file
 
models/__pycache__/swin_transformer.cpython-310.pyc ADDED
Binary file (24.2 kB). View file
 
models/__pycache__/unet.cpython-310.pyc ADDED
Binary file (42.3 kB). View file
 
models/__pycache__/vae.cpython-310.pyc ADDED
Binary file (1.24 kB). View file
 
models/__pycache__/xf.cpython-310.pyc ADDED
Binary file (5.59 kB). View file
 
models/appearance_encoder.py ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ @author: Yanzuo Lu
3
+ @author: oliveryanzuolu@gmail.com
4
+ """
5
+
6
+ import torch
7
+ import torch.nn as nn
8
+ from diffusers.models.attention import BasicTransformerBlock
9
+
10
+
11
+ class AppearanceEncoder(nn.Module):
12
+ def __init__(self, attn_residual_block_idx, inner_dims, ctx_dims, embed_dims, heads, depth,
13
+ to_self_attn, to_queries, to_keys, to_values, aspect_ratio, detach_input,
14
+ convin_kernel_size, convin_stride, convin_padding):
15
+ super().__init__()
16
+ self.attn_residual_block_idx = attn_residual_block_idx
17
+ self.inner_dims = inner_dims
18
+ self.ctx_dims = ctx_dims
19
+ self.embed_dims = embed_dims
20
+ self.to_self_attn = to_self_attn
21
+ self.to_queries = to_queries
22
+ self.to_keys = to_keys
23
+ self.to_values = to_values
24
+ self.aspect_ratio = aspect_ratio
25
+ self.detach_input = detach_input
26
+
27
+ self.zero_conv_ins = []
28
+ self.zero_conv_outs = []
29
+ self.blocks = []
30
+ for inner_dim, embed_dim, ctx_dim, num_head, kernel_size, stride, padding in \
31
+ zip(inner_dims, self.embed_dims, self.ctx_dims, heads, convin_kernel_size, convin_stride, convin_padding):
32
+ self.zero_conv_ins.append(nn.Conv2d(inner_dim, embed_dim, kernel_size=kernel_size,
33
+ stride=stride, padding=padding))
34
+ self.zero_conv_outs.append(nn.Conv2d(embed_dim, ctx_dim, kernel_size=1, stride=1, padding=0))
35
+ self.blocks.append(nn.Sequential(*[BasicTransformerBlock(
36
+ dim=embed_dim,
37
+ num_attention_heads=num_head,
38
+ attention_head_dim=embed_dim//num_head,
39
+ double_self_attention=True
40
+ ) for _ in range(depth)]))
41
+
42
+ self.blocks = nn.ModuleList(self.blocks)
43
+ self.zero_conv_ins = nn.ModuleList(self.zero_conv_ins)
44
+ self.zero_conv_outs = nn.ModuleList(self.zero_conv_outs)
45
+
46
+ for n in self.zero_conv_ins.parameters():
47
+ nn.init.zeros_(n)
48
+ for n in self.zero_conv_outs.parameters():
49
+ nn.init.zeros_(n)
50
+
51
+ # enable xformers
52
+ def fn_recursive_set_mem_eff(module: torch.nn.Module):
53
+ if hasattr(module, "set_use_memory_efficient_attention_xformers"):
54
+ module.set_use_memory_efficient_attention_xformers(True, attention_op=None)
55
+
56
+ for child in module.children():
57
+ fn_recursive_set_mem_eff(child)
58
+
59
+ for module in self.children():
60
+ if isinstance(module, torch.nn.Module):
61
+ fn_recursive_set_mem_eff(module)
62
+
63
+ def forward(self, features):
64
+ additional_residuals = {}
65
+
66
+ for i, block in enumerate(self.blocks):
67
+ hidden_states = features[0]
68
+ if self.detach_input:
69
+ hidden_states = hidden_states.detach()
70
+
71
+ in_H = in_W = int(features[0].shape[1] ** 0.5)
72
+ hidden_states = features[0].permute(0, 2, 1).reshape(-1, self.inner_dims[i], in_H, in_W)
73
+ hidden_states = self.zero_conv_ins[i](hidden_states)
74
+ H = W = hidden_states.shape[2]
75
+ hidden_states = hidden_states.reshape(-1, self.embed_dims[i], H * W).permute(0, 2, 1)
76
+
77
+ hidden_states = block(hidden_states)
78
+
79
+ hidden_states = hidden_states.permute(0, 2, 1).reshape(-1, self.embed_dims[i], H, W)
80
+ hidden_states = self.zero_conv_outs[i](hidden_states)
81
+ hidden_states = hidden_states.reshape(-1, self.ctx_dims[i], H * W).permute(0, 2, 1)
82
+
83
+ if self.to_self_attn:
84
+ if self.to_queries:
85
+ additional_residuals[f"block_{self.attn_residual_block_idx[i]}_self_attn_q"] = hidden_states
86
+ elif self.to_keys:
87
+ additional_residuals[f"block_{self.attn_residual_block_idx[i]}_self_attn_k"] = hidden_states
88
+ elif self.to_values:
89
+ additional_residuals[f"block_{self.attn_residual_block_idx[i]}_self_attn_v"] = hidden_states
90
+ else:
91
+ if self.to_keys and self.to_values:
92
+ additional_residuals[f"block_{self.attn_residual_block_idx[i]}_cross_attn_c"] = hidden_states
93
+ elif self.to_queries:
94
+ additional_residuals[f"block_{self.attn_residual_block_idx[i]}_cross_attn_q"] = hidden_states
95
+ elif self.to_keys:
96
+ additional_residuals[f"block_{self.attn_residual_block_idx[i]}_cross_attn_k"] = hidden_states
97
+ elif self.to_values:
98
+ additional_residuals[f"block_{self.attn_residual_block_idx[i]}_cross_attn_v"] = hidden_states
99
+
100
+ if i != len(self.blocks) - 1 and self.inner_dims[i] != self.inner_dims[i + 1]:
101
+ features.pop(0)
102
+
103
+ return additional_residuals
models/decoder.py ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ @author: Yanzuo Lu
3
+ @email: luyz5@mail2.sysu.edu.cn
4
+ """
5
+
6
+ from typing import Any, Dict, Optional
7
+
8
+ import torch
9
+ import torch.nn as nn
10
+ from diffusers.models.attention import BasicTransformerBlock
11
+
12
+ from .xf import FrozenCLIPImageEmbedder
13
+
14
+
15
+ class CrossAttnFirstTransformerBlock(BasicTransformerBlock):
16
+ def forward(
17
+ self,
18
+ hidden_states: torch.FloatTensor,
19
+ query_pos: torch.FloatTensor,
20
+ attention_mask: Optional[torch.FloatTensor] = None,
21
+ encoder_hidden_states: Optional[torch.FloatTensor] = None,
22
+ encoder_attention_mask: Optional[torch.FloatTensor] = None,
23
+ timestep: Optional[torch.LongTensor] = None,
24
+ cross_attention_kwargs: Dict[str, Any] = None,
25
+ class_labels: Optional[torch.LongTensor] = None,
26
+ ):
27
+ # Notice that normalization is always applied before the real computation in the following blocks.
28
+ cross_attention_kwargs = cross_attention_kwargs if cross_attention_kwargs is not None else {}
29
+
30
+ # 1. Cross-Attention
31
+ if self.attn2 is not None:
32
+ hidden_states = hidden_states + query_pos
33
+ norm_hidden_states = (
34
+ self.norm2(hidden_states, timestep) if self.use_ada_layer_norm else self.norm2(hidden_states)
35
+ )
36
+
37
+ attn_output = self.attn2(
38
+ norm_hidden_states,
39
+ encoder_hidden_states=encoder_hidden_states,
40
+ attention_mask=encoder_attention_mask,
41
+ **cross_attention_kwargs,
42
+ )
43
+ hidden_states = attn_output + hidden_states
44
+
45
+ # 2. Self-Attention
46
+ hidden_states = hidden_states + query_pos
47
+ if self.use_ada_layer_norm:
48
+ norm_hidden_states = self.norm1(hidden_states, timestep)
49
+ elif self.use_ada_layer_norm_zero:
50
+ norm_hidden_states, gate_msa, shift_mlp, scale_mlp, gate_mlp = self.norm1(
51
+ hidden_states, timestep, class_labels, hidden_dtype=hidden_states.dtype
52
+ )
53
+ else:
54
+ norm_hidden_states = self.norm1(hidden_states)
55
+
56
+ attn_output = self.attn1(
57
+ norm_hidden_states,
58
+ encoder_hidden_states=encoder_hidden_states if self.only_cross_attention else None,
59
+ attention_mask=attention_mask,
60
+ **cross_attention_kwargs,
61
+ )
62
+ if self.use_ada_layer_norm_zero:
63
+ attn_output = gate_msa.unsqueeze(1) * attn_output
64
+ hidden_states = attn_output + hidden_states
65
+
66
+ # 3. Feed-forward
67
+ norm_hidden_states = self.norm3(hidden_states)
68
+
69
+ if self.use_ada_layer_norm_zero:
70
+ norm_hidden_states = norm_hidden_states * (1 + scale_mlp[:, None]) + shift_mlp[:, None]
71
+
72
+ if self._chunk_size is not None:
73
+ # "feed_forward_chunk_size" can be used to save memory
74
+ if norm_hidden_states.shape[self._chunk_dim] % self._chunk_size != 0:
75
+ raise ValueError(
76
+ f"`hidden_states` dimension to be chunked: {norm_hidden_states.shape[self._chunk_dim]} has to be divisible by chunk size: {self._chunk_size}. Make sure to set an appropriate `chunk_size` when calling `unet.enable_forward_chunking`."
77
+ )
78
+
79
+ num_chunks = norm_hidden_states.shape[self._chunk_dim] // self._chunk_size
80
+ ff_output = torch.cat(
81
+ [self.ff(hid_slice) for hid_slice in norm_hidden_states.chunk(num_chunks, dim=self._chunk_dim)],
82
+ dim=self._chunk_dim,
83
+ )
84
+ else:
85
+ ff_output = self.ff(norm_hidden_states)
86
+
87
+ if self.use_ada_layer_norm_zero:
88
+ ff_output = gate_mlp.unsqueeze(1) * ff_output
89
+
90
+ hidden_states = ff_output + hidden_states
91
+
92
+ return hidden_states
93
+
94
+
95
+ class Decoder(nn.Module):
96
+ def __init__(self, n_ctx, ctx_dim, heads, depth, last_norm, img_size,
97
+ embed_dim, depths, pose_query, pose_channel):
98
+ super().__init__()
99
+ self.last_norm = last_norm
100
+ self.pose_query = pose_query
101
+ self.pose_channel = pose_channel
102
+ self.ctx_dim = ctx_dim
103
+ self.depth = depth
104
+
105
+ if self.depth > 0:
106
+ n_layers = len(depths)
107
+ embed_dim = embed_dim * 2 ** (n_layers - 1)
108
+
109
+ if not self.pose_query:
110
+ self.query_feat = nn.Parameter(torch.zeros(n_ctx, ctx_dim))
111
+ nn.init.normal_(self.query_feat, std=0.02)
112
+ else:
113
+ self.decoder_fc = nn.Linear(pose_channel, ctx_dim, bias=False)
114
+
115
+ self.pos_embed = nn.Parameter(torch.zeros(n_ctx, ctx_dim))
116
+ nn.init.normal_(self.pos_embed, std=0.02)
117
+
118
+ self.blocks = []
119
+ for _ in range(depth):
120
+ self.blocks.append(CrossAttnFirstTransformerBlock(
121
+ dim=ctx_dim,
122
+ num_attention_heads=heads,
123
+ attention_head_dim=ctx_dim//heads,
124
+ cross_attention_dim=embed_dim
125
+ ))
126
+ self.blocks = nn.ModuleList(self.blocks)
127
+
128
+ if not self.last_norm:
129
+ H, W = img_size[0] // 32, img_size[1] // 32
130
+ self.kv_pos_embed = nn.Parameter(torch.zeros(1, H*W, embed_dim))
131
+ nn.init.normal_(self.kv_pos_embed, std=0.02)
132
+
133
+ # enable xformers
134
+ def fn_recursive_set_mem_eff(module: torch.nn.Module):
135
+ if hasattr(module, "set_use_memory_efficient_attention_xformers"):
136
+ module.set_use_memory_efficient_attention_xformers(True, attention_op=None)
137
+
138
+ for child in module.children():
139
+ fn_recursive_set_mem_eff(child)
140
+
141
+ for module in self.children():
142
+ if isinstance(module, torch.nn.Module):
143
+ fn_recursive_set_mem_eff(module)
144
+ elif self.depth == 0:
145
+ self.clip_model = FrozenCLIPImageEmbedder()
146
+ elif self.depth == -2:
147
+ n_layers = len(depths)
148
+ embed_dim = embed_dim * 2 ** (n_layers - 1)
149
+ self.decoder_fc = nn.Linear(embed_dim, ctx_dim, bias=False)
150
+
151
+ def forward(self, x, features, pose_features):
152
+ if self.depth > 0:
153
+ if self.last_norm:
154
+ B, C = x.shape
155
+ encoder_hidden_states = x.unsqueeze(1)
156
+ else:
157
+ B, L, C = features[-1].shape
158
+ encoder_hidden_states = features.pop()
159
+ kv_pos_embed = self.kv_pos_embed.expand(B, -1, -1)
160
+ encoder_hidden_states = encoder_hidden_states + kv_pos_embed
161
+
162
+ if self.pose_query:
163
+ hidden_states = pose_features.pop()
164
+ if self.training:
165
+ hidden_states = hidden_states.reshape(B*2, self.pose_channel, -1).permute(0, 2, 1)
166
+ pos_embed = self.pos_embed.expand(B*2, -1, -1)
167
+ encoder_hidden_states = torch.cat([encoder_hidden_states, encoder_hidden_states])
168
+ else:
169
+ hidden_states = hidden_states.reshape(B, self.pose_channel, -1).permute(0, 2, 1)
170
+ pos_embed = self.pos_embed.expand(B, -1, -1)
171
+
172
+ hidden_states = self.decoder_fc(hidden_states)
173
+ else:
174
+ hidden_states = self.query_feat.expand(B, -1, -1)
175
+ pos_embed = self.pos_embed.expand(B, -1, -1)
176
+
177
+ for blk in self.blocks:
178
+ hidden_states = blk(hidden_states, pos_embed, encoder_hidden_states=encoder_hidden_states)
179
+ return hidden_states
180
+ elif self.depth == 0:
181
+ x = x * 0.5 + 0.5
182
+ x = x - torch.tensor([0.48145466, 0.4578275, 0.40821073]).view(1, 3, 1, 1).to(dtype=x.dtype, device=x.device)
183
+ x = x / torch.tensor([0.26862954, 0.26130258, 0.27577711]).view(1, 3, 1, 1).to(dtype=x.dtype, device=x.device)
184
+ return self.clip_model(x)
185
+ elif self.depth == -1:
186
+ encoder_hidden_states = features.pop()
187
+ encoder_hidden_states = encoder_hidden_states * 0.
188
+ encoder_hidden_states = encoder_hidden_states.mean(dim=2, keepdim=True).expand(-1, -1, self.ctx_dim)
189
+ return encoder_hidden_states
190
+ elif self.depth == -2:
191
+ encoder_hidden_states = features.pop()
192
+ encoder_hidden_states = self.decoder_fc(encoder_hidden_states)
193
+ return encoder_hidden_states
models/metrics.py ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ @author: Yanzuo Lu
3
+ @author: oliveryanzuolu@gmail.com
4
+ """
5
+
6
+ import torch
7
+ import torch.nn as nn
8
+ import torch.nn.functional as F
9
+ from lpips import LPIPS
10
+ from skimage.metrics import peak_signal_noise_ratio as compare_psnr
11
+ from skimage.metrics import structural_similarity as compare_ssim
12
+ from torchvision import models
13
+
14
+
15
+ class build_metric(nn.Module):
16
+ def __init__(self):
17
+ super().__init__()
18
+
19
+ # FID
20
+ inception = models.inception_v3(weights=models.Inception_V3_Weights.IMAGENET1K_V1)
21
+ self.inception_blocks = nn.Sequential(
22
+ inception.Conv2d_1a_3x3,
23
+ inception.Conv2d_2a_3x3,
24
+ inception.Conv2d_2b_3x3,
25
+ nn.MaxPool2d(kernel_size=3, stride=2),
26
+ inception.Conv2d_3b_1x1,
27
+ inception.Conv2d_4a_3x3,
28
+ nn.MaxPool2d(kernel_size=3, stride=2),
29
+ inception.Mixed_5b,
30
+ inception.Mixed_5c,
31
+ inception.Mixed_5d,
32
+ inception.Mixed_6a,
33
+ inception.Mixed_6b,
34
+ inception.Mixed_6c,
35
+ inception.Mixed_6d,
36
+ inception.Mixed_6e,
37
+ inception.Mixed_7a,
38
+ inception.Mixed_7b,
39
+ inception.Mixed_7c,
40
+ nn.AdaptiveAvgPool2d(output_size=(1, 1))
41
+ )
42
+
43
+ # LPIPS
44
+ self.lpips_model = LPIPS(net="alex", verbose=False)
45
+
46
+ # freeze
47
+ self.eval()
48
+ self.requires_grad_(False)
49
+
50
+ def forward(self, gt, pred=None):
51
+ if pred is None:
52
+ return self.forward_inception(gt).reshape(gt.shape[0], -1) # fid real
53
+
54
+ # inputs should be [0,1] here
55
+ assert gt.shape[0] == pred.shape[0]
56
+ bsz = gt.shape[0]
57
+
58
+ # FID
59
+ out = self.forward_inception(pred).reshape(bsz, -1)
60
+
61
+ # LPIPS
62
+ lpips = self.lpips_model(pred, gt, normalize=True).reshape(bsz, -1)
63
+
64
+ # PSNR & SSIM
65
+ img_gts = gt.cpu().numpy()
66
+ img_preds = pred.cpu().numpy()
67
+ psnr = []
68
+ ssim = []
69
+ ssim_256 = []
70
+
71
+ for i in range(bsz):
72
+ img_gt = img_gts[i]
73
+ img_pred = img_preds[i]
74
+
75
+ psnr.append(compare_psnr(img_gt, img_pred, data_range=1))
76
+ ssim.append(compare_ssim(img_gt, img_pred, data_range=1, win_size=51, channel_axis=0))
77
+
78
+ img_gt_256 = img_gt * 255.0
79
+ img_pred_256 = img_pred * 255.0
80
+ ssim_256.append(compare_ssim(img_gt_256, img_pred_256, gaussian_weights=True, sigma=1.5,
81
+ use_sample_covariance=False, channel_axis=0,
82
+ data_range=img_pred_256.max() - img_pred_256.min()))
83
+
84
+ psnr = torch.tensor(psnr).to(gt.device).reshape(bsz, -1)
85
+ ssim = torch.tensor(ssim).to(gt.device).reshape(bsz, -1)
86
+ ssim_256 = torch.tensor(ssim_256).to(gt.device).reshape(bsz, -1)
87
+ return out, lpips, psnr, ssim, ssim_256
88
+
89
+ def forward_inception(self, x):
90
+ x = F.interpolate(x, size=(299, 299), mode='bilinear')
91
+ x[:, 0] = x[:, 0] * (0.229 / 0.5) + (0.485 - 0.5) / 0.5
92
+ x[:, 1] = x[:, 1] * (0.224 / 0.5) + (0.456 - 0.5) / 0.5
93
+ x[:, 2] = x[:, 2] * (0.225 / 0.5) + (0.406 - 0.5) / 0.5
94
+ out = self.inception_blocks(x)
95
+ return out
models/pose_encoder.py ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ @author: Yanzuo Lu
3
+ @author: oliveryanzuolu@gmail.com
4
+ """
5
+
6
+ import torch.nn as nn
7
+ from diffusers.models.resnet import ResnetBlock2D, Downsample2D
8
+
9
+
10
+ class PoseEncoder(nn.Module):
11
+ def __init__(self, downscale_factor, pose_channels, in_channels, channels):
12
+ super().__init__()
13
+ self.unshuffle = nn.PixelUnshuffle(downscale_factor)
14
+ self.conv_in = nn.Conv2d(int(pose_channels * (downscale_factor ** 2)), in_channels, kernel_size=1)
15
+
16
+ resnets = []
17
+ downsamplers = []
18
+ for i in range(len(channels)):
19
+ in_channels = in_channels if i == 0 else channels[i - 1]
20
+ out_channels = channels[i]
21
+
22
+ resnets.append(ResnetBlock2D(
23
+ in_channels=in_channels,
24
+ out_channels=out_channels,
25
+ temb_channels=None, # no time embed
26
+ ))
27
+ downsamplers.append(Downsample2D(
28
+ out_channels,
29
+ use_conv=False,
30
+ out_channels=out_channels,
31
+ padding=1,
32
+ name="op"
33
+ ) if i != len(channels) - 1 else nn.Identity())
34
+
35
+ self.resnets = nn.ModuleList(resnets)
36
+ self.downsamplers = nn.ModuleList(downsamplers)
37
+
38
+ def forward(self, hidden_states):
39
+ features = []
40
+ hidden_states = self.unshuffle(hidden_states)
41
+ hidden_states = self.conv_in(hidden_states)
42
+ for resnet, downsampler in zip(self.resnets, self.downsamplers):
43
+ hidden_states = resnet(hidden_states, temb=None)
44
+ features.append(hidden_states)
45
+ hidden_states = downsampler(hidden_states)
46
+ return features
models/swin_transformer.py ADDED
@@ -0,0 +1,724 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ @author: Yanzuo Lu
3
+ @author: oliveryanzuolu@gmail.com
4
+ """
5
+
6
+ import logging
7
+ import numpy as np
8
+
9
+ import torch
10
+ import torch.nn as nn
11
+ import torch.utils.checkpoint as checkpoint
12
+ from timm.models.layers import DropPath, to_2tuple, trunc_normal_
13
+
14
+ # we find the kernel to cause nan, simply omit it
15
+ WindowProcess = None
16
+ WindowProcessReverse = None
17
+
18
+ logger = logging.getLogger()
19
+
20
+
21
+ class Mlp(nn.Module):
22
+ def __init__(self, in_features, hidden_features=None, out_features=None, act_layer=nn.GELU, drop=0.):
23
+ super().__init__()
24
+ out_features = out_features or in_features
25
+ hidden_features = hidden_features or in_features
26
+ self.fc1 = nn.Linear(in_features, hidden_features)
27
+ self.act = act_layer()
28
+ self.fc2 = nn.Linear(hidden_features, out_features)
29
+ self.drop = nn.Dropout(drop)
30
+
31
+ def forward(self, x):
32
+ x = self.fc1(x)
33
+ x = self.act(x)
34
+ x = self.drop(x)
35
+ x = self.fc2(x)
36
+ x = self.drop(x)
37
+ return x
38
+
39
+
40
+ def window_partition(x, window_size):
41
+ """
42
+ Args:
43
+ x: (B, H, W, C)
44
+ window_size (int): window size
45
+
46
+ Returns:
47
+ windows: (num_windows*B, window_size, window_size, C)
48
+ """
49
+ B, H, W, C = x.shape
50
+ x = x.view(B, H // window_size, window_size, W // window_size, window_size, C)
51
+ windows = x.permute(0, 1, 3, 2, 4, 5).contiguous().view(-1, window_size, window_size, C)
52
+ return windows
53
+
54
+
55
+ def window_reverse(windows, window_size, H, W):
56
+ """
57
+ Args:
58
+ windows: (num_windows*B, window_size, window_size, C)
59
+ window_size (int): Window size
60
+ H (int): Height of image
61
+ W (int): Width of image
62
+
63
+ Returns:
64
+ x: (B, H, W, C)
65
+ """
66
+ B = int(windows.shape[0] / (H * W / window_size / window_size))
67
+ x = windows.view(B, H // window_size, W // window_size, window_size, window_size, -1)
68
+ x = x.permute(0, 1, 3, 2, 4, 5).contiguous().view(B, H, W, -1)
69
+ return x
70
+
71
+
72
+ class WindowAttention(nn.Module):
73
+ r""" Window based multi-head self attention (W-MSA) module with relative position bias.
74
+ It supports both of shifted and non-shifted window.
75
+
76
+ Args:
77
+ dim (int): Number of input channels.
78
+ window_size (tuple[int]): The height and width of the window.
79
+ num_heads (int): Number of attention heads.
80
+ qkv_bias (bool, optional): If True, add a learnable bias to query, key, value. Default: True
81
+ qk_scale (float | None, optional): Override default qk scale of head_dim ** -0.5 if set
82
+ attn_drop (float, optional): Dropout ratio of attention weight. Default: 0.0
83
+ proj_drop (float, optional): Dropout ratio of output. Default: 0.0
84
+ """
85
+
86
+ def __init__(self, dim, window_size, num_heads, qkv_bias=True, qk_scale=None, attn_drop=0., proj_drop=0.):
87
+
88
+ super().__init__()
89
+ self.dim = dim
90
+ self.window_size = window_size # Wh, Ww
91
+ self.num_heads = num_heads
92
+ head_dim = dim // num_heads
93
+ self.scale = qk_scale or head_dim ** -0.5
94
+
95
+ # define a parameter table of relative position bias
96
+ self.relative_position_bias_table = nn.Parameter(
97
+ torch.zeros((2 * window_size[0] - 1) * (2 * window_size[1] - 1), num_heads)) # 2*Wh-1 * 2*Ww-1, nH
98
+
99
+ # get pair-wise relative position index for each token inside the window
100
+ coords_h = torch.arange(self.window_size[0])
101
+ coords_w = torch.arange(self.window_size[1])
102
+ coords = torch.stack(torch.meshgrid([coords_h, coords_w])) # 2, Wh, Ww
103
+ coords_flatten = torch.flatten(coords, 1) # 2, Wh*Ww
104
+ relative_coords = coords_flatten[:, :, None] - coords_flatten[:, None, :] # 2, Wh*Ww, Wh*Ww
105
+ relative_coords = relative_coords.permute(1, 2, 0).contiguous() # Wh*Ww, Wh*Ww, 2
106
+ relative_coords[:, :, 0] += self.window_size[0] - 1 # shift to start from 0
107
+ relative_coords[:, :, 1] += self.window_size[1] - 1
108
+ relative_coords[:, :, 0] *= 2 * self.window_size[1] - 1
109
+ relative_position_index = relative_coords.sum(-1) # Wh*Ww, Wh*Ww
110
+ self.register_buffer("relative_position_index", relative_position_index)
111
+
112
+ self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias)
113
+ self.attn_drop = nn.Dropout(attn_drop)
114
+ self.proj = nn.Linear(dim, dim)
115
+ self.proj_drop = nn.Dropout(proj_drop)
116
+
117
+ trunc_normal_(self.relative_position_bias_table, std=.02)
118
+ self.softmax = nn.Softmax(dim=-1)
119
+
120
+ def forward(self, x, mask=None):
121
+ """
122
+ Args:
123
+ x: input features with shape of (num_windows*B, N, C)
124
+ mask: (0/-inf) mask with shape of (num_windows, Wh*Ww, Wh*Ww) or None
125
+ """
126
+ B_, N, C = x.shape
127
+ qkv = self.qkv(x).reshape(B_, N, 3, self.num_heads, C // self.num_heads).permute(2, 0, 3, 1, 4)
128
+ q, k, v = qkv[0], qkv[1], qkv[2] # make torchscript happy (cannot use tensor as tuple)
129
+
130
+ q = q * self.scale
131
+ attn = (q @ k.transpose(-2, -1))
132
+
133
+ relative_position_bias = self.relative_position_bias_table[self.relative_position_index.view(-1)].view(
134
+ self.window_size[0] * self.window_size[1], self.window_size[0] * self.window_size[1], -1) # Wh*Ww,Wh*Ww,nH
135
+ relative_position_bias = relative_position_bias.permute(2, 0, 1).contiguous() # nH, Wh*Ww, Wh*Ww
136
+ attn = attn + relative_position_bias.unsqueeze(0)
137
+
138
+ if mask is not None:
139
+ nW = mask.shape[0]
140
+ attn = attn.view(B_ // nW, nW, self.num_heads, N, N) + mask.unsqueeze(1).unsqueeze(0)
141
+ attn = attn.view(-1, self.num_heads, N, N)
142
+ attn = self.softmax(attn)
143
+ else:
144
+ attn = self.softmax(attn)
145
+
146
+ attn = self.attn_drop(attn)
147
+
148
+ x = (attn @ v).transpose(1, 2).reshape(B_, N, C)
149
+ x = self.proj(x)
150
+ x = self.proj_drop(x)
151
+ return x
152
+
153
+ def extra_repr(self) -> str:
154
+ return f'dim={self.dim}, window_size={self.window_size}, num_heads={self.num_heads}'
155
+
156
+ def flops(self, N):
157
+ # calculate flops for 1 window with token length of N
158
+ flops = 0
159
+ # qkv = self.qkv(x)
160
+ flops += N * self.dim * 3 * self.dim
161
+ # attn = (q @ k.transpose(-2, -1))
162
+ flops += self.num_heads * N * (self.dim // self.num_heads) * N
163
+ # x = (attn @ v)
164
+ flops += self.num_heads * N * N * (self.dim // self.num_heads)
165
+ # x = self.proj(x)
166
+ flops += N * self.dim * self.dim
167
+ return flops
168
+
169
+
170
+ class SwinTransformerBlock(nn.Module):
171
+ r""" Swin Transformer Block.
172
+
173
+ Args:
174
+ dim (int): Number of input channels.
175
+ input_resolution (tuple[int]): Input resulotion.
176
+ num_heads (int): Number of attention heads.
177
+ window_size (int): Window size.
178
+ shift_size (int): Shift size for SW-MSA.
179
+ mlp_ratio (float): Ratio of mlp hidden dim to embedding dim.
180
+ qkv_bias (bool, optional): If True, add a learnable bias to query, key, value. Default: True
181
+ qk_scale (float | None, optional): Override default qk scale of head_dim ** -0.5 if set.
182
+ drop (float, optional): Dropout rate. Default: 0.0
183
+ attn_drop (float, optional): Attention dropout rate. Default: 0.0
184
+ drop_path (float, optional): Stochastic depth rate. Default: 0.0
185
+ act_layer (nn.Module, optional): Activation layer. Default: nn.GELU
186
+ norm_layer (nn.Module, optional): Normalization layer. Default: nn.LayerNorm
187
+ fused_window_process (bool, optional): If True, use one kernel to fused window shift & window partition for acceleration, similar for the reversed part. Default: False
188
+ """
189
+
190
+ def __init__(self, dim, input_resolution, num_heads, window_size=7, shift_size=0,
191
+ mlp_ratio=4., qkv_bias=True, qk_scale=None, drop=0., attn_drop=0., drop_path=0.,
192
+ act_layer=nn.GELU, norm_layer=nn.LayerNorm,
193
+ fused_window_process=False):
194
+ super().__init__()
195
+ self.dim = dim
196
+ self.input_resolution = input_resolution
197
+ self.num_heads = num_heads
198
+ self.window_size = window_size
199
+ self.shift_size = shift_size
200
+ self.mlp_ratio = mlp_ratio
201
+ if min(self.input_resolution) <= self.window_size:
202
+ # if window size is larger than input resolution, we don't partition windows
203
+ self.shift_size = 0
204
+ self.window_size = min(self.input_resolution)
205
+ assert 0 <= self.shift_size < self.window_size, "shift_size must in 0-window_size"
206
+
207
+ self.norm1 = norm_layer(dim)
208
+ self.attn = WindowAttention(
209
+ dim, window_size=to_2tuple(self.window_size), num_heads=num_heads,
210
+ qkv_bias=qkv_bias, qk_scale=qk_scale, attn_drop=attn_drop, proj_drop=drop)
211
+
212
+ self.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity()
213
+ self.norm2 = norm_layer(dim)
214
+ mlp_hidden_dim = int(dim * mlp_ratio)
215
+ self.mlp = Mlp(in_features=dim, hidden_features=mlp_hidden_dim, act_layer=act_layer, drop=drop)
216
+
217
+ if self.shift_size > 0:
218
+ # calculate attention mask for SW-MSA
219
+ H, W = self.input_resolution
220
+ img_mask = torch.zeros((1, H, W, 1)) # 1 H W 1
221
+ h_slices = (slice(0, -self.window_size),
222
+ slice(-self.window_size, -self.shift_size),
223
+ slice(-self.shift_size, None))
224
+ w_slices = (slice(0, -self.window_size),
225
+ slice(-self.window_size, -self.shift_size),
226
+ slice(-self.shift_size, None))
227
+ cnt = 0
228
+ for h in h_slices:
229
+ for w in w_slices:
230
+ img_mask[:, h, w, :] = cnt
231
+ cnt += 1
232
+
233
+ mask_windows = window_partition(img_mask, self.window_size) # nW, window_size, window_size, 1
234
+ mask_windows = mask_windows.view(-1, self.window_size * self.window_size)
235
+ attn_mask = mask_windows.unsqueeze(1) - mask_windows.unsqueeze(2)
236
+ attn_mask = attn_mask.masked_fill(attn_mask != 0, float(-100.0)).masked_fill(attn_mask == 0, float(0.0))
237
+ else:
238
+ attn_mask = None
239
+
240
+ self.register_buffer("attn_mask", attn_mask)
241
+ self.fused_window_process = fused_window_process
242
+
243
+ def forward(self, x):
244
+ H, W = self.input_resolution
245
+ B, L, C = x.shape
246
+ assert L == H * W, "input feature has wrong size"
247
+
248
+ shortcut = x
249
+ x = self.norm1(x)
250
+ x = x.view(B, H, W, C)
251
+
252
+ # cyclic shift
253
+ if self.shift_size > 0:
254
+ if not self.fused_window_process:
255
+ shifted_x = torch.roll(x, shifts=(-self.shift_size, -self.shift_size), dims=(1, 2))
256
+ # partition windows
257
+ x_windows = window_partition(shifted_x, self.window_size) # nW*B, window_size, window_size, C
258
+ else:
259
+ x_windows = WindowProcess.apply(x, B, H, W, C, -self.shift_size, self.window_size)
260
+ else:
261
+ shifted_x = x
262
+ # partition windows
263
+ x_windows = window_partition(shifted_x, self.window_size) # nW*B, window_size, window_size, C
264
+
265
+ x_windows = x_windows.view(-1, self.window_size * self.window_size, C) # nW*B, window_size*window_size, C
266
+
267
+ # W-MSA/SW-MSA
268
+ attn_windows = self.attn(x_windows, mask=self.attn_mask) # nW*B, window_size*window_size, C
269
+
270
+ # merge windows
271
+ attn_windows = attn_windows.view(-1, self.window_size, self.window_size, C)
272
+
273
+ # reverse cyclic shift
274
+ if self.shift_size > 0:
275
+ if not self.fused_window_process:
276
+ shifted_x = window_reverse(attn_windows, self.window_size, H, W) # B H' W' C
277
+ x = torch.roll(shifted_x, shifts=(self.shift_size, self.shift_size), dims=(1, 2))
278
+ else:
279
+ x = WindowProcessReverse.apply(attn_windows, B, H, W, C, self.shift_size, self.window_size)
280
+ else:
281
+ shifted_x = window_reverse(attn_windows, self.window_size, H, W) # B H' W' C
282
+ x = shifted_x
283
+ x = x.view(B, H * W, C)
284
+ x = shortcut + self.drop_path(x)
285
+
286
+ # FFN
287
+ x = x + self.drop_path(self.mlp(self.norm2(x)))
288
+
289
+ return x
290
+
291
+ def extra_repr(self) -> str:
292
+ return f"dim={self.dim}, input_resolution={self.input_resolution}, num_heads={self.num_heads}, " \
293
+ f"window_size={self.window_size}, shift_size={self.shift_size}, mlp_ratio={self.mlp_ratio}"
294
+
295
+ def flops(self):
296
+ flops = 0
297
+ H, W = self.input_resolution
298
+ # norm1
299
+ flops += self.dim * H * W
300
+ # W-MSA/SW-MSA
301
+ nW = H * W / self.window_size / self.window_size
302
+ flops += nW * self.attn.flops(self.window_size * self.window_size)
303
+ # mlp
304
+ flops += 2 * H * W * self.dim * self.dim * self.mlp_ratio
305
+ # norm2
306
+ flops += self.dim * H * W
307
+ return flops
308
+
309
+
310
+ class PatchMerging(nn.Module):
311
+ r""" Patch Merging Layer.
312
+
313
+ Args:
314
+ input_resolution (tuple[int]): Resolution of input feature.
315
+ dim (int): Number of input channels.
316
+ norm_layer (nn.Module, optional): Normalization layer. Default: nn.LayerNorm
317
+ """
318
+
319
+ def __init__(self, input_resolution, dim, norm_layer=nn.LayerNorm):
320
+ super().__init__()
321
+ self.input_resolution = input_resolution
322
+ self.dim = dim
323
+ self.reduction = nn.Linear(4 * dim, 2 * dim, bias=False)
324
+ self.norm = norm_layer(4 * dim)
325
+
326
+ def forward(self, x):
327
+ """
328
+ x: B, H*W, C
329
+ """
330
+ H, W = self.input_resolution
331
+ B, L, C = x.shape
332
+ assert L == H * W, "input feature has wrong size"
333
+ assert H % 2 == 0 and W % 2 == 0, f"x size ({H}*{W}) are not even."
334
+
335
+ x = x.view(B, H, W, C)
336
+
337
+ x0 = x[:, 0::2, 0::2, :] # B H/2 W/2 C
338
+ x1 = x[:, 1::2, 0::2, :] # B H/2 W/2 C
339
+ x2 = x[:, 0::2, 1::2, :] # B H/2 W/2 C
340
+ x3 = x[:, 1::2, 1::2, :] # B H/2 W/2 C
341
+ x = torch.cat([x0, x1, x2, x3], -1) # B H/2 W/2 4*C
342
+ x = x.view(B, -1, 4 * C) # B H/2*W/2 4*C
343
+
344
+ x = self.norm(x)
345
+ x = self.reduction(x)
346
+
347
+ return x
348
+
349
+ def extra_repr(self) -> str:
350
+ return f"input_resolution={self.input_resolution}, dim={self.dim}"
351
+
352
+ def flops(self):
353
+ H, W = self.input_resolution
354
+ flops = H * W * self.dim
355
+ flops += (H // 2) * (W // 2) * 4 * self.dim * 2 * self.dim
356
+ return flops
357
+
358
+
359
+ class BasicLayer(nn.Module):
360
+ """ A basic Swin Transformer layer for one stage.
361
+
362
+ Args:
363
+ dim (int): Number of input channels.
364
+ input_resolution (tuple[int]): Input resolution.
365
+ depth (int): Number of blocks.
366
+ num_heads (int): Number of attention heads.
367
+ window_size (int): Local window size.
368
+ mlp_ratio (float): Ratio of mlp hidden dim to embedding dim.
369
+ qkv_bias (bool, optional): If True, add a learnable bias to query, key, value. Default: True
370
+ qk_scale (float | None, optional): Override default qk scale of head_dim ** -0.5 if set.
371
+ drop (float, optional): Dropout rate. Default: 0.0
372
+ attn_drop (float, optional): Attention dropout rate. Default: 0.0
373
+ drop_path (float | tuple[float], optional): Stochastic depth rate. Default: 0.0
374
+ norm_layer (nn.Module, optional): Normalization layer. Default: nn.LayerNorm
375
+ downsample (nn.Module | None, optional): Downsample layer at the end of the layer. Default: None
376
+ use_checkpoint (bool): Whether to use checkpointing to save memory. Default: False.
377
+ fused_window_process (bool, optional): If True, use one kernel to fused window shift & window partition for acceleration, similar for the reversed part. Default: False
378
+ """
379
+
380
+ def __init__(self, dim, input_resolution, depth, num_heads, window_size,
381
+ mlp_ratio=4., qkv_bias=True, qk_scale=None, drop=0., attn_drop=0.,
382
+ drop_path=0., norm_layer=nn.LayerNorm, downsample=None, use_checkpoint=False,
383
+ fused_window_process=False):
384
+
385
+ super().__init__()
386
+ self.dim = dim
387
+ self.input_resolution = input_resolution
388
+ self.depth = depth
389
+ self.use_checkpoint = use_checkpoint
390
+
391
+ # build blocks
392
+ self.blocks = nn.ModuleList([
393
+ SwinTransformerBlock(dim=dim, input_resolution=input_resolution,
394
+ num_heads=num_heads, window_size=window_size,
395
+ shift_size=0 if (i % 2 == 0) else window_size // 2,
396
+ mlp_ratio=mlp_ratio,
397
+ qkv_bias=qkv_bias, qk_scale=qk_scale,
398
+ drop=drop, attn_drop=attn_drop,
399
+ drop_path=drop_path[i] if isinstance(drop_path, list) else drop_path,
400
+ norm_layer=norm_layer,
401
+ fused_window_process=fused_window_process)
402
+ for i in range(depth)])
403
+
404
+ # patch merging layer
405
+ if downsample is not None:
406
+ self.downsample = downsample(input_resolution, dim=dim, norm_layer=norm_layer)
407
+ else:
408
+ self.downsample = None
409
+
410
+ def forward(self, x):
411
+ for blk in self.blocks:
412
+ if self.use_checkpoint:
413
+ x = checkpoint.checkpoint(blk, x)
414
+ else:
415
+ x = blk(x)
416
+ feature = x
417
+ if self.downsample is not None:
418
+ x = self.downsample(x)
419
+ return x, feature
420
+
421
+ def extra_repr(self) -> str:
422
+ return f"dim={self.dim}, input_resolution={self.input_resolution}, depth={self.depth}"
423
+
424
+ def flops(self):
425
+ flops = 0
426
+ for blk in self.blocks:
427
+ flops += blk.flops()
428
+ if self.downsample is not None:
429
+ flops += self.downsample.flops()
430
+ return flops
431
+
432
+
433
+ class PatchEmbed(nn.Module):
434
+ r""" Image to Patch Embedding
435
+
436
+ Args:
437
+ img_size (int): Image size. Default: 224.
438
+ patch_size (int): Patch token size. Default: 4.
439
+ in_chans (int): Number of input image channels. Default: 3.
440
+ embed_dim (int): Number of linear projection output channels. Default: 96.
441
+ norm_layer (nn.Module, optional): Normalization layer. Default: None
442
+ """
443
+
444
+ def __init__(self, img_size=224, patch_size=4, in_chans=3, embed_dim=96, norm_layer=None):
445
+ super().__init__()
446
+ img_size = to_2tuple(img_size)
447
+ patch_size = to_2tuple(patch_size)
448
+ patches_resolution = [img_size[0] // patch_size[0], img_size[1] // patch_size[1]]
449
+ self.img_size = img_size
450
+ self.patch_size = patch_size
451
+ self.patches_resolution = patches_resolution
452
+ self.num_patches = patches_resolution[0] * patches_resolution[1]
453
+
454
+ self.in_chans = in_chans
455
+ self.embed_dim = embed_dim
456
+
457
+ self.proj = nn.Conv2d(in_chans, embed_dim, kernel_size=patch_size, stride=patch_size)
458
+ if norm_layer is not None:
459
+ self.norm = norm_layer(embed_dim)
460
+ else:
461
+ self.norm = None
462
+
463
+ def forward(self, x):
464
+ # B, C, H, W = x.shape
465
+ # FIXME look at relaxing size constraints
466
+ # assert H == self.img_size[0] and W == self.img_size[1], \
467
+ # f"Input image size ({H}*{W}) doesn't match model ({self.img_size[0]}*{self.img_size[1]})."
468
+ # x = self.proj(x).flatten(2).transpose(1, 2) # B Ph*Pw C
469
+ x = self.proj(x)
470
+ B, C, H, W = x.shape
471
+ x = x.flatten(2).transpose(1, 2)
472
+ if self.norm is not None:
473
+ x = self.norm(x)
474
+ return x.transpose(1, 2).reshape(B, C, H, W)
475
+
476
+ def flops(self):
477
+ Ho, Wo = self.patches_resolution
478
+ flops = Ho * Wo * self.embed_dim * self.in_chans * (self.patch_size[0] * self.patch_size[1])
479
+ if self.norm is not None:
480
+ flops += Ho * Wo * self.embed_dim
481
+ return flops
482
+
483
+
484
+ class SwinTransformer(nn.Module):
485
+ r""" Swin Transformer
486
+ A PyTorch impl of : `Swin Transformer: Hierarchical Vision Transformer using Shifted Windows` -
487
+ https://arxiv.org/pdf/2103.14030
488
+
489
+ Args:
490
+ img_size (int | tuple(int)): Input image size. Default 224
491
+ patch_size (int | tuple(int)): Patch size. Default: 4
492
+ in_chans (int): Number of input image channels. Default: 3
493
+ num_classes (int): Number of classes for classification head. Default: 1000
494
+ embed_dim (int): Patch embedding dimension. Default: 96
495
+ depths (tuple(int)): Depth of each Swin Transformer layer.
496
+ num_heads (tuple(int)): Number of attention heads in different layers.
497
+ window_size (int): Window size. Default: 7
498
+ mlp_ratio (float): Ratio of mlp hidden dim to embedding dim. Default: 4
499
+ qkv_bias (bool): If True, add a learnable bias to query, key, value. Default: True
500
+ qk_scale (float): Override default qk scale of head_dim ** -0.5 if set. Default: None
501
+ drop_rate (float): Dropout rate. Default: 0
502
+ attn_drop_rate (float): Attention dropout rate. Default: 0
503
+ drop_path_rate (float): Stochastic depth rate. Default: 0.1
504
+ norm_layer (nn.Module): Normalization layer. Default: nn.LayerNorm.
505
+ ape (bool): If True, add absolute position embedding to the patch embedding. Default: False
506
+ patch_norm (bool): If True, add normalization after patch embedding. Default: True
507
+ use_checkpoint (bool): Whether to use checkpointing to save memory. Default: False
508
+ fused_window_process (bool, optional): If True, use one kernel to fused window shift & window partition for acceleration, similar for the reversed part. Default: False
509
+ """
510
+
511
+ def __init__(self, img_size=224, patch_size=4, in_chans=3, num_classes=0,
512
+ embed_dim=96, depths=[2, 2, 6, 2], num_heads=[3, 6, 12, 24],
513
+ window_size=7, mlp_ratio=4., qkv_bias=True, qk_scale=None,
514
+ drop_rate=0., attn_drop_rate=0., drop_path_rate=0.1,
515
+ norm_layer=nn.LayerNorm, ape=False, patch_norm=True,
516
+ use_checkpoint=False, fused_window_process=False,
517
+ mask=True, last_norm=True, **kwargs):
518
+ super().__init__()
519
+
520
+ self.num_classes = num_classes
521
+ self.num_layers = len(depths)
522
+ self.embed_dim = embed_dim
523
+ self.ape = ape
524
+ self.patch_norm = patch_norm
525
+ self.num_features = int(embed_dim * 2 ** (self.num_layers - 1))
526
+ self.mlp_ratio = mlp_ratio
527
+ self.mask = mask
528
+
529
+ # split image into non-overlapping patches
530
+ self.patch_embed = PatchEmbed(
531
+ img_size=img_size, patch_size=patch_size, in_chans=in_chans, embed_dim=embed_dim,
532
+ norm_layer=norm_layer if self.patch_norm else None)
533
+ num_patches = self.patch_embed.num_patches
534
+ patches_resolution = self.patch_embed.patches_resolution
535
+ self.patches_resolution = patches_resolution
536
+
537
+ # absolute position embedding
538
+ if self.ape:
539
+ self.absolute_pos_embed = nn.Parameter(torch.zeros(1, num_patches, embed_dim))
540
+ trunc_normal_(self.absolute_pos_embed, std=.02)
541
+
542
+ self.pos_drop = nn.Dropout(p=drop_rate)
543
+
544
+ # stochastic depth
545
+ self.dpr = [x.item() for x in torch.linspace(0, drop_path_rate, sum(depths))] # stochastic depth decay rule
546
+
547
+ # build layers
548
+ self.layers = nn.ModuleList()
549
+ for i_layer in range(self.num_layers):
550
+ layer = BasicLayer(dim=int(embed_dim * 2 ** i_layer),
551
+ input_resolution=(patches_resolution[0] // (2 ** i_layer),
552
+ patches_resolution[1] // (2 ** i_layer)),
553
+ depth=depths[i_layer],
554
+ num_heads=num_heads[i_layer],
555
+ window_size=window_size,
556
+ mlp_ratio=self.mlp_ratio,
557
+ qkv_bias=qkv_bias, qk_scale=qk_scale,
558
+ drop=drop_rate, attn_drop=attn_drop_rate,
559
+ drop_path=self.dpr[sum(depths[:i_layer]):sum(depths[:i_layer + 1])],
560
+ norm_layer=norm_layer,
561
+ downsample=PatchMerging if (i_layer < self.num_layers - 1) else None,
562
+ use_checkpoint=use_checkpoint,
563
+ fused_window_process=fused_window_process)
564
+ self.layers.append(layer)
565
+
566
+ self.norm = norm_layer(self.num_features) if last_norm else nn.Identity()
567
+ self.avgpool = nn.AdaptiveAvgPool1d(1)
568
+ self.head = nn.Linear(self.num_features, num_classes) if num_classes > 0 else nn.Identity()
569
+
570
+ self.apply(self._init_weights)
571
+ if self.mask:
572
+ self.masked_embed = nn.Parameter(torch.zeros(1, embed_dim))
573
+
574
+ def _init_weights(self, m):
575
+ if isinstance(m, nn.Linear):
576
+ trunc_normal_(m.weight, std=.02)
577
+ if isinstance(m, nn.Linear) and m.bias is not None:
578
+ nn.init.constant_(m.bias, 0)
579
+ elif isinstance(m, nn.LayerNorm):
580
+ nn.init.constant_(m.bias, 0)
581
+ nn.init.constant_(m.weight, 1.0)
582
+
583
+ @torch.jit.ignore
584
+ def no_weight_decay(self):
585
+ return {'absolute_pos_embed'}
586
+
587
+ @torch.jit.ignore
588
+ def no_weight_decay_keywords(self):
589
+ return {'relative_position_bias_table'}
590
+
591
+ def forward_features(self, x, mask=None):
592
+ x = self.patch_embed(x)
593
+ if self.mask and mask is not None:
594
+ x = self.mask_model(x, mask)
595
+ x = x.flatten(2).transpose(1, 2)
596
+
597
+ if self.ape:
598
+ x = x + self.absolute_pos_embed
599
+ x = self.pos_drop(x)
600
+
601
+ features = []
602
+ for layer in self.layers:
603
+ x, feature = layer(x)
604
+ features.append(feature)
605
+
606
+ x = self.norm(x) # B L C
607
+ x = self.avgpool(x.transpose(1, 2)) # B C 1
608
+ x = torch.flatten(x, 1)
609
+ return x, features
610
+
611
+ def mask_model(self, x, mask):
612
+ if x.shape[-2:] != mask.shape[-2:]:
613
+ htimes, wtimes = np.array(x.shape[-2:]) // np.array(mask.shape[-2:])
614
+ mask = mask.repeat_interleave(htimes, -2).repeat_interleave(wtimes, -1)
615
+
616
+ # mask embed
617
+ x.permute(0, 2, 3, 1)[mask, :] = self.masked_embed.to(x.dtype)
618
+
619
+ return x
620
+
621
+ def forward(self, x, mask=None):
622
+ x, features = self.forward_features(x, mask)
623
+ x = self.head(x)
624
+ return x, features
625
+
626
+ def flops(self):
627
+ flops = 0
628
+ flops += self.patch_embed.flops()
629
+ for i, layer in enumerate(self.layers):
630
+ flops += layer.flops()
631
+ flops += self.num_features * self.patches_resolution[0] * self.patches_resolution[1] // (2 ** self.num_layers)
632
+ flops += self.num_features * self.num_classes
633
+ return flops
634
+
635
+
636
+ def load_pretrained(model, pretrained_path, checkpoint_key="model", checkpoint_prefix=None):
637
+ # logger.info(f"==============> Loading weight {pretrained_path} for fine-tuning......")
638
+ state_dict = torch.load(pretrained_path, map_location='cpu')
639
+ if checkpoint_key:
640
+ state_dict = state_dict[checkpoint_key]
641
+ if checkpoint_prefix:
642
+ state_dict = {k[len(checkpoint_prefix):]: v for k, v in state_dict.items() \
643
+ if k.startswith(checkpoint_prefix)}
644
+
645
+ # delete relative_position_index since we always re-init it
646
+ relative_position_index_keys = [k for k in state_dict.keys() if "relative_position_index" in k]
647
+ for k in relative_position_index_keys:
648
+ del state_dict[k]
649
+
650
+ # delete relative_coords_table since we always re-init it
651
+ relative_position_index_keys = [k for k in state_dict.keys() if "relative_coords_table" in k]
652
+ for k in relative_position_index_keys:
653
+ del state_dict[k]
654
+
655
+ # delete attn_mask since we always re-init it
656
+ attn_mask_keys = [k for k in state_dict.keys() if "attn_mask" in k]
657
+ for k in attn_mask_keys:
658
+ del state_dict[k]
659
+
660
+ # bicubic interpolate relative_position_bias_table if not match
661
+ relative_position_bias_table_keys = [k for k in state_dict.keys() if "relative_position_bias_table" in k]
662
+ for k in relative_position_bias_table_keys:
663
+ relative_position_bias_table_pretrained = state_dict[k]
664
+ relative_position_bias_table_current = model.state_dict()[k]
665
+ L1, nH1 = relative_position_bias_table_pretrained.size()
666
+ L2, nH2 = relative_position_bias_table_current.size()
667
+ if nH1 != nH2:
668
+ logger.info(f"Error in loading {k}, passing......")
669
+ else:
670
+ if L1 != L2:
671
+ # bicubic interpolate relative_position_bias_table if not match
672
+ S1 = int(L1 ** 0.5)
673
+ S2 = int(L2 ** 0.5)
674
+ relative_position_bias_table_pretrained_resized = torch.nn.functional.interpolate(
675
+ relative_position_bias_table_pretrained.permute(1, 0).view(1, nH1, S1, S1), size=(S2, S2),
676
+ mode='bicubic')
677
+ state_dict[k] = relative_position_bias_table_pretrained_resized.view(nH2, L2).permute(1, 0)
678
+
679
+ # bicubic interpolate absolute_pos_embed if not match
680
+ absolute_pos_embed_keys = [k for k in state_dict.keys() if "absolute_pos_embed" in k]
681
+ for k in absolute_pos_embed_keys:
682
+ # dpe
683
+ absolute_pos_embed_pretrained = state_dict[k]
684
+ absolute_pos_embed_current = model.state_dict()[k]
685
+ _, L1, C1 = absolute_pos_embed_pretrained.size()
686
+ _, L2, C2 = absolute_pos_embed_current.size()
687
+ if C1 != C1:
688
+ logger.info(f"Error in loading {k}, passing......")
689
+ else:
690
+ if L1 != L2:
691
+ S1 = int(L1 ** 0.5)
692
+ S2 = int(L2 ** 0.5)
693
+ absolute_pos_embed_pretrained = absolute_pos_embed_pretrained.reshape(-1, S1, S1, C1)
694
+ absolute_pos_embed_pretrained = absolute_pos_embed_pretrained.permute(0, 3, 1, 2)
695
+ absolute_pos_embed_pretrained_resized = torch.nn.functional.interpolate(
696
+ absolute_pos_embed_pretrained, size=(S2, S2), mode='bicubic')
697
+ absolute_pos_embed_pretrained_resized = absolute_pos_embed_pretrained_resized.permute(0, 2, 3, 1)
698
+ absolute_pos_embed_pretrained_resized = absolute_pos_embed_pretrained_resized.flatten(1, 2)
699
+ state_dict[k] = absolute_pos_embed_pretrained_resized
700
+
701
+ msg = model.load_state_dict(state_dict, strict=False)
702
+ logger.info(msg)
703
+
704
+ # logger.info(f"=> loaded successfully '{pretrained_path}'")
705
+
706
+ # del checkpoint
707
+ torch.cuda.empty_cache()
708
+
709
+
710
+ def build_backbone(img_size, embed_dim, depths, num_heads, window_size, drop_path_rate, mask, last_norm, pretrained_path):
711
+ if len(depths) > 0:
712
+ model = SwinTransformer(img_size=img_size, embed_dim=embed_dim, depths=depths, num_heads=num_heads,
713
+ window_size=window_size, drop_path_rate=drop_path_rate, mask=mask, last_norm=last_norm)
714
+ if pretrained_path:
715
+ load_pretrained(model, pretrained_path)
716
+ else:
717
+ class Identity(nn.Module):
718
+ def __init__(self):
719
+ super().__init__()
720
+
721
+ def forward(self, x, mask=None):
722
+ return x, []
723
+ model = Identity()
724
+ return model
models/unet.py ADDED
@@ -0,0 +1,1946 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ @author: Yanzuo Lu
3
+ @author: oliveryanzuolu@gmail.com
4
+ """
5
+
6
+ import torch
7
+ import torch.nn as nn
8
+ from diffusers.models.attention import *
9
+ from diffusers.models.attention_processor import *
10
+ from diffusers.models.resnet import *
11
+ from diffusers.models.transformer_2d import *
12
+ from diffusers.models.unet_2d_blocks import *
13
+ from diffusers.models.unet_2d_condition import *
14
+
15
+
16
+ class ResidualXFormersAttnProcessor(XFormersAttnProcessor):
17
+ def __call__(
18
+ self,
19
+ attn: Attention,
20
+ hidden_states: torch.FloatTensor,
21
+ encoder_hidden_states: Optional[torch.FloatTensor] = None,
22
+ attention_mask: Optional[torch.FloatTensor] = None,
23
+ temb: Optional[torch.FloatTensor] = None,
24
+ block_idx: Optional[int] = None,
25
+ additional_residuals: Optional[Dict[str, torch.FloatTensor]] = None,
26
+ is_self_attn: Optional[bool] = None
27
+ ):
28
+ residual = hidden_states
29
+
30
+ if attn.spatial_norm is not None:
31
+ hidden_states = attn.spatial_norm(hidden_states, temb)
32
+
33
+ input_ndim = hidden_states.ndim
34
+
35
+ if input_ndim == 4:
36
+ batch_size, channel, height, width = hidden_states.shape
37
+ hidden_states = hidden_states.view(batch_size, channel, height * width).transpose(1, 2)
38
+
39
+ batch_size, key_tokens, _ = (
40
+ hidden_states.shape if encoder_hidden_states is None else encoder_hidden_states.shape
41
+ )
42
+
43
+ attention_mask = attn.prepare_attention_mask(attention_mask, key_tokens, batch_size)
44
+ if attention_mask is not None:
45
+ # expand our mask's singleton query_tokens dimension:
46
+ # [batch*heads, 1, key_tokens] ->
47
+ # [batch*heads, query_tokens, key_tokens]
48
+ # so that it can be added as a bias onto the attention scores that xformers computes:
49
+ # [batch*heads, query_tokens, key_tokens]
50
+ # we do this explicitly because xformers doesn't broadcast the singleton dimension for us.
51
+ _, query_tokens, _ = hidden_states.shape
52
+ attention_mask = attention_mask.expand(-1, query_tokens, -1)
53
+
54
+ if attn.group_norm is not None:
55
+ hidden_states = attn.group_norm(hidden_states.transpose(1, 2)).transpose(1, 2)
56
+
57
+ query = attn.to_q(hidden_states)
58
+
59
+ # newly added
60
+ if is_self_attn and additional_residuals and f"block_{block_idx}_self_attn_q" in additional_residuals:
61
+ query = query + additional_residuals[f"block_{block_idx}_self_attn_q"]
62
+ elif not is_self_attn and additional_residuals and f"block_{block_idx}_cross_attn_q" in additional_residuals:
63
+ query = query + additional_residuals[f"block_{block_idx}_cross_attn_q"]
64
+
65
+ if encoder_hidden_states is None:
66
+ encoder_hidden_states = hidden_states
67
+ elif attn.norm_cross:
68
+ encoder_hidden_states = attn.norm_encoder_hidden_states(encoder_hidden_states)
69
+
70
+ if not is_self_attn and additional_residuals and f"block_{block_idx}_cross_attn_c" in additional_residuals:
71
+ not_uc = torch.abs(encoder_hidden_states - torch.zeros_like(encoder_hidden_states)).mean(dim=[1, 2], keepdim=True) < 1e-4
72
+ encoder_hidden_states = encoder_hidden_states + additional_residuals[f"block_{block_idx}_cross_attn_c"] * not_uc
73
+ # encoder_hidden_states[not_uc] = encoder_hidden_states[not_uc] + \
74
+ # additional_residuals[f"block_{block_idx}_cross_attn_c"][not_uc]
75
+ # encoder_hidden_states[~not_uc] = encoder_hidden_states[~not_uc] + \
76
+ # additional_residuals[f"block_{block_idx}_cross_attn_c"][~not_uc] * 0.
77
+
78
+ key = attn.to_k(encoder_hidden_states)
79
+ value = attn.to_v(encoder_hidden_states)
80
+
81
+ # newly added
82
+ if is_self_attn and additional_residuals and f"block_{block_idx}_self_attn_k" in additional_residuals:
83
+ key = key + additional_residuals[f"block_{block_idx}_self_attn_k"]
84
+ elif not is_self_attn and additional_residuals and f"block_{block_idx}_cross_attn_k" in additional_residuals:
85
+ key = key + additional_residuals[f"block_{block_idx}_cross_attn_k"]
86
+
87
+ if is_self_attn and additional_residuals and f"block_{block_idx}_self_attn_v" in additional_residuals:
88
+ value = value + additional_residuals[f"block_{block_idx}_self_attn_v"]
89
+ elif not is_self_attn and additional_residuals and f"block_{block_idx}_cross_attn_v" in additional_residuals:
90
+ value = value + additional_residuals[f"block_{block_idx}_cross_attn_v"]
91
+
92
+ query = attn.head_to_batch_dim(query).contiguous()
93
+ key = attn.head_to_batch_dim(key).contiguous()
94
+ value = attn.head_to_batch_dim(value).contiguous()
95
+
96
+ hidden_states = xformers.ops.memory_efficient_attention(
97
+ query, key, value, attn_bias=attention_mask, op=self.attention_op, scale=attn.scale
98
+ )
99
+ hidden_states = hidden_states.to(query.dtype)
100
+ hidden_states = attn.batch_to_head_dim(hidden_states)
101
+
102
+ # linear proj
103
+ hidden_states = attn.to_out[0](hidden_states)
104
+ # dropout
105
+ hidden_states = attn.to_out[1](hidden_states)
106
+
107
+ if input_ndim == 4:
108
+ hidden_states = hidden_states.transpose(-1, -2).reshape(batch_size, channel, height, width)
109
+
110
+ if attn.residual_connection:
111
+ hidden_states = hidden_states + residual
112
+
113
+ hidden_states = hidden_states / attn.rescale_output_factor
114
+
115
+ return hidden_states
116
+
117
+
118
+ class ResidualAttention(Attention):
119
+ def set_use_memory_efficient_attention_xformers(
120
+ self, use_memory_efficient_attention_xformers: bool, attention_op: Optional[Callable] = None
121
+ ):
122
+ is_lora = hasattr(self, "processor") and isinstance(
123
+ self.processor,
124
+ LORA_ATTENTION_PROCESSORS,
125
+ )
126
+ is_custom_diffusion = hasattr(self, "processor") and isinstance(
127
+ self.processor, (CustomDiffusionAttnProcessor, CustomDiffusionXFormersAttnProcessor)
128
+ )
129
+ is_added_kv_processor = hasattr(self, "processor") and isinstance(
130
+ self.processor,
131
+ (
132
+ AttnAddedKVProcessor,
133
+ AttnAddedKVProcessor2_0,
134
+ SlicedAttnAddedKVProcessor,
135
+ XFormersAttnAddedKVProcessor,
136
+ LoRAAttnAddedKVProcessor,
137
+ ),
138
+ )
139
+
140
+ if use_memory_efficient_attention_xformers:
141
+ if is_added_kv_processor and (is_lora or is_custom_diffusion):
142
+ raise NotImplementedError(
143
+ f"Memory efficient attention is currently not supported for LoRA or custom diffuson for attention processor type {self.processor}"
144
+ )
145
+ if not is_xformers_available():
146
+ raise ModuleNotFoundError(
147
+ (
148
+ "Refer to https://github.com/facebookresearch/xformers for more information on how to install"
149
+ " xformers"
150
+ ),
151
+ name="xformers",
152
+ )
153
+ elif not torch.cuda.is_available():
154
+ raise ValueError(
155
+ "torch.cuda.is_available() should be True but is False. xformers' memory efficient attention is"
156
+ " only available for GPU "
157
+ )
158
+ else:
159
+ try:
160
+ # Make sure we can run the memory efficient attention
161
+ _ = xformers.ops.memory_efficient_attention(
162
+ torch.randn((1, 2, 40), device="cuda"),
163
+ torch.randn((1, 2, 40), device="cuda"),
164
+ torch.randn((1, 2, 40), device="cuda"),
165
+ )
166
+ except Exception as e:
167
+ raise e
168
+
169
+ if is_lora:
170
+ # TODO (sayakpaul): should we throw a warning if someone wants to use the xformers
171
+ # variant when using PT 2.0 now that we have LoRAAttnProcessor2_0?
172
+ processor = LoRAXFormersAttnProcessor(
173
+ hidden_size=self.processor.hidden_size,
174
+ cross_attention_dim=self.processor.cross_attention_dim,
175
+ rank=self.processor.rank,
176
+ attention_op=attention_op,
177
+ )
178
+ processor.load_state_dict(self.processor.state_dict())
179
+ processor.to(self.processor.to_q_lora.up.weight.device)
180
+ elif is_custom_diffusion:
181
+ processor = CustomDiffusionXFormersAttnProcessor(
182
+ train_kv=self.processor.train_kv,
183
+ train_q_out=self.processor.train_q_out,
184
+ hidden_size=self.processor.hidden_size,
185
+ cross_attention_dim=self.processor.cross_attention_dim,
186
+ attention_op=attention_op,
187
+ )
188
+ processor.load_state_dict(self.processor.state_dict())
189
+ if hasattr(self.processor, "to_k_custom_diffusion"):
190
+ processor.to(self.processor.to_k_custom_diffusion.weight.device)
191
+ elif is_added_kv_processor:
192
+ # TODO(Patrick, Suraj, William) - currently xformers doesn't work for UnCLIP
193
+ # which uses this type of cross attention ONLY because the attention mask of format
194
+ # [0, ..., -10.000, ..., 0, ...,] is not supported
195
+ # throw warning
196
+ logger.info(
197
+ "Memory efficient attention with `xformers` might currently not work correctly if an attention mask is required for the attention operation."
198
+ )
199
+ processor = XFormersAttnAddedKVProcessor(attention_op=attention_op)
200
+ else:
201
+ processor = ResidualXFormersAttnProcessor(attention_op=attention_op)
202
+ else:
203
+ if is_lora:
204
+ attn_processor_class = (
205
+ LoRAAttnProcessor2_0 if hasattr(F, "scaled_dot_product_attention") else LoRAAttnProcessor
206
+ )
207
+ processor = attn_processor_class(
208
+ hidden_size=self.processor.hidden_size,
209
+ cross_attention_dim=self.processor.cross_attention_dim,
210
+ rank=self.processor.rank,
211
+ )
212
+ processor.load_state_dict(self.processor.state_dict())
213
+ processor.to(self.processor.to_q_lora.up.weight.device)
214
+ elif is_custom_diffusion:
215
+ processor = CustomDiffusionAttnProcessor(
216
+ train_kv=self.processor.train_kv,
217
+ train_q_out=self.processor.train_q_out,
218
+ hidden_size=self.processor.hidden_size,
219
+ cross_attention_dim=self.processor.cross_attention_dim,
220
+ )
221
+ processor.load_state_dict(self.processor.state_dict())
222
+ if hasattr(self.processor, "to_k_custom_diffusion"):
223
+ processor.to(self.processor.to_k_custom_diffusion.weight.device)
224
+ else:
225
+ # set attention processor
226
+ # We use the AttnProcessor2_0 by default when torch 2.x is used which uses
227
+ # torch.nn.functional.scaled_dot_product_attention for native Flash/memory_efficient_attention
228
+ # but only if it has the default `scale` argument. TODO remove scale_qk check when we move to torch 2.1
229
+ processor = (
230
+ AttnProcessor2_0()
231
+ if hasattr(F, "scaled_dot_product_attention") and self.scale_qk
232
+ else AttnProcessor()
233
+ )
234
+
235
+ self.set_processor(processor)
236
+
237
+ def forward(self, hidden_states, encoder_hidden_states=None, attention_mask=None,
238
+ block_idx: Optional[int] = None, additional_residuals: Optional[Dict[str, torch.FloatTensor]] = None,
239
+ is_self_attn: Optional[bool] = None, **cross_attention_kwargs):
240
+ # The `Attention` class can call different attention processors / attention functions
241
+ # here we simply pass along all tensors to the selected processor class
242
+ # For standard processors that are defined here, `**cross_attention_kwargs` is empty
243
+ return self.processor(
244
+ self,
245
+ hidden_states,
246
+ encoder_hidden_states=encoder_hidden_states,
247
+ attention_mask=attention_mask,
248
+ block_idx=block_idx,
249
+ additional_residuals=additional_residuals,
250
+ is_self_attn=is_self_attn,
251
+ **cross_attention_kwargs,
252
+ )
253
+
254
+
255
+ class ResidualTransformerBlock(BasicTransformerBlock):
256
+ def __init__(
257
+ self,
258
+ dim: int,
259
+ num_attention_heads: int,
260
+ attention_head_dim: int,
261
+ dropout=0.0,
262
+ cross_attention_dim: Optional[int] = None,
263
+ activation_fn: str = "geglu",
264
+ num_embeds_ada_norm: Optional[int] = None,
265
+ attention_bias: bool = False,
266
+ only_cross_attention: bool = False,
267
+ double_self_attention: bool = False,
268
+ upcast_attention: bool = False,
269
+ norm_elementwise_affine: bool = True,
270
+ norm_type: str = "layer_norm",
271
+ final_dropout: bool = False,
272
+ ):
273
+ super(BasicTransformerBlock, self).__init__()
274
+ self.only_cross_attention = only_cross_attention
275
+
276
+ self.use_ada_layer_norm_zero = (num_embeds_ada_norm is not None) and norm_type == "ada_norm_zero"
277
+ self.use_ada_layer_norm = (num_embeds_ada_norm is not None) and norm_type == "ada_norm"
278
+
279
+ if norm_type in ("ada_norm", "ada_norm_zero") and num_embeds_ada_norm is None:
280
+ raise ValueError(
281
+ f"`norm_type` is set to {norm_type}, but `num_embeds_ada_norm` is not defined. Please make sure to"
282
+ f" define `num_embeds_ada_norm` if setting `norm_type` to {norm_type}."
283
+ )
284
+
285
+ # Define 3 blocks. Each block has its own normalization layer.
286
+ # 1. Self-Attn
287
+ if self.use_ada_layer_norm:
288
+ self.norm1 = AdaLayerNorm(dim, num_embeds_ada_norm)
289
+ elif self.use_ada_layer_norm_zero:
290
+ self.norm1 = AdaLayerNormZero(dim, num_embeds_ada_norm)
291
+ else:
292
+ self.norm1 = nn.LayerNorm(dim, elementwise_affine=norm_elementwise_affine)
293
+ self.attn1 = ResidualAttention(
294
+ query_dim=dim,
295
+ heads=num_attention_heads,
296
+ dim_head=attention_head_dim,
297
+ dropout=dropout,
298
+ bias=attention_bias,
299
+ cross_attention_dim=cross_attention_dim if only_cross_attention else None,
300
+ upcast_attention=upcast_attention,
301
+ )
302
+
303
+ # 2. Cross-Attn
304
+ if cross_attention_dim is not None or double_self_attention:
305
+ # We currently only use AdaLayerNormZero for self attention where there will only be one attention block.
306
+ # I.e. the number of returned modulation chunks from AdaLayerZero would not make sense if returned during
307
+ # the second cross attention block.
308
+ self.norm2 = (
309
+ AdaLayerNorm(dim, num_embeds_ada_norm)
310
+ if self.use_ada_layer_norm
311
+ else nn.LayerNorm(dim, elementwise_affine=norm_elementwise_affine)
312
+ )
313
+ self.attn2 = ResidualAttention(
314
+ query_dim=dim,
315
+ cross_attention_dim=cross_attention_dim if not double_self_attention else None,
316
+ heads=num_attention_heads,
317
+ dim_head=attention_head_dim,
318
+ dropout=dropout,
319
+ bias=attention_bias,
320
+ upcast_attention=upcast_attention,
321
+ ) # is self-attn if encoder_hidden_states is none
322
+ else:
323
+ self.norm2 = None
324
+ self.attn2 = None
325
+
326
+ # 3. Feed-forward
327
+ self.norm3 = nn.LayerNorm(dim, elementwise_affine=norm_elementwise_affine)
328
+ self.ff = FeedForward(dim, dropout=dropout, activation_fn=activation_fn, final_dropout=final_dropout)
329
+
330
+ # let chunk size default to None
331
+ self._chunk_size = None
332
+ self._chunk_dim = 0
333
+
334
+ def forward(
335
+ self,
336
+ hidden_states: torch.FloatTensor,
337
+ attention_mask: Optional[torch.FloatTensor] = None,
338
+ encoder_hidden_states: Optional[torch.FloatTensor] = None,
339
+ encoder_attention_mask: Optional[torch.FloatTensor] = None,
340
+ timestep: Optional[torch.LongTensor] = None,
341
+ cross_attention_kwargs: Dict[str, Any] = None,
342
+ class_labels: Optional[torch.LongTensor] = None,
343
+ block_idx: Optional[int] = None,
344
+ additional_residuals: Optional[Dict[str, torch.FloatTensor]] = None
345
+ ):
346
+ # Notice that normalization is always applied before the real computation in the following blocks.
347
+ # 1. Self-Attention
348
+ if self.use_ada_layer_norm:
349
+ norm_hidden_states = self.norm1(hidden_states, timestep)
350
+ elif self.use_ada_layer_norm_zero:
351
+ norm_hidden_states, gate_msa, shift_mlp, scale_mlp, gate_mlp = self.norm1(
352
+ hidden_states, timestep, class_labels, hidden_dtype=hidden_states.dtype
353
+ )
354
+ else:
355
+ norm_hidden_states = self.norm1(hidden_states)
356
+
357
+ cross_attention_kwargs = cross_attention_kwargs if cross_attention_kwargs is not None else {}
358
+
359
+ attn_output = self.attn1(
360
+ norm_hidden_states,
361
+ encoder_hidden_states=encoder_hidden_states if self.only_cross_attention else None,
362
+ attention_mask=attention_mask,
363
+ block_idx=block_idx,
364
+ additional_residuals=additional_residuals,
365
+ is_self_attn=True,
366
+ **cross_attention_kwargs,
367
+ )
368
+ if self.use_ada_layer_norm_zero:
369
+ attn_output = gate_msa.unsqueeze(1) * attn_output
370
+ hidden_states = attn_output + hidden_states
371
+
372
+ # 2. Cross-Attention
373
+ if self.attn2 is not None:
374
+ norm_hidden_states = (
375
+ self.norm2(hidden_states, timestep) if self.use_ada_layer_norm else self.norm2(hidden_states)
376
+ )
377
+
378
+ attn_output = self.attn2(
379
+ norm_hidden_states,
380
+ encoder_hidden_states=encoder_hidden_states,
381
+ attention_mask=encoder_attention_mask,
382
+ block_idx=block_idx,
383
+ additional_residuals=additional_residuals,
384
+ is_self_attn=False,
385
+ **cross_attention_kwargs,
386
+ )
387
+ hidden_states = attn_output + hidden_states
388
+
389
+ # 3. Feed-forward
390
+ norm_hidden_states = self.norm3(hidden_states)
391
+
392
+ if self.use_ada_layer_norm_zero:
393
+ norm_hidden_states = norm_hidden_states * (1 + scale_mlp[:, None]) + shift_mlp[:, None]
394
+
395
+ if self._chunk_size is not None:
396
+ # "feed_forward_chunk_size" can be used to save memory
397
+ if norm_hidden_states.shape[self._chunk_dim] % self._chunk_size != 0:
398
+ raise ValueError(
399
+ f"`hidden_states` dimension to be chunked: {norm_hidden_states.shape[self._chunk_dim]} has to be divisible by chunk size: {self._chunk_size}. Make sure to set an appropriate `chunk_size` when calling `unet.enable_forward_chunking`."
400
+ )
401
+
402
+ num_chunks = norm_hidden_states.shape[self._chunk_dim] // self._chunk_size
403
+ ff_output = torch.cat(
404
+ [self.ff(hid_slice) for hid_slice in norm_hidden_states.chunk(num_chunks, dim=self._chunk_dim)],
405
+ dim=self._chunk_dim,
406
+ )
407
+ else:
408
+ ff_output = self.ff(norm_hidden_states)
409
+
410
+ if self.use_ada_layer_norm_zero:
411
+ ff_output = gate_mlp.unsqueeze(1) * ff_output
412
+
413
+ hidden_states = ff_output + hidden_states
414
+
415
+ return hidden_states
416
+
417
+
418
+ class ResidualResnetBlock2D(ResnetBlock2D):
419
+ def forward(self, input_tensor, temb, block_idx: Optional[int] = None,
420
+ additional_residuals: Optional[Dict[str, torch.FloatTensor]] = None):
421
+ hidden_states = input_tensor
422
+
423
+ if self.time_embedding_norm == "ada_group" or self.time_embedding_norm == "spatial":
424
+ hidden_states = self.norm1(hidden_states, temb)
425
+ else:
426
+ hidden_states = self.norm1(hidden_states)
427
+
428
+ hidden_states = self.nonlinearity(hidden_states)
429
+
430
+ if self.upsample is not None:
431
+ # upsample_nearest_nhwc fails with large batch sizes. see https://github.com/huggingface/diffusers/issues/984
432
+ if hidden_states.shape[0] >= 64:
433
+ input_tensor = input_tensor.contiguous()
434
+ hidden_states = hidden_states.contiguous()
435
+ input_tensor = self.upsample(input_tensor)
436
+ hidden_states = self.upsample(hidden_states)
437
+ elif self.downsample is not None:
438
+ input_tensor = self.downsample(input_tensor)
439
+ hidden_states = self.downsample(hidden_states)
440
+
441
+ hidden_states = self.conv1(hidden_states)
442
+
443
+ if self.time_emb_proj is not None:
444
+ if not self.skip_time_act:
445
+ temb = self.nonlinearity(temb)
446
+ temb = self.time_emb_proj(temb)[:, :, None, None]
447
+
448
+ if temb is not None and self.time_embedding_norm == "default":
449
+ hidden_states = hidden_states + temb
450
+
451
+ if self.time_embedding_norm == "ada_group" or self.time_embedding_norm == "spatial":
452
+ hidden_states = self.norm2(hidden_states, temb)
453
+ else:
454
+ hidden_states = self.norm2(hidden_states)
455
+
456
+ if temb is not None and self.time_embedding_norm == "scale_shift":
457
+ scale, shift = torch.chunk(temb, 2, dim=1)
458
+ hidden_states = hidden_states * (1 + scale) + shift
459
+
460
+ hidden_states = self.nonlinearity(hidden_states)
461
+
462
+ hidden_states = self.dropout(hidden_states)
463
+ hidden_states = self.conv2(hidden_states)
464
+
465
+ if self.conv_shortcut is not None:
466
+ input_tensor = self.conv_shortcut(input_tensor)
467
+
468
+ if additional_residuals and f"block_{block_idx}_resnet_feat" in additional_residuals:
469
+ hidden_states = hidden_states + additional_residuals[f"block_{block_idx}_resnet_feat"]
470
+
471
+ output_tensor = (input_tensor + hidden_states) / self.output_scale_factor
472
+
473
+ return output_tensor
474
+
475
+
476
+ class ResidualTransformer2DModel(Transformer2DModel):
477
+ @register_to_config
478
+ def __init__(
479
+ self,
480
+ num_attention_heads: int = 16,
481
+ attention_head_dim: int = 88,
482
+ in_channels: Optional[int] = None,
483
+ out_channels: Optional[int] = None,
484
+ num_layers: int = 1,
485
+ dropout: float = 0.0,
486
+ norm_num_groups: int = 32,
487
+ cross_attention_dim: Optional[int] = None,
488
+ attention_bias: bool = False,
489
+ sample_size: Optional[int] = None,
490
+ num_vector_embeds: Optional[int] = None,
491
+ patch_size: Optional[int] = None,
492
+ activation_fn: str = "geglu",
493
+ num_embeds_ada_norm: Optional[int] = None,
494
+ use_linear_projection: bool = False,
495
+ only_cross_attention: bool = False,
496
+ upcast_attention: bool = False,
497
+ norm_type: str = "layer_norm",
498
+ norm_elementwise_affine: bool = True,
499
+ ):
500
+ super(Transformer2DModel, self).__init__()
501
+ self.use_linear_projection = use_linear_projection
502
+ self.num_attention_heads = num_attention_heads
503
+ self.attention_head_dim = attention_head_dim
504
+ inner_dim = num_attention_heads * attention_head_dim
505
+
506
+ # 1. Transformer2DModel can process both standard continuous images of shape `(batch_size, num_channels, width, height)` as well as quantized image embeddings of shape `(batch_size, num_image_vectors)`
507
+ # Define whether input is continuous or discrete depending on configuration
508
+ self.is_input_continuous = (in_channels is not None) and (patch_size is None)
509
+ self.is_input_vectorized = num_vector_embeds is not None
510
+ self.is_input_patches = in_channels is not None and patch_size is not None
511
+
512
+ if norm_type == "layer_norm" and num_embeds_ada_norm is not None:
513
+ deprecation_message = (
514
+ f"The configuration file of this model: {self.__class__} is outdated. `norm_type` is either not set or"
515
+ " incorrectly set to `'layer_norm'`.Make sure to set `norm_type` to `'ada_norm'` in the config."
516
+ " Please make sure to update the config accordingly as leaving `norm_type` might led to incorrect"
517
+ " results in future versions. If you have downloaded this checkpoint from the Hugging Face Hub, it"
518
+ " would be very nice if you could open a Pull request for the `transformer/config.json` file"
519
+ )
520
+ deprecate("norm_type!=num_embeds_ada_norm", "1.0.0", deprecation_message, standard_warn=False)
521
+ norm_type = "ada_norm"
522
+
523
+ if self.is_input_continuous and self.is_input_vectorized:
524
+ raise ValueError(
525
+ f"Cannot define both `in_channels`: {in_channels} and `num_vector_embeds`: {num_vector_embeds}. Make"
526
+ " sure that either `in_channels` or `num_vector_embeds` is None."
527
+ )
528
+ elif self.is_input_vectorized and self.is_input_patches:
529
+ raise ValueError(
530
+ f"Cannot define both `num_vector_embeds`: {num_vector_embeds} and `patch_size`: {patch_size}. Make"
531
+ " sure that either `num_vector_embeds` or `num_patches` is None."
532
+ )
533
+ elif not self.is_input_continuous and not self.is_input_vectorized and not self.is_input_patches:
534
+ raise ValueError(
535
+ f"Has to define `in_channels`: {in_channels}, `num_vector_embeds`: {num_vector_embeds}, or patch_size:"
536
+ f" {patch_size}. Make sure that `in_channels`, `num_vector_embeds` or `num_patches` is not None."
537
+ )
538
+
539
+ # 2. Define input layers
540
+ if self.is_input_continuous:
541
+ self.in_channels = in_channels
542
+
543
+ self.norm = torch.nn.GroupNorm(num_groups=norm_num_groups, num_channels=in_channels, eps=1e-6, affine=True)
544
+ if use_linear_projection:
545
+ self.proj_in = LoRACompatibleLinear(in_channels, inner_dim)
546
+ else:
547
+ self.proj_in = LoRACompatibleConv(in_channels, inner_dim, kernel_size=1, stride=1, padding=0)
548
+ elif self.is_input_vectorized:
549
+ assert sample_size is not None, "Transformer2DModel over discrete input must provide sample_size"
550
+ assert num_vector_embeds is not None, "Transformer2DModel over discrete input must provide num_embed"
551
+
552
+ self.height = sample_size
553
+ self.width = sample_size
554
+ self.num_vector_embeds = num_vector_embeds
555
+ self.num_latent_pixels = self.height * self.width
556
+
557
+ self.latent_image_embedding = ImagePositionalEmbeddings(
558
+ num_embed=num_vector_embeds, embed_dim=inner_dim, height=self.height, width=self.width
559
+ )
560
+ elif self.is_input_patches:
561
+ assert sample_size is not None, "Transformer2DModel over patched input must provide sample_size"
562
+
563
+ self.height = sample_size
564
+ self.width = sample_size
565
+
566
+ self.patch_size = patch_size
567
+ self.pos_embed = PatchEmbed(
568
+ height=sample_size,
569
+ width=sample_size,
570
+ patch_size=patch_size,
571
+ in_channels=in_channels,
572
+ embed_dim=inner_dim,
573
+ )
574
+
575
+ # 3. Define transformers blocks
576
+ self.transformer_blocks = nn.ModuleList(
577
+ [
578
+ ResidualTransformerBlock(
579
+ inner_dim,
580
+ num_attention_heads,
581
+ attention_head_dim,
582
+ dropout=dropout,
583
+ cross_attention_dim=cross_attention_dim,
584
+ activation_fn=activation_fn,
585
+ num_embeds_ada_norm=num_embeds_ada_norm,
586
+ attention_bias=attention_bias,
587
+ only_cross_attention=only_cross_attention,
588
+ upcast_attention=upcast_attention,
589
+ norm_type=norm_type,
590
+ norm_elementwise_affine=norm_elementwise_affine,
591
+ )
592
+ for d in range(num_layers)
593
+ ]
594
+ )
595
+
596
+ # 4. Define output layers
597
+ self.out_channels = in_channels if out_channels is None else out_channels
598
+ if self.is_input_continuous:
599
+ # TODO: should use out_channels for continuous projections
600
+ if use_linear_projection:
601
+ self.proj_out = LoRACompatibleLinear(inner_dim, in_channels)
602
+ else:
603
+ self.proj_out = LoRACompatibleConv(inner_dim, in_channels, kernel_size=1, stride=1, padding=0)
604
+ elif self.is_input_vectorized:
605
+ self.norm_out = nn.LayerNorm(inner_dim)
606
+ self.out = nn.Linear(inner_dim, self.num_vector_embeds - 1)
607
+ elif self.is_input_patches:
608
+ self.norm_out = nn.LayerNorm(inner_dim, elementwise_affine=False, eps=1e-6)
609
+ self.proj_out_1 = nn.Linear(inner_dim, 2 * inner_dim)
610
+ self.proj_out_2 = nn.Linear(inner_dim, patch_size * patch_size * self.out_channels)
611
+
612
+ def forward(
613
+ self,
614
+ hidden_states: torch.Tensor,
615
+ encoder_hidden_states: Optional[torch.Tensor] = None,
616
+ timestep: Optional[torch.LongTensor] = None,
617
+ class_labels: Optional[torch.LongTensor] = None,
618
+ cross_attention_kwargs: Dict[str, Any] = None,
619
+ attention_mask: Optional[torch.Tensor] = None,
620
+ encoder_attention_mask: Optional[torch.Tensor] = None,
621
+ block_idx: Optional[int] = None,
622
+ additional_residuals: Optional[Dict[str, torch.FloatTensor]] = None,
623
+ return_dict: bool = True,
624
+ ):
625
+ """
626
+ The [`Transformer2DModel`] forward method.
627
+
628
+ Args:
629
+ hidden_states (`torch.LongTensor` of shape `(batch size, num latent pixels)` if discrete, `torch.FloatTensor` of shape `(batch size, channel, height, width)` if continuous):
630
+ Input `hidden_states`.
631
+ encoder_hidden_states ( `torch.FloatTensor` of shape `(batch size, sequence len, embed dims)`, *optional*):
632
+ Conditional embeddings for cross attention layer. If not given, cross-attention defaults to
633
+ self-attention.
634
+ timestep ( `torch.LongTensor`, *optional*):
635
+ Used to indicate denoising step. Optional timestep to be applied as an embedding in `AdaLayerNorm`.
636
+ class_labels ( `torch.LongTensor` of shape `(batch size, num classes)`, *optional*):
637
+ Used to indicate class labels conditioning. Optional class labels to be applied as an embedding in
638
+ `AdaLayerZeroNorm`.
639
+ encoder_attention_mask ( `torch.Tensor`, *optional*):
640
+ Cross-attention mask applied to `encoder_hidden_states`. Two formats supported:
641
+
642
+ * Mask `(batch, sequence_length)` True = keep, False = discard.
643
+ * Bias `(batch, 1, sequence_length)` 0 = keep, -10000 = discard.
644
+
645
+ If `ndim == 2`: will be interpreted as a mask, then converted into a bias consistent with the format
646
+ above. This bias will be added to the cross-attention scores.
647
+ return_dict (`bool`, *optional*, defaults to `True`):
648
+ Whether or not to return a [`~models.unet_2d_condition.UNet2DConditionOutput`] instead of a plain
649
+ tuple.
650
+
651
+ Returns:
652
+ If `return_dict` is True, an [`~models.transformer_2d.Transformer2DModelOutput`] is returned, otherwise a
653
+ `tuple` where the first element is the sample tensor.
654
+ """
655
+ # ensure attention_mask is a bias, and give it a singleton query_tokens dimension.
656
+ # we may have done this conversion already, e.g. if we came here via UNet2DConditionModel#forward.
657
+ # we can tell by counting dims; if ndim == 2: it's a mask rather than a bias.
658
+ # expects mask of shape:
659
+ # [batch, key_tokens]
660
+ # adds singleton query_tokens dimension:
661
+ # [batch, 1, key_tokens]
662
+ # this helps to broadcast it as a bias over attention scores, which will be in one of the following shapes:
663
+ # [batch, heads, query_tokens, key_tokens] (e.g. torch sdp attn)
664
+ # [batch * heads, query_tokens, key_tokens] (e.g. xformers or classic attn)
665
+ if attention_mask is not None and attention_mask.ndim == 2:
666
+ # assume that mask is expressed as:
667
+ # (1 = keep, 0 = discard)
668
+ # convert mask into a bias that can be added to attention scores:
669
+ # (keep = +0, discard = -10000.0)
670
+ attention_mask = (1 - attention_mask.to(hidden_states.dtype)) * -10000.0
671
+ attention_mask = attention_mask.unsqueeze(1)
672
+
673
+ # convert encoder_attention_mask to a bias the same way we do for attention_mask
674
+ if encoder_attention_mask is not None and encoder_attention_mask.ndim == 2:
675
+ encoder_attention_mask = (1 - encoder_attention_mask.to(hidden_states.dtype)) * -10000.0
676
+ encoder_attention_mask = encoder_attention_mask.unsqueeze(1)
677
+
678
+ # 1. Input
679
+ if self.is_input_continuous:
680
+ batch, _, height, width = hidden_states.shape
681
+ residual = hidden_states
682
+
683
+ hidden_states = self.norm(hidden_states)
684
+ if not self.use_linear_projection:
685
+ hidden_states = self.proj_in(hidden_states)
686
+ inner_dim = hidden_states.shape[1]
687
+ hidden_states = hidden_states.permute(0, 2, 3, 1).reshape(batch, height * width, inner_dim)
688
+ else:
689
+ inner_dim = hidden_states.shape[1]
690
+ hidden_states = hidden_states.permute(0, 2, 3, 1).reshape(batch, height * width, inner_dim)
691
+ hidden_states = self.proj_in(hidden_states)
692
+ elif self.is_input_vectorized:
693
+ hidden_states = self.latent_image_embedding(hidden_states)
694
+ elif self.is_input_patches:
695
+ hidden_states = self.pos_embed(hidden_states)
696
+
697
+ # 2. Blocks
698
+ for block in self.transformer_blocks:
699
+ hidden_states = block(
700
+ hidden_states,
701
+ attention_mask=attention_mask,
702
+ encoder_hidden_states=encoder_hidden_states,
703
+ encoder_attention_mask=encoder_attention_mask,
704
+ timestep=timestep,
705
+ cross_attention_kwargs=cross_attention_kwargs,
706
+ class_labels=class_labels,
707
+ block_idx=block_idx,
708
+ additional_residuals=additional_residuals
709
+ )
710
+
711
+ # 3. Output
712
+ if self.is_input_continuous:
713
+ if not self.use_linear_projection:
714
+ hidden_states = hidden_states.reshape(batch, height, width, inner_dim).permute(0, 3, 1, 2).contiguous()
715
+ hidden_states = self.proj_out(hidden_states)
716
+ else:
717
+ hidden_states = self.proj_out(hidden_states)
718
+ hidden_states = hidden_states.reshape(batch, height, width, inner_dim).permute(0, 3, 1, 2).contiguous()
719
+
720
+ output = hidden_states + residual
721
+ elif self.is_input_vectorized:
722
+ hidden_states = self.norm_out(hidden_states)
723
+ logits = self.out(hidden_states)
724
+ # (batch, self.num_vector_embeds - 1, self.num_latent_pixels)
725
+ logits = logits.permute(0, 2, 1)
726
+
727
+ # log(p(x_0))
728
+ output = F.log_softmax(logits.double(), dim=1).float()
729
+ elif self.is_input_patches:
730
+ # TODO: cleanup!
731
+ conditioning = self.transformer_blocks[0].norm1.emb(
732
+ timestep, class_labels, hidden_dtype=hidden_states.dtype
733
+ )
734
+ shift, scale = self.proj_out_1(F.silu(conditioning)).chunk(2, dim=1)
735
+ hidden_states = self.norm_out(hidden_states) * (1 + scale[:, None]) + shift[:, None]
736
+ hidden_states = self.proj_out_2(hidden_states)
737
+
738
+ # unpatchify
739
+ height = width = int(hidden_states.shape[1] ** 0.5)
740
+ hidden_states = hidden_states.reshape(
741
+ shape=(-1, height, width, self.patch_size, self.patch_size, self.out_channels)
742
+ )
743
+ hidden_states = torch.einsum("nhwpqc->nchpwq", hidden_states)
744
+ output = hidden_states.reshape(
745
+ shape=(-1, self.out_channels, height * self.patch_size, width * self.patch_size)
746
+ )
747
+
748
+ if not return_dict:
749
+ return (output,)
750
+
751
+ return Transformer2DModelOutput(sample=output)
752
+
753
+
754
+ class ResidualUpBlock2D(UpBlock2D):
755
+ def __init__(
756
+ self,
757
+ in_channels: int,
758
+ prev_output_channel: int,
759
+ out_channels: int,
760
+ temb_channels: int,
761
+ dropout: float = 0.0,
762
+ num_layers: int = 1,
763
+ resnet_eps: float = 1e-6,
764
+ resnet_time_scale_shift: str = "default",
765
+ resnet_act_fn: str = "swish",
766
+ resnet_groups: int = 32,
767
+ resnet_pre_norm: bool = True,
768
+ output_scale_factor=1.0,
769
+ add_upsample=True,
770
+ ):
771
+ super(UpBlock2D, self).__init__()
772
+ resnets = []
773
+
774
+ for i in range(num_layers):
775
+ res_skip_channels = in_channels if (i == num_layers - 1) else out_channels
776
+ resnet_in_channels = prev_output_channel if i == 0 else out_channels
777
+
778
+ resnets.append(
779
+ ResidualResnetBlock2D(
780
+ in_channels=resnet_in_channels + res_skip_channels,
781
+ out_channels=out_channels,
782
+ temb_channels=temb_channels,
783
+ eps=resnet_eps,
784
+ groups=resnet_groups,
785
+ dropout=dropout,
786
+ time_embedding_norm=resnet_time_scale_shift,
787
+ non_linearity=resnet_act_fn,
788
+ output_scale_factor=output_scale_factor,
789
+ pre_norm=resnet_pre_norm,
790
+ )
791
+ )
792
+
793
+ self.resnets = nn.ModuleList(resnets)
794
+
795
+ if add_upsample:
796
+ self.upsamplers = nn.ModuleList([Upsample2D(out_channels, use_conv=True, out_channels=out_channels)])
797
+ else:
798
+ self.upsamplers = None
799
+
800
+ self.gradient_checkpointing = False
801
+
802
+ def forward(self, hidden_states, res_hidden_states_tuple, temb=None, upsample_size=None,
803
+ additional_residuals: Optional[Dict[str, torch.FloatTensor]] = None):
804
+ for j, resnet in enumerate(self.resnets):
805
+ # pop res hidden states
806
+ res_hidden_states = res_hidden_states_tuple[-1]
807
+ res_hidden_states_tuple = res_hidden_states_tuple[:-1]
808
+ hidden_states = torch.cat([hidden_states, res_hidden_states], dim=1)
809
+
810
+ if self.training and self.gradient_checkpointing:
811
+
812
+ def create_custom_forward(module):
813
+ def custom_forward(*inputs):
814
+ return module(*inputs)
815
+
816
+ return custom_forward
817
+
818
+ if is_torch_version(">=", "1.11.0"):
819
+ hidden_states = torch.utils.checkpoint.checkpoint(
820
+ create_custom_forward(resnet), hidden_states, temb, use_reentrant=False
821
+ )
822
+ else:
823
+ hidden_states = torch.utils.checkpoint.checkpoint(
824
+ create_custom_forward(resnet), hidden_states, temb
825
+ )
826
+ else:
827
+ hidden_states = resnet(hidden_states, temb, block_idx=j, additional_residuals=additional_residuals)
828
+
829
+ if self.upsamplers is not None:
830
+ for upsampler in self.upsamplers:
831
+ hidden_states = upsampler(hidden_states, upsample_size)
832
+
833
+ return hidden_states
834
+
835
+
836
+ class ResidualCrossAttnUpBlock2D(CrossAttnUpBlock2D):
837
+ def __init__(
838
+ self,
839
+ in_channels: int,
840
+ out_channels: int,
841
+ prev_output_channel: int,
842
+ temb_channels: int,
843
+ dropout: float = 0.0,
844
+ num_layers: int = 1,
845
+ transformer_layers_per_block: int = 1,
846
+ resnet_eps: float = 1e-6,
847
+ resnet_time_scale_shift: str = "default",
848
+ resnet_act_fn: str = "swish",
849
+ resnet_groups: int = 32,
850
+ resnet_pre_norm: bool = True,
851
+ num_attention_heads=1,
852
+ cross_attention_dim=1280,
853
+ output_scale_factor=1.0,
854
+ add_upsample=True,
855
+ dual_cross_attention=False,
856
+ use_linear_projection=False,
857
+ only_cross_attention=False,
858
+ upcast_attention=False,
859
+ ):
860
+ super(CrossAttnUpBlock2D, self).__init__()
861
+ resnets = []
862
+ attentions = []
863
+
864
+ self.has_cross_attention = True
865
+ self.num_attention_heads = num_attention_heads
866
+
867
+ for i in range(num_layers):
868
+ res_skip_channels = in_channels if (i == num_layers - 1) else out_channels
869
+ resnet_in_channels = prev_output_channel if i == 0 else out_channels
870
+
871
+ resnets.append(
872
+ ResidualResnetBlock2D(
873
+ in_channels=resnet_in_channels + res_skip_channels,
874
+ out_channels=out_channels,
875
+ temb_channels=temb_channels,
876
+ eps=resnet_eps,
877
+ groups=resnet_groups,
878
+ dropout=dropout,
879
+ time_embedding_norm=resnet_time_scale_shift,
880
+ non_linearity=resnet_act_fn,
881
+ output_scale_factor=output_scale_factor,
882
+ pre_norm=resnet_pre_norm,
883
+ )
884
+ )
885
+ if not dual_cross_attention:
886
+ attentions.append(
887
+ ResidualTransformer2DModel(
888
+ num_attention_heads,
889
+ out_channels // num_attention_heads,
890
+ in_channels=out_channels,
891
+ num_layers=transformer_layers_per_block,
892
+ cross_attention_dim=cross_attention_dim,
893
+ norm_num_groups=resnet_groups,
894
+ use_linear_projection=use_linear_projection,
895
+ only_cross_attention=only_cross_attention,
896
+ upcast_attention=upcast_attention,
897
+ )
898
+ )
899
+ else:
900
+ attentions.append(
901
+ DualTransformer2DModel(
902
+ num_attention_heads,
903
+ out_channels // num_attention_heads,
904
+ in_channels=out_channels,
905
+ num_layers=1,
906
+ cross_attention_dim=cross_attention_dim,
907
+ norm_num_groups=resnet_groups,
908
+ )
909
+ )
910
+ self.attentions = nn.ModuleList(attentions)
911
+ self.resnets = nn.ModuleList(resnets)
912
+
913
+ if add_upsample:
914
+ self.upsamplers = nn.ModuleList([Upsample2D(out_channels, use_conv=True, out_channels=out_channels)])
915
+ else:
916
+ self.upsamplers = None
917
+
918
+ self.gradient_checkpointing = False
919
+
920
+ def forward(
921
+ self,
922
+ hidden_states: torch.FloatTensor,
923
+ res_hidden_states_tuple: Tuple[torch.FloatTensor, ...],
924
+ temb: Optional[torch.FloatTensor] = None,
925
+ encoder_hidden_states: Optional[torch.FloatTensor] = None,
926
+ cross_attention_kwargs: Optional[Dict[str, Any]] = None,
927
+ upsample_size: Optional[int] = None,
928
+ attention_mask: Optional[torch.FloatTensor] = None,
929
+ encoder_attention_mask: Optional[torch.FloatTensor] = None,
930
+ block_idx: Optional[int] = None,
931
+ additional_residuals: Optional[Dict[str, torch.FloatTensor]] = None
932
+ ):
933
+ for j, (resnet, attn) in enumerate(zip(self.resnets, self.attentions)):
934
+ # pop res hidden states
935
+ res_hidden_states = res_hidden_states_tuple[-1]
936
+ res_hidden_states_tuple = res_hidden_states_tuple[:-1]
937
+ hidden_states = torch.cat([hidden_states, res_hidden_states], dim=1)
938
+
939
+ if self.training and self.gradient_checkpointing:
940
+
941
+ def create_custom_forward(module, return_dict=None):
942
+ def custom_forward(*inputs):
943
+ if return_dict is not None:
944
+ return module(*inputs, return_dict=return_dict)
945
+ else:
946
+ return module(*inputs)
947
+
948
+ return custom_forward
949
+
950
+ ckpt_kwargs: Dict[str, Any] = {"use_reentrant": False} if is_torch_version(">=", "1.11.0") else {}
951
+ hidden_states = torch.utils.checkpoint.checkpoint(
952
+ create_custom_forward(resnet),
953
+ hidden_states,
954
+ temb,
955
+ block_idx * len(self.resnets) + j,
956
+ additional_residuals,
957
+ **ckpt_kwargs,
958
+ )
959
+ hidden_states = torch.utils.checkpoint.checkpoint(
960
+ create_custom_forward(attn, return_dict=False),
961
+ hidden_states,
962
+ encoder_hidden_states,
963
+ None, # timestep
964
+ None, # class_labels
965
+ cross_attention_kwargs,
966
+ attention_mask,
967
+ encoder_attention_mask,
968
+ block_idx * len(self.resnets) + j,
969
+ additional_residuals,
970
+ **ckpt_kwargs,
971
+ )[0]
972
+ else:
973
+ hidden_states = resnet(hidden_states, temb,
974
+ block_idx * len(self.resnets) + j,
975
+ additional_residuals)
976
+ hidden_states = attn(
977
+ hidden_states,
978
+ encoder_hidden_states=encoder_hidden_states,
979
+ cross_attention_kwargs=cross_attention_kwargs,
980
+ attention_mask=attention_mask,
981
+ encoder_attention_mask=encoder_attention_mask,
982
+ return_dict=False,
983
+ block_idx=block_idx * len(self.resnets) + j,
984
+ additional_residuals=additional_residuals
985
+ )[0]
986
+
987
+ if self.upsamplers is not None:
988
+ for upsampler in self.upsamplers:
989
+ hidden_states = upsampler(hidden_states, upsample_size)
990
+
991
+ return hidden_states
992
+
993
+
994
+ def get_residual_up_block(
995
+ up_block_type,
996
+ num_layers,
997
+ in_channels,
998
+ out_channels,
999
+ prev_output_channel,
1000
+ temb_channels,
1001
+ add_upsample,
1002
+ resnet_eps,
1003
+ resnet_act_fn,
1004
+ transformer_layers_per_block=1,
1005
+ num_attention_heads=None,
1006
+ resnet_groups=None,
1007
+ cross_attention_dim=None,
1008
+ dual_cross_attention=False,
1009
+ use_linear_projection=False,
1010
+ only_cross_attention=False,
1011
+ upcast_attention=False,
1012
+ resnet_time_scale_shift="default",
1013
+ resnet_skip_time_act=False,
1014
+ resnet_out_scale_factor=1.0,
1015
+ cross_attention_norm=None,
1016
+ attention_head_dim=None,
1017
+ upsample_type=None,
1018
+ ):
1019
+ # If attn head dim is not defined, we default it to the number of heads
1020
+ if attention_head_dim is None:
1021
+ logger.warn(
1022
+ f"It is recommended to provide `attention_head_dim` when calling `get_up_block`. Defaulting `attention_head_dim` to {num_attention_heads}."
1023
+ )
1024
+ attention_head_dim = num_attention_heads
1025
+
1026
+ up_block_type = up_block_type[7:] if up_block_type.startswith("UNetRes") else up_block_type
1027
+ if up_block_type == "UpBlock2D":
1028
+ return ResidualUpBlock2D(
1029
+ num_layers=num_layers,
1030
+ in_channels=in_channels,
1031
+ out_channels=out_channels,
1032
+ prev_output_channel=prev_output_channel,
1033
+ temb_channels=temb_channels,
1034
+ add_upsample=add_upsample,
1035
+ resnet_eps=resnet_eps,
1036
+ resnet_act_fn=resnet_act_fn,
1037
+ resnet_groups=resnet_groups,
1038
+ resnet_time_scale_shift=resnet_time_scale_shift,
1039
+ )
1040
+ elif up_block_type == "ResnetUpsampleBlock2D":
1041
+ return ResnetUpsampleBlock2D(
1042
+ num_layers=num_layers,
1043
+ in_channels=in_channels,
1044
+ out_channels=out_channels,
1045
+ prev_output_channel=prev_output_channel,
1046
+ temb_channels=temb_channels,
1047
+ add_upsample=add_upsample,
1048
+ resnet_eps=resnet_eps,
1049
+ resnet_act_fn=resnet_act_fn,
1050
+ resnet_groups=resnet_groups,
1051
+ resnet_time_scale_shift=resnet_time_scale_shift,
1052
+ skip_time_act=resnet_skip_time_act,
1053
+ output_scale_factor=resnet_out_scale_factor,
1054
+ )
1055
+ elif up_block_type == "CrossAttnUpBlock2D":
1056
+ if cross_attention_dim is None:
1057
+ raise ValueError("cross_attention_dim must be specified for CrossAttnUpBlock2D")
1058
+ return ResidualCrossAttnUpBlock2D(
1059
+ num_layers=num_layers,
1060
+ transformer_layers_per_block=transformer_layers_per_block,
1061
+ in_channels=in_channels,
1062
+ out_channels=out_channels,
1063
+ prev_output_channel=prev_output_channel,
1064
+ temb_channels=temb_channels,
1065
+ add_upsample=add_upsample,
1066
+ resnet_eps=resnet_eps,
1067
+ resnet_act_fn=resnet_act_fn,
1068
+ resnet_groups=resnet_groups,
1069
+ cross_attention_dim=cross_attention_dim,
1070
+ num_attention_heads=num_attention_heads,
1071
+ dual_cross_attention=dual_cross_attention,
1072
+ use_linear_projection=use_linear_projection,
1073
+ only_cross_attention=only_cross_attention,
1074
+ upcast_attention=upcast_attention,
1075
+ resnet_time_scale_shift=resnet_time_scale_shift,
1076
+ )
1077
+ elif up_block_type == "SimpleCrossAttnUpBlock2D":
1078
+ if cross_attention_dim is None:
1079
+ raise ValueError("cross_attention_dim must be specified for SimpleCrossAttnUpBlock2D")
1080
+ return SimpleCrossAttnUpBlock2D(
1081
+ num_layers=num_layers,
1082
+ in_channels=in_channels,
1083
+ out_channels=out_channels,
1084
+ prev_output_channel=prev_output_channel,
1085
+ temb_channels=temb_channels,
1086
+ add_upsample=add_upsample,
1087
+ resnet_eps=resnet_eps,
1088
+ resnet_act_fn=resnet_act_fn,
1089
+ resnet_groups=resnet_groups,
1090
+ cross_attention_dim=cross_attention_dim,
1091
+ attention_head_dim=attention_head_dim,
1092
+ resnet_time_scale_shift=resnet_time_scale_shift,
1093
+ skip_time_act=resnet_skip_time_act,
1094
+ output_scale_factor=resnet_out_scale_factor,
1095
+ only_cross_attention=only_cross_attention,
1096
+ cross_attention_norm=cross_attention_norm,
1097
+ )
1098
+ elif up_block_type == "AttnUpBlock2D":
1099
+ if add_upsample is False:
1100
+ upsample_type = None
1101
+ else:
1102
+ upsample_type = upsample_type or "conv" # default to 'conv'
1103
+
1104
+ return AttnUpBlock2D(
1105
+ num_layers=num_layers,
1106
+ in_channels=in_channels,
1107
+ out_channels=out_channels,
1108
+ prev_output_channel=prev_output_channel,
1109
+ temb_channels=temb_channels,
1110
+ resnet_eps=resnet_eps,
1111
+ resnet_act_fn=resnet_act_fn,
1112
+ resnet_groups=resnet_groups,
1113
+ attention_head_dim=attention_head_dim,
1114
+ resnet_time_scale_shift=resnet_time_scale_shift,
1115
+ upsample_type=upsample_type,
1116
+ )
1117
+ elif up_block_type == "SkipUpBlock2D":
1118
+ return SkipUpBlock2D(
1119
+ num_layers=num_layers,
1120
+ in_channels=in_channels,
1121
+ out_channels=out_channels,
1122
+ prev_output_channel=prev_output_channel,
1123
+ temb_channels=temb_channels,
1124
+ add_upsample=add_upsample,
1125
+ resnet_eps=resnet_eps,
1126
+ resnet_act_fn=resnet_act_fn,
1127
+ resnet_time_scale_shift=resnet_time_scale_shift,
1128
+ )
1129
+ elif up_block_type == "AttnSkipUpBlock2D":
1130
+ return AttnSkipUpBlock2D(
1131
+ num_layers=num_layers,
1132
+ in_channels=in_channels,
1133
+ out_channels=out_channels,
1134
+ prev_output_channel=prev_output_channel,
1135
+ temb_channels=temb_channels,
1136
+ add_upsample=add_upsample,
1137
+ resnet_eps=resnet_eps,
1138
+ resnet_act_fn=resnet_act_fn,
1139
+ attention_head_dim=attention_head_dim,
1140
+ resnet_time_scale_shift=resnet_time_scale_shift,
1141
+ )
1142
+ elif up_block_type == "UpDecoderBlock2D":
1143
+ return UpDecoderBlock2D(
1144
+ num_layers=num_layers,
1145
+ in_channels=in_channels,
1146
+ out_channels=out_channels,
1147
+ add_upsample=add_upsample,
1148
+ resnet_eps=resnet_eps,
1149
+ resnet_act_fn=resnet_act_fn,
1150
+ resnet_groups=resnet_groups,
1151
+ resnet_time_scale_shift=resnet_time_scale_shift,
1152
+ temb_channels=temb_channels,
1153
+ )
1154
+ elif up_block_type == "AttnUpDecoderBlock2D":
1155
+ return AttnUpDecoderBlock2D(
1156
+ num_layers=num_layers,
1157
+ in_channels=in_channels,
1158
+ out_channels=out_channels,
1159
+ add_upsample=add_upsample,
1160
+ resnet_eps=resnet_eps,
1161
+ resnet_act_fn=resnet_act_fn,
1162
+ resnet_groups=resnet_groups,
1163
+ attention_head_dim=attention_head_dim,
1164
+ resnet_time_scale_shift=resnet_time_scale_shift,
1165
+ temb_channels=temb_channels,
1166
+ )
1167
+ elif up_block_type == "KUpBlock2D":
1168
+ return KUpBlock2D(
1169
+ num_layers=num_layers,
1170
+ in_channels=in_channels,
1171
+ out_channels=out_channels,
1172
+ temb_channels=temb_channels,
1173
+ add_upsample=add_upsample,
1174
+ resnet_eps=resnet_eps,
1175
+ resnet_act_fn=resnet_act_fn,
1176
+ )
1177
+ elif up_block_type == "KCrossAttnUpBlock2D":
1178
+ return KCrossAttnUpBlock2D(
1179
+ num_layers=num_layers,
1180
+ in_channels=in_channels,
1181
+ out_channels=out_channels,
1182
+ temb_channels=temb_channels,
1183
+ add_upsample=add_upsample,
1184
+ resnet_eps=resnet_eps,
1185
+ resnet_act_fn=resnet_act_fn,
1186
+ cross_attention_dim=cross_attention_dim,
1187
+ attention_head_dim=attention_head_dim,
1188
+ )
1189
+
1190
+ raise ValueError(f"{up_block_type} does not exist.")
1191
+
1192
+
1193
+ class ResidualUNet2DConditionModel(UNet2DConditionModel):
1194
+ @register_to_config
1195
+ def __init__(
1196
+ self,
1197
+ sample_size: Optional[int] = None,
1198
+ in_channels: int = 4,
1199
+ out_channels: int = 4,
1200
+ center_input_sample: bool = False,
1201
+ flip_sin_to_cos: bool = True,
1202
+ freq_shift: int = 0,
1203
+ down_block_types: Tuple[str] = (
1204
+ "CrossAttnDownBlock2D",
1205
+ "CrossAttnDownBlock2D",
1206
+ "CrossAttnDownBlock2D",
1207
+ "DownBlock2D",
1208
+ ),
1209
+ mid_block_type: Optional[str] = "UNetMidBlock2DCrossAttn",
1210
+ up_block_types: Tuple[str] = ("UpBlock2D", "CrossAttnUpBlock2D", "CrossAttnUpBlock2D", "CrossAttnUpBlock2D"),
1211
+ only_cross_attention: Union[bool, Tuple[bool]] = False,
1212
+ block_out_channels: Tuple[int] = (320, 640, 1280, 1280),
1213
+ layers_per_block: Union[int, Tuple[int]] = 2,
1214
+ downsample_padding: int = 1,
1215
+ mid_block_scale_factor: float = 1,
1216
+ act_fn: str = "silu",
1217
+ norm_num_groups: Optional[int] = 32,
1218
+ norm_eps: float = 1e-5,
1219
+ cross_attention_dim: Union[int, Tuple[int]] = 1280,
1220
+ transformer_layers_per_block: Union[int, Tuple[int]] = 1,
1221
+ encoder_hid_dim: Optional[int] = None,
1222
+ encoder_hid_dim_type: Optional[str] = None,
1223
+ attention_head_dim: Union[int, Tuple[int]] = 8,
1224
+ num_attention_heads: Optional[Union[int, Tuple[int]]] = None,
1225
+ dual_cross_attention: bool = False,
1226
+ use_linear_projection: bool = False,
1227
+ class_embed_type: Optional[str] = None,
1228
+ addition_embed_type: Optional[str] = None,
1229
+ addition_time_embed_dim: Optional[int] = None,
1230
+ num_class_embeds: Optional[int] = None,
1231
+ upcast_attention: bool = False,
1232
+ resnet_time_scale_shift: str = "default",
1233
+ resnet_skip_time_act: bool = False,
1234
+ resnet_out_scale_factor: int = 1.0,
1235
+ time_embedding_type: str = "positional",
1236
+ time_embedding_dim: Optional[int] = None,
1237
+ time_embedding_act_fn: Optional[str] = None,
1238
+ timestep_post_act: Optional[str] = None,
1239
+ time_cond_proj_dim: Optional[int] = None,
1240
+ conv_in_kernel: int = 3,
1241
+ conv_out_kernel: int = 3,
1242
+ projection_class_embeddings_input_dim: Optional[int] = None,
1243
+ class_embeddings_concat: bool = False,
1244
+ mid_block_only_cross_attention: Optional[bool] = None,
1245
+ cross_attention_norm: Optional[str] = None,
1246
+ addition_embed_type_num_heads=64,
1247
+ ):
1248
+ super(UNet2DConditionModel, self).__init__()
1249
+
1250
+ self.sample_size = sample_size
1251
+
1252
+ if num_attention_heads is not None:
1253
+ raise ValueError(
1254
+ "At the moment it is not possible to define the number of attention heads via `num_attention_heads` because of a naming issue as described in https://github.com/huggingface/diffusers/issues/2011#issuecomment-1547958131. Passing `num_attention_heads` will only be supported in diffusers v0.19."
1255
+ )
1256
+
1257
+ # If `num_attention_heads` is not defined (which is the case for most models)
1258
+ # it will default to `attention_head_dim`. This looks weird upon first reading it and it is.
1259
+ # The reason for this behavior is to correct for incorrectly named variables that were introduced
1260
+ # when this library was created. The incorrect naming was only discovered much later in https://github.com/huggingface/diffusers/issues/2011#issuecomment-1547958131
1261
+ # Changing `attention_head_dim` to `num_attention_heads` for 40,000+ configurations is too backwards breaking
1262
+ # which is why we correct for the naming here.
1263
+ num_attention_heads = num_attention_heads or attention_head_dim
1264
+
1265
+ # Check inputs
1266
+ if len(down_block_types) != len(up_block_types):
1267
+ raise ValueError(
1268
+ f"Must provide the same number of `down_block_types` as `up_block_types`. `down_block_types`: {down_block_types}. `up_block_types`: {up_block_types}."
1269
+ )
1270
+
1271
+ if len(block_out_channels) != len(down_block_types):
1272
+ raise ValueError(
1273
+ f"Must provide the same number of `block_out_channels` as `down_block_types`. `block_out_channels`: {block_out_channels}. `down_block_types`: {down_block_types}."
1274
+ )
1275
+
1276
+ if not isinstance(only_cross_attention, bool) and len(only_cross_attention) != len(down_block_types):
1277
+ raise ValueError(
1278
+ f"Must provide the same number of `only_cross_attention` as `down_block_types`. `only_cross_attention`: {only_cross_attention}. `down_block_types`: {down_block_types}."
1279
+ )
1280
+
1281
+ if not isinstance(num_attention_heads, int) and len(num_attention_heads) != len(down_block_types):
1282
+ raise ValueError(
1283
+ f"Must provide the same number of `num_attention_heads` as `down_block_types`. `num_attention_heads`: {num_attention_heads}. `down_block_types`: {down_block_types}."
1284
+ )
1285
+
1286
+ if not isinstance(attention_head_dim, int) and len(attention_head_dim) != len(down_block_types):
1287
+ raise ValueError(
1288
+ f"Must provide the same number of `attention_head_dim` as `down_block_types`. `attention_head_dim`: {attention_head_dim}. `down_block_types`: {down_block_types}."
1289
+ )
1290
+
1291
+ if isinstance(cross_attention_dim, list) and len(cross_attention_dim) != len(down_block_types):
1292
+ raise ValueError(
1293
+ f"Must provide the same number of `cross_attention_dim` as `down_block_types`. `cross_attention_dim`: {cross_attention_dim}. `down_block_types`: {down_block_types}."
1294
+ )
1295
+
1296
+ if not isinstance(layers_per_block, int) and len(layers_per_block) != len(down_block_types):
1297
+ raise ValueError(
1298
+ f"Must provide the same number of `layers_per_block` as `down_block_types`. `layers_per_block`: {layers_per_block}. `down_block_types`: {down_block_types}."
1299
+ )
1300
+
1301
+ # input
1302
+ conv_in_padding = (conv_in_kernel - 1) // 2
1303
+ self.conv_in = nn.Conv2d(
1304
+ in_channels, block_out_channels[0], kernel_size=conv_in_kernel, padding=conv_in_padding
1305
+ )
1306
+
1307
+ # time
1308
+ if time_embedding_type == "fourier":
1309
+ time_embed_dim = time_embedding_dim or block_out_channels[0] * 2
1310
+ if time_embed_dim % 2 != 0:
1311
+ raise ValueError(f"`time_embed_dim` should be divisible by 2, but is {time_embed_dim}.")
1312
+ self.time_proj = GaussianFourierProjection(
1313
+ time_embed_dim // 2, set_W_to_weight=False, log=False, flip_sin_to_cos=flip_sin_to_cos
1314
+ )
1315
+ timestep_input_dim = time_embed_dim
1316
+ elif time_embedding_type == "positional":
1317
+ time_embed_dim = time_embedding_dim or block_out_channels[0] * 4
1318
+
1319
+ self.time_proj = Timesteps(block_out_channels[0], flip_sin_to_cos, freq_shift)
1320
+ timestep_input_dim = block_out_channels[0]
1321
+ else:
1322
+ raise ValueError(
1323
+ f"{time_embedding_type} does not exist. Please make sure to use one of `fourier` or `positional`."
1324
+ )
1325
+
1326
+ self.time_embedding = TimestepEmbedding(
1327
+ timestep_input_dim,
1328
+ time_embed_dim,
1329
+ act_fn=act_fn,
1330
+ post_act_fn=timestep_post_act,
1331
+ cond_proj_dim=time_cond_proj_dim,
1332
+ )
1333
+
1334
+ if encoder_hid_dim_type is None and encoder_hid_dim is not None:
1335
+ encoder_hid_dim_type = "text_proj"
1336
+ self.register_to_config(encoder_hid_dim_type=encoder_hid_dim_type)
1337
+ logger.info("encoder_hid_dim_type defaults to 'text_proj' as `encoder_hid_dim` is defined.")
1338
+
1339
+ if encoder_hid_dim is None and encoder_hid_dim_type is not None:
1340
+ raise ValueError(
1341
+ f"`encoder_hid_dim` has to be defined when `encoder_hid_dim_type` is set to {encoder_hid_dim_type}."
1342
+ )
1343
+
1344
+ if encoder_hid_dim_type == "text_proj":
1345
+ self.encoder_hid_proj = nn.Linear(encoder_hid_dim, cross_attention_dim)
1346
+ elif encoder_hid_dim_type == "text_image_proj":
1347
+ # image_embed_dim DOESN'T have to be `cross_attention_dim`. To not clutter the __init__ too much
1348
+ # they are set to `cross_attention_dim` here as this is exactly the required dimension for the currently only use
1349
+ # case when `addition_embed_type == "text_image_proj"` (Kadinsky 2.1)`
1350
+ self.encoder_hid_proj = TextImageProjection(
1351
+ text_embed_dim=encoder_hid_dim,
1352
+ image_embed_dim=cross_attention_dim,
1353
+ cross_attention_dim=cross_attention_dim,
1354
+ )
1355
+ elif encoder_hid_dim_type == "image_proj":
1356
+ # Kandinsky 2.2
1357
+ self.encoder_hid_proj = ImageProjection(
1358
+ image_embed_dim=encoder_hid_dim,
1359
+ cross_attention_dim=cross_attention_dim,
1360
+ )
1361
+ elif encoder_hid_dim_type is not None:
1362
+ raise ValueError(
1363
+ f"encoder_hid_dim_type: {encoder_hid_dim_type} must be None, 'text_proj' or 'text_image_proj'."
1364
+ )
1365
+ else:
1366
+ self.encoder_hid_proj = None
1367
+
1368
+ # class embedding
1369
+ if class_embed_type is None and num_class_embeds is not None:
1370
+ self.class_embedding = nn.Embedding(num_class_embeds, time_embed_dim)
1371
+ elif class_embed_type == "timestep":
1372
+ self.class_embedding = TimestepEmbedding(timestep_input_dim, time_embed_dim, act_fn=act_fn)
1373
+ elif class_embed_type == "identity":
1374
+ self.class_embedding = nn.Identity(time_embed_dim, time_embed_dim)
1375
+ elif class_embed_type == "projection":
1376
+ if projection_class_embeddings_input_dim is None:
1377
+ raise ValueError(
1378
+ "`class_embed_type`: 'projection' requires `projection_class_embeddings_input_dim` be set"
1379
+ )
1380
+ # The projection `class_embed_type` is the same as the timestep `class_embed_type` except
1381
+ # 1. the `class_labels` inputs are not first converted to sinusoidal embeddings
1382
+ # 2. it projects from an arbitrary input dimension.
1383
+ #
1384
+ # Note that `TimestepEmbedding` is quite general, being mainly linear layers and activations.
1385
+ # When used for embedding actual timesteps, the timesteps are first converted to sinusoidal embeddings.
1386
+ # As a result, `TimestepEmbedding` can be passed arbitrary vectors.
1387
+ self.class_embedding = TimestepEmbedding(projection_class_embeddings_input_dim, time_embed_dim)
1388
+ elif class_embed_type == "simple_projection":
1389
+ if projection_class_embeddings_input_dim is None:
1390
+ raise ValueError(
1391
+ "`class_embed_type`: 'simple_projection' requires `projection_class_embeddings_input_dim` be set"
1392
+ )
1393
+ self.class_embedding = nn.Linear(projection_class_embeddings_input_dim, time_embed_dim)
1394
+ else:
1395
+ self.class_embedding = None
1396
+
1397
+ if addition_embed_type == "text":
1398
+ if encoder_hid_dim is not None:
1399
+ text_time_embedding_from_dim = encoder_hid_dim
1400
+ else:
1401
+ text_time_embedding_from_dim = cross_attention_dim
1402
+
1403
+ self.add_embedding = TextTimeEmbedding(
1404
+ text_time_embedding_from_dim, time_embed_dim, num_heads=addition_embed_type_num_heads
1405
+ )
1406
+ elif addition_embed_type == "text_image":
1407
+ # text_embed_dim and image_embed_dim DON'T have to be `cross_attention_dim`. To not clutter the __init__ too much
1408
+ # they are set to `cross_attention_dim` here as this is exactly the required dimension for the currently only use
1409
+ # case when `addition_embed_type == "text_image"` (Kadinsky 2.1)`
1410
+ self.add_embedding = TextImageTimeEmbedding(
1411
+ text_embed_dim=cross_attention_dim, image_embed_dim=cross_attention_dim, time_embed_dim=time_embed_dim
1412
+ )
1413
+ elif addition_embed_type == "text_time":
1414
+ self.add_time_proj = Timesteps(addition_time_embed_dim, flip_sin_to_cos, freq_shift)
1415
+ self.add_embedding = TimestepEmbedding(projection_class_embeddings_input_dim, time_embed_dim)
1416
+ elif addition_embed_type == "image":
1417
+ # Kandinsky 2.2
1418
+ self.add_embedding = ImageTimeEmbedding(image_embed_dim=encoder_hid_dim, time_embed_dim=time_embed_dim)
1419
+ elif addition_embed_type == "image_hint":
1420
+ # Kandinsky 2.2 ControlNet
1421
+ self.add_embedding = ImageHintTimeEmbedding(image_embed_dim=encoder_hid_dim, time_embed_dim=time_embed_dim)
1422
+ elif addition_embed_type is not None:
1423
+ raise ValueError(f"addition_embed_type: {addition_embed_type} must be None, 'text' or 'text_image'.")
1424
+
1425
+ if time_embedding_act_fn is None:
1426
+ self.time_embed_act = None
1427
+ else:
1428
+ self.time_embed_act = get_activation(time_embedding_act_fn)
1429
+
1430
+ self.down_blocks = nn.ModuleList([])
1431
+ self.up_blocks = nn.ModuleList([])
1432
+
1433
+ if isinstance(only_cross_attention, bool):
1434
+ if mid_block_only_cross_attention is None:
1435
+ mid_block_only_cross_attention = only_cross_attention
1436
+
1437
+ only_cross_attention = [only_cross_attention] * len(down_block_types)
1438
+
1439
+ if mid_block_only_cross_attention is None:
1440
+ mid_block_only_cross_attention = False
1441
+
1442
+ if isinstance(num_attention_heads, int):
1443
+ num_attention_heads = (num_attention_heads,) * len(down_block_types)
1444
+
1445
+ if isinstance(attention_head_dim, int):
1446
+ attention_head_dim = (attention_head_dim,) * len(down_block_types)
1447
+
1448
+ if isinstance(cross_attention_dim, int):
1449
+ cross_attention_dim = (cross_attention_dim,) * len(down_block_types)
1450
+
1451
+ if isinstance(layers_per_block, int):
1452
+ layers_per_block = [layers_per_block] * len(down_block_types)
1453
+
1454
+ if isinstance(transformer_layers_per_block, int):
1455
+ transformer_layers_per_block = [transformer_layers_per_block] * len(down_block_types)
1456
+
1457
+ if class_embeddings_concat:
1458
+ # The time embeddings are concatenated with the class embeddings. The dimension of the
1459
+ # time embeddings passed to the down, middle, and up blocks is twice the dimension of the
1460
+ # regular time embeddings
1461
+ blocks_time_embed_dim = time_embed_dim * 2
1462
+ else:
1463
+ blocks_time_embed_dim = time_embed_dim
1464
+
1465
+ # down
1466
+ output_channel = block_out_channels[0]
1467
+ for i, down_block_type in enumerate(down_block_types):
1468
+ input_channel = output_channel
1469
+ output_channel = block_out_channels[i]
1470
+ is_final_block = i == len(block_out_channels) - 1
1471
+
1472
+ down_block = get_down_block(
1473
+ down_block_type,
1474
+ num_layers=layers_per_block[i],
1475
+ transformer_layers_per_block=transformer_layers_per_block[i],
1476
+ in_channels=input_channel,
1477
+ out_channels=output_channel,
1478
+ temb_channels=blocks_time_embed_dim,
1479
+ add_downsample=not is_final_block,
1480
+ resnet_eps=norm_eps,
1481
+ resnet_act_fn=act_fn,
1482
+ resnet_groups=norm_num_groups,
1483
+ cross_attention_dim=cross_attention_dim[i],
1484
+ num_attention_heads=num_attention_heads[i],
1485
+ downsample_padding=downsample_padding,
1486
+ dual_cross_attention=dual_cross_attention,
1487
+ use_linear_projection=use_linear_projection,
1488
+ only_cross_attention=only_cross_attention[i],
1489
+ upcast_attention=upcast_attention,
1490
+ resnet_time_scale_shift=resnet_time_scale_shift,
1491
+ resnet_skip_time_act=resnet_skip_time_act,
1492
+ resnet_out_scale_factor=resnet_out_scale_factor,
1493
+ cross_attention_norm=cross_attention_norm,
1494
+ attention_head_dim=attention_head_dim[i] if attention_head_dim[i] is not None else output_channel,
1495
+ )
1496
+ self.down_blocks.append(down_block)
1497
+
1498
+ # mid
1499
+ if mid_block_type == "UNetMidBlock2DCrossAttn":
1500
+ self.mid_block = UNetMidBlock2DCrossAttn(
1501
+ transformer_layers_per_block=transformer_layers_per_block[-1],
1502
+ in_channels=block_out_channels[-1],
1503
+ temb_channels=blocks_time_embed_dim,
1504
+ resnet_eps=norm_eps,
1505
+ resnet_act_fn=act_fn,
1506
+ output_scale_factor=mid_block_scale_factor,
1507
+ resnet_time_scale_shift=resnet_time_scale_shift,
1508
+ cross_attention_dim=cross_attention_dim[-1],
1509
+ num_attention_heads=num_attention_heads[-1],
1510
+ resnet_groups=norm_num_groups,
1511
+ dual_cross_attention=dual_cross_attention,
1512
+ use_linear_projection=use_linear_projection,
1513
+ upcast_attention=upcast_attention,
1514
+ )
1515
+ elif mid_block_type == "UNetMidBlock2DSimpleCrossAttn":
1516
+ self.mid_block = UNetMidBlock2DSimpleCrossAttn(
1517
+ in_channels=block_out_channels[-1],
1518
+ temb_channels=blocks_time_embed_dim,
1519
+ resnet_eps=norm_eps,
1520
+ resnet_act_fn=act_fn,
1521
+ output_scale_factor=mid_block_scale_factor,
1522
+ cross_attention_dim=cross_attention_dim[-1],
1523
+ attention_head_dim=attention_head_dim[-1],
1524
+ resnet_groups=norm_num_groups,
1525
+ resnet_time_scale_shift=resnet_time_scale_shift,
1526
+ skip_time_act=resnet_skip_time_act,
1527
+ only_cross_attention=mid_block_only_cross_attention,
1528
+ cross_attention_norm=cross_attention_norm,
1529
+ )
1530
+ elif mid_block_type is None:
1531
+ self.mid_block = None
1532
+ else:
1533
+ raise ValueError(f"unknown mid_block_type : {mid_block_type}")
1534
+
1535
+ # count how many layers upsample the images
1536
+ self.num_upsamplers = 0
1537
+
1538
+ # up
1539
+ reversed_block_out_channels = list(reversed(block_out_channels))
1540
+ reversed_num_attention_heads = list(reversed(num_attention_heads))
1541
+ reversed_layers_per_block = list(reversed(layers_per_block))
1542
+ reversed_cross_attention_dim = list(reversed(cross_attention_dim))
1543
+ reversed_transformer_layers_per_block = list(reversed(transformer_layers_per_block))
1544
+ only_cross_attention = list(reversed(only_cross_attention))
1545
+
1546
+ output_channel = reversed_block_out_channels[0]
1547
+ for i, up_block_type in enumerate(up_block_types):
1548
+ is_final_block = i == len(block_out_channels) - 1
1549
+
1550
+ prev_output_channel = output_channel
1551
+ output_channel = reversed_block_out_channels[i]
1552
+ input_channel = reversed_block_out_channels[min(i + 1, len(block_out_channels) - 1)]
1553
+
1554
+ # add upsample block for all BUT final layer
1555
+ if not is_final_block:
1556
+ add_upsample = True
1557
+ self.num_upsamplers += 1
1558
+ else:
1559
+ add_upsample = False
1560
+
1561
+ up_block = get_residual_up_block(
1562
+ up_block_type,
1563
+ num_layers=reversed_layers_per_block[i] + 1,
1564
+ transformer_layers_per_block=reversed_transformer_layers_per_block[i],
1565
+ in_channels=input_channel,
1566
+ out_channels=output_channel,
1567
+ prev_output_channel=prev_output_channel,
1568
+ temb_channels=blocks_time_embed_dim,
1569
+ add_upsample=add_upsample,
1570
+ resnet_eps=norm_eps,
1571
+ resnet_act_fn=act_fn,
1572
+ resnet_groups=norm_num_groups,
1573
+ cross_attention_dim=reversed_cross_attention_dim[i],
1574
+ num_attention_heads=reversed_num_attention_heads[i],
1575
+ dual_cross_attention=dual_cross_attention,
1576
+ use_linear_projection=use_linear_projection,
1577
+ only_cross_attention=only_cross_attention[i],
1578
+ upcast_attention=upcast_attention,
1579
+ resnet_time_scale_shift=resnet_time_scale_shift,
1580
+ resnet_skip_time_act=resnet_skip_time_act,
1581
+ resnet_out_scale_factor=resnet_out_scale_factor,
1582
+ cross_attention_norm=cross_attention_norm,
1583
+ attention_head_dim=attention_head_dim[i] if attention_head_dim[i] is not None else output_channel,
1584
+ )
1585
+ self.up_blocks.append(up_block)
1586
+ prev_output_channel = output_channel
1587
+
1588
+ # out
1589
+ if norm_num_groups is not None:
1590
+ self.conv_norm_out = nn.GroupNorm(
1591
+ num_channels=block_out_channels[0], num_groups=norm_num_groups, eps=norm_eps
1592
+ )
1593
+
1594
+ self.conv_act = get_activation(act_fn)
1595
+
1596
+ else:
1597
+ self.conv_norm_out = None
1598
+ self.conv_act = None
1599
+
1600
+ conv_out_padding = (conv_out_kernel - 1) // 2
1601
+ self.conv_out = nn.Conv2d(
1602
+ block_out_channels[0], out_channels, kernel_size=conv_out_kernel, padding=conv_out_padding
1603
+ )
1604
+
1605
+ def forward(
1606
+ self,
1607
+ sample: torch.FloatTensor,
1608
+ timestep: Union[torch.Tensor, float, int],
1609
+ encoder_hidden_states: torch.Tensor,
1610
+ class_labels: Optional[torch.Tensor] = None,
1611
+ timestep_cond: Optional[torch.Tensor] = None,
1612
+ attention_mask: Optional[torch.Tensor] = None,
1613
+ cross_attention_kwargs: Optional[Dict[str, Any]] = None,
1614
+ added_cond_kwargs: Optional[Dict[str, torch.Tensor]] = None,
1615
+ down_block_additional_residuals: Optional[Tuple[torch.Tensor]] = None,
1616
+ mid_block_additional_residual: Optional[torch.Tensor] = None,
1617
+ up_block_additional_residuals: Optional[Dict[str, torch.Tensor]] = None, # newly added
1618
+ encoder_attention_mask: Optional[torch.Tensor] = None,
1619
+ return_dict: bool = True,
1620
+ ) -> Union[UNet2DConditionOutput, Tuple]:
1621
+ r"""
1622
+ The [`UNet2DConditionModel`] forward method.
1623
+
1624
+ Args:
1625
+ sample (`torch.FloatTensor`):
1626
+ The noisy input tensor with the following shape `(batch, channel, height, width)`.
1627
+ timestep (`torch.FloatTensor` or `float` or `int`): The number of timesteps to denoise an input.
1628
+ encoder_hidden_states (`torch.FloatTensor`):
1629
+ The encoder hidden states with shape `(batch, sequence_length, feature_dim)`.
1630
+ encoder_attention_mask (`torch.Tensor`):
1631
+ A cross-attention mask of shape `(batch, sequence_length)` is applied to `encoder_hidden_states`. If
1632
+ `True` the mask is kept, otherwise if `False` it is discarded. Mask will be converted into a bias,
1633
+ which adds large negative values to the attention scores corresponding to "discard" tokens.
1634
+ return_dict (`bool`, *optional*, defaults to `True`):
1635
+ Whether or not to return a [`~models.unet_2d_condition.UNet2DConditionOutput`] instead of a plain
1636
+ tuple.
1637
+ cross_attention_kwargs (`dict`, *optional*):
1638
+ A kwargs dictionary that if specified is passed along to the [`AttnProcessor`].
1639
+ added_cond_kwargs: (`dict`, *optional*):
1640
+ A kwargs dictionary containin additional embeddings that if specified are added to the embeddings that
1641
+ are passed along to the UNet blocks.
1642
+
1643
+ Returns:
1644
+ [`~models.unet_2d_condition.UNet2DConditionOutput`] or `tuple`:
1645
+ If `return_dict` is True, an [`~models.unet_2d_condition.UNet2DConditionOutput`] is returned, otherwise
1646
+ a `tuple` is returned where the first element is the sample tensor.
1647
+ """
1648
+ # By default samples have to be AT least a multiple of the overall upsampling factor.
1649
+ # The overall upsampling factor is equal to 2 ** (# num of upsampling layers).
1650
+ # However, the upsampling interpolation output size can be forced to fit any upsampling size
1651
+ # on the fly if necessary.
1652
+ default_overall_up_factor = 2**self.num_upsamplers
1653
+
1654
+ # upsample size should be forwarded when sample is not a multiple of `default_overall_up_factor`
1655
+ forward_upsample_size = False
1656
+ upsample_size = None
1657
+
1658
+ if any(s % default_overall_up_factor != 0 for s in sample.shape[-2:]):
1659
+ logger.info("Forward upsample size to force interpolation output size.")
1660
+ forward_upsample_size = True
1661
+
1662
+ # ensure attention_mask is a bias, and give it a singleton query_tokens dimension
1663
+ # expects mask of shape:
1664
+ # [batch, key_tokens]
1665
+ # adds singleton query_tokens dimension:
1666
+ # [batch, 1, key_tokens]
1667
+ # this helps to broadcast it as a bias over attention scores, which will be in one of the following shapes:
1668
+ # [batch, heads, query_tokens, key_tokens] (e.g. torch sdp attn)
1669
+ # [batch * heads, query_tokens, key_tokens] (e.g. xformers or classic attn)
1670
+ if attention_mask is not None:
1671
+ # assume that mask is expressed as:
1672
+ # (1 = keep, 0 = discard)
1673
+ # convert mask into a bias that can be added to attention scores:
1674
+ # (keep = +0, discard = -10000.0)
1675
+ attention_mask = (1 - attention_mask.to(sample.dtype)) * -10000.0
1676
+ attention_mask = attention_mask.unsqueeze(1)
1677
+
1678
+ # convert encoder_attention_mask to a bias the same way we do for attention_mask
1679
+ if encoder_attention_mask is not None:
1680
+ encoder_attention_mask = (1 - encoder_attention_mask.to(sample.dtype)) * -10000.0
1681
+ encoder_attention_mask = encoder_attention_mask.unsqueeze(1)
1682
+
1683
+ # 0. center input if necessary
1684
+ if self.config.center_input_sample:
1685
+ sample = 2 * sample - 1.0
1686
+
1687
+ # 1. time
1688
+ timesteps = timestep
1689
+ if not torch.is_tensor(timesteps):
1690
+ # TODO: this requires sync between CPU and GPU. So try to pass timesteps as tensors if you can
1691
+ # This would be a good case for the `match` statement (Python 3.10+)
1692
+ is_mps = sample.device.type == "mps"
1693
+ if isinstance(timestep, float):
1694
+ dtype = torch.float32 if is_mps else torch.float64
1695
+ else:
1696
+ dtype = torch.int32 if is_mps else torch.int64
1697
+ timesteps = torch.tensor([timesteps], dtype=dtype, device=sample.device)
1698
+ elif len(timesteps.shape) == 0:
1699
+ timesteps = timesteps[None].to(sample.device)
1700
+
1701
+ # broadcast to batch dimension in a way that's compatible with ONNX/Core ML
1702
+ timesteps = timesteps.expand(sample.shape[0])
1703
+
1704
+ t_emb = self.time_proj(timesteps)
1705
+
1706
+ # `Timesteps` does not contain any weights and will always return f32 tensors
1707
+ # but time_embedding might actually be running in fp16. so we need to cast here.
1708
+ # there might be better ways to encapsulate this.
1709
+ t_emb = t_emb.to(dtype=sample.dtype)
1710
+
1711
+ emb = self.time_embedding(t_emb, timestep_cond)
1712
+ aug_emb = None
1713
+
1714
+ if self.class_embedding is not None:
1715
+ if class_labels is None:
1716
+ raise ValueError("class_labels should be provided when num_class_embeds > 0")
1717
+
1718
+ if self.config.class_embed_type == "timestep":
1719
+ class_labels = self.time_proj(class_labels)
1720
+
1721
+ # `Timesteps` does not contain any weights and will always return f32 tensors
1722
+ # there might be better ways to encapsulate this.
1723
+ class_labels = class_labels.to(dtype=sample.dtype)
1724
+
1725
+ class_emb = self.class_embedding(class_labels).to(dtype=sample.dtype)
1726
+
1727
+ if self.config.class_embeddings_concat:
1728
+ emb = torch.cat([emb, class_emb], dim=-1)
1729
+ else:
1730
+ emb = emb + class_emb
1731
+
1732
+ if self.config.addition_embed_type == "text":
1733
+ aug_emb = self.add_embedding(encoder_hidden_states)
1734
+ elif self.config.addition_embed_type == "text_image":
1735
+ # Kandinsky 2.1 - style
1736
+ if "image_embeds" not in added_cond_kwargs:
1737
+ raise ValueError(
1738
+ f"{self.__class__} has the config param `addition_embed_type` set to 'text_image' which requires the keyword argument `image_embeds` to be passed in `added_cond_kwargs`"
1739
+ )
1740
+
1741
+ image_embs = added_cond_kwargs.get("image_embeds")
1742
+ text_embs = added_cond_kwargs.get("text_embeds", encoder_hidden_states)
1743
+ aug_emb = self.add_embedding(text_embs, image_embs)
1744
+ elif self.config.addition_embed_type == "text_time":
1745
+ # SDXL - style
1746
+ if "text_embeds" not in added_cond_kwargs:
1747
+ raise ValueError(
1748
+ f"{self.__class__} has the config param `addition_embed_type` set to 'text_time' which requires the keyword argument `text_embeds` to be passed in `added_cond_kwargs`"
1749
+ )
1750
+ text_embeds = added_cond_kwargs.get("text_embeds")
1751
+ if "time_ids" not in added_cond_kwargs:
1752
+ raise ValueError(
1753
+ f"{self.__class__} has the config param `addition_embed_type` set to 'text_time' which requires the keyword argument `time_ids` to be passed in `added_cond_kwargs`"
1754
+ )
1755
+ time_ids = added_cond_kwargs.get("time_ids")
1756
+ time_embeds = self.add_time_proj(time_ids.flatten())
1757
+ time_embeds = time_embeds.reshape((text_embeds.shape[0], -1))
1758
+
1759
+ add_embeds = torch.concat([text_embeds, time_embeds], dim=-1)
1760
+ add_embeds = add_embeds.to(emb.dtype)
1761
+ aug_emb = self.add_embedding(add_embeds)
1762
+ elif self.config.addition_embed_type == "image":
1763
+ # Kandinsky 2.2 - style
1764
+ if "image_embeds" not in added_cond_kwargs:
1765
+ raise ValueError(
1766
+ f"{self.__class__} has the config param `addition_embed_type` set to 'image' which requires the keyword argument `image_embeds` to be passed in `added_cond_kwargs`"
1767
+ )
1768
+ image_embs = added_cond_kwargs.get("image_embeds")
1769
+ aug_emb = self.add_embedding(image_embs)
1770
+ elif self.config.addition_embed_type == "image_hint":
1771
+ # Kandinsky 2.2 - style
1772
+ if "image_embeds" not in added_cond_kwargs or "hint" not in added_cond_kwargs:
1773
+ raise ValueError(
1774
+ f"{self.__class__} has the config param `addition_embed_type` set to 'image_hint' which requires the keyword arguments `image_embeds` and `hint` to be passed in `added_cond_kwargs`"
1775
+ )
1776
+ image_embs = added_cond_kwargs.get("image_embeds")
1777
+ hint = added_cond_kwargs.get("hint")
1778
+ aug_emb, hint = self.add_embedding(image_embs, hint)
1779
+ sample = torch.cat([sample, hint], dim=1)
1780
+
1781
+ emb = emb + aug_emb if aug_emb is not None else emb
1782
+
1783
+ if self.time_embed_act is not None:
1784
+ emb = self.time_embed_act(emb)
1785
+
1786
+ if self.encoder_hid_proj is not None and self.config.encoder_hid_dim_type == "text_proj":
1787
+ encoder_hidden_states = self.encoder_hid_proj(encoder_hidden_states)
1788
+ elif self.encoder_hid_proj is not None and self.config.encoder_hid_dim_type == "text_image_proj":
1789
+ # Kadinsky 2.1 - style
1790
+ if "image_embeds" not in added_cond_kwargs:
1791
+ raise ValueError(
1792
+ f"{self.__class__} has the config param `encoder_hid_dim_type` set to 'text_image_proj' which requires the keyword argument `image_embeds` to be passed in `added_conditions`"
1793
+ )
1794
+
1795
+ image_embeds = added_cond_kwargs.get("image_embeds")
1796
+ encoder_hidden_states = self.encoder_hid_proj(encoder_hidden_states, image_embeds)
1797
+ elif self.encoder_hid_proj is not None and self.config.encoder_hid_dim_type == "image_proj":
1798
+ # Kandinsky 2.2 - style
1799
+ if "image_embeds" not in added_cond_kwargs:
1800
+ raise ValueError(
1801
+ f"{self.__class__} has the config param `encoder_hid_dim_type` set to 'image_proj' which requires the keyword argument `image_embeds` to be passed in `added_conditions`"
1802
+ )
1803
+ image_embeds = added_cond_kwargs.get("image_embeds")
1804
+ encoder_hidden_states = self.encoder_hid_proj(image_embeds)
1805
+ # 2. pre-process
1806
+ sample = self.conv_in(sample)
1807
+
1808
+ # 3. down
1809
+
1810
+ is_controlnet = mid_block_additional_residual is not None and down_block_additional_residuals is not None
1811
+ is_adapter = mid_block_additional_residual is None and down_block_additional_residuals is not None
1812
+
1813
+ down_block_res_samples = (sample,)
1814
+ for downsample_block in self.down_blocks:
1815
+ if hasattr(downsample_block, "has_cross_attention") and downsample_block.has_cross_attention:
1816
+ # For t2i-adapter CrossAttnDownBlock2D
1817
+ additional_residuals = {}
1818
+ if is_adapter and len(down_block_additional_residuals) > 0:
1819
+ additional_residuals["additional_residuals"] = down_block_additional_residuals.pop(0)
1820
+
1821
+ sample, res_samples = downsample_block(
1822
+ hidden_states=sample,
1823
+ temb=emb,
1824
+ encoder_hidden_states=encoder_hidden_states,
1825
+ attention_mask=attention_mask,
1826
+ cross_attention_kwargs=cross_attention_kwargs,
1827
+ encoder_attention_mask=encoder_attention_mask,
1828
+ **additional_residuals,
1829
+ )
1830
+ else:
1831
+ sample, res_samples = downsample_block(hidden_states=sample, temb=emb)
1832
+
1833
+ if is_adapter and len(down_block_additional_residuals) > 0:
1834
+ sample += down_block_additional_residuals.pop(0)
1835
+
1836
+ down_block_res_samples += res_samples
1837
+
1838
+ if is_controlnet:
1839
+ new_down_block_res_samples = ()
1840
+
1841
+ for down_block_res_sample, down_block_additional_residual in zip(
1842
+ down_block_res_samples, down_block_additional_residuals
1843
+ ):
1844
+ down_block_res_sample = down_block_res_sample + down_block_additional_residual
1845
+ new_down_block_res_samples = new_down_block_res_samples + (down_block_res_sample,)
1846
+
1847
+ down_block_res_samples = new_down_block_res_samples
1848
+
1849
+ # 4. mid
1850
+ if self.mid_block is not None:
1851
+ sample = self.mid_block(
1852
+ sample,
1853
+ emb,
1854
+ encoder_hidden_states=encoder_hidden_states,
1855
+ attention_mask=attention_mask,
1856
+ cross_attention_kwargs=cross_attention_kwargs,
1857
+ encoder_attention_mask=encoder_attention_mask,
1858
+ )
1859
+
1860
+ if is_controlnet:
1861
+ sample = sample + mid_block_additional_residual
1862
+
1863
+ # 5. up
1864
+ for i, upsample_block in enumerate(self.up_blocks):
1865
+ is_final_block = i == len(self.up_blocks) - 1
1866
+
1867
+ res_samples = down_block_res_samples[-len(upsample_block.resnets) :]
1868
+ down_block_res_samples = down_block_res_samples[: -len(upsample_block.resnets)]
1869
+
1870
+ # if we have not reached the final block and need to forward the
1871
+ # upsample size, we do it here
1872
+ if not is_final_block and forward_upsample_size:
1873
+ upsample_size = down_block_res_samples[-1].shape[2:]
1874
+
1875
+ if hasattr(upsample_block, "has_cross_attention") and upsample_block.has_cross_attention:
1876
+ sample = upsample_block(
1877
+ hidden_states=sample,
1878
+ temb=emb,
1879
+ res_hidden_states_tuple=res_samples,
1880
+ encoder_hidden_states=encoder_hidden_states,
1881
+ cross_attention_kwargs=cross_attention_kwargs,
1882
+ upsample_size=upsample_size,
1883
+ attention_mask=attention_mask,
1884
+ encoder_attention_mask=encoder_attention_mask,
1885
+ block_idx=i, # newly added
1886
+ additional_residuals=up_block_additional_residuals, # newly added
1887
+ )
1888
+ else:
1889
+ sample = upsample_block(
1890
+ hidden_states=sample, temb=emb, res_hidden_states_tuple=res_samples, upsample_size=upsample_size,
1891
+ additional_residuals=up_block_additional_residuals # newly added
1892
+ )
1893
+
1894
+ # 6. post-process
1895
+ if self.conv_norm_out:
1896
+ sample = self.conv_norm_out(sample)
1897
+ sample = self.conv_act(sample)
1898
+ sample = self.conv_out(sample)
1899
+
1900
+ if not return_dict:
1901
+ return (sample,)
1902
+
1903
+ return UNet2DConditionOutput(sample=sample)
1904
+
1905
+
1906
+ class UNet(nn.Module):
1907
+ def __init__(self, cfg):
1908
+ super().__init__()
1909
+
1910
+ self.model = ResidualUNet2DConditionModel.from_pretrained(
1911
+ cfg.MODEL.UNET_CONFIG.PRETRAINED_PATH, use_safetensors = True)
1912
+ self.model.requires_grad_(False)
1913
+ self.model.enable_xformers_memory_efficient_attention()
1914
+
1915
+ self.model.enable_gradient_checkpointing()
1916
+ for i, up_block in enumerate(self.model.up_blocks):
1917
+ if isinstance(up_block, ResidualCrossAttnUpBlock2D):
1918
+ for j, attn in enumerate(up_block.attentions):
1919
+ assert isinstance(attn, ResidualTransformer2DModel)
1920
+ block_idx = i * len(up_block.attentions) + j
1921
+ if block_idx not in cfg.MODEL.UNET_CONFIG.TRAINABLE_BLOCK_IDX:
1922
+ continue
1923
+
1924
+ assert len(attn.transformer_blocks) == 1
1925
+ assert isinstance(attn.transformer_blocks[0], ResidualTransformerBlock)
1926
+
1927
+ self_attn = attn.transformer_blocks[0].attn1
1928
+ assert isinstance(self_attn, ResidualAttention)
1929
+ if cfg.MODEL.UNET_CONFIG.TRAIN_SELF_ATTN_Q:
1930
+ self_attn.to_q.requires_grad_(True)
1931
+ if cfg.MODEL.UNET_CONFIG.TRAIN_SELF_ATTN_K:
1932
+ self_attn.to_k.requires_grad_(True)
1933
+ if cfg.MODEL.UNET_CONFIG.TRAIN_SELF_ATTN_V:
1934
+ self_attn.to_v.requires_grad_(True)
1935
+
1936
+ cross_attn = attn.transformer_blocks[0].attn2
1937
+ assert isinstance(cross_attn, ResidualAttention)
1938
+ if cfg.MODEL.UNET_CONFIG.TRAIN_CROSS_ATTN_Q:
1939
+ cross_attn.to_q.requires_grad_(True)
1940
+ if cfg.MODEL.UNET_CONFIG.TRAIN_CROSS_ATTN_K:
1941
+ cross_attn.to_k.requires_grad_(True)
1942
+ if cfg.MODEL.UNET_CONFIG.TRAIN_CROSS_ATTN_V:
1943
+ cross_attn.to_v.requires_grad_(True)
1944
+
1945
+ def forward(self, sample, timestep, **kwargs):
1946
+ return self.model(sample, timestep, **kwargs).sample
models/vae.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ @author: Yanzuo Lu
3
+ @author: oliveryanzuolu@gmail.com
4
+ """
5
+
6
+ import diffusers
7
+ import torch
8
+ import torch.nn as nn
9
+
10
+
11
+ class VariationalAutoencoder(nn.Module):
12
+ def __init__(self, pretrained_path):
13
+ super().__init__()
14
+ self.model = diffusers.AutoencoderKL.from_pretrained(pretrained_path, use_safetensors=True)
15
+ self.model.requires_grad_(False)
16
+ self.model.enable_slicing()
17
+
18
+ @torch.no_grad()
19
+ def encode(self, x):
20
+ z = self.model.encode(x).latent_dist
21
+ z = z.sample()
22
+ z = self.model.scaling_factor * z
23
+ return z
24
+
25
+ @torch.no_grad()
26
+ def decode(self, z):
27
+ z = 1. / self.model.scaling_factor * z
28
+ x = self.model.decode(z).sample
29
+ return x
models/xf.py ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ @author: Yanzuo Lu
3
+ @author: oliveryanzuolu@gmail.com
4
+ """
5
+
6
+ import math
7
+
8
+ import torch as th
9
+ import torch.nn as nn
10
+ from transformers import CLIPVisionModel
11
+
12
+
13
+ class LayerNorm(nn.LayerNorm):
14
+ """
15
+ Implementation that supports fp16 inputs but fp32 gains/biases.
16
+ """
17
+
18
+ def forward(self, x: th.Tensor):
19
+ return super().forward(x.float()).to(x.dtype)
20
+
21
+
22
+ class MultiheadAttention(nn.Module):
23
+ def __init__(self, n_ctx, width, heads):
24
+ super().__init__()
25
+ self.n_ctx = n_ctx
26
+ self.width = width
27
+ self.heads = heads
28
+ self.c_qkv = nn.Linear(width, width * 3)
29
+ self.c_proj = nn.Linear(width, width)
30
+ self.attention = QKVMultiheadAttention(heads, n_ctx)
31
+
32
+ def forward(self, x):
33
+ x = self.c_qkv(x)
34
+ x = self.attention(x)
35
+ x = self.c_proj(x)
36
+ return x
37
+
38
+
39
+ class MLP(nn.Module):
40
+ def __init__(self, width):
41
+ super().__init__()
42
+ self.width = width
43
+ self.c_fc = nn.Linear(width, width * 4)
44
+ self.c_proj = nn.Linear(width * 4, width)
45
+ self.gelu = nn.GELU()
46
+
47
+ def forward(self, x):
48
+ return self.c_proj(self.gelu(self.c_fc(x)))
49
+
50
+
51
+ class QKVMultiheadAttention(nn.Module):
52
+ def __init__(self, n_heads: int, n_ctx: int):
53
+ super().__init__()
54
+ self.n_heads = n_heads
55
+ self.n_ctx = n_ctx
56
+
57
+ def forward(self, qkv):
58
+ bs, n_ctx, width = qkv.shape
59
+ attn_ch = width // self.n_heads // 3
60
+ scale = 1 / math.sqrt(math.sqrt(attn_ch))
61
+ qkv = qkv.view(bs, n_ctx, self.n_heads, -1)
62
+ q, k, v = th.split(qkv, attn_ch, dim=-1)
63
+ weight = th.einsum(
64
+ "bthc,bshc->bhts", q * scale, k * scale
65
+ ) # More stable with f16 than dividing afterwards
66
+ wdtype = weight.dtype
67
+ weight = th.softmax(weight.float(), dim=-1).type(wdtype)
68
+ return th.einsum("bhts,bshc->bthc", weight, v).reshape(bs, n_ctx, -1)
69
+
70
+
71
+ class ResidualAttentionBlock(nn.Module):
72
+ def __init__(
73
+ self,
74
+ n_ctx: int,
75
+ width: int,
76
+ heads: int,
77
+ ):
78
+ super().__init__()
79
+
80
+ self.attn = MultiheadAttention(
81
+ n_ctx,
82
+ width,
83
+ heads,
84
+ )
85
+ self.ln_1 = LayerNorm(width)
86
+ self.mlp = MLP(width)
87
+ self.ln_2 = LayerNorm(width)
88
+
89
+ def forward(self, x: th.Tensor):
90
+ x = x + self.attn(self.ln_1(x))
91
+ x = x + self.mlp(self.ln_2(x))
92
+ return x
93
+
94
+
95
+ class Transformer(nn.Module):
96
+ def __init__(
97
+ self,
98
+ n_ctx: int,
99
+ width: int,
100
+ layers: int,
101
+ heads: int,
102
+ ):
103
+ super().__init__()
104
+ self.n_ctx = n_ctx
105
+ self.width = width
106
+ self.layers = layers
107
+ self.resblocks = nn.ModuleList(
108
+ [
109
+ ResidualAttentionBlock(
110
+ n_ctx,
111
+ width,
112
+ heads,
113
+ )
114
+ for _ in range(layers)
115
+ ]
116
+ )
117
+
118
+ def forward(self, x: th.Tensor):
119
+ for block in self.resblocks:
120
+ x = block(x)
121
+ return x
122
+
123
+
124
+ class FrozenCLIPImageEmbedder(nn.Module):
125
+ """Uses the CLIP transformer encoder for text (from Hugging Face)"""
126
+ def __init__(self, version="openai/clip-vit-large-patch14"):
127
+ super().__init__()
128
+ self.transformer = CLIPVisionModel.from_pretrained("pretrained_models/clip", use_safetensors=True)
129
+ self.final_ln = LayerNorm(768)
130
+ self.mapper = nn.Sequential(
131
+ nn.Linear(1024, 768, bias=False),
132
+ Transformer(1, 768, 5, 1)
133
+ )
134
+
135
+ self.freeze()
136
+
137
+ def freeze(self):
138
+ self.transformer = self.transformer.eval()
139
+ for param in self.parameters():
140
+ param.requires_grad = False
141
+ for param in self.mapper.parameters():
142
+ param.requires_grad = True
143
+ for param in self.final_ln.parameters():
144
+ param.requires_grad = True
145
+
146
+ def forward(self, image):
147
+ outputs = self.transformer(pixel_values=image)
148
+ z = outputs.pooler_output
149
+ z = z.unsqueeze(1)
150
+ z = self.mapper(z)
151
+ z = self.final_ln(z)
152
+ return z
153
+
154
+ def encode(self, image):
155
+ return self(image)
playground.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
pose_transfer_test.py ADDED
@@ -0,0 +1,511 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ @author: Yanzuo Lu
3
+ @author: oliveryanzuolu@gmail.com
4
+ """
5
+
6
+ import argparse
7
+ import copy
8
+ import datetime
9
+ import logging
10
+ import os
11
+ import sys
12
+ import time
13
+ import warnings
14
+
15
+ import numpy as np
16
+ import torch
17
+ import torch.nn.functional as F
18
+ from accelerate import Accelerator
19
+ from accelerate.tracking import TensorBoardTracker, WandBTracker
20
+ from accelerate.utils import set_seed
21
+ from diffusers import (DDIMInverseScheduler, DDIMScheduler, DDPMScheduler,
22
+ EulerDiscreteScheduler, PNDMScheduler)
23
+ from einops import rearrange
24
+ from PIL import Image
25
+ from scipy.linalg import sqrtm
26
+ from torch.utils.data import DataLoader
27
+ from torchvision.utils import make_grid
28
+
29
+ from datasets import FidRealDeepFashion, PisTestDeepFashion
30
+ from defaults import pose_transfer_C as cfg
31
+ from models import UNet, VariationalAutoencoder, build_metric
32
+ from utils import AverageMeter
33
+
34
+ warnings.filterwarnings("ignore")
35
+ logger = logging.getLogger()
36
+
37
+
38
+ def build_test_loader(cfg):
39
+ test_data = PisTestDeepFashion(
40
+ cfg.INPUT.ROOT_DIR, cfg.INPUT.GT.IMG_SIZE, cfg.INPUT.POSE.IMG_SIZE,
41
+ cfg.INPUT.COND.IMG_SIZE, cfg.TEST.IMG_SIZE)
42
+ test_loader = DataLoader(
43
+ test_data,
44
+ cfg.TEST.MICRO_BATCH_SIZE,
45
+ num_workers=cfg.TEST.NUM_WORKERS,
46
+ pin_memory=True
47
+ )
48
+
49
+ fid_real_data = FidRealDeepFashion(cfg.INPUT.ROOT_DIR, cfg.TEST.IMG_SIZE)
50
+ fid_real_loader = DataLoader(
51
+ fid_real_data,
52
+ cfg.TEST.MICRO_BATCH_SIZE,
53
+ num_workers=cfg.TEST.NUM_WORKERS,
54
+ pin_memory=True
55
+ )
56
+ return test_loader, fid_real_loader, test_data, fid_real_data
57
+
58
+
59
+ def eval(cfg, model, test_loader, fid_real_loader, weight_dtype, save_dir,
60
+ test_data, fid_real_data, global_step, accelerator, metric,
61
+ noise_scheduler, inverse_noise_scheduler, vae, unet):
62
+ logger.info("start sampling...")
63
+ model.eval()
64
+ unet.eval()
65
+
66
+ gt_out_gathered = []
67
+ pred_out_gathered = []
68
+ lpips_gathered = []
69
+ psnr_gathered = []
70
+ ssim_gathered = []
71
+ ssim_256_gathered = []
72
+
73
+ with torch.no_grad():
74
+ end_time = time.time()
75
+ batch_time = AverageMeter()
76
+
77
+ for i, test_batch in enumerate(test_loader):
78
+ gt_imgs = test_batch["img_gt"]
79
+ img_size = test_batch["img_tgt"].shape[2:]
80
+ bsz = gt_imgs.shape[0]
81
+
82
+ if cfg.TEST.DDIM_INVERSION_STEPS > 0:
83
+ if cfg.TEST.DDIM_INVERSION_DOWN_BLOCK_GUIDANCE:
84
+ c, down_block_additional_residuals, up_block_additional_residuals = model({
85
+ "img_cond": test_batch["img_cond_from"], "pose_img": test_batch["pose_img_from"]})
86
+ else:
87
+ c, down_block_additional_residuals, up_block_additional_residuals = model({
88
+ "img_cond": test_batch["img_cond_from"], "pose_img": test_batch["pose_img_to"]})
89
+
90
+ noisy_latents = inverse_sample(
91
+ cfg.TEST.DDIM_INVERSION_STEPS, accelerator, inverse_noise_scheduler, vae, unet,
92
+ test_batch["img_src"], c[:bsz] if cfg.TEST.DDIM_INVERSION_UNCONDITIONAL else c[bsz:],
93
+ [sample.to(dtype=weight_dtype) for sample in down_block_additional_residuals] if cfg.TEST.DDIM_INVERSION_DOWN_BLOCK_GUIDANCE else None,
94
+ {k: v.to(dtype=weight_dtype) for k, v in up_block_additional_residuals.items()} if cfg.TEST.DDIM_INVERSION_UP_BLOCK_GUIDANCE else None)
95
+ else:
96
+ c, down_block_additional_residuals, up_block_additional_residuals = model({
97
+ "img_cond": test_batch["img_cond_from"], "pose_img": test_batch["pose_img_to"]})
98
+ noisy_latents = torch.randn((bsz, 4, img_size[0]//8, img_size[1]//8)).to(accelerator.device)
99
+
100
+ if cfg.TEST.DDIM_INVERSION_STEPS > 0 and cfg.TEST.DDIM_INVERSION_DOWN_BLOCK_GUIDANCE:
101
+ c, down_block_additional_residuals, up_block_additional_residuals = model({
102
+ "img_cond": test_batch["img_cond_from"], "pose_img": test_batch["pose_img_to"]})
103
+
104
+ sampling_imgs = sample(
105
+ cfg, weight_dtype, accelerator, noise_scheduler, vae, unet, noisy_latents,
106
+ c, down_block_additional_residuals, up_block_additional_residuals)
107
+
108
+ # log one-batch sampling results for visualization
109
+ if i == 0:
110
+ src_imgs = test_batch["img_src"] * 0.5 + 0.5
111
+ tgt_imgs = test_batch["img_tgt"] * 0.5 + 0.5
112
+ pose_imgs = F.interpolate(test_batch["pose_img_to"][:, :3, :, :],
113
+ tuple(test_batch["img_src"].shape[2:]),
114
+ mode="bicubic", antialias=True)
115
+ save_img = torch.stack([src_imgs, pose_imgs, tgt_imgs, sampling_imgs])
116
+ save_img = postprocess_image(save_img, nrow=save_img.shape[0]*2)
117
+ save_img.save(os.path.join(save_dir, f"inpainting_test_{accelerator.process_index}_{i}.jpg"))
118
+
119
+ sampling_imgs = F.interpolate(sampling_imgs, tuple(gt_imgs.shape[2:]), mode="bicubic", antialias=True)
120
+ sampling_imgs = sampling_imgs.float() * 255.0
121
+ sampling_imgs = sampling_imgs.clamp(0, 255).to(dtype=torch.uint8) # can save all images here!!!
122
+ sampling_imgs = sampling_imgs.to(torch.float32) / 255.
123
+
124
+ pred_out, lpips, psnr, ssim, ssim_256 = metric(gt_imgs, sampling_imgs)
125
+ pred_out_gathered.append(accelerator.gather_for_metrics(pred_out).cpu().numpy())
126
+ lpips_gathered.append(accelerator.gather_for_metrics(lpips).cpu().numpy())
127
+ psnr_gathered.append(accelerator.gather_for_metrics(psnr).cpu().numpy())
128
+ ssim_gathered.append(accelerator.gather_for_metrics(ssim).cpu().numpy())
129
+ ssim_256_gathered.append(accelerator.gather_for_metrics(ssim_256).cpu().numpy())
130
+
131
+ batch_time.update(time.time() - end_time)
132
+ end_time = time.time()
133
+
134
+ if (i + 1) % cfg.ACCELERATE.LOG_PERIOD == 0 or i == len(test_loader) - 1:
135
+ etas = batch_time.avg * (len(test_loader) - 1 - i)
136
+ logger.info(
137
+ f"Sampling ({i+1}/{len(test_loader)}) "
138
+ f"Time {batch_time.val:.4f}({batch_time.avg:.4f}) "
139
+ f"Eta {datetime.timedelta(seconds=int(etas))}")
140
+ if os.environ.get("WANDB_MODE", None) == "offline":
141
+ break
142
+
143
+ end_time = time.time()
144
+ batch_time = AverageMeter()
145
+ for i, fid_real_imgs in enumerate(fid_real_loader):
146
+ gt_out = metric(fid_real_imgs)
147
+ gt_out_gathered.append(accelerator.gather_for_metrics(gt_out).cpu().numpy())
148
+
149
+ batch_time.update(time.time() - end_time)
150
+ end_time = time.time()
151
+
152
+ if (i + 1) % cfg.ACCELERATE.LOG_PERIOD == 0 or i == len(fid_real_loader) - 1:
153
+ etas = batch_time.avg * (len(fid_real_loader) - 1 - i)
154
+ logger.info(
155
+ f"FidReal ({i+1}/{len(fid_real_loader)}) "
156
+ f"Time {batch_time.val:.4f}({batch_time.avg:.4f}) "
157
+ f"Eta {datetime.timedelta(seconds=int(etas))}")
158
+
159
+ if accelerator.is_main_process:
160
+ gt_out_gathered = np.concatenate(gt_out_gathered, axis=0)
161
+ pred_out_gathered = np.concatenate(pred_out_gathered, axis=0)
162
+ lpips_gathered = np.concatenate(lpips_gathered, axis=0)
163
+ psnr_gathered = np.concatenate(psnr_gathered, axis=0)
164
+ ssim_gathered = np.concatenate(ssim_gathered, axis=0)
165
+ ssim_256_gathered = np.concatenate(ssim_256_gathered, axis=0)
166
+ if os.environ.get("WANDB_MODE", None) != "offline":
167
+ assert len(gt_out_gathered) == len(fid_real_data)
168
+ assert len(pred_out_gathered) == len(lpips_gathered) == len(psnr_gathered) == \
169
+ len(ssim_gathered) == len(ssim_256_gathered) == len(test_data)
170
+
171
+ mu1 = np.mean(gt_out_gathered, axis=0)
172
+ sigma1 = np.cov(gt_out_gathered, rowvar=False)
173
+ mu2 = np.mean(pred_out_gathered, axis=0)
174
+ sigma2 = np.cov(pred_out_gathered, rowvar=False)
175
+
176
+ mu1 = np.atleast_1d(mu1)
177
+ mu2 = np.atleast_1d(mu2)
178
+ sigma1 = np.atleast_2d(sigma1)
179
+ sigma2 = np.atleast_2d(sigma2)
180
+
181
+ diff = mu1 - mu2
182
+
183
+ # Product might be almost singular
184
+ covmean, _ = sqrtm(sigma1.dot(sigma2), disp=False)
185
+ if not np.isfinite(covmean).all():
186
+ msg = ('fid calculation produces singular product; '
187
+ 'adding %s to diagonal of cov estimates') % 1e-6
188
+ logger.info(msg)
189
+ offset = np.eye(sigma1.shape[0]) * 1e-6
190
+ covmean = sqrtm((sigma1 + offset).dot(sigma2 + offset))
191
+
192
+ # Numerical error might give slight imaginary component
193
+ if np.iscomplexobj(covmean):
194
+ if not np.allclose(np.diagonal(covmean).imag, 0, atol=1e-3):
195
+ m = np.max(np.abs(covmean.imag))
196
+ raise ValueError('Imaginary component {}'.format(m))
197
+ covmean = covmean.real
198
+
199
+ tr_covmean = np.trace(covmean)
200
+
201
+ score_fid = diff.dot(diff) + np.trace(sigma1) + np.trace(sigma2) - 2 * tr_covmean
202
+ score_lpips = np.mean(lpips_gathered)
203
+ score_ssim = np.mean(ssim_gathered)
204
+ score_ssim_256 = np.mean(ssim_256_gathered)
205
+ score_psnr = np.mean(psnr_gathered)
206
+
207
+ logger.info("Evaluation Results:")
208
+ logger.info(f"FID: {score_fid:.3f}")
209
+ logger.info(f"LPIPS: {score_lpips:.4f}")
210
+ logger.info(f"SSIM: {score_ssim:.4f}")
211
+ logger.info(f"SSIM_256: {score_ssim_256:.4f}")
212
+ logger.info(f"PSNR: {score_psnr:.3f}")
213
+
214
+ accelerator.log({
215
+ "score_fid": score_fid,
216
+ "score_lpips": score_lpips,
217
+ "score_ssim": score_ssim,
218
+ "score_ssim_256": score_ssim_256,
219
+ "score_psnr": score_psnr
220
+ }, step=global_step)
221
+
222
+ accelerator.wait_for_everyone()
223
+ torch.cuda.empty_cache()
224
+
225
+
226
+ def sample(cfg, weight_dtype, accelerator, noise_scheduler, vae, unet, noisy_latents,
227
+ c_new, down_block_additional_residuals, up_block_additional_residuals):
228
+ bsz = noisy_latents.shape[0]
229
+ noise_scheduler.set_timesteps(cfg.TEST.NUM_INFERENCE_STEPS)
230
+
231
+ if cfg.TEST.GUIDANCE_TYPE == "uc_full":
232
+ down_block_additional_residuals = [torch.cat([torch.zeros_like(sample), sample]).to(dtype=weight_dtype) \
233
+ for sample in down_block_additional_residuals]
234
+ up_block_additional_residuals = {k: torch.cat([torch.zeros_like(v), v]).to(dtype=weight_dtype) \
235
+ for k, v in up_block_additional_residuals.items()}
236
+
237
+ for t in noise_scheduler.timesteps:
238
+ inputs = torch.cat([noisy_latents, noisy_latents], dim=0)
239
+ inputs = noise_scheduler.scale_model_input(inputs, timestep=t)
240
+ with accelerator.autocast():
241
+ noise_pred = unet(sample=inputs, timestep=t, encoder_hidden_states=c_new,
242
+ down_block_additional_residuals=copy.deepcopy(down_block_additional_residuals),
243
+ up_block_additional_residuals=copy.deepcopy(up_block_additional_residuals))
244
+
245
+ noise_pred_uc, noise_pred_full = noise_pred.chunk(2)
246
+ noise_pred = noise_pred_uc + cfg.TEST.FULL_GUIDANCE_SCALE * (noise_pred_full - noise_pred_uc)
247
+ noisy_latents = noise_scheduler.step(noise_pred, t, noisy_latents)[0]
248
+
249
+ elif cfg.TEST.GUIDANCE_TYPE == "updown_full":
250
+ down_block_additional_residuals = [torch.cat([sample, sample]).to(dtype=weight_dtype) \
251
+ for sample in down_block_additional_residuals]
252
+ up_block_additional_residuals = {k: torch.cat([v, v]).to(dtype=weight_dtype) \
253
+ for k, v in up_block_additional_residuals.items()}
254
+
255
+ for t in noise_scheduler.timesteps:
256
+ inputs = torch.cat([noisy_latents, noisy_latents], dim=0)
257
+ inputs = noise_scheduler.scale_model_input(inputs, timestep=t)
258
+ with accelerator.autocast():
259
+ noise_pred = unet(sample=inputs, timestep=t, encoder_hidden_states=c_new,
260
+ down_block_additional_residuals=copy.deepcopy(down_block_additional_residuals),
261
+ up_block_additional_residuals=copy.deepcopy(up_block_additional_residuals))
262
+
263
+ noise_pred_updown, noise_pred_full = noise_pred.chunk(2)
264
+ noise_pred = noise_pred_updown + cfg.TEST.FULL_GUIDANCE_SCALE * (noise_pred_full - noise_pred_updown)
265
+ noisy_latents = noise_scheduler.step(noise_pred, t, noisy_latents)[0]
266
+
267
+ elif cfg.TEST.GUIDANCE_TYPE == "down_full":
268
+ down_block_additional_residuals = [torch.cat([sample, sample]).to(dtype=weight_dtype) \
269
+ for sample in down_block_additional_residuals]
270
+ up_block_additional_residuals = {k: torch.cat([torch.zeros_like(v), v]).to(dtype=weight_dtype) \
271
+ for k, v in up_block_additional_residuals.items()}
272
+
273
+ for t in noise_scheduler.timesteps:
274
+ inputs = torch.cat([noisy_latents, noisy_latents], dim=0)
275
+ inputs = noise_scheduler.scale_model_input(inputs, timestep=t)
276
+ with accelerator.autocast():
277
+ noise_pred = unet(sample=inputs, timestep=t, encoder_hidden_states=c_new,
278
+ down_block_additional_residuals=copy.deepcopy(down_block_additional_residuals),
279
+ up_block_additional_residuals=copy.deepcopy(up_block_additional_residuals))
280
+
281
+ noise_pred_down, noise_pred_full = noise_pred.chunk(2)
282
+ noise_pred = noise_pred_down + cfg.TEST.FULL_GUIDANCE_SCALE * (noise_pred_full - noise_pred_down)
283
+ noisy_latents = noise_scheduler.step(noise_pred, t, noisy_latents)[0]
284
+
285
+ elif cfg.TEST.GUIDANCE_TYPE == "uc_down_full":
286
+ c_new = torch.cat([c_new[:bsz], c_new[:bsz], c_new[bsz:]])
287
+ down_block_additional_residuals = [torch.cat([torch.zeros_like(sample), sample, sample]).to(dtype=weight_dtype) \
288
+ for sample in down_block_additional_residuals]
289
+ up_block_additional_residuals = {k: torch.cat([torch.zeros_like(v), torch.zeros_like(v), v]).to(dtype=weight_dtype) \
290
+ for k, v in up_block_additional_residuals.items()}
291
+
292
+ for t in noise_scheduler.timesteps:
293
+ inputs = torch.cat([noisy_latents, noisy_latents, noisy_latents], dim=0)
294
+ inputs = noise_scheduler.scale_model_input(inputs, timestep=t)
295
+ with accelerator.autocast():
296
+ noise_pred = unet(sample=inputs, timestep=t, encoder_hidden_states=c_new,
297
+ down_block_additional_residuals=copy.deepcopy(down_block_additional_residuals),
298
+ up_block_additional_residuals=copy.deepcopy(up_block_additional_residuals))
299
+
300
+ noise_pred_uc, noise_pred_down, noise_pred_full = noise_pred.chunk(3)
301
+ noise_pred = noise_pred_uc + \
302
+ cfg.TEST.DOWN_BLOCK_GUIDANCE_SCALE * (noise_pred_down - noise_pred_uc) + \
303
+ cfg.TEST.FULL_GUIDANCE_SCALE * (noise_pred_full - noise_pred_down)
304
+ noisy_latents = noise_scheduler.step(noise_pred, t, noisy_latents)[0]
305
+
306
+ elif cfg.TEST.GUIDANCE_TYPE == "uc_down_updown_cdown":
307
+ c_new = torch.cat([c_new[:bsz], c_new[:bsz], c_new[:bsz], c_new[bsz:]])
308
+ down_block_additional_residuals = [torch.cat([torch.zeros_like(sample), sample, sample, sample]).to(dtype=weight_dtype) \
309
+ for sample in down_block_additional_residuals]
310
+ up_block_additional_residuals = {k: torch.cat([torch.zeros_like(v), torch.zeros_like(v), v, torch.zeros_like(v)]).to(dtype=weight_dtype) \
311
+ for k, v in up_block_additional_residuals.items()}
312
+
313
+ for t in noise_scheduler.timesteps:
314
+ inputs = torch.cat([noisy_latents, noisy_latents, noisy_latents, noisy_latents], dim=0)
315
+ inputs = noise_scheduler.scale_model_input(inputs, timestep=t)
316
+ with accelerator.autocast():
317
+ noise_pred = unet(sample=inputs, timestep=t, encoder_hidden_states=c_new,
318
+ down_block_additional_residuals=copy.deepcopy(down_block_additional_residuals),
319
+ up_block_additional_residuals=copy.deepcopy(up_block_additional_residuals))
320
+
321
+ noise_pred_uc, noise_pred_down, noise_pred_updown, noise_pred_cdown = noise_pred.chunk(4)
322
+ noise_pred = noise_pred_uc + \
323
+ cfg.TEST.DOWN_BLOCK_GUIDANCE_SCALE * (noise_pred_down - noise_pred_uc) + \
324
+ cfg.TEST.ALL_BLOCK_GUIDANCE_SCALE * (noise_pred_updown - noise_pred_down) + \
325
+ cfg.TEST.GUIDANCE_SCALE * (noise_pred_cdown - noise_pred_down)
326
+ noisy_latents = noise_scheduler.step(noise_pred, t, noisy_latents)[0]
327
+
328
+ elif cfg.TEST.GUIDANCE_TYPE == "uc_down_updown_full":
329
+ c_new = torch.cat([c_new[:bsz], c_new[:bsz], c_new[:bsz], c_new[bsz:]])
330
+ down_block_additional_residuals = [torch.cat([torch.zeros_like(sample), sample, sample, sample]).to(dtype=weight_dtype) \
331
+ for sample in down_block_additional_residuals]
332
+ up_block_additional_residuals = {k: torch.cat([torch.zeros_like(v), torch.zeros_like(v), v, v]).to(dtype=weight_dtype) \
333
+ for k, v in up_block_additional_residuals.items()}
334
+
335
+ for t in noise_scheduler.timesteps:
336
+ inputs = torch.cat([noisy_latents, noisy_latents, noisy_latents, noisy_latents], dim=0)
337
+ inputs = noise_scheduler.scale_model_input(inputs, timestep=t)
338
+ with accelerator.autocast():
339
+ noise_pred = unet(sample=inputs, timestep=t, encoder_hidden_states=c_new,
340
+ down_block_additional_residuals=copy.deepcopy(down_block_additional_residuals),
341
+ up_block_additional_residuals=copy.deepcopy(up_block_additional_residuals))
342
+
343
+ noise_pred_uc, noise_pred_down, noise_pred_updown, noise_pred_full = noise_pred.chunk(4)
344
+ noise_pred = noise_pred_uc + \
345
+ cfg.TEST.DOWN_BLOCK_GUIDANCE_SCALE * (noise_pred_down - noise_pred_uc) + \
346
+ cfg.TEST.ALL_BLOCK_GUIDANCE_SCALE * (noise_pred_updown - noise_pred_down) + \
347
+ cfg.TEST.FULL_GUIDANCE_SCALE * (noise_pred_full - noise_pred_updown)
348
+ noisy_latents = noise_scheduler.step(noise_pred, t, noisy_latents)[0]
349
+
350
+ with accelerator.autocast():
351
+ sampling_imgs = vae.decode(noisy_latents) * 0.5 + 0.5 # denormalize
352
+ sampling_imgs = sampling_imgs.clamp(0, 1)
353
+ return sampling_imgs
354
+
355
+
356
+ def inverse_sample(num_inference_steps, accelerator, inverse_noise_scheduler, vae, unet, img_src,
357
+ c_new, down_block_additional_residuals=None, up_block_additional_residuals=None):
358
+ inverse_noise_scheduler.set_timesteps(num_inference_steps)
359
+ with accelerator.autocast():
360
+ noisy_latents = vae.encode(img_src)
361
+
362
+ for t in inverse_noise_scheduler.timesteps:
363
+ inputs = noisy_latents
364
+ with accelerator.autocast():
365
+ noise_pred = unet(sample=inputs, timestep=t, encoder_hidden_states=c_new,
366
+ down_block_additional_residuals=copy.deepcopy(down_block_additional_residuals) if down_block_additional_residuals else None,
367
+ up_block_additional_residuals=copy.deepcopy(up_block_additional_residuals) if up_block_additional_residuals else None)
368
+ noisy_latents = inverse_noise_scheduler.step(noise_pred, t, noisy_latents)[0]
369
+
370
+ return noisy_latents
371
+
372
+
373
+ def postprocess_image(tensor, nrow):
374
+ tensor = tensor * 255.
375
+ tensor = torch.clamp(tensor, min=0., max=255.)
376
+ tensor = rearrange(tensor, 'n b c h w -> b n c h w')
377
+ tensor = rearrange(tensor, 'b n c h w -> (b n) c h w')
378
+ tensor = make_grid(tensor, nrow=nrow)
379
+ img = tensor.cpu().numpy().transpose(1, 2, 0).astype(np.uint8)
380
+ return Image.fromarray(img)
381
+
382
+
383
+ def main(cfg):
384
+ project_dir = os.path.join("outputs", cfg.ACCELERATE.PROJECT_NAME)
385
+ run_dir = os.path.join(project_dir, cfg.ACCELERATE.RUN_NAME)
386
+ os.makedirs(run_dir, exist_ok=True)
387
+
388
+ accelerator = Accelerator(
389
+ log_with = ["wandb", "tensorboard"],
390
+ project_dir = project_dir,
391
+ mixed_precision = cfg.ACCELERATE.MIXED_PRECISION
392
+ )
393
+ torch.backends.cuda.matmul.allow_tf32 = cfg.ACCELERATE.ALLOW_TF32
394
+ set_seed(cfg.ACCELERATE.SEED)
395
+
396
+ if accelerator.is_main_process:
397
+ accelerator.trackers = []
398
+ accelerator.trackers.append(WandBTracker(
399
+ cfg.ACCELERATE.PROJECT_NAME, name=cfg.ACCELERATE.RUN_NAME, config=cfg, dir=project_dir))
400
+ accelerator.trackers.append(TensorBoardTracker(cfg.ACCELERATE.RUN_NAME, project_dir))
401
+
402
+ with open(os.path.join(run_dir, "config.yaml"), "w") as f:
403
+ f.write(cfg.dump())
404
+ accelerator.wait_for_everyone()
405
+
406
+ fmt = "[%(asctime)s %(filename)s:%(lineno)s] %(message)s"
407
+ datefmt = "%Y-%m-%d %H:%M:%S"
408
+ logging.basicConfig(
409
+ level = logging.INFO,
410
+ format = fmt,
411
+ datefmt = datefmt,
412
+ filename = f"{run_dir}/log_rank{accelerator.process_index}.txt",
413
+ filemode = "a"
414
+ )
415
+ if accelerator.is_main_process:
416
+ console_handler = logging.StreamHandler(sys.stdout)
417
+ console_handler.setLevel(logging.INFO)
418
+ console_handler.setFormatter(logging.Formatter(fmt, datefmt))
419
+ logger.addHandler(console_handler)
420
+
421
+ logger.info(f"running with config:\n{str(cfg)}")
422
+
423
+ logger.info("preparing datasets...")
424
+ test_loader, fid_real_loader, test_data, fid_real_data = build_test_loader(cfg)
425
+
426
+ logger.info("preparing model...")
427
+ weight_dtype = torch.float32
428
+ if accelerator.mixed_precision == "fp16":
429
+ weight_dtype = torch.float16
430
+ elif accelerator.mixed_precision == "bf16":
431
+ weight_dtype = torch.bfloat16
432
+
433
+ # not trained, move to 16-bit to save memory
434
+ vae = VariationalAutoencoder(
435
+ pretrained_path=cfg.MODEL.FIRST_STAGE_CONFIG.PRETRAINED_PATH
436
+ ).to(accelerator.device, dtype=weight_dtype)
437
+
438
+ if cfg.MODEL.SCHEDULER_CONFIG.NAME == "euler":
439
+ noise_scheduler = EulerDiscreteScheduler.from_pretrained(cfg.MODEL.SCHEDULER_CONFIG.PRETRAINED_PATH)
440
+ elif cfg.MODEL.SCHEDULER_CONFIG.NAME == "pndm":
441
+ noise_scheduler = PNDMScheduler.from_pretrained(cfg.MODEL.SCHEDULER_CONFIG.PRETRAINED_PATH)
442
+ elif cfg.MODEL.SCHEDULER_CONFIG.NAME == "ddim":
443
+ noise_scheduler = DDIMScheduler.from_pretrained(cfg.MODEL.SCHEDULER_CONFIG.PRETRAINED_PATH)
444
+ elif cfg.MODEL.SCHEDULER_CONFIG.NAME == "ddpm":
445
+ noise_scheduler = DDPMScheduler.from_pretrained(cfg.MODEL.SCHEDULER_CONFIG.PRETRAINED_PATH)
446
+
447
+ inverse_noise_scheduler = DDIMInverseScheduler(
448
+ num_train_timesteps=noise_scheduler.num_train_timesteps,
449
+ beta_start=noise_scheduler.beta_start,
450
+ beta_end=noise_scheduler.beta_end,
451
+ beta_schedule=noise_scheduler.beta_schedule,
452
+ trained_betas=noise_scheduler.trained_betas,
453
+ clip_sample=noise_scheduler.clip_sample,
454
+ set_alpha_to_one=noise_scheduler.set_alpha_to_one,
455
+ steps_offset=noise_scheduler.steps_offset,
456
+ prediction_type=noise_scheduler.prediction_type,
457
+ timestep_spacing=noise_scheduler.timestep_spacing
458
+ )
459
+
460
+ from pose_transfer_train import build_model
461
+ model = build_model(cfg)
462
+ unet = UNet(cfg)
463
+ metric = build_metric().to(accelerator.device)
464
+
465
+ logger.info(model.load_state_dict(torch.load(
466
+ os.path.join(cfg.MODEL.PRETRAINED_PATH, "pytorch_model.bin"), map_location="cpu"
467
+ ), strict=False))
468
+ logger.info(unet.load_state_dict(torch.load(
469
+ os.path.join(cfg.MODEL.PRETRAINED_PATH, "pytorch_model_1.bin"), map_location="cpu"
470
+ ), strict=False))
471
+
472
+ logger.info("preparing accelerator...")
473
+ model, unet, test_loader, fid_real_loader = accelerator.prepare(model, unet, test_loader, fid_real_loader)
474
+
475
+ save_dir = os.path.join(run_dir, "log_images")
476
+ os.makedirs(save_dir, exist_ok=True)
477
+
478
+ eval(
479
+ cfg=cfg,
480
+ model=model,
481
+ test_loader=test_loader,
482
+ fid_real_loader=fid_real_loader,
483
+ weight_dtype=weight_dtype,
484
+ save_dir=save_dir,
485
+ test_data=test_data,
486
+ fid_real_data=fid_real_data,
487
+ global_step=None,
488
+ accelerator=accelerator,
489
+ metric=metric,
490
+ noise_scheduler=noise_scheduler,
491
+ inverse_noise_scheduler=inverse_noise_scheduler,
492
+ vae=vae,
493
+ unet=unet
494
+ )
495
+
496
+ accelerator.end_training()
497
+
498
+
499
+ if __name__ == "__main__":
500
+ parser = argparse.ArgumentParser(description="Pose Transfer Testing")
501
+ parser.add_argument("--config_file", type=str, default="", help="path to config file")
502
+ parser.add_argument("opts", default=None, nargs=argparse.REMAINDER, help=
503
+ "modify config options using the command-line")
504
+ args = parser.parse_args()
505
+
506
+ if args.config_file:
507
+ cfg.merge_from_file(args.config_file)
508
+ cfg.merge_from_list(args.opts)
509
+ cfg.freeze()
510
+
511
+ main(cfg)
pose_transfer_train.py ADDED
@@ -0,0 +1,385 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ @author: Yanzuo Lu
3
+ @author: oliveryanzuolu@gmail.com
4
+ """
5
+
6
+ import argparse
7
+ import datetime
8
+ import logging
9
+ import os
10
+ import sys
11
+ import time
12
+ import warnings
13
+
14
+ import torch
15
+ import torch.nn as nn
16
+ from accelerate import Accelerator
17
+ from accelerate.tracking import TensorBoardTracker, WandBTracker
18
+ from accelerate.utils import DistributedDataParallelKwargs, set_seed
19
+ from diffusers import (DDIMInverseScheduler, DDIMScheduler, DDPMScheduler,
20
+ EulerDiscreteScheduler, PNDMScheduler)
21
+ from torch.utils.data import DataLoader
22
+
23
+ from datasets import PisTrainDeepFashion
24
+ from defaults import pose_transfer_C as cfg
25
+ from lr_scheduler import LinearWarmupMultiStepDecayLRScheduler
26
+ from models import (AppearanceEncoder, Decoder, PoseEncoder, UNet,
27
+ VariationalAutoencoder, build_backbone, build_metric)
28
+ from pose_transfer_test import build_test_loader, eval
29
+ from utils import AverageMeter
30
+
31
+ warnings.filterwarnings("ignore")
32
+ logger = logging.getLogger()
33
+
34
+
35
+ class build_model(nn.Module):
36
+ def __init__(self, cfg):
37
+ super().__init__()
38
+ self.pose_query = cfg.MODEL.DECODER_CONFIG.POSE_QUERY
39
+
40
+ self.backbone = build_backbone(
41
+ img_size=cfg.INPUT.COND.IMG_SIZE,
42
+ embed_dim=cfg.MODEL.COND_STAGE_CONFIG.EMBED_DIM,
43
+ depths=cfg.MODEL.COND_STAGE_CONFIG.DEPTHS,
44
+ num_heads=cfg.MODEL.COND_STAGE_CONFIG.NUM_HEADS,
45
+ window_size=cfg.MODEL.COND_STAGE_CONFIG.WINDOW_SIZE,
46
+ drop_path_rate=cfg.MODEL.COND_STAGE_CONFIG.DROP_PATH_RATE,
47
+ mask=len(cfg.INPUT.COND.PRED_RATIO) > 0,
48
+ last_norm=cfg.MODEL.COND_STAGE_CONFIG.LAST_NORM,
49
+ pretrained_path=cfg.MODEL.COND_STAGE_CONFIG.PRETRAINED_PATH
50
+ )
51
+
52
+ self.appearance_encoder = AppearanceEncoder(
53
+ attn_residual_block_idx=cfg.MODEL.APPEARANCE_GUIDANCE_CONFIG.ATTN_RESIDUAL_BLOCK_IDX,
54
+ inner_dims=cfg.MODEL.APPEARANCE_GUIDANCE_CONFIG.INNER_DIMS,
55
+ ctx_dims=cfg.MODEL.APPEARANCE_GUIDANCE_CONFIG.CTX_DIMS,
56
+ embed_dims=cfg.MODEL.APPEARANCE_GUIDANCE_CONFIG.EMBED_DIMS,
57
+ heads=cfg.MODEL.APPEARANCE_GUIDANCE_CONFIG.HEADS,
58
+ depth=cfg.MODEL.APPEARANCE_GUIDANCE_CONFIG.DEPTH,
59
+ to_self_attn=cfg.MODEL.APPEARANCE_GUIDANCE_CONFIG.TO_SELF_ATTN,
60
+ to_queries=cfg.MODEL.APPEARANCE_GUIDANCE_CONFIG.TO_QUERIES,
61
+ to_keys=cfg.MODEL.APPEARANCE_GUIDANCE_CONFIG.TO_KEYS,
62
+ to_values=cfg.MODEL.APPEARANCE_GUIDANCE_CONFIG.TO_VALUES,
63
+ aspect_ratio=cfg.INPUT.COND.IMG_SIZE[0] // cfg.INPUT.COND.IMG_SIZE[1],
64
+ detach_input=cfg.MODEL.APPEARANCE_GUIDANCE_CONFIG.DETACH_INPUT,
65
+ convin_kernel_size=cfg.MODEL.APPEARANCE_GUIDANCE_CONFIG.CONVIN_KERNEL_SIZE,
66
+ convin_stride=cfg.MODEL.APPEARANCE_GUIDANCE_CONFIG.CONVIN_STRIDE,
67
+ convin_padding=cfg.MODEL.APPEARANCE_GUIDANCE_CONFIG.CONVIN_PADDING
68
+ )
69
+
70
+ self.pose_encoder = PoseEncoder(
71
+ downscale_factor=cfg.MODEL.POSE_GUIDANCE_CONFIG.DOWNSCALE_FACTOR,
72
+ pose_channels=cfg.MODEL.POSE_GUIDANCE_CONFIG.POSE_CHANNELS,
73
+ in_channels=cfg.MODEL.POSE_GUIDANCE_CONFIG.IN_CHANNELS,
74
+ channels=cfg.MODEL.POSE_GUIDANCE_CONFIG.CHANNELS
75
+ )
76
+
77
+ self.decoder = Decoder(
78
+ n_ctx=cfg.MODEL.DECODER_CONFIG.N_CTX,
79
+ ctx_dim=cfg.MODEL.DECODER_CONFIG.CTX_DIM,
80
+ heads=cfg.MODEL.DECODER_CONFIG.HEADS,
81
+ depth=cfg.MODEL.DECODER_CONFIG.DEPTH,
82
+ last_norm=cfg.MODEL.COND_STAGE_CONFIG.LAST_NORM,
83
+ img_size=cfg.INPUT.COND.IMG_SIZE,
84
+ embed_dim=cfg.MODEL.COND_STAGE_CONFIG.EMBED_DIM,
85
+ depths=cfg.MODEL.COND_STAGE_CONFIG.DEPTHS,
86
+ pose_query=cfg.MODEL.DECODER_CONFIG.POSE_QUERY,
87
+ pose_channel=cfg.MODEL.POSE_GUIDANCE_CONFIG.CHANNELS[-1]
88
+ )
89
+
90
+ self.learnable_vector = nn.Parameter(torch.randn((1, cfg.MODEL.DECODER_CONFIG.N_CTX, cfg.MODEL.DECODER_CONFIG.CTX_DIM)))
91
+ self.u_cond_percent = cfg.MODEL.U_COND_PERCENT
92
+ self.u_cond_down_block_guidance = cfg.MODEL.U_COND_DOWN_BLOCK_GUIDANCE
93
+ self.u_cond_up_block_guidance = cfg.MODEL.U_COND_UP_BLOCK_GUIDANCE
94
+
95
+ def forward(self, batched_inputs):
96
+ mask = batched_inputs["mask"] if "mask" in batched_inputs else None
97
+ x, features = self.backbone(batched_inputs["img_cond"], mask=mask)
98
+ up_block_additional_residuals = self.appearance_encoder(features)
99
+
100
+ bsz = x.shape[0]
101
+ if self.training:
102
+ bsz = bsz * 2
103
+ down_block_additional_residuals = self.pose_encoder(torch.cat([batched_inputs["pose_img_src"], batched_inputs["pose_img_tgt"]]))
104
+ up_block_additional_residuals = {k: torch.cat([v, v]) for k, v in up_block_additional_residuals.items()}
105
+ c = self.decoder(x, features, down_block_additional_residuals)
106
+ if not self.pose_query:
107
+ c = torch.cat([c, c])
108
+
109
+ u_cond_prop = torch.rand(bsz, 1, 1)
110
+ u_cond_prop = (u_cond_prop < self.u_cond_percent).to(dtype=x.dtype, device=x.device)
111
+ c = self.learnable_vector.expand(bsz, -1, -1).to(dtype=x.dtype) * u_cond_prop + c * (1 - u_cond_prop)
112
+ if self.u_cond_down_block_guidance:
113
+ down_block_additional_residuals = [torch.zeros_like(sample) * u_cond_prop.unsqueeze(1) + \
114
+ sample * (1 - u_cond_prop.unsqueeze(1)) \
115
+ for sample in down_block_additional_residuals]
116
+ if self.u_cond_up_block_guidance:
117
+ up_block_additional_residuals = {k: torch.zeros_like(v) * u_cond_prop + v * (1 - u_cond_prop) \
118
+ for k, v in up_block_additional_residuals.items()}
119
+ else:
120
+ down_block_additional_residuals = self.pose_encoder(batched_inputs["pose_img"])
121
+ c = self.decoder(x, features, down_block_additional_residuals)
122
+ c = torch.cat([self.learnable_vector.expand(bsz, -1, -1).to(dtype=x.dtype), c], dim=0)
123
+
124
+ return c, down_block_additional_residuals, up_block_additional_residuals
125
+
126
+
127
+ def main(cfg):
128
+ project_dir = os.path.join("outputs", cfg.ACCELERATE.PROJECT_NAME)
129
+ run_dir = os.path.join(project_dir, cfg.ACCELERATE.RUN_NAME)
130
+ os.makedirs(run_dir, exist_ok=True)
131
+
132
+ accelerator = Accelerator(
133
+ log_with=["wandb", "tensorboard"],
134
+ project_dir=project_dir,
135
+ mixed_precision=cfg.ACCELERATE.MIXED_PRECISION,
136
+ gradient_accumulation_steps=cfg.ACCELERATE.GRADIENT_ACCUMULATION_STEPS,
137
+ kwargs_handlers=[DistributedDataParallelKwargs(bucket_cap_mb=200, gradient_as_bucket_view=True)]
138
+ )
139
+ torch.backends.cuda.matmul.allow_tf32 = cfg.ACCELERATE.ALLOW_TF32
140
+ set_seed(cfg.ACCELERATE.SEED)
141
+
142
+ if accelerator.is_main_process:
143
+ accelerator.trackers = []
144
+ accelerator.trackers.append(WandBTracker(
145
+ cfg.ACCELERATE.PROJECT_NAME, name=cfg.ACCELERATE.RUN_NAME, config=cfg, dir=project_dir))
146
+ accelerator.trackers.append(TensorBoardTracker(cfg.ACCELERATE.RUN_NAME, project_dir))
147
+
148
+ with open(os.path.join(run_dir, "config.yaml"), "w") as f:
149
+ f.write(cfg.dump())
150
+ accelerator.wait_for_everyone()
151
+
152
+ fmt = "[%(asctime)s %(filename)s:%(lineno)s] %(message)s"
153
+ datefmt = "%Y-%m-%d %H:%M:%S"
154
+ logging.basicConfig(
155
+ level=logging.INFO,
156
+ format=fmt,
157
+ datefmt=datefmt,
158
+ filename=f"{run_dir}/log_rank{accelerator.process_index}.txt",
159
+ filemode="a"
160
+ )
161
+ if accelerator.is_main_process:
162
+ console_handler = logging.StreamHandler(sys.stdout)
163
+ console_handler.setLevel(logging.INFO)
164
+ console_handler.setFormatter(logging.Formatter(fmt, datefmt))
165
+ logger.addHandler(console_handler)
166
+
167
+ logger.info(f"running with config:\n{str(cfg)}")
168
+
169
+ logger.info("preparing datasets...")
170
+ train_data = PisTrainDeepFashion(
171
+ root_dir=cfg.INPUT.ROOT_DIR,
172
+ gt_img_size=cfg.INPUT.GT.IMG_SIZE,
173
+ pose_img_size=cfg.INPUT.POSE.IMG_SIZE,
174
+ cond_img_size=cfg.INPUT.COND.IMG_SIZE,
175
+ min_scale=cfg.INPUT.COND.MIN_SCALE,
176
+ log_aspect_ratio=cfg.INPUT.COND.PRED_ASPECT_RATIO,
177
+ pred_ratio=cfg.INPUT.COND.PRED_RATIO,
178
+ pred_ratio_var=cfg.INPUT.COND.PRED_RATIO_VAR,
179
+ psz=cfg.INPUT.COND.MASK_PATCH_SIZE
180
+ )
181
+ train_loader = DataLoader(
182
+ train_data,
183
+ cfg.INPUT.BATCH_SIZE // accelerator.num_processes // cfg.ACCELERATE.GRADIENT_ACCUMULATION_STEPS,
184
+ shuffle = True,
185
+ drop_last = True,
186
+ num_workers = cfg.INPUT.NUM_WORKERS,
187
+ pin_memory = True
188
+ )
189
+
190
+ test_loader, fid_real_loader, test_data, fid_real_data = build_test_loader(cfg)
191
+
192
+ logger.info("preparing model...")
193
+ weight_dtype = torch.float32
194
+ if accelerator.mixed_precision == "fp16":
195
+ weight_dtype = torch.float16
196
+ elif accelerator.mixed_precision == "bf16":
197
+ weight_dtype = torch.bfloat16
198
+
199
+ # not trained, move to 16-bit to save memory
200
+ vae = VariationalAutoencoder(
201
+ pretrained_path=cfg.MODEL.FIRST_STAGE_CONFIG.PRETRAINED_PATH
202
+ ).to(accelerator.device, dtype=weight_dtype)
203
+
204
+ if cfg.MODEL.SCHEDULER_CONFIG.NAME == "euler":
205
+ noise_scheduler = EulerDiscreteScheduler.from_pretrained(cfg.MODEL.SCHEDULER_CONFIG.PRETRAINED_PATH)
206
+ elif cfg.MODEL.SCHEDULER_CONFIG.NAME == "pndm":
207
+ noise_scheduler = PNDMScheduler.from_pretrained(cfg.MODEL.SCHEDULER_CONFIG.PRETRAINED_PATH)
208
+ elif cfg.MODEL.SCHEDULER_CONFIG.NAME == "ddim":
209
+ noise_scheduler = DDIMScheduler.from_pretrained(cfg.MODEL.SCHEDULER_CONFIG.PRETRAINED_PATH)
210
+ elif cfg.MODEL.SCHEDULER_CONFIG.NAME == "ddpm":
211
+ noise_scheduler = DDPMScheduler.from_pretrained(cfg.MODEL.SCHEDULER_CONFIG.PRETRAINED_PATH)
212
+
213
+ inverse_noise_scheduler = DDIMInverseScheduler(
214
+ num_train_timesteps=noise_scheduler.num_train_timesteps,
215
+ beta_start=noise_scheduler.beta_start,
216
+ beta_end=noise_scheduler.beta_end,
217
+ beta_schedule=noise_scheduler.beta_schedule,
218
+ trained_betas=noise_scheduler.trained_betas,
219
+ clip_sample=noise_scheduler.clip_sample,
220
+ set_alpha_to_one=noise_scheduler.set_alpha_to_one,
221
+ steps_offset=noise_scheduler.steps_offset,
222
+ prediction_type=noise_scheduler.prediction_type,
223
+ timestep_spacing=noise_scheduler.timestep_spacing
224
+ )
225
+
226
+ model = build_model(cfg)
227
+ unet = UNet(cfg)
228
+ metric = build_metric().to(accelerator.device)
229
+ trainable_params = sum([p.numel() for p in model.parameters() if p.requires_grad] + \
230
+ [p.numel() for p in unet.parameters() if p.requires_grad])
231
+ logger.info(f"number of trainable parameters: {trainable_params}")
232
+
233
+ logger.info("preparing optimizer...")
234
+ lr = cfg.OPTIMIZER.LR * cfg.INPUT.BATCH_SIZE if cfg.OPTIMIZER.SCALE_LR else cfg.OPTIMIZER.LR
235
+ params = [p for p in model.parameters() if p.requires_grad] + \
236
+ [p for p in unet.parameters() if p.requires_grad]
237
+ optimizer = torch.optim.Adam(params, lr=lr)
238
+
239
+ logger.info("preparing accelerator...")
240
+ model, unet, optimizer, train_loader, test_loader, fid_real_loader = accelerator.prepare(
241
+ model, unet, optimizer, train_loader, test_loader, fid_real_loader)
242
+
243
+ last_epoch = cfg.MODEL.LAST_EPOCH
244
+ if cfg.MODEL.PRETRAINED_PATH:
245
+ logger.info(f"loading states from {cfg.MODEL.PRETRAINED_PATH}")
246
+ accelerator.load_state(cfg.MODEL.PRETRAINED_PATH)
247
+ global_step = last_epoch * len(train_loader)
248
+
249
+ logger.info("preparing lr scheduler...")
250
+ lr_scheduler = LinearWarmupMultiStepDecayLRScheduler(
251
+ optimizer, cfg.OPTIMIZER.WARMUP_STEPS, cfg.OPTIMIZER.WARMUP_RATE, cfg.OPTIMIZER.DECAY_RATE,
252
+ cfg.OPTIMIZER.EPOCHS, cfg.OPTIMIZER.DECAY_EPOCHS, len(train_loader),
253
+ last_epoch=len(train_loader)*last_epoch-1, override_lr=cfg.OPTIMIZER.OVERRIDE_LR)
254
+
255
+ logger.info("start training...")
256
+ start_time = time.time()
257
+ end_time = time.time()
258
+
259
+ for epoch in range(last_epoch, cfg.OPTIMIZER.EPOCHS, 1):
260
+ model.train()
261
+ unet.train()
262
+
263
+ epoch_time = time.time()
264
+ logger.info(f"epoch {epoch + 1} start")
265
+ batch_time = AverageMeter()
266
+ total_loss = AverageMeter()
267
+
268
+ for i, batch in enumerate(train_loader):
269
+ with accelerator.accumulate(model, unet):
270
+ optimizer.zero_grad()
271
+
272
+ # Convert images to latent space
273
+ with accelerator.autocast():
274
+ latents = vae.encode(torch.cat([batch["img_src"], batch["img_tgt"]]))
275
+
276
+ # Sample noise that we'll add to the latents
277
+ noise = torch.randn_like(latents)
278
+ bsz = latents.shape[0]
279
+
280
+ if cfg.MODEL.SCHEDULER_CONFIG.CUBIC_SAMPLING:
281
+ # Cubic sampling to sample a random timestep for each image
282
+ timesteps = torch.rand((bsz, ), device=accelerator.device)
283
+ timesteps = (1 - timesteps**3) * noise_scheduler.config.num_train_timesteps
284
+ timesteps = timesteps.long()
285
+ timesteps = torch.clamp(timesteps, 0, noise_scheduler.config.num_train_timesteps - 1)
286
+ else:
287
+ # Uniform sampling to sample a random timestep for each image
288
+ timesteps = torch.randint(noise_scheduler.config.num_train_timesteps, (bsz, ), device=accelerator.device)
289
+
290
+ # Add noise to the latents according to the noise magnitude at each timestep
291
+ # (this is the forward diffusion process)
292
+ noisy_latents = noise_scheduler.add_noise(latents, noise, timesteps)
293
+
294
+ # get embedding
295
+ c, down_block_additional_residuals, up_block_additional_residuals = model(batch)
296
+ down_block_additional_residuals = [sample.to(dtype=weight_dtype) for sample in down_block_additional_residuals]
297
+ up_block_additional_residuals = {k: v.to(dtype=weight_dtype) for k, v in up_block_additional_residuals.items()}
298
+
299
+ # predict
300
+ with accelerator.autocast():
301
+ encoder_hidden_states = c.to(dtype=weight_dtype)
302
+ model_pred = unet(
303
+ sample=noisy_latents, timestep=timesteps, encoder_hidden_states=encoder_hidden_states,
304
+ down_block_additional_residuals=down_block_additional_residuals,
305
+ up_block_additional_residuals=up_block_additional_residuals)
306
+
307
+ loss_simple = (noise - model_pred) ** 2
308
+ loss_simple = loss_simple.mean()
309
+ loss = loss_simple / cfg.ACCELERATE.GRADIENT_ACCUMULATION_STEPS
310
+ if torch.isnan(loss).any():
311
+ accelerator.set_trigger()
312
+ if accelerator.check_trigger():
313
+ logger.info("loss is nan, stop training")
314
+ accelerator.end_training()
315
+ time.sleep(86400) # waiting for...
316
+
317
+ accelerator.backward(loss)
318
+ if accelerator.sync_gradients:
319
+ global_step += 1
320
+ optimizer.step()
321
+ lr_scheduler.step()
322
+
323
+ total_loss.update(loss_simple.item())
324
+ batch_time.update(time.time() - end_time)
325
+ end_time = time.time()
326
+
327
+ if (i + 1) % cfg.ACCELERATE.LOG_PERIOD == 0 or i == len(train_loader) - 1:
328
+ accelerator.log({
329
+ "loss": loss_simple.item(),
330
+ "loss_avg": total_loss.avg,
331
+ "lr": optimizer.param_groups[-1]["lr"]
332
+ }, step=global_step)
333
+
334
+ etas = batch_time.avg * (len(train_loader) - 1 - i)
335
+ logger.info(
336
+ f"Train [{epoch+1}/{cfg.OPTIMIZER.EPOCHS}]({i+1}/{len(train_loader)}) "
337
+ f"Time {batch_time.val:.4f}({batch_time.avg:.4f}) "
338
+ f"Loss {total_loss.val:.4f}({total_loss.avg:.4f}) "
339
+ f"Lr {optimizer.param_groups[-1]['lr']:.8f} "
340
+ f"Eta {datetime.timedelta(seconds=int(etas))}")
341
+
342
+ logger.info(f"epoch {epoch + 1} finished, running time {datetime.timedelta(seconds=int(time.time() - epoch_time))}")
343
+ save_dir = os.path.join(run_dir, f"epochs_{(epoch+1):03d}")
344
+
345
+ if (epoch + 1) % cfg.ACCELERATE.EVAL_PERIOD == 0:
346
+ accelerator.save_state(os.path.join(save_dir, "checkpoints"))
347
+ save_dir = os.path.join(save_dir, "log_images")
348
+ os.makedirs(save_dir, exist_ok=True)
349
+
350
+ eval(
351
+ cfg=cfg,
352
+ model=model,
353
+ test_loader=test_loader,
354
+ fid_real_loader=fid_real_loader,
355
+ weight_dtype=weight_dtype,
356
+ save_dir=save_dir,
357
+ test_data=test_data,
358
+ fid_real_data=fid_real_data,
359
+ global_step=None,
360
+ accelerator=accelerator,
361
+ metric=metric,
362
+ noise_scheduler=noise_scheduler,
363
+ inverse_noise_scheduler=inverse_noise_scheduler,
364
+ vae=vae,
365
+ unet=unet
366
+ )
367
+
368
+ train_time = time.time() - start_time
369
+ logger.info(f'training completed, running time {datetime.timedelta(seconds=int(train_time))}')
370
+ accelerator.end_training()
371
+
372
+
373
+ if __name__ == "__main__":
374
+ parser = argparse.ArgumentParser(description="Pose Transfer Training")
375
+ parser.add_argument("--config_file", type=str, default="", help="path to config file")
376
+ parser.add_argument("opts", default=None, nargs=argparse.REMAINDER, help=
377
+ "modify config options using the command-line")
378
+ args = parser.parse_args()
379
+
380
+ if args.config_file:
381
+ cfg.merge_from_file(args.config_file)
382
+ cfg.merge_from_list(args.opts)
383
+ cfg.freeze()
384
+
385
+ main(cfg)
pose_utils.py ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ @author: Yanzuo Lu
3
+ @author: oliveryanzuolu@gmail.com
4
+ """
5
+
6
+ import json
7
+ import logging
8
+ import cv2
9
+
10
+ import numpy as np
11
+
12
+ logger = logging.getLogger()
13
+
14
+ BONES = [[1,2], [1,5], [2,3], [3,4], [5,6], [6,7], [1,8], [8,9],
15
+ [9,10], [1,11], [11,12], [12,13], [1,0], [0,14], [14,16],
16
+ [0,15], [15,17]]
17
+
18
+ JOINT_COLORS = [[255, 0, 0], [255, 85, 0], [255, 170, 0], [255, 255, 0], [170, 255, 0], [85, 255, 0], [0, 255, 0],
19
+ [0, 255, 85], [0, 255, 170], [0, 255, 255], [0, 170, 255], [0, 85, 255], [0, 0, 255], [85, 0, 255],
20
+ [170, 0, 255], [255, 0, 255], [255, 0, 170], [255, 0, 85]]
21
+
22
+ BONE_COLORS = [[153, 0, 0], [153, 51, 0], [153, 102, 0], [153, 153, 0], [102, 153, 0], [51, 153, 0], [0, 153, 0], [0, 153, 51],
23
+ [0, 153, 102], [0, 153, 153], [0, 102, 153], [0, 51, 153], [0, 0, 153], [51, 0, 153], [102, 0, 153],
24
+ [153, 0, 153], [153, 0, 102]]
25
+
26
+ def load_pose_cords_from_strings(y_str, x_str):
27
+ y_cords = json.loads(y_str)
28
+ x_cords = json.loads(x_str)
29
+ return np.concatenate([np.expand_dims(y_cords, -1), np.expand_dims(x_cords, -1)], axis=1)
30
+
31
+
32
+ def cords_to_map(cords, img_size, old_size=(128, 64), affine_matrix=None, sigma=6):
33
+ old_size = img_size if old_size is None else old_size
34
+ cords = cords.astype(float)
35
+ result = np.zeros(img_size + cords.shape[0:1], dtype='float32')
36
+ for i, point in enumerate(cords):
37
+ if point[0] == -1 or point[1] == -1:
38
+ continue
39
+ point[0] = point[0]/old_size[0] * img_size[0]
40
+ point[1] = point[1]/old_size[1] * img_size[1]
41
+ if affine_matrix is not None:
42
+ point_ =np.dot(affine_matrix, np.matrix([point[1], point[0], 1]).reshape(3,1))
43
+ point_0 = int(point_[1])
44
+ point_1 = int(point_[0])
45
+ else:
46
+ point_0 = int(point[0])
47
+ point_1 = int(point[1])
48
+ xx, yy = np.meshgrid(np.arange(img_size[1]), np.arange(img_size[0]))
49
+ result[..., i] = np.exp(-((yy - point_0) ** 2 + (xx - point_1) ** 2) / (2 * sigma ** 2))
50
+ return result
51
+
52
+
53
+ def draw_pose_from_cords(array, img_size, old_size=(128, 64), radius=2, draw_bones=True):
54
+ colors = np.zeros(shape=img_size + (3, ), dtype=np.uint8)
55
+ scale_y = img_size[0] / old_size[0]
56
+ scale_x = img_size[1] / old_size[1]
57
+
58
+ if draw_bones:
59
+ for i, (f, t) in enumerate(BONES):
60
+ from_missing = array[f][0] == -1 or array[f][1] == -1
61
+ to_missing = array[t][0] == -1 or array[t][1] == -1
62
+ if from_missing or to_missing:
63
+ continue
64
+ cv2.line(colors, (int(array[f][1] * scale_x), int(array[f][0] * scale_y)),
65
+ (int(array[t][1] * scale_x), int(array[t][0] * scale_y)), BONE_COLORS[i], radius, cv2.LINE_AA)
66
+
67
+ for i, joint in enumerate(array):
68
+ if array[i][0] == -1 or array[i][1] == -1:
69
+ continue
70
+ cv2.circle(colors, (int(joint[1] * scale_x), int(joint[0] * scale_y)), radius + 1, JOINT_COLORS[i], -1, cv2.LINE_AA)
71
+
72
+ return colors
requirements.txt ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ torch==2.0.1 --index-url https://download.pytorch.org/whl/cu118
2
+ torchvision==0.15.2 --index-url https://download.pytorch.org/whl/cu118
3
+ torchaudio==2.0.2 --index-url https://download.pytorch.org/whl/cu118
4
+ xformers==0.0.21
5
+ diffusers==0.19.3
6
+ transformers==4.35.0
7
+ accelerate==0.23.0
8
+ einops==0.3.0
9
+ opencv-python==4.7.0.72
10
+ timm==0.9.7
11
+ safetensors==0.3.1
12
+ scipy==1.10.1
13
+ lpips==0.1.4
14
+ tensorboard==2.13.0
15
+ wandb==0.15.11
16
+ numpy==1.23.1
17
+ yacs==0.1.6
18
+ pandas==2.0.3
19
+ scikit-image==0.20.0
20
+ huggingface-hub==0.17.3
21
+ jax==0.4.13
22
+ jaxlib==0.4.13
23
+ flax==0.7.0
24
+ fastapi==0.104.1
25
+ uvicorn==0.24.0
26
+ python-multipart==0.0.6
27
+ gradio==4.7.1
28
+ pillow==10.0.1
29
+ matplotlib==3.7.2z
scripts/multi_gpu/pose_transfer_test.sh ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ source $(dirname "${CONDA_PYTHON_EXE}")/activate CFLD
4
+ export CUDA_VISIBLE_DEVICES=$1
5
+ export NUM_GPUS=$(echo $CUDA_VISIBLE_DEVICES | awk -F "," '{print NF}')
6
+ shift
7
+
8
+ while true # find unused tcp port
9
+ do
10
+ PORT=$(( ((RANDOM<<15)|RANDOM) % 49152 + 10000 ))
11
+ status="$(nc -z 127.0.0.1 $PORT < /dev/null &>/dev/null; echo $?)"
12
+ if [ "${status}" != "0" ]; then
13
+ break;
14
+ fi
15
+ done
16
+
17
+ accelerate launch \
18
+ --multi_gpu \
19
+ --num_processes $NUM_GPUS \
20
+ --num_machines 1 \
21
+ --dynamo_backend "no" \
22
+ --main_process_port $PORT \
23
+ pose_transfer_test.py $@ \
24
+ INPUT.ROOT_DIR ./fashion
scripts/multi_gpu/pose_transfer_train.sh ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ source $(dirname "${CONDA_PYTHON_EXE}")/activate CFLD
4
+ export CUDA_VISIBLE_DEVICES=$1
5
+ export NUM_GPUS=$(echo $CUDA_VISIBLE_DEVICES | awk -F "," '{print NF}')
6
+ shift
7
+
8
+ while true # find unused tcp port
9
+ do
10
+ PORT=$(( ((RANDOM<<15)|RANDOM) % 49152 + 10000 ))
11
+ status="$(nc -z 127.0.0.1 $PORT < /dev/null &>/dev/null; echo $?)"
12
+ if [ "${status}" != "0" ]; then
13
+ break;
14
+ fi
15
+ done
16
+
17
+ accelerate launch \
18
+ --multi_gpu \
19
+ --num_processes $NUM_GPUS \
20
+ --num_machines 1 \
21
+ --dynamo_backend "no" \
22
+ --main_process_port $PORT \
23
+ pose_transfer_train.py $@ \
24
+ INPUT.ROOT_DIR ./fashion
scripts/single_gpu/pose_transfer_test.sh ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ source $(dirname "${CONDA_PYTHON_EXE}")/activate CFLD
4
+ export CUDA_VISIBLE_DEVICES=$1
5
+ shift
6
+
7
+ python pose_transfer_test.py $@ \
8
+ INPUT.ROOT_DIR ./fashion
scripts/single_gpu/pose_transfer_train.sh ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ source $(dirname "${CONDA_PYTHON_EXE}")/activate CFLD
4
+ export CUDA_VISIBLE_DEVICES=$1
5
+ shift
6
+
7
+ python pose_transfer_train.py $@ \
8
+ INPUT.ROOT_DIR ./fashion
utils.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ @author: Yanzuo Lu
3
+ @author: oliveryanzuolu@gmail.com
4
+ """
5
+
6
+ import logging
7
+
8
+ logger = logging.getLogger()
9
+
10
+
11
+ class AverageMeter:
12
+ def __init__(self):
13
+ self.val = 0
14
+ self.avg = 0
15
+ self.sum = 0
16
+ self.count = 0
17
+
18
+ def update(self, val, n=1):
19
+ self.val = val
20
+ self.sum += val * n
21
+ self.count += n
22
+ self.avg = self.sum / self.count