lycoris-lora 2.3.0.dev11__tar.gz → 3.0.0.dev1__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 (57) hide show
  1. {lycoris_lora-2.3.0.dev11/lycoris_lora.egg-info → lycoris_lora-3.0.0.dev1}/PKG-INFO +1 -1
  2. lycoris_lora-3.0.0.dev1/lycoris/functional/__init__.py +13 -0
  3. lycoris_lora-3.0.0.dev1/lycoris/functional/general.py +74 -0
  4. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris/functional/locon.py +1 -1
  5. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris/functional/loha.py +8 -8
  6. lycoris_lora-2.3.0.dev11/lycoris/kohya/__init__.py → lycoris_lora-3.0.0.dev1/lycoris/kohya.py +18 -18
  7. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris/modules/base.py +24 -0
  8. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris/modules/boft.py +20 -31
  9. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris/modules/diag_oft.py +32 -30
  10. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris/modules/full.py +57 -16
  11. lycoris_lora-3.0.0.dev1/lycoris/modules/glora.py +196 -0
  12. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris/modules/locon.py +20 -16
  13. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris/modules/loha.py +23 -18
  14. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris/modules/lokr.py +22 -87
  15. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris/modules/norms.py +35 -1
  16. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1/lycoris_lora.egg-info}/PKG-INFO +1 -1
  17. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris_lora.egg-info/SOURCES.txt +1 -18
  18. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/setup.py +1 -1
  19. lycoris_lora-2.3.0.dev11/lycoris/functional/__init__.py +0 -4
  20. lycoris_lora-2.3.0.dev11/lycoris/functional/general.py +0 -8
  21. lycoris_lora-2.3.0.dev11/lycoris/hcp/__init__.py +0 -4
  22. lycoris_lora-2.3.0.dev11/lycoris/hcp/base.py +0 -153
  23. lycoris_lora-2.3.0.dev11/lycoris/hcp/diag_oft.py +0 -62
  24. lycoris_lora-2.3.0.dev11/lycoris/hcp/loha.py +0 -85
  25. lycoris_lora-2.3.0.dev11/lycoris/hcp/lokr.py +0 -131
  26. lycoris_lora-2.3.0.dev11/lycoris/kohya/model_utils.py +0 -1633
  27. lycoris_lora-2.3.0.dev11/lycoris/kohya/original_unet.py +0 -1760
  28. lycoris_lora-2.3.0.dev11/lycoris/kohya/sdxl_model_util.py +0 -581
  29. lycoris_lora-2.3.0.dev11/lycoris/kohya/sdxl_original_unet.py +0 -1243
  30. lycoris_lora-2.3.0.dev11/lycoris/kohya/test_hyperdream.py +0 -527
  31. lycoris_lora-2.3.0.dev11/lycoris/kohya/utils.py +0 -48
  32. lycoris_lora-2.3.0.dev11/lycoris/modules/attention.py +0 -259
  33. lycoris_lora-2.3.0.dev11/lycoris/modules/glokr.py +0 -310
  34. lycoris_lora-2.3.0.dev11/lycoris/modules/glora.py +0 -136
  35. lycoris_lora-2.3.0.dev11/lycoris/modules/hypernet/__init__.py +0 -1
  36. lycoris_lora-2.3.0.dev11/lycoris/modules/hypernet/generater.py +0 -223
  37. lycoris_lora-2.3.0.dev11/lycoris/modules/hypernet/text_encoder.py +0 -266
  38. lycoris_lora-2.3.0.dev11/lycoris/modules/lilora.py +0 -339
  39. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/LICENSE.md +0 -0
  40. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/README.md +0 -0
  41. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris/__init__.py +0 -0
  42. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris/config.py +0 -0
  43. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris/logging.py +0 -0
  44. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris/modules/__init__.py +0 -0
  45. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris/modules/dylora.py +0 -0
  46. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris/modules/ia3.py +0 -0
  47. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris/utils/__init__.py +0 -0
  48. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris/utils/bnb.py +0 -0
  49. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris/utils/logger.py +0 -0
  50. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris/utils/preset.py +0 -0
  51. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris/utils/xformers_utils.py +0 -0
  52. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris/wrapper.py +0 -0
  53. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris_lora.egg-info/dependency_links.txt +0 -0
  54. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris_lora.egg-info/not-zip-safe +0 -0
  55. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris_lora.egg-info/requires.txt +0 -0
  56. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/lycoris_lora.egg-info/top_level.txt +0 -0
  57. {lycoris_lora-2.3.0.dev11 → lycoris_lora-3.0.0.dev1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lycoris_lora
3
- Version: 2.3.0.dev11
3
+ Version: 3.0.0.dev1
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
@@ -0,0 +1,13 @@
1
+ from .general import (
2
+ rebuild_tucker,
3
+ factorization,
4
+ power2factorization,
5
+ )
6
+ from .locon import (
7
+ lora_diff_weight,
8
+ lora_bypass_forward_diff,
9
+ )
10
+ from .loha import (
11
+ loha_diff_weight,
12
+ loha_bypass_forward_diff,
13
+ )
@@ -0,0 +1,74 @@
1
+ import torch
2
+ import torch.nn as nn
3
+ import torch.nn.functional as F
4
+
5
+
6
+ def rebuild_tucker(t, wa, wb):
7
+ rebuild2 = torch.einsum("i j ..., i p, j r -> p r ...", t, wa, wb)
8
+ return rebuild2
9
+
10
+
11
+ def factorization(dimension: int, factor: int = -1) -> tuple[int, int]:
12
+ """
13
+ return a tuple of two value of input dimension decomposed by the number closest to factor
14
+ second value is higher or equal than first value.
15
+
16
+ In LoRA with Kroneckor Product, first value is a value for weight scale.
17
+ second value is a value for weight.
18
+
19
+ Because of non-commutative property, A⊗B ≠ B⊗A. Meaning of two matrices is slightly different.
20
+
21
+ examples)
22
+ factor
23
+ -1 2 4 8 16 ...
24
+ 127 -> 1, 127 127 -> 1, 127 127 -> 1, 127 127 -> 1, 127 127 -> 1, 127
25
+ 128 -> 8, 16 128 -> 2, 64 128 -> 4, 32 128 -> 8, 16 128 -> 8, 16
26
+ 250 -> 10, 25 250 -> 2, 125 250 -> 2, 125 250 -> 5, 50 250 -> 10, 25
27
+ 360 -> 8, 45 360 -> 2, 180 360 -> 4, 90 360 -> 8, 45 360 -> 12, 30
28
+ 512 -> 16, 32 512 -> 2, 256 512 -> 4, 128 512 -> 8, 64 512 -> 16, 32
29
+ 1024 -> 32, 32 1024 -> 2, 512 1024 -> 4, 256 1024 -> 8, 128 1024 -> 16, 64
30
+ """
31
+
32
+ if factor > 0 and (dimension % factor) == 0:
33
+ m = factor
34
+ n = dimension // factor
35
+ if m > n:
36
+ n, m = m, n
37
+ return m, n
38
+ if factor < 0:
39
+ factor = dimension
40
+ m, n = 1, dimension
41
+ length = m + n
42
+ while m < n:
43
+ new_m = m + 1
44
+ while dimension % new_m != 0:
45
+ new_m += 1
46
+ new_n = dimension // new_m
47
+ if new_m + new_n > length or new_m > factor:
48
+ break
49
+ else:
50
+ m, n = new_m, new_n
51
+ if m > n:
52
+ n, m = m, n
53
+ return m, n
54
+
55
+
56
+ def power2factorization(dimension: int, factor: int = -1) -> tuple[int, int]:
57
+ """
58
+ m = 2k
59
+ n = 2**p
60
+ m*n = dim
61
+ """
62
+
63
+ # Find the first solution and check if it is even doable
64
+ m = n = 0
65
+ while m <= factor:
66
+ m += 2
67
+ while dimension % m != 0 and m < dimension:
68
+ m += 2
69
+ if m > factor:
70
+ break
71
+ if sum(int(i) for i in f"{dimension//m:b}") == 1:
72
+ n = dimension // m
73
+
74
+ return dimension // n, n
@@ -97,7 +97,7 @@ def lora_bypass_forward_diff(x, d, u, m=None, gamma=1.0, extra_args={}):
97
97
  if __name__ == "__main__":
98
98
  w = torch.randn(32, 32, 3, 3, 3)
99
99
  d, u, m = lora_weight_gen(w, 4)
100
- u = u+0.01
100
+ u = u + 0.01
101
101
  extra_args = {"padding": 1}
102
102
 
103
103
  x = torch.randn(1, 32, 8, 8, 8)
@@ -15,12 +15,12 @@ class HadaWeight(torch.autograd.Function):
15
15
  (w1d, w1u, w2d, w2u, scale) = ctx.saved_tensors
16
16
  grad_out = grad_out * scale
17
17
  temp = grad_out * (w2u @ w2d)
18
- grad_w1d = temp @ w1d.T
19
- grad_w1u = w1u.T @ temp
18
+ grad_w1u = temp @ w1d.T
19
+ grad_w1d = w1u.T @ temp
20
20
 
21
21
  temp = grad_out * (w1u @ w1d)
22
- grad_w2d = temp @ w2d.T
23
- grad_w2u = w2u.T @ temp
22
+ grad_w2u = temp @ w2d.T
23
+ grad_w2d = w2u.T @ temp
24
24
 
25
25
  del temp
26
26
  return grad_w1d, grad_w1u, grad_w2d, grad_w2u, None
@@ -47,11 +47,11 @@ class HadaWeightTucker(torch.autograd.Function):
47
47
  grad_w = rebuild * grad_out
48
48
  del rebuild
49
49
 
50
- grad_w1d = torch.einsum("r j ..., i j ... -> r i", temp, grad_w)
50
+ grad_w1u = torch.einsum("r j ..., i j ... -> r i", temp, grad_w)
51
51
  grad_temp = torch.einsum("i j ..., i r -> r j ...", grad_w, w1u.T)
52
52
  del grad_w, temp
53
53
 
54
- grad_w1u = torch.einsum("i r ..., i j ... -> r j", t1, grad_temp)
54
+ grad_w1d = torch.einsum("i r ..., i j ... -> r j", t1, grad_temp)
55
55
  grad_t1 = torch.einsum("i j ..., j r -> i r ...", grad_temp, w1d.T)
56
56
  del grad_temp
57
57
 
@@ -61,11 +61,11 @@ class HadaWeightTucker(torch.autograd.Function):
61
61
  grad_w = rebuild * grad_out
62
62
  del rebuild
63
63
 
64
- grad_w2d = torch.einsum("r j ..., i j ... -> r i", temp, grad_w)
64
+ grad_w2u = torch.einsum("r j ..., i j ... -> r i", temp, grad_w)
65
65
  grad_temp = torch.einsum("i j ..., i r -> r j ...", grad_w, w2u.T)
66
66
  del grad_w, temp
67
67
 
68
- grad_w2u = torch.einsum("i r ..., i j ... -> r j", t2, grad_temp)
68
+ grad_w2d = torch.einsum("i r ..., i j ... -> r j", t2, grad_temp)
69
69
  grad_t2 = torch.einsum("i j ..., j r -> i r ...", grad_temp, w2d.T)
70
70
  del grad_temp
71
71
  return grad_t1, grad_w1d, grad_w1u, grad_t2, grad_w2d, grad_w2u, None
@@ -10,24 +10,24 @@ from typing import List
10
10
 
11
11
  import torch
12
12
 
13
- from .utils import *
14
- from ..wrapper import LycorisNetwork
15
- from ..modules.locon import LoConModule
16
- from ..modules.loha import LohaModule
17
- from ..modules.ia3 import IA3Module
18
- from ..modules.lokr import LokrModule
19
- from ..modules.dylora import DyLoraModule
20
- from ..modules.glora import GLoRAModule
21
- from ..modules.norms import NormModule
22
- from ..modules.full import FullModule
23
- from ..modules.diag_oft import DiagOFTModule
24
- from ..modules.boft import ButterflyOFTModule
25
- from ..modules import make_module
26
-
27
- from ..config import PRESET
28
- from ..utils.preset import read_preset
29
- from ..utils import get_module, str_bool
30
- from ..logging import logger
13
+ from library.train_util import *
14
+ from .wrapper import LycorisNetwork
15
+ from .modules.locon import LoConModule
16
+ from .modules.loha import LohaModule
17
+ from .modules.ia3 import IA3Module
18
+ from .modules.lokr import LokrModule
19
+ from .modules.dylora import DyLoraModule
20
+ from .modules.glora import GLoRAModule
21
+ from .modules.norms import NormModule
22
+ from .modules.full import FullModule
23
+ from .modules.diag_oft import DiagOFTModule
24
+ from .modules.boft import ButterflyOFTModule
25
+ from .modules import make_module
26
+
27
+ from .config import PRESET
28
+ from .utils.preset import read_preset
29
+ from .utils import get_module, str_bool
30
+ from .logging import logger
31
31
 
32
32
 
33
33
  network_module_dict = {
@@ -61,6 +61,7 @@ class ModuleCustomSD(nn.Module):
61
61
 
62
62
 
63
63
  class LycorisBaseModule(ModuleCustomSD):
64
+ dtype_tensor: torch.Tensor
64
65
  support_module = {}
65
66
 
66
67
  def __init__(
@@ -150,6 +151,8 @@ class LycorisBaseModule(ModuleCustomSD):
150
151
  else:
151
152
  self.module_type = "unknown"
152
153
 
154
+ self.register_buffer("dtype_tensor", torch.tensor(0.0), persistent=False)
155
+
153
156
  self.is_bnb = False
154
157
  if isinstance(org_module, QuantLinears):
155
158
  if not bypass_mode:
@@ -162,9 +165,30 @@ class LycorisBaseModule(ModuleCustomSD):
162
165
  self.rank_dropout_scale = rank_dropout_scale
163
166
  self.module_dropout = module_dropout
164
167
 
168
+ ## Dropout things
169
+ # Since LoKr/LoHa/OFT/BOFT are hard to follow the rank_dropout definition from kohya
170
+ # We redefine the dropout procedure here.
171
+ # g(x) = WX + drop(Brank_drop(AX)) for LoCon(lora), bypass
172
+ # g(x) = WX + drop(ΔWX) for any algo except LoCon(lora), bypass
173
+ # g(x) = (W + Brank_drop(A))X for LoCon(lora), rebuid
174
+ # g(x) = (W + rank_drop(ΔW))X for any algo except LoCon(lora), rebuild
175
+ self.drop = nn.Identity() if dropout == 0.0 else nn.Dropout(dropout)
176
+ self.rank_drop = (
177
+ nn.Identity() if rank_dropout == 0.0 else nn.Dropout(rank_dropout)
178
+ )
179
+
165
180
  self.multiplier = multiplier
181
+ self.org_forward = org_module.forward
166
182
  self.org_module = [org_module]
167
183
 
184
+ @property
185
+ def dtype(self):
186
+ return self.dtype_tensor.dtype
187
+
188
+ @property
189
+ def device(self):
190
+ return self.dtype_tensor.device
191
+
168
192
  @property
169
193
  def org_weight(self):
170
194
  return self.org_module[0].weight
@@ -8,6 +8,7 @@ import torch.nn.functional as F
8
8
  from einops import rearrange
9
9
 
10
10
  from .base import LycorisBaseModule
11
+ from ..functional import power2factorization
11
12
  from ..logging import logger
12
13
  from ..utils.bnb import LinearNF4
13
14
 
@@ -22,30 +23,15 @@ def log_butterfly_factorize(dim, factor, result):
22
23
 
23
24
 
24
25
  def butterfly_factor(dimension: int, factor: int = -1) -> tuple[int, int]:
25
- """
26
- m = 2k
27
- n = 2**p
28
- m*n = dim
29
- """
30
-
31
- # Find the first solution and check if it is even doable
32
- m = n = 0
33
- while m <= factor:
34
- m += 2
35
- while dimension % m != 0 and m < dimension:
36
- m += 2
37
- if m > factor:
38
- break
39
- if sum(int(i) for i in f"{dimension//m:b}") == 1:
40
- n = dimension // m
26
+ m, n = power2factorization(dimension, factor)
41
27
 
42
28
  if n == 0:
43
29
  raise ValueError(
44
30
  f"It is impossible to decompose {dimension} with factor {factor} under BOFT constrains."
45
31
  )
46
32
 
47
- log_butterfly_factorize(dimension, factor, (dimension // n, n))
48
- return dimension // n, n
33
+ log_butterfly_factorize(dimension, factor, (m, n))
34
+ return m, n
49
35
 
50
36
 
51
37
  class ButterflyOFTModule(LycorisBaseModule):
@@ -108,7 +94,7 @@ class ButterflyOFTModule(LycorisBaseModule):
108
94
 
109
95
  @property
110
96
  def I(self):
111
- return torch.eye(self.block_size, device=next(self.parameters()).device)
97
+ return torch.eye(self.block_size, device=self.device)
112
98
 
113
99
  def get_r(self):
114
100
  I = self.I
@@ -215,29 +201,32 @@ class ButterflyOFTModule(LycorisBaseModule):
215
201
 
216
202
  if __name__ == "__main__":
217
203
  base = nn.Linear(128, 128).cuda()
218
- lokr = ButterflyOFTModule("test", base, 1, 4, 1, weight_decompose=True).cuda()
219
- print(lokr)
220
- test_input = torch.randn(1, 128).cuda()
221
- test_output = lokr(test_input)
204
+ boft = ButterflyOFTModule(
205
+ "test", base, 1, 4, 1, weight_decompose=True, factor=8
206
+ ).cuda()
207
+ print(boft)
208
+ test_input = torch.randn(1, 77, 128).cuda()
209
+ test_output = boft(test_input)
210
+ torch.sum(test_output).backward()
222
211
  print(test_output.shape)
223
- print(F.mse_loss(test_output, lokr.bypass_forward(test_input)))
224
212
 
225
213
  base_4bit = LinearNF4(128, 128)
226
214
  base_4bit.load_state_dict(base.state_dict())
227
215
  base_4bit.cuda()
228
- qlocon = ButterflyOFTModule(
216
+ qboft = ButterflyOFTModule(
229
217
  "test", base_4bit, 1, 4, 1, weight_decompose=False
230
218
  ).cuda()
231
- print(qlocon)
232
- test_input = torch.randn(1, 128).cuda()
233
- test_output = qlocon(test_input)
219
+ print(qboft)
220
+ test_output = qboft(test_input)
221
+ torch.sum(test_output).backward()
234
222
  print(test_output.shape)
235
223
 
236
224
  base = nn.Conv2d(128, 128, 3, 1, 1)
237
- lokr = ButterflyOFTModule(
225
+ boft = ButterflyOFTModule(
238
226
  "test", base, 1, 4, 1, weight_decompose=True, use_tucker=True
239
227
  )
240
- print(lokr)
228
+ print(boft)
241
229
  test_input = torch.randn(1, 128, 16, 16)
242
- test_output = lokr(test_input)
230
+ test_output = boft(test_input)
231
+ torch.sum(test_output).backward()
243
232
  print(test_output.shape)
@@ -7,7 +7,7 @@ import torch.nn.functional as F
7
7
  from einops import rearrange
8
8
 
9
9
  from .base import LycorisBaseModule
10
- from .lokr import factorization
10
+ from ..functional import factorization
11
11
  from ..logging import logger
12
12
  from ..utils.bnb import LinearNF4
13
13
 
@@ -83,7 +83,7 @@ class DiagOFTModule(LycorisBaseModule):
83
83
 
84
84
  @property
85
85
  def I(self):
86
- return torch.eye(self.block_size, device=next(self.parameters()).device)
86
+ return torch.eye(self.block_size, device=self.device)
87
87
 
88
88
  def get_r(self):
89
89
  I = self.I
@@ -100,22 +100,19 @@ class DiagOFTModule(LycorisBaseModule):
100
100
 
101
101
  def make_weight(self, scale=1, device=None, diff=False):
102
102
  r = self.get_r()
103
+ _, *shape = self.org_weight.shape
103
104
  org_weight = self.org_weight.to(device, dtype=r.dtype)
104
- org_weight = rearrange(
105
- org_weight,
106
- "(k n) ... -> k n ...",
107
- k=self.block_num,
108
- n=self.block_size,
109
- )
105
+ org_weight = org_weight.view(self.block_num, self.block_size, *shape)
110
106
  # Init R=0, so add I on it to ensure the output of step0 is original model output
111
107
  weight = torch.einsum(
112
108
  "k n m, k n ... -> k m ...",
113
- r * scale - scale * self.I + (self.I if diff else 0),
109
+ self.rank_drop(r * scale) - scale * self.I + (0 if diff else self.I),
114
110
  org_weight,
115
- )
116
- weight = rearrange(weight, "k m ... -> (k m) ...")
111
+ ).view(-1, *shape)
117
112
  if self.rescaled:
118
113
  weight = self.rescale * weight
114
+ if diff:
115
+ weight = weight + (self.rescale - 1) * org_weight
119
116
  return weight
120
117
 
121
118
  def get_diff_weight(self, multiplier=1, shape=None, device=None):
@@ -148,18 +145,21 @@ class DiagOFTModule(LycorisBaseModule):
148
145
  org_out = self.org_forward(x)
149
146
  if self.op == F.conv2d:
150
147
  org_out = org_out.transpose(1, -1)
151
- org_out = rearrange(
152
- org_out,
153
- "... (k n) ->... k n",
154
- k=self.block_num,
155
- n=self.block_size,
156
- )
148
+ *shape, _ = org_out.shape
149
+ org_out = org_out.view(*shape, self.block_num, self.block_size)
150
+ mask = neg_mask = 1
151
+ if self.dropout != 0 and self.training:
152
+ mask = torch.ones_like(org_out)
153
+ mask = self.drop(mask)
154
+ neg_mask = torch.max(mask) - mask
157
155
  oft_out = torch.einsum(
158
156
  "k n m, ... k n -> ... k m",
159
- r * scale - scale * self.I + (self.I if diff else 0),
157
+ r * scale * mask + (1 - scale) * self.I * neg_mask,
160
158
  org_out,
161
159
  )
162
- out = rearrange(oft_out, "... k m -> ... (k m)")
160
+ if diff:
161
+ out = out - org_out
162
+ out = oft_out.view(*shape, -1)
163
163
  if self.op == F.conv2d:
164
164
  out = out.transpose(1, -1)
165
165
  return out
@@ -186,24 +186,26 @@ class DiagOFTModule(LycorisBaseModule):
186
186
 
187
187
  if __name__ == "__main__":
188
188
  base = nn.Linear(128, 128).cuda()
189
- lokr = DiagOFTModule("test", base, 1, 4, 1, weight_decompose=True).cuda()
190
- print(lokr)
191
- test_input = torch.randn(1, 128).cuda()
192
- test_output = lokr(test_input)
189
+ doft = DiagOFTModule("test", base, 1, 4, 1, weight_decompose=True, factor=8).cuda()
190
+ print(doft)
191
+ test_input = torch.randn(1, 77, 128).cuda()
192
+ test_output = doft(test_input)
193
+ torch.sum(test_output).backward()
193
194
  print(test_output.shape)
194
195
 
195
196
  base_4bit = LinearNF4(128, 128)
196
197
  base_4bit.load_state_dict(base.state_dict())
197
198
  base_4bit.cuda()
198
- qlocon = DiagOFTModule("test", base_4bit, 1, 4, 1, weight_decompose=False).cuda()
199
- print(qlocon)
200
- test_input = torch.randn(1, 128).cuda()
201
- test_output = qlocon(test_input)
199
+ qdoft = DiagOFTModule("test", base_4bit, 1, 4, 1, weight_decompose=False).cuda()
200
+ print(qdoft)
201
+ test_output = qdoft(test_input)
202
+ torch.sum(test_output).backward()
202
203
  print(test_output.shape)
203
204
 
204
205
  base = nn.Conv2d(128, 128, 3, 1, 1)
205
- lokr = DiagOFTModule("test", base, 1, 4, 1, weight_decompose=True, use_tucker=True)
206
- print(lokr)
206
+ doft = DiagOFTModule("test", base, 1, 4, 1, weight_decompose=True, use_tucker=True)
207
+ print(doft)
207
208
  test_input = torch.randn(1, 128, 16, 16)
208
- test_output = lokr(test_input)
209
+ test_output = doft(test_input)
210
+ torch.sum(test_output).backward()
209
211
  print(test_output.shape)
@@ -41,6 +41,11 @@ class FullModule(LycorisBaseModule):
41
41
  if self.module_type not in self.support_module:
42
42
  raise ValueError(f"{self.module_type} is not supported in Full algo.")
43
43
 
44
+ if self.is_bnb:
45
+ raise ValueError(
46
+ "Quant Linear is not supported and meaningless in Full algo."
47
+ )
48
+
44
49
  if self.bypass_mode:
45
50
  raise ValueError("bypass mode is not supported in Full algo.")
46
51
 
@@ -50,6 +55,14 @@ class FullModule(LycorisBaseModule):
50
55
  else:
51
56
  self.bias = None
52
57
 
58
+ @property
59
+ def org_weight(self):
60
+ return self._org_weight[0]
61
+
62
+ @org_weight.setter
63
+ def org_weight(self, value):
64
+ self.org_module[0].weight.data.copy_(value)
65
+
53
66
  def apply_to(self, **kwargs):
54
67
  self.org_forward = self.org_module[0].forward
55
68
  self.org_module[0].forward = self.forward
@@ -85,32 +98,40 @@ class FullModule(LycorisBaseModule):
85
98
  diff_bias = state_dict["diff_b"]
86
99
  self.bias.data.add_(diff_bias)
87
100
 
88
- def make_weight(self, scale=1, device=None, original=False):
89
- if original:
90
- weight = self._org_weight[0].to(device, dtype=self.weight.dtype)
91
- if self.org_bias is not None:
92
- bias = self.org_bias[0].to(device, dtype=self.bias.dtype)
93
- else:
94
- bias = None
95
- return weight, bias
101
+ def make_weight(self, scale=1, device=None):
96
102
  drop = (
97
103
  torch.rand(self.dim, device=device) > self.rank_dropout
98
104
  if self.rank_dropout and self.training
99
105
  else 1
100
106
  )
101
107
  if drop != 1 or scale != 1:
102
- org_weight = self.org_module[0].weight.to(device, dtype=self.weight.dtype)
103
- diff = self.weight.to(device) - org_weight
104
- weight = diff * drop * scale + org_weight
105
- if self.bias is not None:
106
- org_bias = self.org_module[0].bias.to(device, dtype=self.bias.dtype)
107
- diff_b = self.bias.to(device) - org_bias
108
- bias = diff_b * drop * scale + org_bias
108
+ diff_w, diff_b = self.get_diff_weight(scale, device=device)
109
+ weight = self.org_module[0].weight + diff_w * drop
110
+ bias = self.org_module[0].bias + diff_b * drop
109
111
  else:
110
112
  weight = self.weight
111
113
  bias = self.bias
112
114
  return weight, bias
113
115
 
116
+ def get_diff_weight(self, multiplier=1, shape=None, device=None):
117
+ org_weight = self.org_module[0].weight.to(device, dtype=self.weight.dtype)
118
+ diff = self.weight.to(device) - org_weight
119
+ diff_b = None
120
+ if shape:
121
+ diff = diff.view(shape)
122
+ if self.bias is not None:
123
+ org_bias = self.org_module[0].bias.to(device, dtype=self.bias.dtype)
124
+ diff_b = self.bias.to(device) - org_bias
125
+ if device is not None:
126
+ diff = diff.to(device)
127
+ if self.bias is not None:
128
+ diff_b = diff_b.to(device)
129
+ if multiplier != 1:
130
+ diff = diff * multiplier
131
+ if diff_b is not None:
132
+ diff_b = diff_b * multiplier
133
+ return diff * multiplier, diff_b
134
+
114
135
  def get_merged_weight(self, multiplier=1, shape=None, device=None):
115
136
  weight, bias = self.make_weight(multiplier, device)
116
137
  if shape is not None:
@@ -128,7 +149,27 @@ class FullModule(LycorisBaseModule):
128
149
  original = True
129
150
  else:
130
151
  original = False
152
+ if original:
153
+ return self.org_forward(x)
131
154
  scale = self.multiplier
132
- weight, bias = self.make_weight(scale, x.device, original=original)
155
+ weight, bias = self.make_weight(scale, x.device)
133
156
  kw_dict = self.kw_dict | {"weight": weight, "bias": bias}
134
157
  return self.op(x, **kw_dict)
158
+
159
+
160
+ if __name__ == "__main__":
161
+ base = nn.Linear(128, 128).cuda()
162
+ full = FullModule("test", base, 1, 4, 1, weight_decompose=True, factor=8).cuda()
163
+ print(full)
164
+ test_input = torch.randn(1, 77, 128).cuda()
165
+ test_output = full(test_input)
166
+ torch.sum(test_output).backward()
167
+ print(test_output.shape)
168
+
169
+ base = nn.Conv2d(128, 128, 3, 1, 1)
170
+ full = FullModule("test", base, 1, 4, 1, weight_decompose=True, use_tucker=True)
171
+ print(full)
172
+ test_input = torch.randn(1, 128, 16, 16)
173
+ test_output = full(test_input)
174
+ torch.sum(test_output).backward()
175
+ print(test_output.shape)