lycoris-lora 3.0.0.dev4__tar.gz → 3.0.0.dev6__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 (39) hide show
  1. {lycoris_lora-3.0.0.dev4/lycoris_lora.egg-info → lycoris_lora-3.0.0.dev6}/PKG-INFO +2 -1
  2. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/functional/general.py +3 -0
  3. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/functional/locon.py +7 -14
  4. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/functional/loha.py +50 -14
  5. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/kohya.py +1 -11
  6. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/modules/__init__.py +13 -4
  7. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/modules/base.py +1 -1
  8. lycoris_lora-3.0.0.dev6/lycoris/modules/dylora.py +198 -0
  9. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/modules/ia3.py +0 -6
  10. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/modules/locon.py +4 -4
  11. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/utils/__init__.py +30 -1
  12. lycoris_lora-3.0.0.dev6/lycoris/utils/general.py +5 -0
  13. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/wrapper.py +6 -5
  14. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6/lycoris_lora.egg-info}/PKG-INFO +2 -1
  15. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris_lora.egg-info/SOURCES.txt +1 -0
  16. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris_lora.egg-info/requires.txt +1 -0
  17. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/setup.py +2 -6
  18. lycoris_lora-3.0.0.dev4/lycoris/modules/dylora.py +0 -132
  19. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/LICENSE.md +0 -0
  20. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/README.md +0 -0
  21. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/__init__.py +0 -0
  22. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/config.py +0 -0
  23. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/functional/__init__.py +0 -0
  24. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/logging.py +0 -0
  25. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/modules/boft.py +0 -0
  26. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/modules/diag_oft.py +0 -0
  27. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/modules/full.py +0 -0
  28. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/modules/glora.py +0 -0
  29. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/modules/loha.py +0 -0
  30. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/modules/lokr.py +0 -0
  31. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/modules/norms.py +0 -0
  32. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/utils/bnb.py +0 -0
  33. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/utils/logger.py +0 -0
  34. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/utils/preset.py +0 -0
  35. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/utils/xformers_utils.py +0 -0
  36. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris_lora.egg-info/dependency_links.txt +0 -0
  37. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris_lora.egg-info/not-zip-safe +0 -0
  38. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris_lora.egg-info/top_level.txt +0 -0
  39. {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lycoris_lora
3
- Version: 3.0.0.dev4
3
+ Version: 3.0.0.dev6
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
@@ -10,3 +10,4 @@ License-File: LICENSE.md
10
10
  Requires-Dist: torch
11
11
  Requires-Dist: einops
12
12
  Requires-Dist: toml
13
+ Requires-Dist: tqdm
@@ -3,6 +3,9 @@ import torch.nn as nn
3
3
  import torch.nn.functional as F
4
4
 
5
5
 
6
+ FUNC_LIST = [None, None, F.linear, F.conv1d, F.conv2d, F.conv3d]
7
+
8
+
6
9
  def rebuild_tucker(t, wa, wb):
7
10
  rebuild2 = torch.einsum("i j ..., i p, j r -> p r ...", t, wa, wb)
8
11
  return rebuild2
@@ -4,21 +4,18 @@ import torch
4
4
  import torch.nn as nn
5
5
  import torch.nn.functional as F
6
6
 
7
- from .general import rebuild_tucker
7
+ from .general import rebuild_tucker, FUNC_LIST
8
8
 
9
9
 
10
10
  def lora_weight_gen(org_weight, rank, tucker=True):
11
11
  """### lora_weight_gen
12
12
 
13
13
  Args:
14
- out_dim (int): output dimension
15
- in_dim (int): input dimension
14
+ org_weight (torch.Tensor): the weight tensor
16
15
  rank (int): low rank
17
16
 
18
17
  Returns:
19
- torch.Tensor: down proj weight
20
- torch.Tensor: up proj weight
21
- torch.Tensor(optional): mid proj weight
18
+ torch.Tensor: down, up[, mid]
22
19
  """
23
20
  out_dim, in_dim, *k = org_weight.shape
24
21
  if k and tucker:
@@ -45,14 +42,12 @@ def lora_diff_weight(d, u, m=None, gamma=1.0):
45
42
  Args:
46
43
  d (torch.Tensor): weight of down proj linear/conv layer
47
44
  u (torch.Tensor): weight of up proj linear/conv layer
48
- m (torch.Tensor, optional): weight of mid proj linear/conv layer, \
49
- for tucker deomposition
45
+ m (torch.Tensor, optional): middle weight of tucker decomposition
50
46
  gamma (float, optional): scale factor, normally alpha/rank here
51
47
 
52
48
  Returns:
53
49
  torch.Tensor: ΔW
54
50
  """
55
- assert d.size(0) == u.size(1)
56
51
  R, I, *k = d.shape
57
52
  O, R, *_ = u.shape
58
53
  u = u * gamma
@@ -67,9 +62,6 @@ def lora_diff_weight(d, u, m=None, gamma=1.0):
67
62
  return result.reshape(O, I, *k)
68
63
 
69
64
 
70
- FUNC_LIST = [None, None, F.linear, F.conv1d, F.conv2d, F.conv3d]
71
-
72
-
73
65
  def lora_bypass_forward_diff(x, d, u, m=None, gamma=1.0, extra_args={}):
74
66
  """### lora_bypass_forward_diff
75
67
 
@@ -77,9 +69,10 @@ def lora_bypass_forward_diff(x, d, u, m=None, gamma=1.0, extra_args={}):
77
69
  x (torch.Tensor): input tensor
78
70
  d (torch.Tensor): weight of down proj linear/conv layer
79
71
  u (torch.Tensor): weight of up proj linear/conv layer
80
- m (torch.Tensor, optional): weight of mid proj linear/conv layer, \
81
- for tucker deomposition
72
+ m (torch.Tensor, optional): middle weight of tucker decomposition
82
73
  gamma (float, optional): scale factor, normally alpha/rank here
74
+ extra_args (dict, optional): extra args for forward func, \
75
+ e.g. padding, stride for Conv1/2/3d
83
76
 
84
77
  Returns:
85
78
  torch.Tensor: output tensor
@@ -1,7 +1,11 @@
1
+ import math
2
+
1
3
  import torch
2
4
  import torch.nn as nn
3
5
  import torch.nn.functional as F
4
6
 
7
+ from .general import FUNC_LIST
8
+
5
9
 
6
10
  class HadaWeight(torch.autograd.Function):
7
11
  @staticmethod
@@ -79,6 +83,43 @@ def make_weight_tucker(t1, w1d, w1u, t2, w2d, w2u, scale):
79
83
  return HadaWeightTucker.apply(t1, w1d, w1u, t2, w2d, w2u, scale)
80
84
 
81
85
 
86
+ def loha_weight_gen(org_weight, rank, tucker=True):
87
+ """### loha_weight_gen
88
+
89
+ Args:
90
+ org_weight (torch.Tensor): the weight tensor
91
+ rank (int): low rank
92
+
93
+ Returns:
94
+ torch.Tensor: w1d, w2d, w1u, w2u[, t1, t2]
95
+ """
96
+ out_dim, in_dim, *k = org_weight.shape
97
+ if k and tucker:
98
+ w1d = torch.empty(rank, in_dim)
99
+ w1u = torch.empty(rank, out_dim)
100
+ t1 = torch.empty(rank, rank, *k)
101
+ w2d = torch.empty(rank, in_dim)
102
+ w2u = torch.empty(rank, out_dim)
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
+ nn.init.normal_(t1, std=0.1)
109
+ nn.init.normal_(t2, std=0.1)
110
+ return w1d, w2d, w1u, w2u, t1, t2
111
+ else:
112
+ w1d = torch.empty(rank, in_dim)
113
+ w1u = torch.empty(rank, out_dim)
114
+ 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
121
+
122
+
82
123
  def loha_diff_weight(w1d, w1u, w2d, w2u, t1=None, t2=None, gamma=1.0):
83
124
  """### loha_diff_weight
84
125
 
@@ -87,23 +128,18 @@ def loha_diff_weight(w1d, w1u, w2d, w2u, t1=None, t2=None, gamma=1.0):
87
128
  Args:
88
129
  w1d, w2d (torch.Tensor): weight of down proj linear/conv layer
89
130
  w1u, w2u (torch.Tensor): weight of up proj linear/conv layer
131
+ t1, t2 (torch.Tensor, optional): middle weight of tucker decomposition
90
132
  gamma (float, optional): scale factor, normally alpha/rank here
91
133
 
92
134
  Returns:
93
135
  torch.Tensor: ΔW
94
136
  """
95
137
  if t1 is not None and t2 is not None:
96
- assert w1d.size(0) == t1.size(1)
97
- assert w1u.size(0) == t1.size(0)
98
- assert w2d.size(0) == t2.size(1)
99
- assert w2u.size(0) == t2.size(0)
100
138
  R, I = w1d.shape
101
139
  R, O = w1u.shape
102
140
  R, R, *k = t1.shape
103
141
  result = make_weight_tucker(t1, w1d, w1u, t2, w2d, w2u, gamma)
104
142
  else:
105
- assert w1d.size(0) == w1u.size(1)
106
- assert w2d.size(0) == w2u.size(1)
107
143
  R, I, *k = w1d.shape
108
144
  O, R, *_ = w1u.shape
109
145
  w1d = w1d.reshape(w1d.size(0), -1)
@@ -116,9 +152,6 @@ def loha_diff_weight(w1d, w1u, w2d, w2u, t1=None, t2=None, gamma=1.0):
116
152
  return result
117
153
 
118
154
 
119
- FUNC_LIST = [None, None, F.linear, F.conv1d, F.conv2d, F.conv3d]
120
-
121
-
122
155
  def loha_bypass_forward_diff(
123
156
  x, w1d, w1u, w2d, w2u, t1=None, t2=None, gamma=1.0, extra_args={}
124
157
  ):
@@ -129,6 +162,8 @@ def loha_bypass_forward_diff(
129
162
  w1d, w2d (torch.Tensor): weight of up proj linear/conv layer
130
163
  w1u, w2u (torch.Tensor): weight of down proj linear/conv layer
131
164
  gamma (float, optional): scale factor, normally alpha/rank here
165
+ extra_args (dict, optional): extra args for forward func, \
166
+ e.g. padding, stride for Conv1/2/3d
132
167
 
133
168
  Returns:
134
169
  torch.Tensor: output tensor
@@ -139,15 +174,16 @@ def loha_bypass_forward_diff(
139
174
 
140
175
  if __name__ == "__main__":
141
176
  w = torch.randn(128, 128, 3, 3, 3)
142
- a = torch.randn(16, 128) * 0.01
143
- b = torch.randn(16, 128) * 0.01
144
- m = torch.randn(16, 16, 3, 3, 3) * 0.01
177
+ w1d, w2d, w1u, w2u, t1, t2 = loha_weight_gen(
178
+ w, 4, tucker=True
179
+ )
180
+ w1u += 0.01
145
181
  extra_args = {"padding": 1}
146
182
 
147
183
  x = torch.randn(1, 128, 8, 8, 8)
148
184
  y = FUNC_LIST[w.dim()](x, w, **extra_args)
149
- diff_w = loha_diff_weight(a, b, a, b, m, m, 1)
150
- diff_y = loha_bypass_forward_diff(x, a, b, a, b, m, m, 1, extra_args)
185
+ diff_w = loha_diff_weight(w1d, w2d, w1u, w2u, t1, t2, 1)
186
+ diff_y = loha_bypass_forward_diff(x, w1d, w2d, w1u, w2u, t1, t2, 1, extra_args)
151
187
 
152
188
  print(F.mse_loss(y, y + diff_y))
153
189
  print(F.mse_loss(w, w + diff_w))
@@ -1,16 +1,10 @@
1
- # network module for kohya
2
- # reference:
3
- # https://github.com/microsoft/LoRA/blob/main/loralib/layers.py
4
- # https://github.com/cloneofsimo/lora/blob/master/lora_diffusion/lora.py
5
- # https://github.com/kohya-ss/sd-scripts/blob/main/networks/lora.py
6
-
7
1
  import os
8
2
  import re
9
3
  from typing import List
10
4
 
11
5
  import torch
12
6
 
13
- from library.train_util import *
7
+ from .utils import precalculate_safetensors_hashes
14
8
  from .wrapper import LycorisNetwork
15
9
  from .modules.locon import LoConModule
16
10
  from .modules.loha import LohaModule
@@ -150,10 +144,6 @@ def create_network(
150
144
  unbalanced_factorization=unbalanced_factorization,
151
145
  )
152
146
 
153
- if algo == "dylora":
154
- # dylora didn't support scale weight norm yet
155
- delattr(type(network), "apply_max_norm_regularization")
156
-
157
147
  return network
158
148
 
159
149
 
@@ -1,13 +1,19 @@
1
1
  import torch
2
2
  import torch.nn as nn
3
3
 
4
- from .full import FullModule
5
- from .norms import NormModule
6
4
  from .locon import LoConModule
7
5
  from .loha import LohaModule
8
- from .lokr import LokrModule, factorization
6
+ from .lokr import LokrModule
7
+ from .full import FullModule
8
+ from .norms import NormModule
9
+ from .diag_oft import DiagOFTModule
10
+ from .boft import ButterflyOFTModule
11
+ from .glora import GLoRAModule
12
+ from .dylora import DyLoraModule
9
13
  from .ia3 import IA3Module
10
14
 
15
+ from ..functional.general import factorization
16
+
11
17
 
12
18
  @torch.no_grad()
13
19
  def make_module(lyco_type, params, lora_name, orig_module):
@@ -51,12 +57,14 @@ def make_module(lyco_type, params, lora_name, orig_module):
51
57
  module.dora_scale.copy_(dora_scale)
52
58
  elif lyco_type == "kron":
53
59
  w1, w1a, w1b, w2, w2a, w2b, _, t2, alpha, dora_scale = params
60
+ full_matrix=False
54
61
  if w1a is not None:
55
62
  lora_dim = w1a.size(1)
56
63
  elif w2a is not None:
57
64
  lora_dim = w2a.size(1)
58
65
  else:
59
- lora_dim = 10000000000000
66
+ full_matrix = True
67
+ lora_dim = 1
60
68
 
61
69
  if w1 is None:
62
70
  out_dim = w1a.size(0)
@@ -91,6 +99,7 @@ def make_module(lyco_type, params, lora_name, orig_module):
91
99
  decompose_both=w1 is None and w2 is None,
92
100
  factor=factor,
93
101
  weight_decompose=dora_scale is not None,
102
+ full_matrix=full_matrix,
94
103
  )
95
104
  if w1 is not None:
96
105
  module.lokr_w1.copy_(w1)
@@ -256,7 +256,7 @@ class LycorisBaseModule(ModuleCustomSD):
256
256
 
257
257
  @torch.no_grad()
258
258
  def apply_max_norm(self, max_norm, device=None):
259
- raise NotImplementedError
259
+ return None, None
260
260
 
261
261
  def bypass_forward_diff(self, x, scale=1):
262
262
  raise NotImplementedError
@@ -0,0 +1,198 @@
1
+ import math
2
+ import random
3
+
4
+ import torch
5
+ import torch.nn as nn
6
+ import torch.nn.functional as F
7
+
8
+ from .base import LycorisBaseModule
9
+ from ..utils import product
10
+ from ..utils.bnb import LinearNF4
11
+
12
+
13
+ class DyLoraModule(LycorisBaseModule):
14
+ support_module = {
15
+ "linear",
16
+ "conv1d",
17
+ "conv2d",
18
+ "conv3d",
19
+ }
20
+
21
+ def __init__(
22
+ self,
23
+ lora_name,
24
+ org_module: nn.Module,
25
+ multiplier=1.0,
26
+ lora_dim=4,
27
+ alpha=1,
28
+ dropout=0.0,
29
+ rank_dropout=0.0,
30
+ module_dropout=0.0,
31
+ use_tucker=False,
32
+ block_size=4,
33
+ use_scalar=False,
34
+ rank_dropout_scale=False,
35
+ weight_decompose=False,
36
+ bypass_mode=False,
37
+ rs_lora=False,
38
+ train_on_input=False,
39
+ **kwargs,
40
+ ):
41
+ """if alpha == 0 or None, alpha is rank (no scaling)."""
42
+ super().__init__(
43
+ lora_name,
44
+ org_module,
45
+ multiplier,
46
+ dropout,
47
+ rank_dropout,
48
+ module_dropout,
49
+ rank_dropout_scale,
50
+ bypass_mode,
51
+ )
52
+ if self.module_type not in self.support_module:
53
+ raise ValueError(f"{self.module_type} is not supported in IA^3 algo.")
54
+ assert lora_dim % block_size == 0, "lora_dim must be a multiple of block_size"
55
+ self.block_count = lora_dim // block_size
56
+ self.block_size = block_size
57
+
58
+ shape = (
59
+ self.shape[0],
60
+ product(self.shape[1:]),
61
+ )
62
+
63
+ self.lora_dim = lora_dim
64
+ self.up_list = nn.ParameterList(
65
+ [torch.empty(shape[0], self.block_size) for i in range(self.block_count)]
66
+ )
67
+ self.down_list = nn.ParameterList(
68
+ [torch.empty(self.block_size, shape[1]) for i in range(self.block_count)]
69
+ )
70
+
71
+ if type(alpha) == torch.Tensor:
72
+ alpha = alpha.detach().float().numpy() # without casting, bf16 causes error
73
+ alpha = lora_dim if alpha is None or alpha == 0 else alpha
74
+ self.scale = alpha / self.lora_dim
75
+ self.register_buffer("alpha", torch.tensor(alpha)) # 定数として扱える
76
+
77
+ # Need more experiences on init method
78
+ for v in self.down_list:
79
+ torch.nn.init.kaiming_uniform_(v, a=math.sqrt(5))
80
+ for v in self.up_list:
81
+ torch.nn.init.zeros_(v)
82
+
83
+ def custom_state_dict(self):
84
+ destination = {}
85
+ destination["alpha"] = self.alpha
86
+ destination["lora_up.weight"] = nn.Parameter(
87
+ torch.concat(list(self.up_list), dim=1)
88
+ )
89
+ destination["lora_down.weight"] = nn.Parameter(
90
+ torch.concat(list(self.down_list)).reshape(
91
+ self.lora_dim, -1, *self.shape[2:]
92
+ )
93
+ )
94
+ return destination
95
+
96
+ def get_weight(self, rank):
97
+ b = math.ceil(rank / self.block_size)
98
+ down = torch.concat(
99
+ list(i.data for i in self.down_list[:b]) + list(self.down_list[b : (b + 1)])
100
+ )
101
+ up = torch.concat(
102
+ list(i.data for i in self.up_list[:b]) + list(self.up_list[b : (b + 1)]),
103
+ dim=1,
104
+ )
105
+ return down, up, self.alpha / (b + 1)
106
+
107
+ def get_random_rank_weight(self):
108
+ b = random.randint(0, self.block_count - 1)
109
+ return self.get_weight(b * self.block_size)
110
+
111
+ def get_diff_weight(self, multiplier=1, shape=None, device=None, rank=None):
112
+ if rank is None:
113
+ down, up, scale = self.get_random_rank_weight()
114
+ else:
115
+ down, up, scale = self.get_random_rank_weight()
116
+ w = up @ (down * (scale * multiplier))
117
+ if device is not None:
118
+ w = w.to(device)
119
+ if shape is not None:
120
+ w = w.view(shape)
121
+ else:
122
+ w = w.view(self.shape)
123
+ return w, None
124
+
125
+ def get_merged_weight(self, multiplier=1, shape=None, device=None, rank=None):
126
+ diff, _ = self.get_diff_weight(multiplier, shape, device, rank)
127
+ return diff + self.org_weight, None
128
+
129
+ def bypass_forward_diff(self, x, scale=1, rank=None):
130
+ if rank is None:
131
+ down, up, gamma = self.get_random_rank_weight()
132
+ else:
133
+ down, up, gamma = self.get_random_rank_weight()
134
+ down = down.view(self.lora_dim, -1, *self.shape[2:])
135
+ up = up.view(-1, self.lora_dim, *(1 for _ in self.shape[2:]))
136
+ scale = scale * gamma
137
+ return self.op(self.op(x, down, **self.kw_dict), up)
138
+
139
+ def bypass_forward(self, x, scale=1, rank=None):
140
+ return self.org_forward(x) + self.bypass_forward_diff(x, scale, rank)
141
+
142
+ def forward(self, x, *args, **kwargs):
143
+ if self.module_dropout and self.training:
144
+ if torch.rand(1) < self.module_dropout:
145
+ return self.org_forward(x)
146
+ if self.bypass_mode:
147
+ return self.bypass_forward(x, self.multiplier)
148
+ else:
149
+ weight = self.get_merged_weight(multiplier=self.multiplier)[0]
150
+ bias = (
151
+ None
152
+ if self.org_module[0].bias is None
153
+ else self.org_module[0].bias.data
154
+ )
155
+ return self.op(x, weight, bias, **self.kw_dict)
156
+
157
+
158
+ if __name__ == "__main__":
159
+ device = torch.device("cuda")
160
+ module = DyLoraModule
161
+ with torch.autocast("cuda" if torch.cuda.is_available() else "cpu"):
162
+ base = nn.Linear(128, 128).to(device).half()
163
+ net = module("test", base, 1, 4, 1, weight_decompose=True).to(device)
164
+ print(net)
165
+ test_input = torch.randn(1, 128).to(device).half()
166
+ test_output = net(test_input)
167
+ torch.sum(test_output).backward()
168
+ print(test_output.shape)
169
+
170
+ base_4bit = LinearNF4(128, 128, device="cuda")
171
+ base_4bit.load_state_dict(base.state_dict())
172
+ base_4bit.to(device)
173
+ qnet = module("test", base_4bit, 1, 4, 1, weight_decompose=False).to(device)
174
+ print(qnet)
175
+ test_input = torch.randn(1, 128).to(device).half()
176
+ test_output = qnet(test_input)
177
+ torch.sum(test_output).backward()
178
+ print(test_output.shape)
179
+
180
+ base = nn.Conv2d(128, 128, 3, 1, 1).to(device).half()
181
+ net = module("test", base, 1, 4, 1, weight_decompose=True, use_tucker=True).to(
182
+ device
183
+ )
184
+ print(net)
185
+ test_input = torch.randn(1, 128, 16, 16).to(device).half()
186
+ test_output = net(test_input)
187
+ torch.sum(test_output).backward()
188
+ print(test_output.shape)
189
+
190
+ base = nn.Conv2d(128, 128, 3, 1, 1).to(device).half()
191
+ net = module.parametrize(
192
+ base, "weight", 1, 4, 1, weight_decompose=True, use_tucker=True
193
+ ).to(device)
194
+ print(base)
195
+ test_input = torch.randn(1, 128, 16, 16).to(device).half()
196
+ test_output = base(test_input)
197
+ torch.sum(test_output).backward()
198
+ print(test_output.shape)
@@ -45,11 +45,7 @@ class IA3Module(LycorisBaseModule):
45
45
  )
46
46
  if self.module_type not in self.support_module:
47
47
  raise ValueError(f"{self.module_type} is not supported in IA^3 algo.")
48
- self.lora_dim = lora_dim
49
- self.tucker = False
50
- self.rs_lora = rs_lora
51
48
 
52
- self.shape = org_module.weight.shape
53
49
  if self.module_type.startswith("conv"):
54
50
  self.isconv = True
55
51
  in_dim = org_module.in_channels
@@ -73,8 +69,6 @@ class IA3Module(LycorisBaseModule):
73
69
 
74
70
  # Need more experiences on init method
75
71
  torch.nn.init.constant_(self.weight, 0)
76
-
77
- self.multiplier = multiplier
78
72
  self.train_input = train_on_input
79
73
  self.register_buffer("on_input", torch.tensor(int(train_on_input)))
80
74
 
@@ -157,9 +157,9 @@ class LoConModule(LycorisBaseModule):
157
157
  wa = self.lora_up.weight.to(device)
158
158
  wb = self.lora_down.weight.to(device)
159
159
  if self.tucker:
160
- t = self.lora_mid.weight.to(device)
161
- wa = wa.reshape(wa.size(0), -1).transpose(0, 1)
162
- wb = wb.reshape(wb.size(0), -1)
160
+ t = self.lora_mid.weight
161
+ wa = wa.view(wa.size(0), -1).transpose(0, 1)
162
+ wb = wb.view(wb.size(0), -1)
163
163
  weight = rebuild_tucker(t, wa, wb)
164
164
  else:
165
165
  weight = wa.view(wa.size(0), -1) @ wb.view(wb.size(0), -1)
@@ -174,7 +174,7 @@ class LoConModule(LycorisBaseModule):
174
174
  drop /= drop.mean()
175
175
  weight *= drop
176
176
 
177
- return weight * self.scalar
177
+ return weight * self.scalar.to(device)
178
178
 
179
179
  def get_diff_weight(self, multiplier=1, shape=None, device=None):
180
180
  scale = self.scale * multiplier
@@ -1,4 +1,6 @@
1
1
  import re
2
+ import hashlib
3
+ from io import BytesIO
2
4
  from typing import Dict, Tuple, Union
3
5
 
4
6
  import numpy as np
@@ -6,10 +8,37 @@ import numpy as np
6
8
  import torch
7
9
  import torch.nn as nn
8
10
  import torch.nn.functional as F
9
-
10
11
  import torch.linalg as linalg
11
12
 
13
+ import safetensors.torch
14
+
12
15
  from tqdm import tqdm
16
+ from .general import *
17
+
18
+
19
+ def load_bytes_in_safetensors(tensors):
20
+ bytes = safetensors.torch.save(tensors)
21
+ b = BytesIO(bytes)
22
+
23
+ b.seek(0)
24
+ header = b.read(8)
25
+ n = int.from_bytes(header, "little")
26
+
27
+ offset = n + 8
28
+ b.seek(offset)
29
+
30
+ return b.read()
31
+
32
+
33
+ def precalculate_safetensors_hashes(state_dict):
34
+ # calculate each tensor one by one to reduce memory usage
35
+ hash_sha256 = hashlib.sha256()
36
+ for tensor in state_dict.values():
37
+ single_tensor_sd = {"tensor": tensor}
38
+ bytes_for_tensor = load_bytes_in_safetensors(single_tensor_sd)
39
+ hash_sha256.update(bytes_for_tensor)
40
+
41
+ return f"0x{hash_sha256.hexdigest()}"
13
42
 
14
43
 
15
44
  def str_bool(val):
@@ -0,0 +1,5 @@
1
+ def product(xs: list[int | float]):
2
+ res = 1
3
+ for x in xs:
4
+ res *= x
5
+ return res
@@ -468,11 +468,12 @@ class LycorisNetwork(torch.nn.Module):
468
468
  def apply_max_norm_regularization(self, max_norm_value, device):
469
469
  key_scaled = 0
470
470
  norms = []
471
- for model in self.loras:
472
- if hasattr(model, "apply_max_norm"):
473
- scaled, norm = model.apply_max_norm(max_norm_value, device)
474
- norms.append(norm)
475
- key_scaled += scaled
471
+ for module in self.loras:
472
+ scaled, norm = module.apply_max_norm(max_norm_value, device)
473
+ if scaled is None:
474
+ continue
475
+ norms.append(norm)
476
+ key_scaled += scaled
476
477
 
477
478
  if key_scaled == 0:
478
479
  return key_scaled, 0, 0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lycoris_lora
3
- Version: 3.0.0.dev4
3
+ Version: 3.0.0.dev6
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
@@ -10,3 +10,4 @@ License-File: LICENSE.md
10
10
  Requires-Dist: torch
11
11
  Requires-Dist: einops
12
12
  Requires-Dist: toml
13
+ Requires-Dist: tqdm
@@ -24,6 +24,7 @@ lycoris/modules/lokr.py
24
24
  lycoris/modules/norms.py
25
25
  lycoris/utils/__init__.py
26
26
  lycoris/utils/bnb.py
27
+ lycoris/utils/general.py
27
28
  lycoris/utils/logger.py
28
29
  lycoris/utils/preset.py
29
30
  lycoris/utils/xformers_utils.py
@@ -4,16 +4,12 @@ from setuptools import setup, find_packages
4
4
  setup(
5
5
  name="lycoris_lora",
6
6
  packages=find_packages(),
7
- version="3.0.0.dev4",
7
+ version="3.0.0.dev6",
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",
11
11
  author_email="apolloyeh0123@gmail.com",
12
12
  zip_safe=False,
13
- install_requires=[
14
- "torch",
15
- "einops",
16
- "toml",
17
- ],
13
+ install_requires=["torch", "einops", "toml", "tqdm"],
18
14
  python_requires=">=3.10",
19
15
  )
@@ -1,132 +0,0 @@
1
- import math
2
- import random
3
-
4
- import torch
5
- import torch.nn as nn
6
- import torch.nn.functional as F
7
-
8
- from .base import ModuleCustomSD
9
-
10
-
11
- class DyLoraModule(ModuleCustomSD):
12
- """
13
- Hadamard product Implementaion for Dynamic Low Rank adaptation
14
- """
15
-
16
- def __init__(
17
- self,
18
- lora_name,
19
- org_module: nn.Module,
20
- multiplier=1.0,
21
- lora_dim=4,
22
- alpha=1,
23
- dropout=0.0,
24
- rank_dropout=0.0,
25
- module_dropout=0.0,
26
- use_tucker=False,
27
- block_size=1,
28
- **kwargs,
29
- ):
30
- """if alpha == 0 or None, alpha is rank (no scaling)."""
31
- super().__init__()
32
- self.lora_name = lora_name
33
- self.lora_dim = lora_dim
34
- assert lora_dim % block_size == 0, "lora_dim must be a multiple of block_size"
35
- self.block_count = lora_dim // block_size
36
- self.block_size = block_size
37
-
38
- self.shape = org_module.weight.shape
39
- if org_module.__class__.__name__ == "Conv2d":
40
- in_dim = org_module.in_channels
41
- k_size = org_module.kernel_size
42
- out_dim = org_module.out_channels
43
- shape = (out_dim, in_dim * k_size[0] * k_size[1])
44
- self.op = F.conv2d
45
- self.extra_args = {
46
- "stride": org_module.stride,
47
- "padding": org_module.padding,
48
- "dilation": org_module.dilation,
49
- "groups": org_module.groups,
50
- }
51
- else:
52
- in_dim = org_module.in_features
53
- out_dim = org_module.out_features
54
- shape = (out_dim, in_dim)
55
- self.op = F.linear
56
- self.extra_args = {}
57
-
58
- self.lora_dim = lora_dim
59
- self.up_list = nn.ParameterList(
60
- [torch.empty(shape[0], 1) for i in range(lora_dim)]
61
- )
62
-
63
- self.down_list = nn.ParameterList(
64
- [torch.empty(1, shape[1]) for i in range(lora_dim)]
65
- )
66
-
67
- self.index = 0
68
-
69
- if type(alpha) == torch.Tensor:
70
- alpha = alpha.detach().float().numpy() # without casting, bf16 causes error
71
- alpha = lora_dim if alpha is None or alpha == 0 else alpha
72
- self.scale = alpha / self.lora_dim
73
- self.register_buffer("alpha", torch.tensor(alpha)) # 定数として扱える
74
-
75
- # Need more experiences on init method
76
-
77
- for v in self.down_list:
78
- torch.nn.init.kaiming_uniform_(v, a=math.sqrt(5))
79
- for v in self.up_list:
80
- torch.nn.init.zeros_(v)
81
-
82
- self.multiplier = multiplier
83
- self.org_module = [org_module] # remove in applying
84
- self.org_forward = self.org_module[0].forward
85
- self.grad_ckpt = False
86
- self.state_dict()
87
-
88
- def custom_state_dict(self):
89
- destination = {}
90
- destination["alpha"] = self.alpha
91
- destination["lora_up.weight"] = nn.Parameter(
92
- torch.concat(list(self.up_list), dim=1)
93
- )
94
- destination["lora_down.weight"] = nn.Parameter(
95
- torch.concat(list(self.down_list))
96
- )
97
- return destination
98
-
99
- def apply_to(self):
100
- self.org_module[0].forward = self.forward
101
-
102
- def restore(self):
103
- self.org_module[0].forward = self.org_forward
104
-
105
- def merge_to(self, multiplier=1.0):
106
- up = torch.concat(list(self.up_list), dim=1)
107
- down = torch.concat(list(self.down_list))
108
- diff_weight = up @ down * self.scale * multiplier / up.size(1)
109
- self.org_module[0].weight.data.add_(diff_weight)
110
-
111
- @torch.enable_grad()
112
- def forward(self, x):
113
- b = random.randint(0, self.block_count - 1)
114
-
115
- down = torch.concat(
116
- list(i.data for i in self.down_list[: b * self.block_size])
117
- + list(self.down_list[b * self.block_size : (b + 1) * self.block_size])
118
- )
119
- up = torch.concat(
120
- list(i.data for i in self.up_list[: b * self.block_size])
121
- + list(self.up_list[b * self.block_size : (b + 1) * self.block_size]),
122
- dim=1,
123
- )
124
-
125
- bias = None if self.org_module[0].bias is None else self.org_module[0].bias.data
126
- return self.op(
127
- x,
128
- self.org_module[0].weight
129
- + (up @ down).view(self.shape) * self.alpha / (b + 1),
130
- bias,
131
- **self.extra_args,
132
- )