lycoris-lora 2.2.0.dev6__tar.gz → 2.2.0.dev8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. {lycoris_lora-2.2.0.dev6/lycoris_lora.egg-info → lycoris_lora-2.2.0.dev8}/PKG-INFO +1 -1
  2. lycoris_lora-2.2.0.dev6/lycoris/modules/locon.py → lycoris_lora-2.2.0.dev8/lycoris/modules/lilora.py +7 -62
  3. lycoris_lora-2.2.0.dev8/lycoris/modules/locon.py +288 -0
  4. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/modules/loha.py +63 -15
  5. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/modules/lokr.py +56 -17
  6. lycoris_lora-2.2.0.dev8/lycoris/utils/bnb.py +30 -0
  7. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8/lycoris_lora.egg-info}/PKG-INFO +1 -1
  8. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris_lora.egg-info/SOURCES.txt +2 -0
  9. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/setup.py +1 -1
  10. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/LICENSE.md +0 -0
  11. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/README.md +0 -0
  12. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/__init__.py +0 -0
  13. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/config.py +0 -0
  14. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/hcp/__init__.py +0 -0
  15. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/hcp/base.py +0 -0
  16. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/hcp/diag_oft.py +0 -0
  17. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/hcp/loha.py +0 -0
  18. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/hcp/lokr.py +0 -0
  19. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/kohya/__init__.py +0 -0
  20. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/kohya/model_utils.py +0 -0
  21. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/kohya/original_unet.py +0 -0
  22. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/kohya/sdxl_model_util.py +0 -0
  23. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/kohya/sdxl_original_unet.py +0 -0
  24. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/kohya/test_hyperdream.py +0 -0
  25. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/kohya/utils.py +0 -0
  26. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/logging.py +0 -0
  27. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/modules/__init__.py +0 -0
  28. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/modules/attention.py +0 -0
  29. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/modules/base.py +0 -0
  30. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/modules/boft.py +0 -0
  31. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/modules/diag_oft.py +0 -0
  32. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/modules/dylora.py +0 -0
  33. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/modules/full.py +0 -0
  34. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/modules/glokr.py +0 -0
  35. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/modules/glora.py +0 -0
  36. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/modules/hypernet/__init__.py +0 -0
  37. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/modules/hypernet/generater.py +0 -0
  38. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/modules/hypernet/text_encoder.py +0 -0
  39. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/modules/ia3.py +0 -0
  40. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/modules/norms.py +0 -0
  41. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/utils/__init__.py +0 -0
  42. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/utils/logger.py +0 -0
  43. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/utils/preset.py +0 -0
  44. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/utils/xformers_utils.py +0 -0
  45. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris/wrapper.py +0 -0
  46. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris_lora.egg-info/dependency_links.txt +0 -0
  47. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris_lora.egg-info/not-zip-safe +0 -0
  48. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris_lora.egg-info/requires.txt +0 -0
  49. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/lycoris_lora.egg-info/top_level.txt +0 -0
  50. {lycoris_lora-2.2.0.dev6 → lycoris_lora-2.2.0.dev8}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lycoris_lora
3
- Version: 2.2.0.dev6
3
+ Version: 2.2.0.dev8
4
4
  Summary: Lora beYond Conventional methods, Other Rank adaptation Implementations for Stable diffusion
5
5
  Home-page: https://github.com/KohakuBlueleaf/LyCORIS
6
6
  Author: Shih-Ying Yeh(KohakuBlueLeaf), Yu-Guan Hsieh, Zhidong Gao
@@ -8,7 +8,6 @@ import torch.nn.functional as F
8
8
  from .base import ModuleCustomSD
9
9
  from ..logging import logger
10
10
 
11
-
12
11
  @cache
13
12
  def log_wd():
14
13
  return logger.warning(
@@ -17,7 +16,7 @@ def log_wd():
17
16
  )
18
17
 
19
18
 
20
- class LoConModule(ModuleCustomSD):
19
+ class LiLoConModule(ModuleCustomSD):
21
20
  """
22
21
  modifed from kohya-ss/sd-scripts/networks/lora:LoRAModule
23
22
  """
@@ -36,6 +35,7 @@ class LoConModule(ModuleCustomSD):
36
35
  use_scalar=False,
37
36
  rank_dropout_scale=False,
38
37
  weight_decompose=False,
38
+ bypass_mode=False,
39
39
  **kwargs,
40
40
  ):
41
41
  """if alpha == 0 or None, alpha is rank (no scaling)."""
@@ -43,8 +43,9 @@ class LoConModule(ModuleCustomSD):
43
43
  self.lora_name = lora_name
44
44
  self.lora_dim = lora_dim
45
45
  self.tucker = False
46
+ assert not (bypass_mode and weight_decompose), "bypass_mode and dora_wd cannot be used together"
46
47
 
47
- if org_module.__class__.__name__ == "Conv2d":
48
+ if isinstance(org_module, nn.Conv2d):
48
49
  in_dim = org_module.in_channels
49
50
  k_size = org_module.kernel_size
50
51
  out_dim = org_module.out_channels
@@ -122,7 +123,8 @@ class LoConModule(ModuleCustomSD):
122
123
  if use_scalar:
123
124
  self.scalar = nn.Parameter(torch.tensor(0.0))
124
125
  else:
125
- self.scalar = torch.tensor(1.0)
126
+ self.scalar: torch.FloatTensor
127
+ self.register_buffer("scalar", torch.tensor(1.0), persistent=False)
126
128
  # same as microsoft's
127
129
  torch.nn.init.kaiming_uniform_(self.lora_down.weight, a=math.sqrt(5))
128
130
  if use_scalar:
@@ -176,7 +178,7 @@ class LoConModule(ModuleCustomSD):
176
178
  drop /= drop.mean()
177
179
  weight *= drop
178
180
 
179
- return weight * self.scalar
181
+ return weight * self.scalar.to(device)
180
182
 
181
183
  def apply_weight_decompose(self, weight):
182
184
  return (
@@ -319,60 +321,3 @@ class LoConModule(ModuleCustomSD):
319
321
  org_out = self.org_forward(x)
320
322
  # print(x.shape, org_out.shape, up.shape)
321
323
  return org_out + self.dropout(up) * scale
322
-
323
- def forward(self, x):
324
- if self.module_dropout and self.training:
325
- if torch.rand(1) < self.module_dropout:
326
- return self.org_forward(x)
327
- scale = self.scale * self.multiplier
328
-
329
- if self.wd:
330
- weight = (
331
- self.org_module[0].weight.data.to(self.scalar)
332
- + self.make_weight(x.device).to(self.scalar) * scale
333
- )
334
- if self.wd:
335
- weight = self.apply_weight_decompose(weight)
336
- bias = (
337
- None
338
- if self.org_module[0].bias is None
339
- else self.org_module[0].bias.data
340
- )
341
- return self.op(x, weight, bias, **self.extra_args)
342
- else:
343
- if self.tucker:
344
- mid = self.lora_mid(self.lora_down(x))
345
- else:
346
- mid = self.lora_down(x)
347
-
348
- if self.rank_dropout and self.training:
349
- drop = (
350
- torch.rand(self.lora_dim, device=mid.device) > self.rank_dropout
351
- ).to(mid.dtype)
352
- if self.rank_dropout_scale:
353
- drop /= drop.mean()
354
- if (dims := len(x.shape)) == 4:
355
- drop = drop.view(1, -1, 1, 1)
356
- else:
357
- drop = drop.view(*[1] * (dims - 1), -1)
358
- mid = mid * drop
359
-
360
- return self.org_forward(x) + self.dropout(
361
- self.lora_up(mid) * self.scalar * scale
362
- )
363
-
364
-
365
- if __name__ == "__main__":
366
- base = nn.Linear(128, 128)
367
- lokr = LoConModule("test", base, 1, 4, 1, weight_decompose=True)
368
- print(lokr)
369
- test_input = torch.randn(1, 128)
370
- test_output = lokr(test_input)
371
- print(test_output.shape)
372
-
373
- base = nn.Conv2d(128, 128, 3, 1, 1)
374
- lokr = LoConModule("test", base, 1, 4, 1, weight_decompose=True, use_tucker=True)
375
- print(lokr)
376
- test_input = torch.randn(1, 128, 16, 16)
377
- test_output = lokr(test_input)
378
- print(test_output.shape)
@@ -0,0 +1,288 @@
1
+ import math
2
+ from functools import cache
3
+
4
+ import torch
5
+ import torch.nn as nn
6
+ import torch.nn.functional as F
7
+
8
+ from .base import ModuleCustomSD
9
+ from ..logging import logger
10
+ from ..utils.bnb import (
11
+ LinearNF4,
12
+ QuantLinears,
13
+ log_bypass
14
+ )
15
+
16
+ @cache
17
+ def log_wd():
18
+ return logger.warning(
19
+ "Using weight_decompose=True with LoRA (DoRA) will ignore network_dropout."
20
+ "Only rank dropout and module dropout will be applied"
21
+ )
22
+
23
+
24
+ class LoConModule(ModuleCustomSD):
25
+ """
26
+ modifed from kohya-ss/sd-scripts/networks/lora:LoRAModule
27
+ """
28
+
29
+ def __init__(
30
+ self,
31
+ lora_name,
32
+ org_module: nn.Module,
33
+ multiplier=1.0,
34
+ lora_dim=4,
35
+ alpha=1,
36
+ dropout=0.0,
37
+ rank_dropout=0.0,
38
+ module_dropout=0.0,
39
+ use_tucker=False,
40
+ use_scalar=False,
41
+ rank_dropout_scale=False,
42
+ weight_decompose=False,
43
+ bypass_mode=False,
44
+ **kwargs,
45
+ ):
46
+ """if alpha == 0 or None, alpha is rank (no scaling)."""
47
+ super().__init__()
48
+ self.lora_name = lora_name
49
+ self.lora_dim = lora_dim
50
+ self.tucker = False
51
+
52
+ if isinstance(org_module, nn.Conv2d):
53
+ in_dim = org_module.in_channels
54
+ k_size = org_module.kernel_size
55
+ out_dim = org_module.out_channels
56
+ self.tucker = use_tucker and k_size != (1, 1)
57
+ self.op = F.conv2d
58
+ self.extra_args = {
59
+ "stride": org_module.stride,
60
+ "padding": org_module.padding,
61
+ "dilation": org_module.dilation,
62
+ "groups": org_module.groups,
63
+ }
64
+ else:
65
+ in_dim = org_module.in_features
66
+ out_dim = org_module.out_features
67
+ self.op = F.linear
68
+ self.extra_args = {}
69
+
70
+ if isinstance(org_module, QuantLinears):
71
+ if not bypass_mode:
72
+ log_bypass()
73
+ bypass_mode = True
74
+ self.bypass_mode = bypass_mode
75
+ assert not (bypass_mode and weight_decompose), "bypass_mode and dora_wd cannot be used together"
76
+
77
+ if isinstance(org_module, nn.Conv2d):
78
+ self.isconv = True
79
+ # For general LoCon
80
+ in_dim = org_module.in_channels
81
+ k_size = org_module.kernel_size
82
+ stride = org_module.stride
83
+ padding = org_module.padding
84
+ out_dim = org_module.out_channels
85
+ self.down_op = F.conv2d
86
+ self.up_op = F.conv2d
87
+ if use_tucker and k_size != (1, 1):
88
+ self.lora_down = nn.Conv2d(in_dim, lora_dim, (1, 1), bias=False)
89
+ self.lora_mid = nn.Conv2d(
90
+ lora_dim, lora_dim, k_size, stride, padding, bias=False
91
+ )
92
+ self.tucker = True
93
+ else:
94
+ self.lora_down = nn.Conv2d(
95
+ in_dim, lora_dim, k_size, stride, padding, bias=False
96
+ )
97
+ self.lora_up = nn.Conv2d(lora_dim, out_dim, (1, 1), bias=False)
98
+ elif isinstance(org_module, nn.Linear):
99
+ self.isconv = False
100
+ self.down_op = F.linear
101
+ self.up_op = F.linear
102
+ in_dim = org_module.in_features
103
+ out_dim = org_module.out_features
104
+ self.lora_down = nn.Linear(in_dim, lora_dim, bias=False)
105
+ self.lora_up = nn.Linear(lora_dim, out_dim, bias=False)
106
+ else:
107
+ raise NotImplementedError
108
+ self.shape = org_module.weight.shape
109
+
110
+ self.wd = weight_decompose
111
+ if self.wd:
112
+ org_weight: nn.Parameter = org_module.weight
113
+ self.dora_mean_dim = tuple(i for i in range(org_weight.dim()) if i != 1)
114
+ self.dora_scale = nn.Parameter(
115
+ torch.mean(org_weight, dim=self.dora_mean_dim, keepdim=True)
116
+ )
117
+
118
+ if dropout:
119
+ self.dropout = nn.Dropout(dropout)
120
+ if self.wd:
121
+ log_wd()
122
+ else:
123
+ self.dropout = nn.Identity()
124
+ self.rank_dropout = rank_dropout
125
+ self.rank_dropout_scale = rank_dropout_scale
126
+ self.module_dropout = module_dropout
127
+
128
+ if type(alpha) == torch.Tensor:
129
+ alpha = alpha.detach().float().numpy() # without casting, bf16 causes error
130
+ alpha = lora_dim if alpha is None or alpha == 0 else alpha
131
+ self.scale = alpha / self.lora_dim
132
+ self.register_buffer("alpha", torch.tensor(alpha)) # 定数として扱える
133
+
134
+ if use_scalar:
135
+ self.scalar = nn.Parameter(torch.tensor(0.0))
136
+ else:
137
+ self.scalar: torch.FloatTensor
138
+ self.register_buffer("scalar", torch.tensor(1.0), persistent=False)
139
+ # same as microsoft's
140
+ torch.nn.init.kaiming_uniform_(self.lora_down.weight, a=math.sqrt(5))
141
+ if use_scalar:
142
+ torch.nn.init.kaiming_uniform_(self.lora_up.weight, a=math.sqrt(5))
143
+ else:
144
+ torch.nn.init.constant_(self.lora_up.weight, 0)
145
+ if self.tucker:
146
+ torch.nn.init.kaiming_uniform_(self.lora_mid.weight, a=math.sqrt(5))
147
+
148
+ self.multiplier = multiplier
149
+ self.org_module = [org_module]
150
+ self.org_forward = self.org_module[0].forward
151
+
152
+ def load_weight_hook(self, module: nn.Module, incompatible_keys):
153
+ missing_keys = incompatible_keys.missing_keys
154
+ for key in missing_keys:
155
+ if "scalar" in key:
156
+ del missing_keys[missing_keys.index(key)]
157
+ self.scalar = nn.Parameter(torch.ones_like(self.scalar))
158
+
159
+ def apply_to(self, is_hypernet=False, **kwargs):
160
+ self.org_forward = self.org_module[0].forward
161
+ if is_hypernet:
162
+ self.org_module[0].forward = self.hypernet_forward
163
+ else:
164
+ self.org_module[0].forward = self.forward
165
+
166
+ def restore(self):
167
+ self.org_module[0].forward = self.org_forward
168
+
169
+ def merge_to(self, multiplier=1.0):
170
+ weight = self.make_weight() * self.scale * multiplier
171
+ self.org_module[0].weight.data.add_(weight)
172
+
173
+ def make_weight(self, device=None):
174
+ wa = self.lora_up.weight.to(device)
175
+ wb = self.lora_down.weight.to(device)
176
+ if self.tucker:
177
+ t = self.lora_mid.weight.to(device)
178
+ wa = wa.squeeze(-1, -2)
179
+ wb = wb.squeeze(-1, -2)
180
+ weight = torch.einsum("i j k l, p i, j r -> p r k l", t, wa, wb)
181
+ else:
182
+ weight = wa.view(wa.size(0), -1) @ wb.view(wb.size(0), -1)
183
+
184
+ weight = weight.view(self.shape)
185
+ if self.training and self.rank_dropout:
186
+ drop = (torch.rand(weight.size(0)) > self.rank_dropout).to(weight.dtype)
187
+ drop = drop.view(-1, *[1] * len(weight.shape[1:])).to(weight.device)
188
+ if self.rank_dropout_scale:
189
+ drop /= drop.mean()
190
+ weight *= drop
191
+
192
+ return weight * self.scalar.to(device)
193
+
194
+ def apply_weight_decompose(self, weight):
195
+ return (
196
+ weight / weight.mean(dim=self.dora_mean_dim, keepdim=True) * self.dora_scale
197
+ )
198
+
199
+ def custom_state_dict(self):
200
+ destination = {}
201
+ if self.wd:
202
+ destination["dora_scale"] = self.dora_scale
203
+ destination["alpha"] = self.alpha
204
+ destination["lora_up.weight"] = self.lora_up.weight * self.scalar
205
+ destination["lora_down.weight"] = self.lora_down.weight
206
+ if self.tucker:
207
+ destination["lora_mid.weight"] = self.lora_mid.weight
208
+ return destination
209
+
210
+ @torch.no_grad()
211
+ def apply_max_norm(self, max_norm, device=None):
212
+ orig_norm = self.make_weight(device).norm() * self.scale
213
+ norm = torch.clamp(orig_norm, max_norm / 2)
214
+ desired = torch.clamp(norm, max=max_norm)
215
+ ratio = desired.cpu() / norm.cpu()
216
+
217
+ scaled = norm != desired
218
+ if scaled:
219
+ self.scalar *= ratio
220
+
221
+ return scaled, orig_norm * ratio
222
+
223
+ def forward(self, x):
224
+ if self.module_dropout and self.training:
225
+ if torch.rand(1) < self.module_dropout:
226
+ return self.org_forward(x)
227
+ scale = self.scale * self.multiplier
228
+
229
+ dtype_device = next(self.parameters())
230
+ if not self.bypass_mode:
231
+ weight = (
232
+ self.org_module[0].weight.data.to(dtype_device)
233
+ + self.make_weight(x.device).to(dtype_device) * scale
234
+ )
235
+ if self.wd:
236
+ weight = self.apply_weight_decompose(weight)
237
+ bias = (
238
+ None
239
+ if self.org_module[0].bias is None
240
+ else self.org_module[0].bias.data
241
+ )
242
+ return self.op(x, weight, bias, **self.extra_args)
243
+ else:
244
+ if self.tucker:
245
+ mid = self.lora_mid(self.lora_down(x))
246
+ else:
247
+ mid = self.lora_down(x)
248
+
249
+ if self.rank_dropout and self.training:
250
+ drop = (
251
+ torch.rand(self.lora_dim, device=mid.device) > self.rank_dropout
252
+ ).to(mid.dtype)
253
+ if self.rank_dropout_scale:
254
+ drop /= drop.mean()
255
+ if (dims := len(x.shape)) == 4:
256
+ drop = drop.view(1, -1, 1, 1)
257
+ else:
258
+ drop = drop.view(*[1] * (dims - 1), -1)
259
+ mid = mid * drop
260
+
261
+ return self.org_forward(x) + self.dropout(
262
+ self.lora_up(mid) * self.scalar * scale
263
+ )
264
+
265
+
266
+ if __name__ == "__main__":
267
+ base = nn.Linear(128, 128).cuda()
268
+ lokr = LoConModule("test", base, 1, 4, 1, weight_decompose=True).cuda()
269
+ print(lokr)
270
+ test_input = torch.randn(1, 128).cuda()
271
+ test_output = lokr(test_input)
272
+ print(test_output.shape)
273
+
274
+ base_4bit = LinearNF4(128, 128)
275
+ base_4bit.load_state_dict(base.state_dict())
276
+ base_4bit.cuda()
277
+ qlocon = LoConModule("test", base_4bit, 1, 4, 1, weight_decompose=False).cuda()
278
+ print(qlocon)
279
+ test_input = torch.randn(1, 128).cuda()
280
+ test_output = qlocon(test_input)
281
+ print(test_output.shape)
282
+
283
+ base = nn.Conv2d(128, 128, 3, 1, 1)
284
+ lokr = LoConModule("test", base, 1, 4, 1, weight_decompose=True, use_tucker=True)
285
+ print(lokr)
286
+ test_input = torch.randn(1, 128, 16, 16)
287
+ test_output = lokr(test_input)
288
+ print(test_output.shape)
@@ -3,6 +3,11 @@ import torch.nn as nn
3
3
  import torch.nn.functional as F
4
4
 
5
5
  from .base import ModuleCustomSD
6
+ from ..utils.bnb import (
7
+ LinearNF4,
8
+ QuantLinears,
9
+ log_bypass
10
+ )
6
11
 
7
12
 
8
13
  class HadaWeight(torch.autograd.Function):
@@ -100,6 +105,7 @@ class LohaModule(ModuleCustomSD):
100
105
  use_scalar=False,
101
106
  rank_dropout_scale=False,
102
107
  weight_decompose=False,
108
+ bypass_mode=False,
103
109
  **kwargs,
104
110
  ):
105
111
  """if alpha == 0 or None, alpha is rank (no scaling)."""
@@ -113,6 +119,7 @@ class LohaModule(ModuleCustomSD):
113
119
  in_dim = org_module.in_channels
114
120
  k_size = org_module.kernel_size
115
121
  out_dim = org_module.out_channels
122
+ self.shape = (out_dim, in_dim, *k_size)
116
123
  self.tucker = use_tucker and k_size != (1, 1)
117
124
  if self.tucker:
118
125
  shape = (out_dim, in_dim, *k_size)
@@ -129,9 +136,17 @@ class LohaModule(ModuleCustomSD):
129
136
  in_dim = org_module.in_features
130
137
  out_dim = org_module.out_features
131
138
  shape = (out_dim, in_dim)
139
+ self.shape = shape
132
140
  self.op = F.linear
133
141
  self.extra_args = {}
134
142
 
143
+ if isinstance(org_module, QuantLinears):
144
+ if not bypass_mode:
145
+ log_bypass()
146
+ bypass_mode = True
147
+ self.bypass_mode = bypass_mode
148
+ assert not (bypass_mode and weight_decompose), "bypass_mode and dora_wd cannot be used together"
149
+
135
150
  if self.tucker:
136
151
  self.hada_t1 = nn.Parameter(
137
152
  torch.empty(lora_dim, lora_dim, shape[2], shape[3])
@@ -215,10 +230,10 @@ class LohaModule(ModuleCustomSD):
215
230
  self.org_module[0].forward = self.org_forward
216
231
 
217
232
  def merge_to(self, multiplier=1.0):
218
- weight = self.get_weight(self.org_module[0].weight)
233
+ weight = self.get_weight(self.shape)
219
234
  self.org_module[0].weight.data.add_(weight * multiplier)
220
235
 
221
- def get_weight(self, orig_weight=None):
236
+ def get_weight(self, shape):
222
237
  if self.tucker:
223
238
  weight = make_weight_tucker(
224
239
  self.hada_t1,
@@ -237,8 +252,8 @@ class LohaModule(ModuleCustomSD):
237
252
  self.hada_w2_b,
238
253
  scale=torch.tensor(self.scale),
239
254
  )
240
- if orig_weight is not None:
241
- weight = weight.reshape(orig_weight.shape)
255
+ if shape is not None:
256
+ weight = weight.reshape(shape)
242
257
  if self.training and self.rank_dropout:
243
258
  drop = (torch.rand(weight.size(0)) > self.rank_dropout).to(weight.dtype)
244
259
  drop = drop.view(-1, *[1] * len(weight.shape[1:])).to(weight.device)
@@ -292,14 +307,47 @@ class LohaModule(ModuleCustomSD):
292
307
  else self.org_module[0].bias.data
293
308
  ),
294
309
  )
295
- weight = (
296
- self.org_module[0].weight.data.to(x.device, dtype=self.hada_w1_a.dtype)
297
- + self.get_weight(self.org_module[0].weight.data)
298
- * self.scalar
299
- * self.multiplier
300
- )
301
- bias = None if self.org_module[0].bias is None else self.org_module[0].bias.data
302
-
303
- if self.wd:
304
- weight = self.apply_weight_decompose(weight)
305
- return self.op(x, weight.view(self.shape), bias, **self.extra_args)
310
+ if self.bypass_mode:
311
+ diff_weight = (
312
+ self.get_weight(self.shape)
313
+ * self.scalar
314
+ * self.multiplier
315
+ )
316
+ return self.org_forward(x) + self.op(x, diff_weight.view(self.shape), **self.extra_args)
317
+ else:
318
+ weight = (
319
+ self.org_module[0].weight.data.to(x.device, dtype=self.hada_w1_a.dtype)
320
+ + self.get_weight(self.shape)
321
+ * self.scalar
322
+ * self.multiplier
323
+ )
324
+ bias = None if self.org_module[0].bias is None else self.org_module[0].bias.data
325
+
326
+ if self.wd:
327
+ weight = self.apply_weight_decompose(weight)
328
+ return self.op(x, weight.view(self.shape), bias, **self.extra_args)
329
+
330
+
331
+ if __name__ == "__main__":
332
+ base = nn.Linear(128, 128).cuda()
333
+ lokr = LohaModule("test", base, 1, 4, 1, weight_decompose=True).cuda()
334
+ print(lokr)
335
+ test_input = torch.randn(1, 128).cuda()
336
+ test_output = lokr(test_input)
337
+ print(test_output.shape)
338
+
339
+ base_4bit = LinearNF4(128, 128)
340
+ base_4bit.load_state_dict(base.state_dict())
341
+ base_4bit.cuda()
342
+ qlocon = LohaModule("test", base_4bit, 1, 4, 1, weight_decompose=False).cuda()
343
+ print(qlocon)
344
+ test_input = torch.randn(1, 128).cuda()
345
+ test_output = qlocon(test_input)
346
+ print(test_output.shape)
347
+
348
+ base = nn.Conv2d(128, 128, 3, 1, 1)
349
+ lokr = LohaModule("test", base, 1, 4, 1, weight_decompose=True, use_tucker=True)
350
+ print(lokr)
351
+ test_input = torch.randn(1, 128, 16, 16)
352
+ test_output = lokr(test_input)
353
+ print(test_output.shape)
@@ -7,6 +7,11 @@ import torch.nn.functional as F
7
7
 
8
8
  from .base import ModuleCustomSD
9
9
  from ..logging import logger
10
+ from ..utils.bnb import (
11
+ LinearNF4,
12
+ QuantLinears,
13
+ log_bypass
14
+ )
10
15
 
11
16
 
12
17
  @cache
@@ -101,6 +106,7 @@ class LokrModule(ModuleCustomSD):
101
106
  rank_dropout_scale=False,
102
107
  weight_decompose=False,
103
108
  full_matrix=False,
109
+ bypass_mode=False,
104
110
  **kwargs,
105
111
  ):
106
112
  """if alpha == 0 or None, alpha is rank (no scaling)."""
@@ -118,6 +124,7 @@ class LokrModule(ModuleCustomSD):
118
124
  in_dim = org_module.in_channels
119
125
  k_size = org_module.kernel_size
120
126
  out_dim = org_module.out_channels
127
+ self.shape = (out_dim, in_dim, *k_size)
121
128
 
122
129
  in_m, in_n = factorization(in_dim, factor)
123
130
  out_l, out_k = factorization(out_dim, factor)
@@ -172,6 +179,7 @@ class LokrModule(ModuleCustomSD):
172
179
  else: # Linear
173
180
  in_dim = org_module.in_features
174
181
  out_dim = org_module.out_features
182
+ self.shape = (out_dim, in_dim)
175
183
 
176
184
  in_m, in_n = factorization(in_dim, factor)
177
185
  out_l, out_k = factorization(out_dim, factor)
@@ -200,6 +208,13 @@ class LokrModule(ModuleCustomSD):
200
208
  self.op = F.linear
201
209
  self.extra_args = {}
202
210
 
211
+ if isinstance(org_module, QuantLinears):
212
+ if not bypass_mode:
213
+ log_bypass()
214
+ bypass_mode = True
215
+ self.bypass_mode = bypass_mode
216
+ assert not (bypass_mode and weight_decompose), "bypass_mode and dora_wd cannot be used together"
217
+
203
218
  self.wd = weight_decompose
204
219
  if self.wd:
205
220
  org_weight: nn.Parameter = org_module.weight
@@ -283,10 +298,10 @@ class LokrModule(ModuleCustomSD):
283
298
  self.org_module[0].forward = self.org_forward
284
299
 
285
300
  def merge_to(self, multiplier=1.0):
286
- weight = self.get_weight(self.org_module[0].weight)
301
+ weight = self.get_weight(self.shape)
287
302
  self.org_module[0].weight.data.add_(weight * multiplier)
288
303
 
289
- def get_weight(self, orig_weight=None):
304
+ def get_weight(self, shape):
290
305
  weight = make_kron(
291
306
  self.lokr_w1 if self.use_w1 else self.lokr_w1_a @ self.lokr_w1_b,
292
307
  (
@@ -300,8 +315,8 @@ class LokrModule(ModuleCustomSD):
300
315
  ),
301
316
  torch.tensor(self.scale),
302
317
  )
303
- if orig_weight is not None:
304
- weight = weight.reshape(orig_weight.shape)
318
+ if shape is not None:
319
+ weight = weight.reshape(shape)
305
320
  if self.training and self.rank_dropout:
306
321
  drop = (torch.rand(weight.size(0)) > self.rank_dropout).to(weight.dtype)
307
322
  drop = drop.view(-1, *[1] * len(weight.shape[1:])).to(weight.device)
@@ -373,23 +388,47 @@ class LokrModule(ModuleCustomSD):
373
388
  else self.org_module[0].bias.data
374
389
  ),
375
390
  )
376
- weight = (
377
- self.org_module[0].weight.data.to(x.device, dtype=self.lokr_w1.dtype)
378
- + self.get_weight(self.org_module[0].weight.data)
379
- * self.scalar
380
- * self.multiplier
381
- )
382
- bias = None if self.org_module[0].bias is None else self.org_module[0].bias.data
391
+ if self.bypass_mode:
392
+ diff_weight = (
393
+ self.get_weight(self.shape)
394
+ * self.scalar
395
+ * self.multiplier
396
+ )
397
+ return self.org_forward(x) + self.op(x, diff_weight.view(self.shape), **self.extra_args)
398
+ else:
399
+ weight = (
400
+ self.org_module[0].weight.data.to(x.device, dtype=next(self.parameters()).dtype)
401
+ + self.get_weight(self.shape)
402
+ * self.scalar
403
+ * self.multiplier
404
+ )
405
+ bias = None if self.org_module[0].bias is None else self.org_module[0].bias.data
383
406
 
384
- if self.wd:
385
- weight = self.apply_weight_decompose(weight)
386
- return self.op(x, weight.view(self.shape), bias, **self.extra_args)
407
+ if self.wd:
408
+ weight = self.apply_weight_decompose(weight)
409
+ return self.op(x, weight.view(self.shape), bias, **self.extra_args)
387
410
 
388
411
 
389
412
  if __name__ == "__main__":
390
- base = nn.Linear(128, 128)
391
- lokr = LokrModule("test", base, 1, 4, 1, weight_decompose=True)
413
+ base = nn.Linear(128, 128).cuda()
414
+ lokr = LokrModule("test", base, 1, 4, 1, weight_decompose=True).cuda()
415
+ print(lokr)
416
+ test_input = torch.randn(1, 128).cuda()
417
+ test_output = lokr(test_input)
418
+ print(test_output.shape)
419
+
420
+ base_4bit = LinearNF4(128, 128)
421
+ base_4bit.load_state_dict(base.state_dict())
422
+ base_4bit.cuda()
423
+ qlocon = LokrModule("test", base_4bit, 1, 4, 1, weight_decompose=False).cuda()
424
+ print(qlocon)
425
+ test_input = torch.randn(1, 128).cuda()
426
+ test_output = qlocon(test_input)
427
+ print(test_output.shape)
428
+
429
+ base = nn.Conv2d(128, 128, 3, 1, 1)
430
+ lokr = LokrModule("test", base, 1, 4, 1, weight_decompose=True, use_tucker=True)
392
431
  print(lokr)
393
- test_input = torch.randn(1, 128)
432
+ test_input = torch.randn(1, 128, 16, 16)
394
433
  test_output = lokr(test_input)
395
434
  print(test_output.shape)
@@ -0,0 +1,30 @@
1
+ from functools import cache
2
+
3
+ try:
4
+ from bitsandbytes.nn import (
5
+ LinearNF4, Linear8bitLt, LinearFP4
6
+ )
7
+ except:
8
+ import torch.nn as nn
9
+ class LinearNF4(nn.Linear):
10
+ pass
11
+ class Linear8bitLt(nn.Linear):
12
+ pass
13
+ class LinearFP4(nn.Linear):
14
+ pass
15
+
16
+ from ..logging import logger
17
+
18
+
19
+ QuantLinears = (
20
+ Linear8bitLt,
21
+ LinearFP4,
22
+ LinearNF4
23
+ )
24
+
25
+
26
+ @cache
27
+ def log_bypass():
28
+ return logger.warning(
29
+ "Using bnb with LyCORIS will enable force-bypass mode."
30
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lycoris_lora
3
- Version: 2.2.0.dev6
3
+ Version: 2.2.0.dev8
4
4
  Summary: Lora beYond Conventional methods, Other Rank adaptation Implementations for Stable diffusion
5
5
  Home-page: https://github.com/KohakuBlueleaf/LyCORIS
6
6
  Author: Shih-Ying Yeh(KohakuBlueLeaf), Yu-Guan Hsieh, Zhidong Gao
@@ -27,6 +27,7 @@ lycoris/modules/full.py
27
27
  lycoris/modules/glokr.py
28
28
  lycoris/modules/glora.py
29
29
  lycoris/modules/ia3.py
30
+ lycoris/modules/lilora.py
30
31
  lycoris/modules/locon.py
31
32
  lycoris/modules/loha.py
32
33
  lycoris/modules/lokr.py
@@ -35,6 +36,7 @@ lycoris/modules/hypernet/__init__.py
35
36
  lycoris/modules/hypernet/generater.py
36
37
  lycoris/modules/hypernet/text_encoder.py
37
38
  lycoris/utils/__init__.py
39
+ lycoris/utils/bnb.py
38
40
  lycoris/utils/logger.py
39
41
  lycoris/utils/preset.py
40
42
  lycoris/utils/xformers_utils.py
@@ -4,7 +4,7 @@ from setuptools import setup, find_packages
4
4
  setup(
5
5
  name="lycoris_lora",
6
6
  packages=find_packages(),
7
- version="2.2.0.dev6",
7
+ version="2.2.0.dev8",
8
8
  url="https://github.com/KohakuBlueleaf/LyCORIS",
9
9
  description="Lora beYond Conventional methods, Other Rank adaptation Implementations for Stable diffusion",
10
10
  author="Shih-Ying Yeh(KohakuBlueLeaf), Yu-Guan Hsieh, Zhidong Gao",