summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-02-14 00:47:01 +0100
committerskal <pascal.massimino@gmail.com>2026-02-14 00:47:01 +0100
commit54a0d834dc942ae051d28623a522c72fedf68f1c (patch)
tree370373bebb69b254ba8c5a66d098f88297d216ad
parent8b8b041f2b3437945c173b675d5daa08498f08dc (diff)
gen_identity_weights: Add --mix option for static feature blending
Adds --mix flag to blend input channels with static features: - p0+p4 → p0 (RGBA + UV.x) - p1+p5 → p1 (RGBA + UV.y) - p2+p6 → p2 (RGBA + sin encoding) - p3+p7 → p3 (RGBA + bias) Useful for debugging static feature contribution in CNN v2. Updated doc/CNN_V2_DEBUG_TOOLS.md with --mix usage examples. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
-rw-r--r--doc/CNN_V2_DEBUG_TOOLS.md7
-rwxr-xr-xtraining/gen_identity_weights.py24
2 files changed, 25 insertions, 6 deletions
diff --git a/doc/CNN_V2_DEBUG_TOOLS.md b/doc/CNN_V2_DEBUG_TOOLS.md
index b6dc65f..25e5205 100644
--- a/doc/CNN_V2_DEBUG_TOOLS.md
+++ b/doc/CNN_V2_DEBUG_TOOLS.md
@@ -18,14 +18,17 @@ Tools for investigating CNN v2 mismatch between HTML tool and cnn_test.
# 3×3 identity
./training/gen_identity_weights.py workspaces/main/weights/cnn_v2_identity_3x3.bin --kernel-size 3
+# Mix mode: p0+p4, p1+p5, p2+p6, p3+p7
+./training/gen_identity_weights.py output.bin --mix
+
# Custom mip level
./training/gen_identity_weights.py output.bin --kernel-size 1 --mip-level 2
```
**Output:**
- Single layer, 12D→4D (4 input channels + 8 static features)
-- Identity matrix: Output Ch{0,1,2,3} = Input Ch{0,1,2,3}
-- Static features (Ch 4-11) are zeroed
+- Identity mode: Output Ch{0,1,2,3} = Input Ch{0,1,2,3}
+- Mix mode (--mix): Output Ch{i} = Input Ch{i} + Input Ch{i+4} (blends input with static features)
- Minimal file size (~136 bytes for 1×1, ~904 bytes for 3×3)
**Validation:**
diff --git a/training/gen_identity_weights.py b/training/gen_identity_weights.py
index a84ea87..c996758 100755
--- a/training/gen_identity_weights.py
+++ b/training/gen_identity_weights.py
@@ -4,8 +4,12 @@
Creates trivial .bin with 1 layer, 1×1 kernel, identity passthrough.
Output Ch{0,1,2,3} = Input Ch{0,1,2,3} (ignores static features).
+With --mix: Output Ch{i} = Input Ch{i} + Input Ch{i+4}
+ (p0+p4, p1+p5, p2+p6, p3+p7)
+
Usage:
./training/gen_identity_weights.py [output.bin]
+ ./training/gen_identity_weights.py --mix [output.bin]
"""
import argparse
@@ -14,9 +18,11 @@ import struct
from pathlib import Path
-def generate_identity_weights(output_path, kernel_size=1, mip_level=0):
+def generate_identity_weights(output_path, kernel_size=1, mip_level=0, mix=False):
"""Generate identity weights: output = input (ignores static features).
+ If mix=True, adds p4→p0, p5→p1, p6→p2, p7→p3 (blends input with static).
+
Binary format:
Header (20 bytes):
uint32 magic ('CNN2')
@@ -34,7 +40,8 @@ def generate_identity_weights(output_path, kernel_size=1, mip_level=0):
Weights (u32 packed f16):
Identity matrix for first 4 input channels
- Zeros for static features (channels 4-11)
+ Zeros for static features (channels 4-11) OR
+ Mix matrix (p0+p4, p1+p5, p2+p6, p3+p7) if mix=True
"""
# Identity: 4 output channels, 12 input channels
# Weight shape: [out_ch, in_ch, kernel_h, kernel_w]
@@ -51,15 +58,22 @@ def generate_identity_weights(output_path, kernel_size=1, mip_level=0):
for i in range(out_channels):
weights[i, i, center, center] = 1.0
+ # If mix, add p4→p0, p5→p1, p6→p2, p7→p3
+ if mix:
+ for i in range(out_channels):
+ weights[i, i + 4, center, center] = 1.0
+
# Flatten
weights_flat = weights.flatten()
weight_count = len(weights_flat)
- print(f"Generating identity weights:")
+ print(f"Generating {'mix' if mix else 'identity'} weights:")
print(f" Kernel size: {kernel_size}×{kernel_size}")
print(f" Channels: 12D→4D")
print(f" Weights: {weight_count}")
print(f" Mip level: {mip_level}")
+ if mix:
+ print(f" Mode: p0+p4, p1+p5, p2+p6, p3+p7")
# Convert to f16
weights_f16 = np.array(weights_flat, dtype=np.float16)
@@ -122,11 +136,13 @@ def main():
help='Kernel size (default: 1×1)')
parser.add_argument('--mip-level', type=int, default=0,
help='Mip level for p0-p3 features (default: 0)')
+ parser.add_argument('--mix', action='store_true',
+ help='Mix mode: p0+p4, p1+p5, p2+p6, p3+p7')
args = parser.parse_args()
print("=== Identity Weight Generator ===\n")
- generate_identity_weights(args.output, args.kernel_size, args.mip_level)
+ generate_identity_weights(args.output, args.kernel_size, args.mip_level, args.mix)
print("\nDone!")