Elea Zhong commited on
Commit
b4df47c
·
1 Parent(s): 25daeff

add experiments

Browse files
app.py CHANGED
@@ -29,16 +29,15 @@ from qwenimage.models.qwen_fa3_processor import QwenDoubleStreamAttnProcessorFA3
29
  dtype = torch.bfloat16
30
  device = "cuda" if torch.cuda.is_available() else "cpu"
31
 
32
- exp = ExperimentRegistry.get("qwen_lightning_lora")()
33
-
34
- exp.load()
35
 
36
  @spaces.GPU(duration=1500)
37
  def optim_pipe(exp):
 
 
38
  exp.optimize()
39
  return exp.pipe
40
 
41
- pipe = optim_pipe(exp)
42
 
43
 
44
  MAX_SEED = np.iinfo(np.int32).max
 
29
  dtype = torch.bfloat16
30
  device = "cuda" if torch.cuda.is_available() else "cpu"
31
 
 
 
 
32
 
33
  @spaces.GPU(duration=1500)
34
  def optim_pipe(exp):
35
+ exp = ExperimentRegistry.get("qwen_lightning_fa3_aot_int8_fuse_2step")()
36
+ exp.load()
37
  exp.optimize()
38
  return exp.pipe
39
 
40
+ pipe = optim_pipe()
41
 
42
 
43
  MAX_SEED = np.iinfo(np.int32).max
qwenimage/experiments/experiments_qwen.py CHANGED
@@ -255,14 +255,14 @@ class Qwen_Base_3step(QwenBaseExperiment):
255
  return self.pipe(*args, **kwargs).images[0]
256
 
257
  @ExperimentRegistry.register(name="qwen_lightning_lora_2step")
258
- class Qwen_Lightning_Lora_3step(Qwen_Lightning_Lora):
259
  @ftimed
260
  def run_once(self, *args, **kwargs):
261
  kwargs["num_inference_steps"] = 2
262
  return self.pipe(*args, **kwargs).images[0]
263
 
264
  @ExperimentRegistry.register(name="qwen_base_2step")
265
- class Qwen_Base_3step(QwenBaseExperiment):
266
  @ftimed
267
  def run_once(self, *args, **kwargs):
268
  kwargs["num_inference_steps"] = 2
@@ -338,7 +338,7 @@ class Qwen_FA3_AoT_int8(QwenBaseExperiment):
338
  )
339
 
340
 
341
- # @ExperimentRegistry.register(name="qwen_fp8")
342
  class Qwen_fp8(QwenBaseExperiment):
343
  @ftimed
344
  def optimize(self):
@@ -347,7 +347,7 @@ class Qwen_fp8(QwenBaseExperiment):
347
  quantize_(self.pipe.transformer, Float8WeightOnlyConfig())
348
 
349
 
350
- # @ExperimentRegistry.register(name="qwen_int8")
351
  class Qwen_int8(QwenBaseExperiment):
352
  @ftimed
353
  def optimize(self):
@@ -410,3 +410,165 @@ class Qwen_FA3_AoT_fp8(QwenBaseExperiment):
410
 
411
  aoti_apply(compiled_transformer, self.pipe.transformer)
412
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
255
  return self.pipe(*args, **kwargs).images[0]
256
 
257
  @ExperimentRegistry.register(name="qwen_lightning_lora_2step")
258
+ class Qwen_Lightning_Lora_2step(Qwen_Lightning_Lora):
259
  @ftimed
260
  def run_once(self, *args, **kwargs):
261
  kwargs["num_inference_steps"] = 2
262
  return self.pipe(*args, **kwargs).images[0]
263
 
264
  @ExperimentRegistry.register(name="qwen_base_2step")
265
+ class Qwen_Base_2step(QwenBaseExperiment):
266
  @ftimed
267
  def run_once(self, *args, **kwargs):
268
  kwargs["num_inference_steps"] = 2
 
338
  )
339
 
340
 
341
+ @ExperimentRegistry.register(name="qwen_fp8")
342
  class Qwen_fp8(QwenBaseExperiment):
343
  @ftimed
344
  def optimize(self):
 
347
  quantize_(self.pipe.transformer, Float8WeightOnlyConfig())
348
 
349
 
350
+ @ExperimentRegistry.register(name="qwen_int8")
351
  class Qwen_int8(QwenBaseExperiment):
352
  @ftimed
353
  def optimize(self):
 
410
 
411
  aoti_apply(compiled_transformer, self.pipe.transformer)
412
 
413
+ # FA3_AoT_fp8_fuse
414
+ @ExperimentRegistry.register(name="qwen_fa3_aot_fp8_fuse")
415
+ class Qwen_FA3_AoT_fp8_fuse(QwenBaseExperiment):
416
+ @ftimed
417
+ # @spaces.GPU()
418
+ def optimize(self):
419
+ self.pipe.transformer.__class__ = QwenImageTransformer2DModel
420
+ self.pipe.transformer.set_attn_processor(QwenDoubleStreamAttnProcessorFA3())
421
+ self.pipe.transformer.fuse_qkv_projections()
422
+
423
+ pipe_kwargs={
424
+ "image": [Image.new("RGB", (1024, 1024))],
425
+ "prompt":"prompt",
426
+ "num_inference_steps":4
427
+ }
428
+ suffix="_fa3_fuse"
429
+
430
+ cache_compiled=self.config.cache_compiled
431
+
432
+ transformer_pt2_cache_path = f"checkpoints/transformer_fp8{suffix}_archive.pt2"
433
+ transformer_weights_cache_path = f"checkpoints/transformer_fp8{suffix}_weights.pt"
434
+
435
+ print(f"original model size: {get_model_size_in_bytes(self.pipe.transformer) / 1024 / 1024} MB")
436
+ quantize_(self.pipe.transformer, Float8DynamicActivationFloat8WeightConfig())
437
+ print_first_param(self.pipe.transformer)
438
+ print(f"quantized model size: {get_model_size_in_bytes(self.pipe.transformer) / 1024 / 1024} MB")
439
+
440
+ inductor_config = INDUCTOR_CONFIGS
441
+
442
+ if os.path.isfile(transformer_pt2_cache_path) and cache_compiled:
443
+ drain_module_parameters(self.pipe.transformer)
444
+ zerogpu_weights = torch.load(transformer_weights_cache_path, weights_only=False)
445
+ compiled_transformer = ZeroGPUCompiledModel(transformer_pt2_cache_path, zerogpu_weights)
446
+ else:
447
+ with spaces.aoti_capture(self.pipe.transformer) as call:
448
+ self.pipe(**pipe_kwargs)
449
+
450
+ dynamic_shapes = tree_map(lambda t: None, call.kwargs)
451
+ dynamic_shapes |= TRANSFORMER_DYNAMIC_SHAPES
452
+
453
+ exported = torch.export.export(
454
+ mod=self.pipe.transformer,
455
+ args=call.args,
456
+ kwargs=call.kwargs,
457
+ dynamic_shapes=dynamic_shapes,
458
+ )
459
+
460
+ compiled_transformer = spaces.aoti_compile(exported, inductor_config)
461
+ with open(transformer_pt2_cache_path, "wb") as f:
462
+ f.write(compiled_transformer.archive_file.getvalue())
463
+ torch.save(compiled_transformer.weights, transformer_weights_cache_path)
464
+
465
+
466
+ aoti_apply(compiled_transformer, self.pipe.transformer)
467
+
468
+
469
+
470
+ # FA3_AoT_int8_fuse
471
+ @ExperimentRegistry.register(name="qwen_fa3_aot_int8_fuse")
472
+ class Qwen_FA3_AoT_int8_fuse(QwenBaseExperiment):
473
+ @ftimed
474
+ def optimize(self):
475
+ self.pipe.transformer.__class__ = QwenImageTransformer2DModel
476
+ self.pipe.transformer.set_attn_processor(QwenDoubleStreamAttnProcessorFA3())
477
+ self.pipe.transformer.fuse_qkv_projections()
478
+ optimize_pipeline_(
479
+ self.pipe,
480
+ cache_compiled=self.config.cache_compiled,
481
+ quantize=True,
482
+ suffix="_fa3_fuse",
483
+ pipe_kwargs={
484
+ "image": [Image.new("RGB", (1024, 1024))],
485
+ "prompt":"prompt",
486
+ "num_inference_steps":4
487
+ }
488
+ )
489
+
490
+ # lightning_FA3_AoT_fp8_fuse
491
+
492
+ @ExperimentRegistry.register(name="qwen_lightning_fa3_aot_fp8_fuse")
493
+ class Qwen_lightning_FA3_AoT_fp8_fuse(Qwen_Lightning_Lora):
494
+ @ftimed
495
+ # @spaces.GPU()
496
+ def optimize(self):
497
+ self.pipe.transformer.__class__ = QwenImageTransformer2DModel
498
+ self.pipe.transformer.set_attn_processor(QwenDoubleStreamAttnProcessorFA3())
499
+ self.pipe.transformer.fuse_qkv_projections()
500
+
501
+ pipe_kwargs={
502
+ "image": [Image.new("RGB", (1024, 1024))],
503
+ "prompt":"prompt",
504
+ "num_inference_steps":4
505
+ }
506
+ suffix="_fa3_fuse"
507
+
508
+ cache_compiled=self.config.cache_compiled
509
+
510
+ transformer_pt2_cache_path = f"checkpoints/transformer_fp8{suffix}_archive.pt2"
511
+ transformer_weights_cache_path = f"checkpoints/transformer_fp8{suffix}_weights.pt"
512
+
513
+ print(f"original model size: {get_model_size_in_bytes(self.pipe.transformer) / 1024 / 1024} MB")
514
+ quantize_(self.pipe.transformer, Float8DynamicActivationFloat8WeightConfig())
515
+ print_first_param(self.pipe.transformer)
516
+ print(f"quantized model size: {get_model_size_in_bytes(self.pipe.transformer) / 1024 / 1024} MB")
517
+
518
+ inductor_config = INDUCTOR_CONFIGS
519
+
520
+ if os.path.isfile(transformer_pt2_cache_path) and cache_compiled:
521
+ drain_module_parameters(self.pipe.transformer)
522
+ zerogpu_weights = torch.load(transformer_weights_cache_path, weights_only=False)
523
+ compiled_transformer = ZeroGPUCompiledModel(transformer_pt2_cache_path, zerogpu_weights)
524
+ else:
525
+ with spaces.aoti_capture(self.pipe.transformer) as call:
526
+ self.pipe(**pipe_kwargs)
527
+
528
+ dynamic_shapes = tree_map(lambda t: None, call.kwargs)
529
+ dynamic_shapes |= TRANSFORMER_DYNAMIC_SHAPES
530
+
531
+ exported = torch.export.export(
532
+ mod=self.pipe.transformer,
533
+ args=call.args,
534
+ kwargs=call.kwargs,
535
+ dynamic_shapes=dynamic_shapes,
536
+ )
537
+
538
+ compiled_transformer = spaces.aoti_compile(exported, inductor_config)
539
+ with open(transformer_pt2_cache_path, "wb") as f:
540
+ f.write(compiled_transformer.archive_file.getvalue())
541
+ torch.save(compiled_transformer.weights, transformer_weights_cache_path)
542
+
543
+
544
+ aoti_apply(compiled_transformer, self.pipe.transformer)
545
+
546
+
547
+ # lightning_FA3_AoT_int8_fuse
548
+
549
+ @ExperimentRegistry.register(name="qwen_lightning_fa3_aot_int8_fuse")
550
+ class Qwen_Lightning_FA3_AoT_int8_fuse(Qwen_Lightning_Lora):
551
+ @ftimed
552
+ def optimize(self):
553
+ self.pipe.transformer.__class__ = QwenImageTransformer2DModel
554
+ self.pipe.transformer.set_attn_processor(QwenDoubleStreamAttnProcessorFA3())
555
+ self.pipe.transformer.fuse_qkv_projections()
556
+ optimize_pipeline_(
557
+ self.pipe,
558
+ cache_compiled=self.config.cache_compiled,
559
+ quantize=True,
560
+ suffix="_fa3_fuse",
561
+ pipe_kwargs={
562
+ "image": [Image.new("RGB", (1024, 1024))],
563
+ "prompt":"prompt",
564
+ "num_inference_steps":4
565
+ }
566
+ )
567
+
568
+
569
+ @ExperimentRegistry.register(name="qwen_lightning_fa3_aot_int8_fuse_2step")
570
+ class Qwen_Lightning_FA3_AoT_int8_fuse_2step(Qwen_Lightning_FA3_AoT_int8_fuse):
571
+ @ftimed
572
+ def run_once(self, *args, **kwargs):
573
+ kwargs["num_inference_steps"] = 2
574
+ return self.pipe(*args, **kwargs).images[0]
scripts/plot_data.ipynb CHANGED
The diff for this file is too large to render. See raw diff
 
scripts/visual_compare.ipynb CHANGED
@@ -2,25 +2,17 @@
2
  "cells": [
3
  {
4
  "cell_type": "code",
5
- "execution_count": 1,
6
  "id": "e5649df3",
7
  "metadata": {},
8
- "outputs": [
9
- {
10
- "name": "stdout",
11
- "output_type": "stream",
12
- "text": [
13
- "/home/ubuntu/Qwen-Image-Edit-Angles\n"
14
- ]
15
- }
16
- ],
17
  "source": [
18
  "%cd /home/ubuntu/Qwen-Image-Edit-Angles"
19
  ]
20
  },
21
  {
22
  "cell_type": "code",
23
- "execution_count": 2,
24
  "metadata": {},
25
  "outputs": [],
26
  "source": [
@@ -30,53 +22,43 @@
30
  },
31
  {
32
  "cell_type": "code",
33
- "execution_count": 3,
34
  "metadata": {},
35
- "outputs": [
36
- {
37
- "name": "stderr",
38
- "output_type": "stream",
39
- "text": [
40
- "/home/ubuntu/.local/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
41
- " from .autonotebook import tqdm as notebook_tqdm\n",
42
- "/usr/lib/python3/dist-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.17.3 and <1.25.0 is required for this version of SciPy (detected version 1.26.4\n",
43
- " warnings.warn(f\"A NumPy version >={np_minversion} and <{np_maxversion}\"\n",
44
- "Skipping import of cpp extensions due to incompatible torch version 2.9.1+cu128 for torchao version 0.14.1 Please see https://github.com/pytorch/ao/issues/2919 for more info\n",
45
- "TMA benchmarks will be running without grid constant TMA descriptor.\n",
46
- "2025-11-13 17:17:45.758469: I tensorflow/core/util/port.cc:153] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.\n",
47
- "2025-11-13 17:17:45.772437: E external/local_xla/xla/stream_executor/cuda/cuda_fft.cc:467] Unable to register cuFFT factory: Attempting to register factory for plugin cuFFT when one has already been registered\n",
48
- "WARNING: All log messages before absl::InitializeLog() is called are written to STDERR\n",
49
- "E0000 00:00:1763054265.789504 1013472 cuda_dnn.cc:8579] Unable to register cuDNN factory: Attempting to register factory for plugin cuDNN when one has already been registered\n",
50
- "E0000 00:00:1763054265.795008 1013472 cuda_blas.cc:1407] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered\n",
51
- "W0000 00:00:1763054265.808263 1013472 computation_placer.cc:177] computation placer already registered. Please check linkage and avoid linking the same target more than once.\n",
52
- "W0000 00:00:1763054265.808277 1013472 computation_placer.cc:177] computation placer already registered. Please check linkage and avoid linking the same target more than once.\n",
53
- "W0000 00:00:1763054265.808280 1013472 computation_placer.cc:177] computation placer already registered. Please check linkage and avoid linking the same target more than once.\n",
54
- "W0000 00:00:1763054265.808281 1013472 computation_placer.cc:177] computation placer already registered. Please check linkage and avoid linking the same target more than once.\n",
55
- "2025-11-13 17:17:45.812477: I tensorflow/core/platform/cpu_feature_guard.cc:210] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.\n",
56
- "To enable the following instructions: AVX512F AVX512_VNNI AVX512_BF16 AVX512_FP16 AVX_VNNI, in other operations, rebuild TensorFlow with the appropriate compiler flags.\n",
57
- "Fetching 7 files: 100%|██████████| 7/7 [00:00<00:00, 81555.91it/s]\n"
58
- ]
59
- }
60
- ],
61
  "source": [
62
  "from qwenimage.experiment import ExperimentConfig\n",
63
  "from qwenimage.experiments.experiments_qwen import ExperimentRegistry\n",
64
  "\n",
65
  "\n",
66
  "# experiment_names = ExperimentRegistry.keys()\n",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  "experiment_names = [\n",
68
- " \"qwen_base\",\n",
69
  " # \"qwen_fa3\",\n",
70
  " # \"qwen_aot\",\n",
71
  " # \"qwen_fa3_aot\",\n",
72
- " # \"qwen_fa3_aot_int8\",\n",
73
- " # \"qwen_fa3_aot_fp8\",\n",
74
- " # \"qwen_fuse\",\n",
75
- " \"qwen_base_3step\",\n",
76
- " \"qwen_base_2step\",\n",
77
- " \"qwen_lightning_lora\",\n",
78
- " \"qwen_lightning_lora_3step\",\n",
79
- " \"qwen_lightning_lora_2step\",\n",
 
80
  "]\n",
81
  "\n",
82
  "report_dir = ExperimentConfig().report_dir\n",
@@ -94,21 +76,10 @@
94
  },
95
  {
96
  "cell_type": "code",
97
- "execution_count": 23,
98
  "id": "29077eb8",
99
  "metadata": {},
100
- "outputs": [
101
- {
102
- "data": {
103
- "text/plain": [
104
- "PosixPath('reports/qwen_base_outputs/000.jpg')"
105
- ]
106
- },
107
- "execution_count": 23,
108
- "metadata": {},
109
- "output_type": "execute_result"
110
- }
111
- ],
112
  "source": [
113
  "experiment_outputs[\"qwen_base\"][0]"
114
  ]
@@ -119,119 +90,7 @@
119
  "id": "a591fdd6",
120
  "metadata": {},
121
  "outputs": [],
122
- "source": [
123
- "\n",
124
- "import lpips\n",
125
- "import torch\n",
126
- "from PIL import Image\n",
127
- "import torchvision.transforms as transforms\n",
128
- "\n",
129
- "# Initialize LPIPS model\n",
130
- "loss_fn = lpips.LPIPS(net='alex') # or 'vgg' or 'squeeze'\n",
131
- "if torch.cuda.is_available():\n",
132
- " loss_fn = loss_fn.cuda()\n",
133
- "\n",
134
- "# Transform to convert PIL images to tensors\n",
135
- "transform = transforms.Compose([\n",
136
- " transforms.ToTensor(),\n",
137
- " transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])\n",
138
- "])\n",
139
- "\n",
140
- "def calculate_lpips_scores(base_paths, compare_paths):\n",
141
- " \"\"\"Calculate LPIPS scores between two sets of images.\"\"\"\n",
142
- " scores = []\n",
143
- " \n",
144
- " # Get the minimum number of images available\n",
145
- " num_images = min(len(base_paths), len(compare_paths))\n",
146
- " \n",
147
- " for idx in range(num_images):\n",
148
- " # Load images\n",
149
- " img1 = Image.open(base_paths[idx]).convert('RGB')\n",
150
- " img2 = Image.open(compare_paths[idx]).convert('RGB')\n",
151
- " \n",
152
- " # Resize if dimensions don't match\n",
153
- " if img1.size != img2.size:\n",
154
- " img2 = img2.resize(img1.size, Image.LANCZOS)\n",
155
- " \n",
156
- " # Transform to tensors\n",
157
- " img1_tensor = transform(img1).unsqueeze(0)\n",
158
- " img2_tensor = transform(img2).unsqueeze(0)\n",
159
- " \n",
160
- " if torch.cuda.is_available():\n",
161
- " img1_tensor = img1_tensor.cuda()\n",
162
- " img2_tensor = img2_tensor.cuda()\n",
163
- " \n",
164
- " # Calculate LPIPS\n",
165
- " with torch.no_grad():\n",
166
- " score = loss_fn(img1_tensor, img2_tensor)\n",
167
- " \n",
168
- " scores.append(score.item())\n",
169
- " \n",
170
- " return scores\n",
171
- "\n",
172
- "# Define experiment sets\n",
173
- "experiment_sets = {\n",
174
- " 'qwen_base': {\n",
175
- " '4step': 'qwen_base',\n",
176
- " '3step': 'qwen_base_3step',\n",
177
- " '2step': 'qwen_base_2step'\n",
178
- " },\n",
179
- " 'qwen_lightning_lora': {\n",
180
- " '4step': 'qwen_lightning_lora',\n",
181
- " '3step': 'qwen_lightning_lora_3step',\n",
182
- " '2step': 'qwen_lightning_lora_2step'\n",
183
- " }\n",
184
- "}\n",
185
- "\n",
186
- "# Calculate LPIPS scores for each set\n",
187
- "results = {}\n",
188
- "\n",
189
- "for set_name, experiments in experiment_sets.items():\n",
190
- " print(f\"\\nProcessing {set_name}...\")\n",
191
- " \n",
192
- " # Get image paths\n",
193
- " base_4step_paths = experiment_outputs[experiments['4step']]\n",
194
- " step_3_paths = experiment_outputs[experiments['3step']]\n",
195
- " step_2_paths = experiment_outputs[experiments['2step']]\n",
196
- " \n",
197
- " # Calculate LPIPS scores\n",
198
- " print(f\"Calculating LPIPS: 4-step vs 3-step...\")\n",
199
- " scores_4vs3 = calculate_lpips_scores(base_4step_paths, step_3_paths)\n",
200
- " \n",
201
- " print(f\"Calculating LPIPS: 4-step vs 2-step...\")\n",
202
- " scores_4vs2 = calculate_lpips_scores(base_4step_paths, step_2_paths)\n",
203
- " \n",
204
- " # Create results dataframe\n",
205
- " results_df = pd.DataFrame({\n",
206
- " 'comparison': ['4step_vs_3step', '4step_vs_2step'],\n",
207
- " 'mean_lpips': [\n",
208
- " np.mean(scores_4vs3),\n",
209
- " np.mean(scores_4vs2)\n",
210
- " ],\n",
211
- " 'std_lpips': [\n",
212
- " np.std(scores_4vs3),\n",
213
- " np.std(scores_4vs2)\n",
214
- " ],\n",
215
- " 'num_samples': [\n",
216
- " len(scores_4vs3),\n",
217
- " len(scores_4vs2)\n",
218
- " ]\n",
219
- " })\n",
220
- " \n",
221
- " # Save to CSV\n",
222
- " csv_path = report_dir / f\"lpips_scores_{set_name}.csv\"\n",
223
- " results_df.to_csv(csv_path, index=False)\n",
224
- " \n",
225
- " print(f\"\\nResults for {set_name}:\")\n",
226
- " print(results_df)\n",
227
- " print(f\"\\nSaved to: {csv_path}\")\n",
228
- " \n",
229
- " results[set_name] = results_df\n",
230
- "\n",
231
- "print(\"\\n\" + \"=\"*60)\n",
232
- "print(\"LPIPS Analysis Complete!\")\n",
233
- "print(\"=\"*60)\n"
234
- ]
235
  },
236
  {
237
  "cell_type": "code",
@@ -249,17 +108,7 @@
249
  "execution_count": null,
250
  "id": "601aa246",
251
  "metadata": {},
252
- "outputs": [
253
- {
254
- "name": "stdout",
255
- "output_type": "stream",
256
- "text": [
257
- "\n",
258
- "Processing rFID for qwen_base...\n",
259
- "Calculating rFID: 4-step vs 3-step...\n"
260
- ]
261
- }
262
- ],
263
  "source": [
264
  "\n"
265
  ]
@@ -302,58 +151,17 @@
302
  },
303
  {
304
  "cell_type": "code",
305
- "execution_count": 4,
306
  "id": "41e36dc8",
307
  "metadata": {},
308
- "outputs": [
309
- {
310
- "name": "stdout",
311
- "output_type": "stream",
312
- "text": [
313
- "Saved comparison grid 1/32 to reports/comparison_grid/comparison_000.jpg\n",
314
- "Saved comparison grid 2/32 to reports/comparison_grid/comparison_001.jpg\n",
315
- "Saved comparison grid 3/32 to reports/comparison_grid/comparison_002.jpg\n",
316
- "Saved comparison grid 4/32 to reports/comparison_grid/comparison_003.jpg\n",
317
- "Saved comparison grid 5/32 to reports/comparison_grid/comparison_004.jpg\n",
318
- "Saved comparison grid 6/32 to reports/comparison_grid/comparison_005.jpg\n",
319
- "Saved comparison grid 7/32 to reports/comparison_grid/comparison_006.jpg\n",
320
- "Saved comparison grid 8/32 to reports/comparison_grid/comparison_007.jpg\n",
321
- "Saved comparison grid 9/32 to reports/comparison_grid/comparison_008.jpg\n",
322
- "Saved comparison grid 10/32 to reports/comparison_grid/comparison_009.jpg\n",
323
- "Saved comparison grid 11/32 to reports/comparison_grid/comparison_010.jpg\n",
324
- "Saved comparison grid 12/32 to reports/comparison_grid/comparison_011.jpg\n",
325
- "Saved comparison grid 13/32 to reports/comparison_grid/comparison_012.jpg\n",
326
- "Saved comparison grid 14/32 to reports/comparison_grid/comparison_013.jpg\n",
327
- "Saved comparison grid 15/32 to reports/comparison_grid/comparison_014.jpg\n",
328
- "Saved comparison grid 16/32 to reports/comparison_grid/comparison_015.jpg\n",
329
- "Saved comparison grid 17/32 to reports/comparison_grid/comparison_016.jpg\n",
330
- "Saved comparison grid 18/32 to reports/comparison_grid/comparison_017.jpg\n",
331
- "Saved comparison grid 19/32 to reports/comparison_grid/comparison_018.jpg\n",
332
- "Saved comparison grid 20/32 to reports/comparison_grid/comparison_019.jpg\n",
333
- "Saved comparison grid 21/32 to reports/comparison_grid/comparison_020.jpg\n",
334
- "Saved comparison grid 22/32 to reports/comparison_grid/comparison_021.jpg\n",
335
- "Saved comparison grid 23/32 to reports/comparison_grid/comparison_022.jpg\n",
336
- "Saved comparison grid 24/32 to reports/comparison_grid/comparison_023.jpg\n",
337
- "Saved comparison grid 25/32 to reports/comparison_grid/comparison_024.jpg\n",
338
- "Saved comparison grid 26/32 to reports/comparison_grid/comparison_025.jpg\n",
339
- "Saved comparison grid 27/32 to reports/comparison_grid/comparison_026.jpg\n",
340
- "Saved comparison grid 28/32 to reports/comparison_grid/comparison_027.jpg\n",
341
- "Saved comparison grid 29/32 to reports/comparison_grid/comparison_028.jpg\n",
342
- "Saved comparison grid 30/32 to reports/comparison_grid/comparison_029.jpg\n",
343
- "Saved comparison grid 31/32 to reports/comparison_grid/comparison_030.jpg\n",
344
- "Saved comparison grid 32/32 to reports/comparison_grid/comparison_031.jpg\n",
345
- "\n",
346
- "All comparison grids saved to reports/comparison_grid\n"
347
- ]
348
- }
349
- ],
350
  "source": [
351
  "import math\n",
352
  "from PIL import Image\n",
353
  "import numpy as np\n",
354
  "from pathlib import Path\n",
355
  "\n",
356
- "comparison_dir = report_dir / \"comparison_grid\"\n",
357
  "comparison_dir.mkdir(exist_ok=True, parents=True)\n",
358
  "\n",
359
  "\n",
@@ -423,7 +231,119 @@
423
  "id": "244dfe0f",
424
  "metadata": {},
425
  "outputs": [],
426
- "source": []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
427
  }
428
  ],
429
  "metadata": {
 
2
  "cells": [
3
  {
4
  "cell_type": "code",
5
+ "execution_count": null,
6
  "id": "e5649df3",
7
  "metadata": {},
8
+ "outputs": [],
 
 
 
 
 
 
 
 
9
  "source": [
10
  "%cd /home/ubuntu/Qwen-Image-Edit-Angles"
11
  ]
12
  },
13
  {
14
  "cell_type": "code",
15
+ "execution_count": null,
16
  "metadata": {},
17
  "outputs": [],
18
  "source": [
 
22
  },
23
  {
24
  "cell_type": "code",
25
+ "execution_count": null,
26
  "metadata": {},
27
+ "outputs": [],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  "source": [
29
  "from qwenimage.experiment import ExperimentConfig\n",
30
  "from qwenimage.experiments.experiments_qwen import ExperimentRegistry\n",
31
  "\n",
32
  "\n",
33
  "# experiment_names = ExperimentRegistry.keys()\n",
34
+ "# experiment_names = [\n",
35
+ "# \"qwen_base\",\n",
36
+ "# # \"qwen_fa3\",\n",
37
+ "# # \"qwen_aot\",\n",
38
+ "# # \"qwen_fa3_aot\",\n",
39
+ "# # \"qwen_fa3_aot_int8\",\n",
40
+ "# # \"qwen_fa3_aot_fp8\",\n",
41
+ "# # \"qwen_fuse\",\n",
42
+ "# \"qwen_base_3step\",\n",
43
+ "# \"qwen_base_2step\",\n",
44
+ "# \"qwen_lightning_lora\",\n",
45
+ "# \"qwen_lightning_lora_3step\",\n",
46
+ "# \"qwen_lightning_lora_2step\",\n",
47
+ "# ]\n",
48
+ "\n",
49
  "experiment_names = [\n",
 
50
  " # \"qwen_fa3\",\n",
51
  " # \"qwen_aot\",\n",
52
  " # \"qwen_fa3_aot\",\n",
53
+ " \"qwen_fa3_aot_int8\",\n",
54
+ " \"qwen_fa3_aot_int8_fuse\",\n",
55
+ " \"qwen_lightning_fa3_aot_int8_fuse\",\n",
56
+ " # \"qwen_fa3_fuse\",\n",
57
+ " \"qwen_fa3_aot_fp8\",\n",
58
+ " \"qwen_fa3_aot_fp8_fuse\",\n",
59
+ " \"qwen_lightning_fa3_aot_fp8_fuse\",\n",
60
+ " \"qwen_lightning_fa3_aot_int8_fuse_2step\",\n",
61
+ " \"qwen_base\",\n",
62
  "]\n",
63
  "\n",
64
  "report_dir = ExperimentConfig().report_dir\n",
 
76
  },
77
  {
78
  "cell_type": "code",
79
+ "execution_count": null,
80
  "id": "29077eb8",
81
  "metadata": {},
82
+ "outputs": [],
 
 
 
 
 
 
 
 
 
 
 
83
  "source": [
84
  "experiment_outputs[\"qwen_base\"][0]"
85
  ]
 
90
  "id": "a591fdd6",
91
  "metadata": {},
92
  "outputs": [],
93
+ "source": []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  },
95
  {
96
  "cell_type": "code",
 
108
  "execution_count": null,
109
  "id": "601aa246",
110
  "metadata": {},
111
+ "outputs": [],
 
 
 
 
 
 
 
 
 
 
112
  "source": [
113
  "\n"
114
  ]
 
151
  },
152
  {
153
  "cell_type": "code",
154
+ "execution_count": null,
155
  "id": "41e36dc8",
156
  "metadata": {},
157
+ "outputs": [],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
  "source": [
159
  "import math\n",
160
  "from PIL import Image\n",
161
  "import numpy as np\n",
162
  "from pathlib import Path\n",
163
  "\n",
164
+ "comparison_dir = report_dir / \"comparison_grid_2\"\n",
165
  "comparison_dir.mkdir(exist_ok=True, parents=True)\n",
166
  "\n",
167
  "\n",
 
231
  "id": "244dfe0f",
232
  "metadata": {},
233
  "outputs": [],
234
+ "source": [
235
+ "\n",
236
+ "import lpips\n",
237
+ "import torch\n",
238
+ "from PIL import Image\n",
239
+ "import torchvision.transforms as transforms\n",
240
+ "\n",
241
+ "# Initialize LPIPS model\n",
242
+ "loss_fn = lpips.LPIPS(net='alex') # or 'vgg' or 'squeeze'\n",
243
+ "if torch.cuda.is_available():\n",
244
+ " loss_fn = loss_fn.cuda()\n",
245
+ "\n",
246
+ "# Transform to convert PIL images to tensors\n",
247
+ "transform = transforms.Compose([\n",
248
+ " transforms.ToTensor(),\n",
249
+ " transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])\n",
250
+ "])\n",
251
+ "\n",
252
+ "def calculate_lpips_scores(base_paths, compare_paths):\n",
253
+ " \"\"\"Calculate LPIPS scores between two sets of images.\"\"\"\n",
254
+ " scores = []\n",
255
+ " \n",
256
+ " # Get the minimum number of images available\n",
257
+ " num_images = min(len(base_paths), len(compare_paths))\n",
258
+ " \n",
259
+ " for idx in range(num_images):\n",
260
+ " # Load images\n",
261
+ " img1 = Image.open(base_paths[idx]).convert('RGB')\n",
262
+ " img2 = Image.open(compare_paths[idx]).convert('RGB')\n",
263
+ " \n",
264
+ " # Resize if dimensions don't match\n",
265
+ " if img1.size != img2.size:\n",
266
+ " img2 = img2.resize(img1.size, Image.LANCZOS)\n",
267
+ " \n",
268
+ " # Transform to tensors\n",
269
+ " img1_tensor = transform(img1).unsqueeze(0)\n",
270
+ " img2_tensor = transform(img2).unsqueeze(0)\n",
271
+ " \n",
272
+ " if torch.cuda.is_available():\n",
273
+ " img1_tensor = img1_tensor.cuda()\n",
274
+ " img2_tensor = img2_tensor.cuda()\n",
275
+ " \n",
276
+ " # Calculate LPIPS\n",
277
+ " with torch.no_grad():\n",
278
+ " score = loss_fn(img1_tensor, img2_tensor)\n",
279
+ " \n",
280
+ " scores.append(score.item())\n",
281
+ " \n",
282
+ " return scores\n",
283
+ "\n",
284
+ "# Define experiment sets\n",
285
+ "experiment_sets = {\n",
286
+ " 'qwen_base': {\n",
287
+ " '4step': 'qwen_base',\n",
288
+ " '3step': 'qwen_base_3step',\n",
289
+ " '2step': 'qwen_base_2step'\n",
290
+ " },\n",
291
+ " 'qwen_lightning_lora': {\n",
292
+ " '4step': 'qwen_lightning_lora',\n",
293
+ " '3step': 'qwen_lightning_lora_3step',\n",
294
+ " '2step': 'qwen_lightning_lora_2step'\n",
295
+ " }\n",
296
+ "}\n",
297
+ "\n",
298
+ "# Calculate LPIPS scores for each set\n",
299
+ "results = {}\n",
300
+ "\n",
301
+ "for set_name, experiments in experiment_sets.items():\n",
302
+ " print(f\"\\nProcessing {set_name}...\")\n",
303
+ " \n",
304
+ " # Get image paths\n",
305
+ " base_4step_paths = experiment_outputs[experiments['4step']]\n",
306
+ " step_3_paths = experiment_outputs[experiments['3step']]\n",
307
+ " step_2_paths = experiment_outputs[experiments['2step']]\n",
308
+ " \n",
309
+ " # Calculate LPIPS scores\n",
310
+ " print(f\"Calculating LPIPS: 4-step vs 3-step...\")\n",
311
+ " scores_4vs3 = calculate_lpips_scores(base_4step_paths, step_3_paths)\n",
312
+ " \n",
313
+ " print(f\"Calculating LPIPS: 4-step vs 2-step...\")\n",
314
+ " scores_4vs2 = calculate_lpips_scores(base_4step_paths, step_2_paths)\n",
315
+ " \n",
316
+ " # Create results dataframe\n",
317
+ " results_df = pd.DataFrame({\n",
318
+ " 'comparison': ['4step_vs_3step', '4step_vs_2step'],\n",
319
+ " 'mean_lpips': [\n",
320
+ " np.mean(scores_4vs3),\n",
321
+ " np.mean(scores_4vs2)\n",
322
+ " ],\n",
323
+ " 'std_lpips': [\n",
324
+ " np.std(scores_4vs3),\n",
325
+ " np.std(scores_4vs2)\n",
326
+ " ],\n",
327
+ " 'num_samples': [\n",
328
+ " len(scores_4vs3),\n",
329
+ " len(scores_4vs2)\n",
330
+ " ]\n",
331
+ " })\n",
332
+ " \n",
333
+ " # Save to CSV\n",
334
+ " csv_path = report_dir / f\"lpips_scores_{set_name}.csv\"\n",
335
+ " results_df.to_csv(csv_path, index=False)\n",
336
+ " \n",
337
+ " print(f\"\\nResults for {set_name}:\")\n",
338
+ " print(results_df)\n",
339
+ " print(f\"\\nSaved to: {csv_path}\")\n",
340
+ " \n",
341
+ " results[set_name] = results_df\n",
342
+ "\n",
343
+ "print(\"\\n\" + \"=\"*60)\n",
344
+ "print(\"LPIPS Analysis Complete!\")\n",
345
+ "print(\"=\"*60)\n"
346
+ ]
347
  }
348
  ],
349
  "metadata": {