akhaliq HF Staff commited on
Commit
73cf8d6
·
verified ·
1 Parent(s): 53516a8

load_arm_lora: handle mixed-rank LoRAs via zero padding

Browse files
Files changed (1) hide show
  1. training/v2/model.py +12 -6
training/v2/model.py CHANGED
@@ -113,14 +113,19 @@ def load_arm_lora(model, path):
113
  """Load an ai-toolkit/kohya edit LoRA (e.g. armV5) into a frozen LoRA module on `model`.
114
  Handles lora_down/lora_up and lora_A/lora_B keys; folds file alpha/rank into B."""
115
  sd = load_file(path)
116
- rank = None
117
  for k, v in sd.items():
118
  if k.endswith(('.lora_down.weight', '.lora_A.weight')):
119
- rank = v.shape[0]
120
- break
121
- if rank is None:
122
  raise ValueError('no LoRA tensors found')
 
 
 
123
  lora = LoRA(model.dims, model.depth, rank, rank).requires_grad_(False)
 
 
 
124
  for i in range(model.depth):
125
  for name in PROJ:
126
  p = f'diffusion_model.layers.{i}.proj.{name}'
@@ -130,8 +135,9 @@ def load_arm_lora(model, path):
130
  down, up = sd[p + '.lora_A.weight'], sd[p + '.lora_B.weight']
131
  alpha_t = sd.get(p + '.alpha')
132
  alpha = float(alpha_t) if alpha_t is not None else float(down.shape[0])
133
- lora.A[name][i].copy_(down.float())
134
- lora.B[name][i].copy_(up.float() * (alpha / down.shape[0]) / lora.scale)
 
135
  return lora.to(next(model.tr.parameters()).device)
136
 
137
 
 
113
  """Load an ai-toolkit/kohya edit LoRA (e.g. armV5) into a frozen LoRA module on `model`.
114
  Handles lora_down/lora_up and lora_A/lora_B keys; folds file alpha/rank into B."""
115
  sd = load_file(path)
116
+ ranks = set()
117
  for k, v in sd.items():
118
  if k.endswith(('.lora_down.weight', '.lora_A.weight')):
119
+ ranks.add(v.shape[0])
120
+ if not ranks:
 
121
  raise ValueError('no LoRA tensors found')
122
+ rank = max(ranks) # mixed-rank LoRAs: pad smaller deltas with zeros (exact)
123
+ if len(ranks) > 1:
124
+ print(f'load_arm_lora: mixed ranks {sorted(ranks)}, padding to {rank}', flush=True)
125
  lora = LoRA(model.dims, model.depth, rank, rank).requires_grad_(False)
126
+ with torch.no_grad():
127
+ for p in lora.parameters():
128
+ p.zero_()
129
  for i in range(model.depth):
130
  for name in PROJ:
131
  p = f'diffusion_model.layers.{i}.proj.{name}'
 
135
  down, up = sd[p + '.lora_A.weight'], sd[p + '.lora_B.weight']
136
  alpha_t = sd.get(p + '.alpha')
137
  alpha = float(alpha_t) if alpha_t is not None else float(down.shape[0])
138
+ r = down.shape[0]
139
+ lora.A[name][i, :r].copy_(down.float())
140
+ lora.B[name][i, :, :r].copy_(up.float() * (alpha / r) / lora.scale)
141
  return lora.to(next(model.tr.parameters()).device)
142
 
143