lycoris-lora 3.0.0.dev13__tar.gz → 3.0.0.dev15__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 (47) hide show
  1. {lycoris_lora-3.0.0.dev13/lycoris_lora.egg-info → lycoris_lora-3.0.0.dev15}/PKG-INFO +1 -1
  2. lycoris_lora-3.0.0.dev15/lycoris/functional/__init__.py +9 -0
  3. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/functional/boft.py +14 -28
  4. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/functional/diag_oft.py +10 -26
  5. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/functional/general.py +27 -0
  6. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/functional/locon.py +6 -21
  7. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/functional/loha.py +15 -34
  8. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/functional/lokr.py +5 -24
  9. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/modules/base.py +2 -1
  10. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/modules/boft.py +1 -1
  11. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/modules/diag_oft.py +1 -1
  12. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/modules/glora.py +1 -1
  13. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/modules/loha.py +1 -1
  14. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/utils/__init__.py +21 -158
  15. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15/lycoris_lora.egg-info}/PKG-INFO +1 -1
  16. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/setup.py +1 -1
  17. lycoris_lora-3.0.0.dev15/test/functional.py +87 -0
  18. lycoris_lora-3.0.0.dev13/lycoris/functional/__init__.py +0 -20
  19. lycoris_lora-3.0.0.dev13/test/functional.py +0 -71
  20. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/LICENSE.md +0 -0
  21. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/README.md +0 -0
  22. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/__init__.py +0 -0
  23. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/config.py +0 -0
  24. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/kohya.py +0 -0
  25. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/logging.py +0 -0
  26. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/modules/__init__.py +0 -0
  27. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/modules/dylora.py +0 -0
  28. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/modules/full.py +0 -0
  29. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/modules/ia3.py +0 -0
  30. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/modules/locon.py +0 -0
  31. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/modules/lokr.py +0 -0
  32. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/modules/norms.py +0 -0
  33. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/utils/bnb.py +0 -0
  34. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/utils/general.py +0 -0
  35. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/utils/logger.py +0 -0
  36. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/utils/preset.py +0 -0
  37. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/utils/xformers_utils.py +0 -0
  38. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris/wrapper.py +0 -0
  39. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris_lora.egg-info/SOURCES.txt +0 -0
  40. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris_lora.egg-info/dependency_links.txt +0 -0
  41. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris_lora.egg-info/not-zip-safe +0 -0
  42. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris_lora.egg-info/requires.txt +0 -0
  43. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/lycoris_lora.egg-info/top_level.txt +0 -0
  44. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/setup.cfg +0 -0
  45. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/test/__init__.py +0 -0
  46. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/test/module.py +0 -0
  47. {lycoris_lora-3.0.0.dev13 → lycoris_lora-3.0.0.dev15}/test/wrapper.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lycoris_lora
3
- Version: 3.0.0.dev13
3
+ Version: 3.0.0.dev15
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,9 @@
1
+ from .general import (
2
+ rebuild_tucker,
3
+ factorization,
4
+ power2factorization,
5
+ FUNC_LIST,
6
+ tucker_weight,
7
+ tucker_weight_from_conv,
8
+ apply_dora_scale,
9
+ )
@@ -10,7 +10,7 @@ from .general import power2factorization, FUNC_LIST
10
10
  from .diag_oft import get_r
11
11
 
12
12
 
13
- def boft_weight_gen(org_weight, max_block_size, boft_m=-1, rescale=False):
13
+ def weight_gen(org_weight, max_block_size, boft_m=-1, rescale=False):
14
14
  """### boft_weight_gen
15
15
 
16
16
  Args:
@@ -28,13 +28,13 @@ def boft_weight_gen(org_weight, max_block_size, boft_m=-1, rescale=False):
28
28
  boft_m = max_boft_m
29
29
  boft_m = min(boft_m, max_boft_m)
30
30
  oft_blocks = torch.zeros(boft_m, block_num, block_size, block_size)
31
- if rescale:
31
+ if rescale is not None:
32
32
  return oft_blocks, torch.ones(out_dim, *[1] * len(rest))
33
33
  else:
34
34
  return oft_blocks, None
35
35
 
36
36
 
37
- def boft_diff_weight(org_weight, oft_blocks, rescale=None, constraint=None):
37
+ def diff_weight(org_weight, oft_blocks, rescale=None, constraint=None):
38
38
  """### boft_diff_weight
39
39
 
40
40
  Args:
@@ -57,11 +57,14 @@ def boft_diff_weight(org_weight, oft_blocks, rescale=None, constraint=None):
57
57
  inp = rearrange(inp, "d b ... -> (d b) ...")
58
58
  inp = rearrange(inp, "(c k g) ... -> (c g k) ...", g=2, k=2**i * r_b)
59
59
 
60
- return inp * rescale - org
60
+ if rescale is not None:
61
+ inp = inp * rescale
61
62
 
63
+ return inp - org
62
64
 
63
- def boft_bypass_forward_diff(
64
- org_out, need_transpose, oft_blocks, rescale=None, constraint=None
65
+
66
+ def bypass_forward_diff(
67
+ org_out, oft_blocks, rescale=None, constraint=None, need_transpose=False
65
68
  ):
66
69
  """### boft_bypass_forward_diff
67
70
 
@@ -75,7 +78,7 @@ def boft_bypass_forward_diff(
75
78
  r_b = b // 2
76
79
  I = torch.eye(b, device=oft_blocks.device)
77
80
  r = get_r(oft_blocks, I, constraint)
78
- inp = org_out.to(dtype=r.dtype)
81
+ inp = org = org_out.to(dtype=r.dtype)
79
82
  if need_transpose:
80
83
  inp = org = inp.transpose(1, -1)
81
84
 
@@ -87,27 +90,10 @@ def boft_bypass_forward_diff(
87
90
  inp = rearrange(inp, "... d b -> ... (d b)")
88
91
  inp = rearrange(inp, "... (c k g) -> ... (c g k)", g=2, k=2**i * r_b)
89
92
 
90
- inp = inp * rescale.transpose(0, -1) - org
93
+ if rescale is not None:
94
+ inp = inp * rescale.transpose(0, -1)
95
+
96
+ inp = inp - org
91
97
  if need_transpose:
92
98
  inp = inp.transpose(1, -1)
93
99
  return inp
94
-
95
-
96
- if __name__ == "__main__":
97
- w = torch.randn(32, 32, 3, 3, 3)
98
- blocks, rescale = boft_weight_gen(w, 4, -1, True)
99
- blocks = blocks + torch.randn_like(blocks) * 0.01
100
- extra_args = {"padding": 1}
101
-
102
- x = torch.randn(1, 32, 8, 8, 8)
103
- y = FUNC_LIST[x.dim()](x, w, **extra_args)
104
- diff_w = boft_diff_weight(w, blocks, rescale, 0.1)
105
- diff_y_rebuild = FUNC_LIST[x.dim()](x, diff_w, **extra_args)
106
- diff_y = boft_bypass_forward_diff(y, w.dim() > 2, blocks, rescale, 0.1)
107
-
108
- print(y.shape, diff_y.shape, diff_y_rebuild.shape)
109
- print(w.shape, diff_w.shape)
110
-
111
- print(F.mse_loss(y, y + diff_y))
112
- print(F.mse_loss(w, w + diff_w))
113
- print(F.mse_loss(diff_y, diff_y_rebuild))
@@ -16,7 +16,7 @@ def get_r(oft_blocks, I=None, constraint=0):
16
16
  # for Q = -Q^T
17
17
  q = oft_blocks - oft_blocks.transpose(-1, -2)
18
18
  normed_q = q
19
- if constraint > 0:
19
+ if constraint is not None and constraint > 0:
20
20
  q_norm = torch.norm(q) + 1e-8
21
21
  if q_norm > constraint:
22
22
  normed_q = q * constraint / q_norm
@@ -25,8 +25,8 @@ def get_r(oft_blocks, I=None, constraint=0):
25
25
  return r
26
26
 
27
27
 
28
- def daig_oft_weight_gen(org_weight, max_block_size, rescale=False):
29
- """### daig_oft_weight_gen
28
+ def weight_gen(org_weight, max_block_size, rescale=False):
29
+ """### weight_gen
30
30
 
31
31
  Args:
32
32
  org_weight (torch.Tensor): the weight tensor
@@ -45,8 +45,8 @@ def daig_oft_weight_gen(org_weight, max_block_size, rescale=False):
45
45
  return oft_blocks, None
46
46
 
47
47
 
48
- def daig_oft_diff_weight(org_weight, oft_blocks, rescale=None, constraint=None):
49
- """### daig_oft_diff_weight
48
+ def diff_weight(org_weight, oft_blocks, rescale=None, constraint=None):
49
+ """### diff_weight
50
50
 
51
51
  Args:
52
52
  TODO
@@ -67,16 +67,16 @@ def daig_oft_diff_weight(org_weight, oft_blocks, rescale=None, constraint=None):
67
67
  r - I,
68
68
  org_weight,
69
69
  ).view(-1, *shape)
70
- if rescale is None:
70
+ if rescale is not None:
71
71
  weight = rescale * weight
72
72
  weight = weight + (rescale - 1) * org_weight
73
73
  return weight
74
74
 
75
75
 
76
- def daig_oft_bypass_forward_diff(
77
- org_out, need_transpose, oft_blocks, rescale=None, constraint=None
76
+ def bypass_forward_diff(
77
+ org_out, oft_blocks, rescale=None, constraint=None, need_transpose=False
78
78
  ):
79
- """### daig_oft_bypass_forward_diff
79
+ """### bypass_forward_diff
80
80
 
81
81
  Args:
82
82
  TODO
@@ -89,6 +89,7 @@ def daig_oft_bypass_forward_diff(
89
89
  r = get_r(oft_blocks, I, constraint)
90
90
  if need_transpose:
91
91
  org_out = org_out.transpose(1, -1)
92
+ org_out = org_out.to(dtype=r.dtype)
92
93
  *shape, _ = org_out.shape
93
94
  oft_out = torch.einsum(
94
95
  "k n m, ... k n -> ... k m", r - I, org_out.view(*shape, block_num, block_size)
@@ -100,20 +101,3 @@ def daig_oft_bypass_forward_diff(
100
101
  if need_transpose:
101
102
  out = out.transpose(1, -1)
102
103
  return out
103
-
104
-
105
- if __name__ == "__main__":
106
- w = torch.randn(32, 32, 3, 3, 3)
107
- blocks, rescale = daig_oft_weight_gen(w, 4, True)
108
- blocks = blocks + torch.randn_like(blocks) * 0.01
109
- extra_args = {"padding": 1}
110
-
111
- x = torch.randn(1, 32, 8, 8, 8)
112
- y = FUNC_LIST[x.dim()](x, w, **extra_args)
113
- diff_w = daig_oft_diff_weight(w, blocks, rescale, 0.1)
114
- diff_y_rebuild = FUNC_LIST[x.dim()](x, diff_w, **extra_args)
115
- diff_y = daig_oft_bypass_forward_diff(y, w.dim() > 2, blocks, rescale, 0.1)
116
-
117
- print(F.mse_loss(y, y + diff_y))
118
- print(F.mse_loss(w, w + diff_w))
119
- print(F.mse_loss(diff_y, diff_y_rebuild))
@@ -77,3 +77,30 @@ def power2factorization(dimension: int, factor: int = -1) -> tuple[int, int]:
77
77
  n = dimension // m
78
78
 
79
79
  return dimension // n, n
80
+
81
+
82
+ def tucker_weight_from_conv(up, down, mid):
83
+ up = up.reshape(up.size(0), up.size(1))
84
+ down = down.reshape(down.size(0), down.size(1))
85
+ return torch.einsum("m n ..., i m, n j -> i j ...", mid, up, down)
86
+
87
+
88
+ def tucker_weight(wa, wb, t):
89
+ temp = torch.einsum("i j ..., j r -> i r ...", t, wb)
90
+ return torch.einsum("i j ..., i r -> r j ...", temp, wa)
91
+
92
+
93
+ def apply_dora_scale(org_weight, rebuild, dora_scale, scale):
94
+ dora_norm_dims = org_weight.dim() - 1
95
+ weight = org_weight + rebuild
96
+ weight = weight.to(dora_scale.dtype)
97
+ weight_norm = (
98
+ weight.transpose(0, 1)
99
+ .reshape(weight.shape[1], -1)
100
+ .norm(dim=1, keepdim=True)
101
+ .reshape(weight.shape[1], *[1] * dora_norm_dims)
102
+ .transpose(0, 1)
103
+ )
104
+ merged_scale1 = weight / weight_norm * dora_scale
105
+ diff_weight = merged_scale1 - org_weight
106
+ return org_weight + diff_weight * scale
@@ -7,8 +7,8 @@ import torch.nn.functional as F
7
7
  from .general import rebuild_tucker, FUNC_LIST
8
8
 
9
9
 
10
- def lora_weight_gen(org_weight, rank, tucker=True):
11
- """### lora_weight_gen
10
+ def weight_gen(org_weight, rank, tucker=True):
11
+ """### weight_gen
12
12
 
13
13
  Args:
14
14
  org_weight (torch.Tensor): the weight tensor
@@ -34,8 +34,8 @@ def lora_weight_gen(org_weight, rank, tucker=True):
34
34
  return down, up
35
35
 
36
36
 
37
- def lora_diff_weight(d, u, m=None, gamma=1.0):
38
- """### lora_diff_weight
37
+ def diff_weight(d, u, m=None, gamma=1.0):
38
+ """### diff_weight
39
39
 
40
40
  Get ΔW = BA, where BA is low rank decomposition
41
41
 
@@ -62,8 +62,8 @@ def lora_diff_weight(d, u, m=None, gamma=1.0):
62
62
  return result.reshape(O, I, *k)
63
63
 
64
64
 
65
- def lora_bypass_forward_diff(x, d, u, m=None, gamma=1.0, extra_args={}):
66
- """### lora_bypass_forward_diff
65
+ def bypass_forward_diff(x, d, u, m=None, gamma=1.0, extra_args={}):
66
+ """### bypass_forward_diff
67
67
 
68
68
  Args:
69
69
  x (torch.Tensor): input tensor
@@ -85,18 +85,3 @@ def lora_bypass_forward_diff(x, d, u, m=None, gamma=1.0, extra_args={}):
85
85
  down = FUNC_LIST[d.dim()](x, d, **extra_args)
86
86
  up = FUNC_LIST[d.dim()](down, u)
87
87
  return up * gamma
88
-
89
-
90
- if __name__ == "__main__":
91
- w = torch.randn(32, 32, 3, 3, 3)
92
- d, u, m = lora_weight_gen(w, 4)
93
- u = u + 0.01
94
- extra_args = {"padding": 1}
95
-
96
- x = torch.randn(1, 32, 8, 8, 8)
97
- y = FUNC_LIST[d.dim()](x, w, **extra_args)
98
- diff_w = lora_diff_weight(d, u, m, 1)
99
- diff_y = lora_bypass_forward_diff(x, d, u, m, 1, extra_args)
100
-
101
- print(F.mse_loss(y, y + diff_y))
102
- print(F.mse_loss(w, w + diff_w))
@@ -83,8 +83,8 @@ def make_weight_tucker(t1, w1d, w1u, t2, w2d, w2u, scale):
83
83
  return HadaWeightTucker.apply(t1, w1d, w1u, t2, w2d, w2u, scale)
84
84
 
85
85
 
86
- def loha_weight_gen(org_weight, rank, tucker=True):
87
- """### loha_weight_gen
86
+ def weight_gen(org_weight, rank, tucker=True):
87
+ """### weight_gen
88
88
 
89
89
  Args:
90
90
  org_weight (torch.Tensor): the weight tensor
@@ -101,27 +101,23 @@ def loha_weight_gen(org_weight, rank, tucker=True):
101
101
  w2d = torch.empty(rank, in_dim)
102
102
  w2u = torch.empty(rank, out_dim)
103
103
  t2 = torch.empty(rank, rank, *k)
104
- nn.init.normal_(w1d, std=1)
105
- nn.init.constant_(w1u, 0)
106
- nn.init.normal_(w2d, std=1)
107
- nn.init.normal_(w2u, std=0.1)
108
104
  nn.init.normal_(t1, std=0.1)
109
105
  nn.init.normal_(t2, std=0.1)
110
- return w1d, w2d, w1u, w2u, t1, t2
111
106
  else:
112
107
  w1d = torch.empty(rank, in_dim)
113
- w1u = torch.empty(rank, out_dim)
108
+ w1u = torch.empty(out_dim, rank)
114
109
  w2d = torch.empty(rank, in_dim)
115
- w2u = torch.empty(rank, out_dim)
116
- nn.init.normal_(w1d, std=1)
117
- nn.init.constant_(w1u, 0)
118
- nn.init.normal_(w2d, std=1)
119
- nn.init.normal_(w2u, std=0.1)
120
- return w1d, w2d, w1u, w2u
110
+ w2u = torch.empty(out_dim, rank)
111
+ t1 = t2 = None
112
+ nn.init.normal_(w1d, std=1)
113
+ nn.init.constant_(w1u, 0)
114
+ nn.init.normal_(w2d, std=1)
115
+ nn.init.normal_(w2u, std=0.1)
116
+ return w1d, w1u, w2d, w2u, t1, t2
121
117
 
122
118
 
123
- def loha_diff_weight(w1d, w1u, w2d, w2u, t1=None, t2=None, gamma=1.0):
124
- """### loha_diff_weight
119
+ def diff_weight(w1d, w1u, w2d, w2u, t1=None, t2=None, gamma=1.0):
120
+ """### diff_weight
125
121
 
126
122
  Get ΔW = BA, where BA is low rank decomposition
127
123
 
@@ -152,10 +148,10 @@ def loha_diff_weight(w1d, w1u, w2d, w2u, t1=None, t2=None, gamma=1.0):
152
148
  return result
153
149
 
154
150
 
155
- def loha_bypass_forward_diff(
151
+ def bypass_forward_diff(
156
152
  x, w1d, w1u, w2d, w2u, t1=None, t2=None, gamma=1.0, extra_args={}
157
153
  ):
158
- """### loha_bypass_forward_diff
154
+ """### bypass_forward_diff
159
155
 
160
156
  Args:
161
157
  x (torch.Tensor): input tensor
@@ -168,20 +164,5 @@ def loha_bypass_forward_diff(
168
164
  Returns:
169
165
  torch.Tensor: output tensor
170
166
  """
171
- diff_w = loha_diff_weight(w1d, w1u, w2d, w2u, t1, t2, gamma)
167
+ diff_w = diff_weight(w1d, w1u, w2d, w2u, t1, t2, gamma)
172
168
  return FUNC_LIST[w1d.dim() if t1 is None else t1.dim()](x, diff_w, **extra_args)
173
-
174
-
175
- if __name__ == "__main__":
176
- w = torch.randn(128, 128, 3, 3, 3)
177
- w1d, w2d, w1u, w2u, t1, t2 = loha_weight_gen(w, 4, tucker=True)
178
- w1u += 0.01
179
- extra_args = {"padding": 1}
180
-
181
- x = torch.randn(1, 128, 8, 8, 8)
182
- y = FUNC_LIST[w.dim()](x, w, **extra_args)
183
- diff_w = loha_diff_weight(w1d, w2d, w1u, w2u, t1, t2, 1)
184
- diff_y = loha_bypass_forward_diff(x, w1d, w2d, w1u, w2u, t1, t2, 1, extra_args)
185
-
186
- print(F.mse_loss(y, y + diff_y))
187
- print(F.mse_loss(w, w + diff_w))
@@ -17,7 +17,7 @@ def make_kron(w1, w2, scale):
17
17
  return rebuild * scale
18
18
 
19
19
 
20
- def lokr_weight_gen(
20
+ def weight_gen(
21
21
  org_weight,
22
22
  rank,
23
23
  tucker=True,
@@ -118,8 +118,8 @@ def lokr_weight_gen(
118
118
  return w1, w1a, w1b, w2, w2a, w2b, t2
119
119
 
120
120
 
121
- def lokr_diff_weight(w1, w1a, w1b, w2, w2a, w2b, t, gamma=1.0):
122
- """### lokr_diff_weight
121
+ def diff_weight(w1, w1a, w1b, w2, w2a, w2b, t, gamma=1.0):
122
+ """### diff_weight
123
123
 
124
124
  Args:
125
125
  gamma (float, optional): scale factor, normally alpha/rank here
@@ -146,10 +146,8 @@ def lokr_diff_weight(w1, w1a, w1b, w2, w2a, w2b, t, gamma=1.0):
146
146
  return make_kron(w1, w2, scale)
147
147
 
148
148
 
149
- def lokr_bypass_forward_diff(
150
- h, w1, w1a, w1b, w2, w2a, w2b, t, gamma=1.0, extra_args={}
151
- ):
152
- """### lokr_bypass_forward_diff
149
+ def bypass_forward_diff(h, w1, w1a, w1b, w2, w2a, w2b, t, gamma=1.0, extra_args={}):
150
+ """### bypass_forward_diff
153
151
 
154
152
  Args:
155
153
  gamma (float, optional): scale factor, normally alpha/rank here
@@ -163,7 +161,6 @@ def lokr_bypass_forward_diff(
163
161
  use_w2 = w2 is not None
164
162
  tucker = t is not None
165
163
  dim = t.dim() if tucker else w2.dim() if w2 is not None else w2b.dim()
166
- print(dim)
167
164
  rank = w1b.size(0) if not use_w1 else w2b.size(0) if not use_w2 else gamma
168
165
  scale = gamma / rank
169
166
  is_conv = dim > 2
@@ -241,19 +238,3 @@ def lokr_bypass_forward_diff(
241
238
  h = hc.reshape(*hc.shape[:-2], -1)
242
239
 
243
240
  return h * scale
244
-
245
-
246
- if __name__ == "__main__":
247
- w = torch.randn(32, 32, 3, 3, 3)
248
- w1, w1a, w1b, w2, w2a, w2b, t = lokr_weight_gen(w, 2, tucker=False)
249
- extra_args = {"padding": 1}
250
-
251
- x = torch.randn(1, 32, 8, 8, 8)
252
- y = FUNC_LIST[w.dim()](x, w, **extra_args)
253
- diff_w = lokr_diff_weight(w1, w1a, w1b, w2, w2a, w2b, t, 1)
254
- diff_y_w = FUNC_LIST[w.dim()](x, diff_w, **extra_args)
255
- diff_y = lokr_bypass_forward_diff(x, w1, w1a, w1b, w2, w2a, w2b, t, 1, extra_args)
256
-
257
- print(F.mse_loss(y, y + diff_y))
258
- print(F.mse_loss(w, w + diff_w))
259
- print(F.mse_loss(diff_y, diff_y_w))
@@ -269,8 +269,9 @@ class LycorisBaseModule(ModuleCustomSD):
269
269
  weight, bias = self.get_merged_weight(
270
270
  multiplier, self.org_weight.shape, self.org_weight.device
271
271
  )
272
- self.org_weight = weight
272
+ self.org_weight = weight.to(self.org_weight)
273
273
  if bias is not None:
274
+ bias = bias.to(self.org_weight)
274
275
  if self.org_module[0].bias is not None:
275
276
  self.org_module[0].bias.data.copy_(bias)
276
277
  else:
@@ -197,7 +197,7 @@ class ButterflyOFTModule(LycorisBaseModule):
197
197
  r = self.get_r()
198
198
  inp = org = self.org_forward(x)
199
199
  if self.op in {F.conv2d, F.conv1d, F.conv3d}:
200
- org_out = org_out.transpose(1, -1)
200
+ inp = inp.transpose(1, -1)
201
201
 
202
202
  for i in range(m):
203
203
  bi = r[i] # b_num, b_size, b_size
@@ -188,7 +188,7 @@ class DiagOFTModule(LycorisBaseModule):
188
188
  if diff:
189
189
  out = out - org_out
190
190
  out = oft_out.view(*shape, -1)
191
- if self.rescale is not None:
191
+ if self.rescaled:
192
192
  out = self.rescale.transpose(-1, 0) * out
193
193
  out = out + (self.rescale.transpose(-1, 0) - 1) * org_out
194
194
  if self.op in {F.conv2d, F.conv1d, F.conv3d}:
@@ -5,7 +5,7 @@ import torch.nn as nn
5
5
  import torch.nn.functional as F
6
6
 
7
7
  from .base import LycorisBaseModule
8
- from ..utils import tucker_weight_from_conv
8
+ from ..functional import tucker_weight_from_conv
9
9
  from ..utils.bnb import LinearNF4
10
10
 
11
11
 
@@ -4,7 +4,7 @@ import torch
4
4
  import torch.nn as nn
5
5
 
6
6
  from .base import LycorisBaseModule
7
- from ..functional.loha import loha_diff_weight
7
+ from ..functional.loha import diff_weight as loha_diff_weight
8
8
  from ..utils.bnb import LinearNF4
9
9
 
10
10
 
@@ -417,138 +417,10 @@ def convert_diffusers_name_to_compvis(key):
417
417
  return key
418
418
 
419
419
 
420
- def tucker_weight_from_conv(up, down, mid):
421
- up = up.reshape(up.size(0), up.size(1))
422
- down = down.reshape(down.size(0), down.size(1))
423
- return torch.einsum("m n ..., i m, n j -> i j ...", mid, up, down)
424
-
425
-
426
- def tucker_weight(wa, wb, t):
427
- temp = torch.einsum("i j ..., j r -> i r ...", t, wb)
428
- return torch.einsum("i j ..., i r -> r j ...", temp, wa)
429
-
430
-
431
- def apply_dora_scale(org_weight, rebuild, dora_scale, scale):
432
- dora_norm_dims = org_weight.dim() - 1
433
- weight = org_weight + rebuild
434
- weight = weight.to(dora_scale.dtype)
435
- weight_norm = (
436
- weight.transpose(0, 1)
437
- .reshape(weight.shape[1], -1)
438
- .norm(dim=1, keepdim=True)
439
- .reshape(weight.shape[1], *[1] * dora_norm_dims)
440
- .transpose(0, 1)
441
- )
442
- merged_scale1 = weight / weight_norm * dora_scale
443
- diff_weight = merged_scale1 - org_weight
444
- return org_weight + diff_weight * scale
445
-
446
-
447
- @torch.no_grad()
448
- def rebuild_weight(module_type, params, orig_weight, orig_bias, scale=1):
449
- if orig_weight is None:
450
- return None, None
451
- merged = orig_weight
452
- merged_bias = orig_bias
453
- if module_type == "locon":
454
- up, down, mid, alpha, dora_scale = params
455
- if alpha is not None:
456
- scale *= alpha / up.size(1)
457
- if mid is not None:
458
- rebuild = tucker_weight_from_conv(up, down, mid)
459
- else:
460
- rebuild = up.reshape(up.size(0), -1) @ down.reshape(down.size(0), -1)
461
- rebuild = rebuild.reshape(orig_weight.shape)
462
- if dora_scale is None:
463
- merged = orig_weight + rebuild * scale
464
- else:
465
- merged = apply_dora_scale(orig_weight, rebuild, dora_scale, scale)
466
- del up, down, mid, alpha, params, rebuild
467
- elif module_type == "hada":
468
- w1a, w1b, w2a, w2b, t1, t2, alpha, dora_scale = params
469
- if alpha is not None:
470
- scale *= alpha / w1b.size(0)
471
- if t1 is not None:
472
- rebuild1 = tucker_weight(w1a, w1b, t1)
473
- else:
474
- rebuild1 = w1a @ w1b
475
- if t2 is not None:
476
- rebuild2 = tucker_weight(w2a, w2b, t2)
477
- else:
478
- rebuild2 = w2a @ w2b
479
- rebuild = (rebuild1 * rebuild2).reshape(orig_weight.shape)
480
- if dora_scale is None:
481
- merged = orig_weight + rebuild * scale
482
- else:
483
- merged = apply_dora_scale(orig_weight, rebuild, dora_scale, scale)
484
- del w1a, w1b, w2a, w2b, t1, t2, alpha, params, rebuild, rebuild1, rebuild2
485
- elif module_type == "ia3":
486
- weight, on_input = params
487
- if not on_input:
488
- weight = weight.reshape(-1, 1)
489
- merged = orig_weight + weight * orig_weight * scale
490
- del weight, on_input, params
491
- elif module_type == "kron":
492
- w1, w1a, w1b, w2, w2a, w2b, t1, t2, alpha, dora_scale = params
493
- if alpha is not None and (w1b is not None or w2b is not None):
494
- scale *= alpha / (w1b.size(0) if w1b else w2b.size(0))
495
- if w1a is not None and w1b is not None:
496
- if t1 is not None:
497
- w1 = tucker_weight(w1a, w1b, t1)
498
- else:
499
- w1 = w1a @ w1b
500
- if w2a is not None and w2b is not None:
501
- if t2 is not None:
502
- w2 = tucker_weight(w2a, w2b, t2)
503
- else:
504
- w2 = w2a @ w2b
505
- if len(w2.shape) == 4:
506
- w1 = w1.unsqueeze(2).unsqueeze(2)
507
- w2 = w2.contiguous()
508
- rebuild = torch.kron(w1, w2).reshape(orig_weight.shape)
509
- if dora_scale is None:
510
- merged = orig_weight + rebuild * scale
511
- else:
512
- merged = apply_dora_scale(orig_weight, rebuild, dora_scale, scale)
513
- del w1, w1a, w1b, w2, w2a, w2b, t1, t2, alpha, params, rebuild
514
- elif module_type == "full":
515
- rebuild = params[0].reshape(orig_weight.shape)
516
- rebuild_b = (
517
- params[1].reshape(orig_bias.shape) if orig_bias is not None else None
518
- )
519
- merged = orig_weight + rebuild * scale
520
- if rebuild_b is not None:
521
- merged_bias = orig_bias + rebuild_b * scale
522
- del params, rebuild, rebuild_b
523
- elif module_type == "norm":
524
- rebuild = params[0].reshape(orig_weight.shape)
525
- rebuild_b = params[1].reshape(orig_bias.shape)
526
- merged = orig_weight + rebuild * scale
527
- merged_bias = orig_bias + rebuild_b * scale
528
- else:
529
- return None, None
530
-
531
- return merged, merged_bias
532
-
533
-
534
420
  @torch.no_grad()
535
421
  def merge(tes, unet, lyco_state_dict, scale: float = 1.0, device="cpu"):
536
- UNET_TARGET_REPLACE_MODULE = [
537
- "Linear",
538
- "Conv2d",
539
- "LayerNorm",
540
- "GroupNorm",
541
- "GroupNorm32",
542
- ]
543
- TEXT_ENCODER_TARGET_REPLACE_MODULE = [
544
- "Embedding",
545
- "Linear",
546
- "Conv2d",
547
- "LayerNorm",
548
- "GroupNorm",
549
- "GroupNorm32",
550
- "Embedding",
551
- ]
422
+ from ..modules import make_module, get_module
423
+
552
424
  LORA_PREFIX_UNET = "lora_unet"
553
425
  LORA_PREFIX_TEXT_ENCODER = "lora_te"
554
426
  merged = 0
@@ -557,29 +429,25 @@ def merge(tes, unet, lyco_state_dict, scale: float = 1.0, device="cpu"):
557
429
  prefix,
558
430
  root_module: torch.nn.Module,
559
431
  lyco_state_dict: Dict[str, torch.Tensor],
560
- target_replace_modules,
561
432
  ):
562
433
  nonlocal merged
563
434
  for child_name, child_module in tqdm(
564
435
  list(root_module.named_modules()), desc=f"Merging {prefix}"
565
436
  ):
566
- if child_module.__class__.__name__ in target_replace_modules:
567
- lora_name = prefix + "." + child_name
568
- lora_name = lora_name.replace(".", "_")
569
-
570
- result, result_b = rebuild_weight(
571
- *get_module(lyco_state_dict, lora_name),
572
- getattr(child_module, "weight"),
573
- getattr(child_module, "bias", None),
574
- scale,
575
- )
576
- if result is not None:
577
- key_dict.pop(lora_name)
578
- merged += 1
579
- child_module.requires_grad_(False)
580
- child_module.weight.copy_(result)
581
- if result_b is not None:
582
- child_module.bias.copy_(result_b)
437
+ lora_name = prefix + "." + child_name
438
+ lora_name = lora_name.replace(".", "_")
439
+
440
+ lyco_type, params = get_module(lyco_state_dict, lora_name)
441
+ if lyco_type is None:
442
+ continue
443
+ module = make_module(lyco_type, params, lora_name, child_module)
444
+ if module is None:
445
+ continue
446
+ module.to(device)
447
+ module.merge_to(scale)
448
+ key_dict.pop(convert_diffusers_name_to_compvis(lora_name), None)
449
+ key_dict.pop(lora_name, None)
450
+ merged += 1
583
451
 
584
452
  key_dict = {}
585
453
  for k, v in tqdm(list(lyco_state_dict.items()), desc="Converting Dtype and Device"):
@@ -592,12 +460,7 @@ def merge(tes, unet, lyco_state_dict, scale: float = 1.0, device="cpu"):
592
460
  k = f"{convert_key}.{weight_key}"
593
461
  else:
594
462
  key_dict[module] = key_dict.get(module, []) + [k]
595
- if device == "cpu":
596
- lyco_state_dict[k] = v.float().cpu()
597
- else:
598
- lyco_state_dict[k] = v.to(
599
- device, dtype=tes[0].parameters().__next__().dtype
600
- )
463
+ lyco_state_dict[k] = v.float().cpu()
601
464
 
602
465
  for idx, te in enumerate(tes):
603
466
  if len(tes) > 1:
@@ -606,15 +469,15 @@ def merge(tes, unet, lyco_state_dict, scale: float = 1.0, device="cpu"):
606
469
  prefix = LORA_PREFIX_TEXT_ENCODER
607
470
  merge_state_dict(
608
471
  prefix,
609
- te.to(device),
472
+ te,
610
473
  lyco_state_dict,
611
- TEXT_ENCODER_TARGET_REPLACE_MODULE,
612
474
  )
475
+ torch.cuda.empty_cache()
613
476
  merge_state_dict(
614
477
  LORA_PREFIX_UNET,
615
- unet.to(device),
478
+ unet,
616
479
  lyco_state_dict,
617
- UNET_TARGET_REPLACE_MODULE,
618
480
  )
481
+ torch.cuda.empty_cache()
619
482
  print(f"Unused state dict key: {key_dict}")
620
483
  print(f"{merged} Modules been merged")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lycoris_lora
3
- Version: 3.0.0.dev13
3
+ Version: 3.0.0.dev15
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
@@ -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="3.0.0.dev13",
7
+ version="3.0.0.dev15",
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",
@@ -0,0 +1,87 @@
1
+ import unittest
2
+ from itertools import product
3
+ from parameterized import parameterized
4
+
5
+ import torch
6
+ import torch.nn as nn
7
+ import torch.nn.functional as F
8
+
9
+ from lycoris.functional import locon, loha, lokr, diag_oft, boft
10
+
11
+
12
+ EPS_DTYPE = {
13
+ torch.float32: 5e-6,
14
+ torch.float16: 5e-5,
15
+ torch.bfloat16: 5e-4,
16
+ }
17
+
18
+
19
+ modules = [locon, loha, lokr, diag_oft, boft]
20
+ base_module_and_input_adn_weight = [
21
+ lambda dim: (F.linear, torch.randn(dim, dim), torch.randn(1, dim)),
22
+ lambda dim: (F.conv1d, torch.randn(dim, dim, 3), torch.randn(1, dim, 16)),
23
+ lambda dim: (F.conv2d, torch.randn(dim, dim, 3, 3), torch.randn(1, dim, 16, 16)),
24
+ lambda dim: (
25
+ F.conv3d,
26
+ torch.randn(dim, dim, 3, 3, 3),
27
+ torch.randn(1, dim, 16, 16, 16),
28
+ ),
29
+ ]
30
+ device_and_dtype = [
31
+ (torch.device("cpu"), torch.float32),
32
+ ]
33
+
34
+ if torch.cuda.is_available():
35
+ device_and_dtype.append((torch.device("cuda"), torch.float32))
36
+ device_and_dtype.append((torch.device("cuda"), torch.float16))
37
+ device_and_dtype.append((torch.device("cuda"), torch.bfloat16))
38
+
39
+ if torch.backends.mps.is_available():
40
+ device_and_dtype.append((torch.device("mps"), torch.float32))
41
+
42
+
43
+ patch_forward_param_list = list(
44
+ product(
45
+ modules,
46
+ base_module_and_input_adn_weight,
47
+ device_and_dtype,
48
+ )
49
+ )
50
+
51
+
52
+ class LycorisFunctionalTests(unittest.TestCase):
53
+ @parameterized.expand(patch_forward_param_list)
54
+ def test_lycoris_functional(self, module, base, device_dtype):
55
+ func, test_weight, test_input = base(16)
56
+ device, dtype = device_dtype
57
+ print(
58
+ f"{module.__name__: <27}",
59
+ f"{func.__name__: <7}",
60
+ f"device={str(device): <5}",
61
+ f"dtype={str(dtype): <15}",
62
+ sep="||",
63
+ )
64
+
65
+ w = test_weight.to(device, dtype)
66
+ x = test_input.to(device, dtype)
67
+ y = func(x, w)
68
+
69
+ params = list(module.weight_gen(w, 4))
70
+ for idx, param in enumerate(params):
71
+ if param is not None:
72
+ param = param.to(device, dtype)
73
+ params[idx] = param + torch.randn_like(param) * 0.01
74
+
75
+ if module in {boft, diag_oft}:
76
+ diff_w = module.diff_weight(w, *params)
77
+ diff_y = module.bypass_forward_diff(y, *params, need_transpose=w.ndim > 2)
78
+ else:
79
+ diff_w = module.diff_weight(*params)
80
+ diff_y = module.bypass_forward_diff(x, *params)
81
+
82
+ diff_y_from_diff_w = func(x, diff_w.to(x))
83
+ self.assertTrue(
84
+ F.mse_loss(diff_y, diff_y_from_diff_w).item() < EPS_DTYPE[dtype],
85
+ f"Error: {module.__name__} {base.__name__} {device} {dtype} ||"
86
+ f"{F.mse_loss(diff_y, diff_y_from_diff_w).item()}",
87
+ )
@@ -1,20 +0,0 @@
1
- from .general import (
2
- rebuild_tucker,
3
- factorization,
4
- power2factorization,
5
- )
6
- from .locon import (
7
- lora_weight_gen,
8
- lora_diff_weight,
9
- lora_bypass_forward_diff,
10
- )
11
- from .loha import (
12
- loha_weight_gen,
13
- loha_diff_weight,
14
- loha_bypass_forward_diff,
15
- )
16
- from .lokr import (
17
- lokr_weight_gen,
18
- lokr_diff_weight,
19
- lokr_bypass_forward_diff,
20
- )
@@ -1,71 +0,0 @@
1
- import unittest
2
- from itertools import product
3
- from parameterized import parameterized
4
-
5
- import torch
6
- import torch.nn as nn
7
-
8
- from lycoris.modules import (
9
- LycorisBaseModule,
10
- LoConModule,
11
- LohaModule,
12
- LokrModule,
13
- FullModule,
14
- DiagOFTModule,
15
- ButterflyOFTModule,
16
- GLoRAModule,
17
- DyLoraModule,
18
- IA3Module,
19
- )
20
-
21
-
22
- modules: list[LycorisBaseModule] = [
23
- LoConModule,
24
- LohaModule,
25
- LokrModule,
26
- FullModule,
27
- DiagOFTModule,
28
- ButterflyOFTModule,
29
- GLoRAModule,
30
- DyLoraModule,
31
- IA3Module,
32
- ]
33
- base_module_and_input = [
34
- lambda dim: (nn.Linear(dim, dim), torch.randn(1, dim)),
35
- lambda dim: (nn.Conv1d(dim, dim, 3, 1, 1), torch.randn(1, dim, 16)),
36
- lambda dim: (nn.Conv2d(dim, dim, (3, 3), 1, 1), torch.randn(1, dim, 16, 16)),
37
- # lambda dim: (nn.Conv3d(dim, dim, (3, 3, 3), 1, 1), torch.randn(1, dim, 16, 16, 16)),
38
- ]
39
- device_and_dtype = [
40
- (torch.device("cpu"), torch.float32),
41
- ]
42
- weight_decompose = [False, True]
43
- use_tucker = [False, True]
44
- use_scalar = [False, True]
45
-
46
- if torch.cuda.is_available():
47
- device_and_dtype.append((torch.device("cuda"), torch.float32))
48
- device_and_dtype.append((torch.device("cuda"), torch.float16))
49
- device_and_dtype.append((torch.device("cuda"), torch.bfloat16))
50
-
51
- if torch.backends.mps.is_available():
52
- device_and_dtype.append((torch.device("mps"), torch.float32))
53
-
54
-
55
- patch_forward_param_list = list(
56
- product(
57
- modules,
58
- base_module_and_input,
59
- device_and_dtype,
60
- weight_decompose,
61
- use_tucker,
62
- use_scalar,
63
- )
64
- )
65
-
66
-
67
- class LycorisModuleTests(unittest.TestCase):
68
- @parameterized.expand(patch_forward_param_list)
69
- def test_lycoris_functional(self, module, base, device_dtype, wd, tucker, scalar):
70
- base, test_input = base(16)
71
- device, dtype = device_dtype