td-builder commited on
Commit
129299a
·
verified ·
1 Parent(s): 91670c7

Upload 141 files

Browse files
Files changed (1) hide show
  1. hugging/td_fuse/transport.py +44 -22
hugging/td_fuse/transport.py CHANGED
@@ -394,6 +394,9 @@ def _compute_plans_fallback(
394
  print("[transport] This may take 2-5 minutes...")
395
  sys.stdout.flush()
396
 
 
 
 
397
  for i, (sl, tl) in enumerate(zip(source_layers, target_layers)):
398
  S = source_act[sl].numpy()
399
  T = target_act[tl].numpy()
@@ -403,26 +406,45 @@ def _compute_plans_fallback(
403
  # Neurons already correspond (e.g. DeepSeek) — identity Q
404
  Q_matrices[(sl, tl)] = np.eye(S.shape[1]) / S.shape[1]
405
  else:
406
- # Neurons are SCRAMBLED (e.g. MiMo) — find the permutation
407
- # 1. Compute correlation matrix between source and target neurons
408
- S_norm = (S - S.mean(0)) / (S.std(0) + 1e-8)
409
- T_norm = (T - T.mean(0)) / (T.std(0) + 1e-8)
410
- corr = S_norm.T @ T_norm / S.shape[0] # [hidden_dim, hidden_dim]
411
-
412
- # 2. Run Sinkhorn on cost matrix to get soft transport plan
413
- cost = 1.0 - corr
414
- Q_soft = _sinkhorn(cost, reg=0.05, max_iter=cfg.sinkhorn_max_iter)
415
-
416
- # 3. Extract hard permutation: for each source neuron, which target neuron?
417
- perm = np.argmax(Q_soft, axis=1) # source_neuron -> target_neuron
418
-
419
- # 4. Check for duplicate assignments (Sinkhorn should avoid this, but be safe)
420
- if len(set(perm)) < len(perm) * 0.9:
421
- # Too many collisions — fall back to Hungarian-style greedy
422
- perm = _greedy_permutation(corr)
423
-
424
- permutations[(sl, tl)] = perm
425
- Q_matrices[(sl, tl)] = Q_soft
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
426
  else:
427
  # Different dims -- do lightweight Sinkhorn on this pair only
428
  print(f" Layer {i}: dim mismatch ({S.shape[1]} vs {T.shape[1]}), using Sinkhorn...")
@@ -438,8 +460,8 @@ def _compute_plans_fallback(
438
  print(f" Matched layer {i + 1}/{n_source}: {sl} -> {tl}")
439
  sys.stdout.flush()
440
 
441
- # Timeout: 15 min (permutation takes longer than identity)
442
- tracker.check_timeout(timeout_seconds=900)
443
 
444
  if permutations:
445
  print(f"[transport] Computed {len(permutations)} neuron permutations")
 
394
  print("[transport] This may take 2-5 minutes...")
395
  sys.stdout.flush()
396
 
397
+ # Track which block indices already have permutations (avoid computing twice)
398
+ block_perms = {} # block_index -> perm array
399
+
400
  for i, (sl, tl) in enumerate(zip(source_layers, target_layers)):
401
  S = source_act[sl].numpy()
402
  T = target_act[tl].numpy()
 
406
  # Neurons already correspond (e.g. DeepSeek) — identity Q
407
  Q_matrices[(sl, tl)] = np.eye(S.shape[1]) / S.shape[1]
408
  else:
409
+ # Extract block index (e.g. "model.layers.5.mlp" -> 5)
410
+ block_idx = None
411
+ for part_j, part in enumerate(tl.split(".")):
412
+ if part == "layers":
413
+ try:
414
+ block_idx = int(tl.split(".")[part_j + 1])
415
+ except (ValueError, IndexError):
416
+ pass
417
+ break
418
+
419
+ # Reuse permutation if we already computed it for this block
420
+ if block_idx is not None and block_idx in block_perms:
421
+ perm = block_perms[block_idx]
422
+ permutations[(sl, tl)] = perm
423
+ Q_matrices[(sl, tl)] = np.eye(S.shape[1]) / S.shape[1] # placeholder
424
+ else:
425
+ # Neurons are SCRAMBLED (e.g. MiMo) — find the permutation
426
+ # 1. Compute correlation matrix between source and target neurons
427
+ S_norm = (S - S.mean(0)) / (S.std(0) + 1e-8)
428
+ T_norm = (T - T.mean(0)) / (T.std(0) + 1e-8)
429
+ corr = S_norm.T @ T_norm / S.shape[0] # [hidden_dim, hidden_dim]
430
+
431
+ # 2. Run Sinkhorn on cost matrix to get soft transport plan
432
+ # Use reg=0.1 and 30 iters (faster — we only need argmax, not precision)
433
+ cost = 1.0 - corr
434
+ Q_soft = _sinkhorn(cost, reg=0.1, max_iter=30)
435
+
436
+ # 3. Extract hard permutation: for each source neuron, which target neuron?
437
+ perm = np.argmax(Q_soft, axis=1) # source_neuron -> target_neuron
438
+
439
+ # 4. Check for duplicate assignments (Sinkhorn should avoid this, but be safe)
440
+ if len(set(perm)) < len(perm) * 0.9:
441
+ # Too many collisions — fall back to Hungarian-style greedy
442
+ perm = _greedy_permutation(corr)
443
+
444
+ permutations[(sl, tl)] = perm
445
+ Q_matrices[(sl, tl)] = Q_soft
446
+ if block_idx is not None:
447
+ block_perms[block_idx] = perm
448
  else:
449
  # Different dims -- do lightweight Sinkhorn on this pair only
450
  print(f" Layer {i}: dim mismatch ({S.shape[1]} vs {T.shape[1]}), using Sinkhorn...")
 
460
  print(f" Matched layer {i + 1}/{n_source}: {sl} -> {tl}")
461
  sys.stdout.flush()
462
 
463
+ # Timeout: 90 min (Sinkhorn on 4096x4096 is slow on CPU)
464
+ tracker.check_timeout(timeout_seconds=5400)
465
 
466
  if permutations:
467
  print(f"[transport] Computed {len(permutations)} neuron permutations")