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.
- {lycoris_lora-3.0.0.dev4/lycoris_lora.egg-info → lycoris_lora-3.0.0.dev6}/PKG-INFO +2 -1
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/functional/general.py +3 -0
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/functional/locon.py +7 -14
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/functional/loha.py +50 -14
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/kohya.py +1 -11
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/modules/__init__.py +13 -4
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/modules/base.py +1 -1
- lycoris_lora-3.0.0.dev6/lycoris/modules/dylora.py +198 -0
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/modules/ia3.py +0 -6
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/modules/locon.py +4 -4
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/utils/__init__.py +30 -1
- lycoris_lora-3.0.0.dev6/lycoris/utils/general.py +5 -0
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/wrapper.py +6 -5
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6/lycoris_lora.egg-info}/PKG-INFO +2 -1
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris_lora.egg-info/SOURCES.txt +1 -0
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris_lora.egg-info/requires.txt +1 -0
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/setup.py +2 -6
- lycoris_lora-3.0.0.dev4/lycoris/modules/dylora.py +0 -132
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/LICENSE.md +0 -0
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/README.md +0 -0
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/__init__.py +0 -0
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/config.py +0 -0
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/functional/__init__.py +0 -0
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/logging.py +0 -0
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/modules/boft.py +0 -0
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/modules/diag_oft.py +0 -0
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/modules/full.py +0 -0
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/modules/glora.py +0 -0
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/modules/loha.py +0 -0
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/modules/lokr.py +0 -0
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/modules/norms.py +0 -0
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/utils/bnb.py +0 -0
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/utils/logger.py +0 -0
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/utils/preset.py +0 -0
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris/utils/xformers_utils.py +0 -0
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris_lora.egg-info/dependency_links.txt +0 -0
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris_lora.egg-info/not-zip-safe +0 -0
- {lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris_lora.egg-info/top_level.txt +0 -0
- {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.
|
|
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
|
|
@@ -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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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(
|
|
150
|
-
diff_y = loha_bypass_forward_diff(x,
|
|
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
|
|
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
|
|
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
|
-
|
|
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)
|
|
@@ -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
|
|
161
|
-
wa = wa.
|
|
162
|
-
wb = wb.
|
|
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):
|
|
@@ -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
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
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.
|
|
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
|
|
@@ -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.
|
|
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
|
-
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lycoris_lora-3.0.0.dev4 → lycoris_lora-3.0.0.dev6}/lycoris_lora.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|