supli6669 commited on
Commit
d06e6ed
·
1 Parent(s): a282d8c

feat: implement custom training configurations and runner script for model improvement

Browse files
handover.md CHANGED
@@ -92,3 +92,83 @@
92
  - **Files Staged:** `app.py`, `pipeline.py`, `download_weights.py`, `handover.md`
93
  - **Commit Message:** "feat: integrate Real-ESRGAN background upscaling and face detection threshold"
94
  - **Remote Push:** Scheduled for execution.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  - **Files Staged:** `app.py`, `pipeline.py`, `download_weights.py`, `handover.md`
93
  - **Commit Message:** "feat: integrate Real-ESRGAN background upscaling and face detection threshold"
94
  - **Remote Push:** Scheduled for execution.
95
+
96
+ ---
97
+
98
+ ## Task 5: Peak End-to-End Model Improvement Plan
99
+
100
+ ### Overview
101
+ This plan describes the comprehensive, peak end-to-end strategy to improve and fine-tune the CodeFormer face restoration model on custom target domain datasets, covering data preparation, degradation pipeline adjustment, advanced loss selection, distributed training, validation, and integration.
102
+
103
+ ---
104
+
105
+ ### Step 1: Data Preparation & Preprocessing Pipeline
106
+ To fine-tune the model, you need a high-quality (HQ) training dataset. If you have low-quality (LQ) images, you also need to align them.
107
+ 1. **Acquire HQ Face Dataset:** Prepare 2,000 - 10,000 high-quality face images (e.g. from your target domain or high-res portraits).
108
+ 2. **Crop & Align Faces:**
109
+ Run the face detection and alignment helper to crop faces to $512 \times 512$ pixels:
110
+ ```bash
111
+ python models/CodeFormer/scripts/crop_align_face.py -i <input_raw_images_dir> -o <output_aligned_faces_dir>
112
+ ```
113
+ 3. **Data Splitting:** Divide aligned faces into training (90%), validation (5%), and test (5%) splits. Store them under `models/CodeFormer/datasets/custom_dataset/`.
114
+
115
+ ---
116
+
117
+ ### Step 2: Degradation Modeling Customization
118
+ Modify the blind dataset configurations in your custom training option file (e.g. `CodeFormer_stage3_custom.yml`) to represent target real-world degradations:
119
+ - **Motion Blur:** Set `motion_kernel_prob` and add motion blur kernels to model camera movement.
120
+ - **Gaussian Blur:** Modify `blur_kernel_size` and `blur_sigma` to match degradation level.
121
+ - **Noise:** Add Poisson and Gaussian noise with custom parameters (`noise_range` or `noise_range_large`).
122
+ - **JPEG Compression:** Decrease the minimum of `jpeg_range` if dealing with high compression blockiness.
123
+
124
+ ---
125
+
126
+ ### Step 3: Architecture & Fine-Tuning Scenarios
127
+ Depending on your project's goals, select one of the following training pathways:
128
+ - **Scenario A: CFT Module Fine-Tuning (Stage III) - Recommended First Step**
129
+ - Keeps Stage 1 (VQGAN) and Stage 2 (Transformer) frozen. Fine-tunes the controllable feature transformation layers to balance likeness (fidelity) and quality.
130
+ - Very stable, relatively fast, and requires less GPU memory.
131
+ - **Scenario B: Transformer & CFT Fine-Tuning (Stage II & III)**
132
+ - Fine-tunes the lookup transformer to map distorted inputs to the clean codebook indices.
133
+ - Useful if the degradations are highly non-linear or stylized (e.g. cartoons, oil paintings).
134
+ - **Scenario C: Full VQGAN + Transformer Retraining (Stage I, II & III)**
135
+ - Re-trains the VQGAN codebook representation from scratch.
136
+ - Necessary only if restoring non-human faces (e.g., animal faces, fictional creatures).
137
+
138
+ ---
139
+
140
+ ### Step 4: Advanced Loss Function Adjustments
141
+ To enhance qualitative results and identity preservation:
142
+ 1. **Identity Preservation (ArcFace Loss):** Integrate an ArcFace feature extractor to compute Cosine Similarity between restored and original faces:
143
+ $$\mathcal{L}_{id} = 1 - \cos(\text{ArcFace}(I_{rec}), \text{ArcFace}(I_{HQ}))$$
144
+ 2. **Structural & Detail Control:**
145
+ - **Perceptual (LPIPS) Loss:** Retain at weight `1.0` for natural textures.
146
+ - **GAN Loss:** Use Hinge GAN Loss (`loss_weight: 0.1`) to generate sharp details without artifacts.
147
+ - **Pixel (L1) Loss:** Retain at weight `1.0` to avoid drift in color/lighting.
148
+
149
+ ---
150
+
151
+ ### Step 5: Distributed GPU Training Setup
152
+ For official training, use GPU(s) with CUDA:
153
+ 1. **Create Option File:** Save configuration to [CodeFormer_stage3_custom.yml](file:///c:/Users/admin/.gemini/antigravity-ide/scratch/custom-ai-enhancer/models/CodeFormer/options/CodeFormer_stage3_custom.yml). Set `num_gpu: 1` (or more).
154
+ 2. **Execute Training via torchrun (Distributed):**
155
+ ```bash
156
+ torchrun --nproc_per_node=gpu_num models/CodeFormer/basicsr/train.py -opt models/CodeFormer/options/CodeFormer_stage3_custom.yml --launcher pytorch
157
+ ```
158
+ 3. **Mixed Precision (AMP):** Enable AMP to save memory and speed up computation.
159
+
160
+ ---
161
+
162
+ ### Step 6: Evaluation & Metrics Validation
163
+ Validate checkpoints quantitatively and qualitatively:
164
+ - **PSNR / SSIM:** Measure reconstruction fidelity.
165
+ - **LPIPS:** Measure perceptual closeness to human vision.
166
+ - **FID:** Measure distribution quality of generated faces.
167
+ - **ArcFace Cosine similarity:** Validate face identity preservation.
168
+
169
+ ---
170
+
171
+ ### Step 7: Streamlit Integration
172
+ 1. Export the best trained checkpoint (`params_ema` key) from `experiments/` to `weights/CodeFormer/codeformer_custom.pth`.
173
+ 2. Update [pipeline.py](file:///c:/Users/admin/.gemini/antigravity-ide/scratch/custom-ai-enhancer/pipeline.py) to point to the new model weights.
174
+ 3. Update [app.py](file:///c:/Users/admin/.gemini/antigravity-ide/scratch/custom-ai-enhancer/app.py) to add a model-selection dropdown or toggle, letting users compare the vanilla CodeFormer against your custom fine-tuned model.
models/CodeFormer/options/CodeFormer_stage3_custom.yml ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: CodeFormer_stage3_custom
2
+ model_type: CodeFormerJointModel
3
+ num_gpu: 0
4
+ manual_seed: 0
5
+ datasets:
6
+ train:
7
+ name: CustomDataset
8
+ type: FFHQBlindJointDataset
9
+ dataroot_gt: datasets/ffhq/ffhq_512
10
+ filename_tmpl: '{}'
11
+ io_backend:
12
+ type: disk
13
+ in_size: 512
14
+ gt_size: 512
15
+ mean:
16
+ - 0.5
17
+ - 0.5
18
+ - 0.5
19
+ std:
20
+ - 0.5
21
+ - 0.5
22
+ - 0.5
23
+ use_hflip: true
24
+ use_corrupt: true
25
+ blur_kernel_size: 41
26
+ use_motion_kernel: true
27
+ motion_kernel_prob: 0.05
28
+ kernel_list:
29
+ - iso
30
+ - aniso
31
+ kernel_prob:
32
+ - 0.5
33
+ - 0.5
34
+ blur_sigma:
35
+ - 0.1
36
+ - 10.0
37
+ downsample_range:
38
+ - 1.0
39
+ - 12.0
40
+ noise_range:
41
+ - 0.0
42
+ - 20.0
43
+ jpeg_range:
44
+ - 50
45
+ - 100
46
+ blur_sigma_large:
47
+ - 1.0
48
+ - 15.0
49
+ downsample_range_large:
50
+ - 4.0
51
+ - 30.0
52
+ noise_range_large:
53
+ - 0.0
54
+ - 30.0
55
+ jpeg_range_large:
56
+ - 30
57
+ - 80
58
+ latent_gt_path: null
59
+ num_worker_per_gpu: 0
60
+ batch_size_per_gpu: 1
61
+ dataset_enlarge_ratio: 1
62
+ prefetch_mode: cpu
63
+ network_g:
64
+ type: CodeFormer
65
+ dim_embd: 512
66
+ n_head: 8
67
+ n_layers: 9
68
+ codebook_size: 1024
69
+ connect_list:
70
+ - '32'
71
+ - '64'
72
+ - '128'
73
+ - '256'
74
+ fix_modules:
75
+ - quantize
76
+ - generator
77
+ network_vqgan:
78
+ type: VQAutoEncoder
79
+ img_size: 512
80
+ nf: 64
81
+ ch_mult:
82
+ - 1
83
+ - 2
84
+ - 2
85
+ - 4
86
+ - 4
87
+ - 8
88
+ quantizer: nearest
89
+ codebook_size: 1024
90
+ network_d:
91
+ type: VQGANDiscriminator
92
+ nc: 3
93
+ ndf: 64
94
+ n_layers: 4
95
+ path:
96
+ pretrain_network_g: ../../weights/CodeFormer/codeformer.pth
97
+ param_key_g: params_ema
98
+ strict_load_g: false
99
+ pretrain_network_d: null
100
+ resume_state: null
101
+ train:
102
+ use_hq_feat_loss: true
103
+ feat_loss_weight: 1.0
104
+ cross_entropy_loss: true
105
+ entropy_loss_weight: 0.5
106
+ scale_adaptive_gan_weight: 0.1
107
+ optim_g:
108
+ type: Adam
109
+ lr: 5.0e-05
110
+ weight_decay: 0
111
+ betas:
112
+ - 0.9
113
+ - 0.99
114
+ optim_d:
115
+ type: Adam
116
+ lr: 5.0e-05
117
+ weight_decay: 0
118
+ betas:
119
+ - 0.9
120
+ - 0.99
121
+ scheduler:
122
+ type: CosineAnnealingRestartLR
123
+ periods:
124
+ - 150000
125
+ restart_weights:
126
+ - 1
127
+ eta_min: 2.0e-05
128
+ total_iter: 10
129
+ warmup_iter: -1
130
+ ema_decay: 0.997
131
+ pixel_opt:
132
+ type: L1Loss
133
+ loss_weight: 1.0
134
+ reduction: mean
135
+ perceptual_opt:
136
+ type: LPIPSLoss
137
+ loss_weight: 1.0
138
+ use_input_norm: true
139
+ range_norm: true
140
+ gan_opt:
141
+ type: GANLoss
142
+ gan_type: hinge
143
+ loss_weight: 1.0
144
+ use_adaptive_weight: true
145
+ net_g_start_iter: 0
146
+ net_d_iters: 1
147
+ net_d_start_iter: 5001
148
+ manual_seed: 0
149
+ val:
150
+ val_freq: 50000000000.0
151
+ save_img: true
152
+ metrics:
153
+ psnr:
154
+ type: calculate_psnr
155
+ crop_border: 4
156
+ test_y_channel: false
157
+ logger:
158
+ print_freq: 1
159
+ save_checkpoint_freq: 5
160
+ use_tb_logger: false
161
+ wandb:
162
+ project: null
163
+ dist: false
164
+ dist_params: null
train_custom.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import torch
4
+ import yaml
5
+ import subprocess
6
+
7
+ def main():
8
+ project_dir = os.path.dirname(os.path.abspath(__file__))
9
+ codeformer_dir = os.path.join(project_dir, "models", "CodeFormer")
10
+
11
+ print("=== Custom CodeFormer Training Runner ===")
12
+
13
+ # 1. Check GPU availability
14
+ device = "cuda" if torch.cuda.is_available() else "cpu"
15
+ num_gpus = torch.cuda.device_count() if device == "cuda" else 0
16
+ print(f"Device detected: {device.upper()}")
17
+ print(f"Number of GPUs available: {num_gpus}")
18
+
19
+ # 2. Check and prepare dataset
20
+ dataset_dir = os.path.join(codeformer_dir, "datasets", "ffhq", "ffhq_512")
21
+ if not os.path.exists(dataset_dir) or len(os.listdir(dataset_dir)) == 0:
22
+ print("Dataset directory is empty. Preparing dataset images...")
23
+ try:
24
+ import prepare_toy_training
25
+ prepare_toy_training.main()
26
+ print("Dataset preparation completed.")
27
+ except Exception as e:
28
+ print(f"Error preparing dataset: {e}")
29
+ sys.exit(1)
30
+ else:
31
+ print(f"Dataset found at {dataset_dir} ({len(os.listdir(dataset_dir))} images).")
32
+
33
+ # 3. Update configuration file
34
+ config_path = os.path.join(codeformer_dir, "options", "CodeFormer_stage3_custom.yml")
35
+ if not os.path.exists(config_path):
36
+ print(f"Error: Config file not found at {config_path}")
37
+ sys.exit(1)
38
+
39
+ print(f"Reading configuration from {config_path}...")
40
+ with open(config_path, "r", encoding="utf-8") as f:
41
+ config = yaml.safe_load(f)
42
+
43
+ # Dynamically set GPU count
44
+ config["num_gpu"] = num_gpus
45
+ config["dist"] = False
46
+ config["dist_params"] = None
47
+
48
+ # Force single worker on Windows / CPU to prevent pickling issues
49
+ if "datasets" in config:
50
+ for phase in config["datasets"]:
51
+ dataset = config["datasets"][phase]
52
+ dataset["num_worker_per_gpu"] = 0
53
+ if device == "cpu":
54
+ dataset["prefetch_mode"] = "cpu"
55
+
56
+ # Update weights path if they are in the project weights folder
57
+ project_weights_path = os.path.join(project_dir, "weights", "CodeFormer", "codeformer.pth")
58
+ if os.path.exists(project_weights_path):
59
+ # basicSR is relative to the running dir which is models/CodeFormer
60
+ config["path"]["pretrain_network_g"] = "../../weights/CodeFormer/codeformer.pth"
61
+ print(f"Configured pretrain generator path to: {config['path']['pretrain_network_g']}")
62
+
63
+ # Write back the updated configuration
64
+ with open(config_path, "w", encoding="utf-8") as f:
65
+ yaml.dump(config, f, default_flow_style=False, sort_keys=False)
66
+ print(f"Updated configuration file for device={device.upper()}, num_gpu={num_gpus}")
67
+
68
+ # 4. Run the training process
69
+ train_script = os.path.join("basicsr", "train.py")
70
+ cmd = [
71
+ sys.executable,
72
+ train_script,
73
+ "-opt",
74
+ os.path.join("options", "CodeFormer_stage3_custom.yml"),
75
+ "--launcher",
76
+ "none"
77
+ ]
78
+
79
+ # Add models/CodeFormer to PYTHONPATH
80
+ env = os.environ.copy()
81
+ env["PYTHONPATH"] = os.path.pathsep.join([codeformer_dir, env.get("PYTHONPATH", "")])
82
+
83
+ print("\nStarting training process. Command:")
84
+ print(" ".join(cmd))
85
+ print(f"Working directory: {codeformer_dir}")
86
+ print("------------------------------------------")
87
+
88
+ try:
89
+ # Run subprocess under models/CodeFormer working directory
90
+ result = subprocess.run(cmd, cwd=codeformer_dir, env=env, check=True)
91
+ print("------------------------------------------")
92
+ print("Training execution completed successfully!")
93
+ except subprocess.CalledProcessError as e:
94
+ print("------------------------------------------")
95
+ print(f"Training failed with exit code: {e.returncode}")
96
+ sys.exit(e.returncode)
97
+
98
+ if __name__ == "__main__":
99
+ main()