lycoris-lora 3.0.0.dev3__tar.gz → 3.0.0.dev5__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.dev3/lycoris_lora.egg-info → lycoris_lora-3.0.0.dev5}/PKG-INFO +2 -1
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris/functional/general.py +3 -0
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris/functional/locon.py +7 -14
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris/functional/loha.py +50 -14
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris/kohya.py +1 -11
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris/modules/__init__.py +13 -4
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris/modules/base.py +1 -1
- lycoris_lora-3.0.0.dev5/lycoris/modules/dylora.py +198 -0
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris/modules/glora.py +63 -28
- lycoris_lora-3.0.0.dev5/lycoris/modules/ia3.py +173 -0
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris/modules/locon.py +5 -5
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris/modules/loha.py +1 -1
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris/modules/lokr.py +2 -2
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris/utils/__init__.py +30 -1
- lycoris_lora-3.0.0.dev5/lycoris/utils/general.py +5 -0
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris/wrapper.py +6 -5
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5/lycoris_lora.egg-info}/PKG-INFO +2 -1
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris_lora.egg-info/SOURCES.txt +1 -0
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris_lora.egg-info/requires.txt +1 -0
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/setup.py +2 -6
- lycoris_lora-3.0.0.dev3/lycoris/modules/dylora.py +0 -132
- lycoris_lora-3.0.0.dev3/lycoris/modules/ia3.py +0 -67
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/LICENSE.md +0 -0
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/README.md +0 -0
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris/__init__.py +0 -0
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris/config.py +0 -0
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris/functional/__init__.py +0 -0
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris/logging.py +0 -0
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris/modules/boft.py +0 -0
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris/modules/diag_oft.py +0 -0
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris/modules/full.py +0 -0
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris/modules/norms.py +0 -0
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris/utils/bnb.py +0 -0
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris/utils/logger.py +0 -0
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris/utils/preset.py +0 -0
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris/utils/xformers_utils.py +0 -0
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris_lora.egg-info/dependency_links.txt +0 -0
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris_lora.egg-info/not-zip-safe +0 -0
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/lycoris_lora.egg-info/top_level.txt +0 -0
- {lycoris_lora-3.0.0.dev3 → lycoris_lora-3.0.0.dev5}/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.dev5
|
|
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)
|
|
@@ -5,6 +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
9
|
from ..utils.bnb import LinearNF4
|
|
9
10
|
|
|
10
11
|
|
|
@@ -52,7 +53,7 @@ class GLoRAModule(LycorisBaseModule):
|
|
|
52
53
|
bypass_mode,
|
|
53
54
|
)
|
|
54
55
|
if self.module_type not in self.support_module:
|
|
55
|
-
raise ValueError(f"{self.module_type} is not supported in
|
|
56
|
+
raise ValueError(f"{self.module_type} is not supported in GLoRA algo.")
|
|
56
57
|
self.lora_dim = lora_dim
|
|
57
58
|
self.tucker = False
|
|
58
59
|
self.rs_lora = rs_lora
|
|
@@ -68,17 +69,12 @@ class GLoRAModule(LycorisBaseModule):
|
|
|
68
69
|
self.tucker = use_tucker and k_size != (1, 1)
|
|
69
70
|
self.down_op = self.op
|
|
70
71
|
self.up_op = self.op
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
lora_dim, lora_dim, k_size, stride, padding, bias=False
|
|
75
|
-
)
|
|
76
|
-
self.tucker = True
|
|
77
|
-
else:
|
|
78
|
-
self.a2 = self.module(
|
|
79
|
-
in_dim, lora_dim, k_size, stride, padding, bias=False
|
|
80
|
-
)
|
|
72
|
+
|
|
73
|
+
# A
|
|
74
|
+
self.a2 = self.module(in_dim, lora_dim, (1, 1), bias=False)
|
|
81
75
|
self.a1 = self.module(lora_dim, in_dim, (1, 1), bias=False)
|
|
76
|
+
|
|
77
|
+
# B
|
|
82
78
|
if use_tucker and k_size != (1, 1):
|
|
83
79
|
self.b2 = self.module(in_dim, lora_dim, (1, 1), bias=False)
|
|
84
80
|
self.bm = self.module(
|
|
@@ -90,7 +86,7 @@ class GLoRAModule(LycorisBaseModule):
|
|
|
90
86
|
in_dim, lora_dim, k_size, stride, padding, bias=False
|
|
91
87
|
)
|
|
92
88
|
self.b1 = self.module(lora_dim, out_dim, (1, 1), bias=False)
|
|
93
|
-
|
|
89
|
+
else:
|
|
94
90
|
self.isconv = False
|
|
95
91
|
self.down_op = F.linear
|
|
96
92
|
self.up_op = F.linear
|
|
@@ -100,8 +96,6 @@ class GLoRAModule(LycorisBaseModule):
|
|
|
100
96
|
self.a1 = nn.Linear(lora_dim, in_dim, bias=False)
|
|
101
97
|
self.b2 = nn.Linear(in_dim, lora_dim, bias=False)
|
|
102
98
|
self.b1 = nn.Linear(lora_dim, out_dim, bias=False)
|
|
103
|
-
else:
|
|
104
|
-
raise NotImplementedError
|
|
105
99
|
|
|
106
100
|
if type(alpha) == torch.Tensor:
|
|
107
101
|
alpha = alpha.detach().float().numpy() # without casting, bf16 causes error
|
|
@@ -129,19 +123,35 @@ class GLoRAModule(LycorisBaseModule):
|
|
|
129
123
|
def make_weight(self, device=None):
|
|
130
124
|
wa1 = self.a1.weight.view(self.a1.weight.size(0), -1)
|
|
131
125
|
wa2 = self.a2.weight.view(self.a2.weight.size(0), -1)
|
|
132
|
-
wb1 = self.b1.weight.view(self.b1.weight.size(0), -1)
|
|
133
|
-
wb2 = self.b2.weight.view(self.b2.weight.size(0), -1)
|
|
134
|
-
orig = self.org_weight.view(self.org_module[0].weight.size(0), -1)
|
|
135
|
-
return (wb2 @ wb1) + ((orig @ wa2) @ wa1)
|
|
136
126
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
127
|
+
if self.tucker:
|
|
128
|
+
wb = tucker_weight_from_conv(self.b1.weight, self.b2.weight, self.bm.weight)
|
|
129
|
+
else:
|
|
130
|
+
wb1 = self.b1.weight.view(self.b1.weight.size(0), -1)
|
|
131
|
+
wb2 = self.b2.weight.view(self.b2.weight.size(0), -1)
|
|
132
|
+
wb = wb1 @ wb2
|
|
133
|
+
orig = self.org_weight
|
|
134
|
+
if orig.dim() > 2:
|
|
135
|
+
w_wa1 = torch.einsum("o i ..., i j -> o j ...", orig, wa1)
|
|
136
|
+
w_wa2 = torch.einsum("o i ..., i j -> o j ...", w_wa1, wa2)
|
|
137
|
+
else:
|
|
138
|
+
w_wa2 = (orig @ wa1) @ wa2
|
|
139
|
+
return (wb + w_wa2) * self.scale
|
|
140
|
+
|
|
141
|
+
def get_diff_weight(self, multiplier=1.0, shape=None, device=None):
|
|
142
|
+
weight = self.make_weight(device) * multiplier
|
|
143
|
+
if shape is not None:
|
|
144
|
+
weight = weight.view(shape)
|
|
145
|
+
return weight, None
|
|
142
146
|
|
|
143
|
-
|
|
144
|
-
|
|
147
|
+
def get_merged_weight(self, multiplier=1, shape=None, device=None):
|
|
148
|
+
diff_w, _ = self.get_diff_weight(multiplier, shape, device)
|
|
149
|
+
return self.org_weight + diff_w, None
|
|
150
|
+
|
|
151
|
+
def _bypass_forward(self, x, scale=1, diff=False):
|
|
152
|
+
scale = self.scale * scale
|
|
153
|
+
ax_mid = self.a2(x) * scale
|
|
154
|
+
bx_mid = self.b2(x) * scale
|
|
145
155
|
|
|
146
156
|
if self.rank_dropout and self.training:
|
|
147
157
|
drop_a = (
|
|
@@ -161,12 +171,37 @@ class GLoRAModule(LycorisBaseModule):
|
|
|
161
171
|
drop_b = drop_b.view(*[1] * (dims - 1), -1)
|
|
162
172
|
ax_mid = ax_mid * drop_a
|
|
163
173
|
bx_mid = bx_mid * drop_b
|
|
164
|
-
|
|
165
174
|
return (
|
|
166
|
-
self.org_forward(
|
|
167
|
-
|
|
175
|
+
self.org_forward(
|
|
176
|
+
(0 if diff else x) + self.drop(self.a1(ax_mid)) * self.scale
|
|
177
|
+
)
|
|
178
|
+
+ self.drop(self.b1(bx_mid)) * self.scale
|
|
168
179
|
)
|
|
169
180
|
|
|
181
|
+
def bypass_forward_diff(self, x, scale=1):
|
|
182
|
+
return self._bypass_forward(x, scale=scale, diff=True)
|
|
183
|
+
|
|
184
|
+
def bypass_forward(self, x, scale=1):
|
|
185
|
+
return self._bypass_forward(x, scale=scale, diff=False)
|
|
186
|
+
|
|
187
|
+
def forward(self, x, *args, **kwargs):
|
|
188
|
+
if self.module_dropout and self.training:
|
|
189
|
+
if torch.rand(1) < self.module_dropout:
|
|
190
|
+
return self.org_forward(x)
|
|
191
|
+
if self.bypass_mode:
|
|
192
|
+
return self.bypass_forward(x, self.multiplier)
|
|
193
|
+
else:
|
|
194
|
+
weight = (
|
|
195
|
+
self.org_module[0].weight.data.to(self.dtype)
|
|
196
|
+
+ self.get_diff_weight(multiplier=self.multiplier)[0]
|
|
197
|
+
)
|
|
198
|
+
bias = (
|
|
199
|
+
None
|
|
200
|
+
if self.org_module[0].bias is None
|
|
201
|
+
else self.org_module[0].bias.data
|
|
202
|
+
)
|
|
203
|
+
return self.op(x, weight, bias, **self.kw_dict)
|
|
204
|
+
|
|
170
205
|
|
|
171
206
|
if __name__ == "__main__":
|
|
172
207
|
device = torch.device("cuda")
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import torch
|
|
2
|
+
import torch.nn as nn
|
|
3
|
+
|
|
4
|
+
from .base import LycorisBaseModule
|
|
5
|
+
from ..utils.bnb import LinearNF4
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class IA3Module(LycorisBaseModule):
|
|
9
|
+
support_module = {
|
|
10
|
+
"linear",
|
|
11
|
+
"conv1d",
|
|
12
|
+
"conv2d",
|
|
13
|
+
"conv3d",
|
|
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
|
+
use_scalar=False,
|
|
28
|
+
rank_dropout_scale=False,
|
|
29
|
+
weight_decompose=False,
|
|
30
|
+
bypass_mode=False,
|
|
31
|
+
rs_lora=False,
|
|
32
|
+
train_on_input=False,
|
|
33
|
+
**kwargs,
|
|
34
|
+
):
|
|
35
|
+
"""if alpha == 0 or None, alpha is rank (no scaling)."""
|
|
36
|
+
super().__init__(
|
|
37
|
+
lora_name,
|
|
38
|
+
org_module,
|
|
39
|
+
multiplier,
|
|
40
|
+
dropout,
|
|
41
|
+
rank_dropout,
|
|
42
|
+
module_dropout,
|
|
43
|
+
rank_dropout_scale,
|
|
44
|
+
bypass_mode,
|
|
45
|
+
)
|
|
46
|
+
if self.module_type not in self.support_module:
|
|
47
|
+
raise ValueError(f"{self.module_type} is not supported in IA^3 algo.")
|
|
48
|
+
|
|
49
|
+
if self.module_type.startswith("conv"):
|
|
50
|
+
self.isconv = True
|
|
51
|
+
in_dim = org_module.in_channels
|
|
52
|
+
out_dim = org_module.out_channels
|
|
53
|
+
if train_on_input:
|
|
54
|
+
train_dim = in_dim
|
|
55
|
+
else:
|
|
56
|
+
train_dim = out_dim
|
|
57
|
+
self.weight = nn.Parameter(
|
|
58
|
+
torch.empty(1, train_dim, *(1 for _ in self.shape[2:]))
|
|
59
|
+
)
|
|
60
|
+
else:
|
|
61
|
+
in_dim = org_module.in_features
|
|
62
|
+
out_dim = org_module.out_features
|
|
63
|
+
if train_on_input:
|
|
64
|
+
train_dim = in_dim
|
|
65
|
+
else:
|
|
66
|
+
train_dim = out_dim
|
|
67
|
+
|
|
68
|
+
self.weight = nn.Parameter(torch.empty(train_dim))
|
|
69
|
+
|
|
70
|
+
# Need more experiences on init method
|
|
71
|
+
torch.nn.init.constant_(self.weight, 0)
|
|
72
|
+
self.train_input = train_on_input
|
|
73
|
+
self.register_buffer("on_input", torch.tensor(int(train_on_input)))
|
|
74
|
+
|
|
75
|
+
def apply_to(self):
|
|
76
|
+
self.org_forward = self.org_module[0].forward
|
|
77
|
+
self.org_module[0].forward = self.forward
|
|
78
|
+
|
|
79
|
+
def make_weight(self, multiplier=1, shape=None, device=None, diff=False):
|
|
80
|
+
weight = self.weight * multiplier + int(not diff)
|
|
81
|
+
if self.train_input:
|
|
82
|
+
diff = self.org_weight * weight
|
|
83
|
+
else:
|
|
84
|
+
diff = self.org_weight.transpose(0, 1) * weight
|
|
85
|
+
diff = diff.transpose(0, 1)
|
|
86
|
+
if shape is not None:
|
|
87
|
+
diff = diff.view(shape)
|
|
88
|
+
if device is not None:
|
|
89
|
+
diff = diff.to(device)
|
|
90
|
+
return diff
|
|
91
|
+
|
|
92
|
+
def get_diff_weight(self, multiplier=1, shape=None, device=None):
|
|
93
|
+
diff = self.make_weight(
|
|
94
|
+
multiplier=multiplier, shape=shape, device=device, diff=True
|
|
95
|
+
)
|
|
96
|
+
return diff, None
|
|
97
|
+
|
|
98
|
+
def get_merged_weight(self, multiplier=1, shape=None, device=None):
|
|
99
|
+
diff = self.make_weight(multiplier=multiplier, shape=shape, device=device)
|
|
100
|
+
return diff, None
|
|
101
|
+
|
|
102
|
+
def _bypass_forward(self, x, scale=1, diff=False):
|
|
103
|
+
weight = self.weight * scale + int(not diff)
|
|
104
|
+
if self.train_input:
|
|
105
|
+
x = x * weight
|
|
106
|
+
out = self.org_forward(x)
|
|
107
|
+
if not self.train_input:
|
|
108
|
+
out = out * weight
|
|
109
|
+
return out
|
|
110
|
+
|
|
111
|
+
def bypass_forward_diff(self, x, scale=1):
|
|
112
|
+
return self._bypass_forward(x, scale, diff=True)
|
|
113
|
+
|
|
114
|
+
def bypass_forward(self, x, scale=1):
|
|
115
|
+
return self._bypass_forward(x, scale, diff=False)
|
|
116
|
+
|
|
117
|
+
def forward(self, x, *args, **kwargs):
|
|
118
|
+
if self.module_dropout and self.training:
|
|
119
|
+
if torch.rand(1) < self.module_dropout:
|
|
120
|
+
return self.org_forward(x)
|
|
121
|
+
if self.bypass_mode:
|
|
122
|
+
return self.bypass_forward(x, self.multiplier)
|
|
123
|
+
else:
|
|
124
|
+
weight = self.get_merged_weight(multiplier=self.multiplier)[0]
|
|
125
|
+
bias = (
|
|
126
|
+
None
|
|
127
|
+
if self.org_module[0].bias is None
|
|
128
|
+
else self.org_module[0].bias.data
|
|
129
|
+
)
|
|
130
|
+
return self.op(x, weight, bias, **self.kw_dict)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
if __name__ == "__main__":
|
|
134
|
+
device = torch.device("cuda")
|
|
135
|
+
module = IA3Module
|
|
136
|
+
with torch.autocast("cuda" if torch.cuda.is_available() else "cpu"):
|
|
137
|
+
base = nn.Linear(128, 128).to(device).half()
|
|
138
|
+
net = module("test", base, 1, 4, 1, weight_decompose=True).to(device)
|
|
139
|
+
print(net)
|
|
140
|
+
test_input = torch.randn(1, 128).to(device).half()
|
|
141
|
+
test_output = net(test_input)
|
|
142
|
+
torch.sum(test_output).backward()
|
|
143
|
+
print(test_output.shape)
|
|
144
|
+
|
|
145
|
+
base_4bit = LinearNF4(128, 128, device="cuda")
|
|
146
|
+
base_4bit.load_state_dict(base.state_dict())
|
|
147
|
+
base_4bit.to(device)
|
|
148
|
+
qnet = module("test", base_4bit, 1, 4, 1, weight_decompose=False).to(device)
|
|
149
|
+
print(qnet)
|
|
150
|
+
test_input = torch.randn(1, 128).to(device).half()
|
|
151
|
+
test_output = qnet(test_input)
|
|
152
|
+
torch.sum(test_output).backward()
|
|
153
|
+
print(test_output.shape)
|
|
154
|
+
|
|
155
|
+
base = nn.Conv2d(128, 128, 3, 1, 1).to(device).half()
|
|
156
|
+
net = module("test", base, 1, 4, 1, weight_decompose=True, use_tucker=True).to(
|
|
157
|
+
device
|
|
158
|
+
)
|
|
159
|
+
print(net)
|
|
160
|
+
test_input = torch.randn(1, 128, 16, 16).to(device).half()
|
|
161
|
+
test_output = net(test_input)
|
|
162
|
+
torch.sum(test_output).backward()
|
|
163
|
+
print(test_output.shape)
|
|
164
|
+
|
|
165
|
+
base = nn.Conv2d(128, 128, 3, 1, 1).to(device).half()
|
|
166
|
+
net = module.parametrize(
|
|
167
|
+
base, "weight", 1, 4, 1, weight_decompose=True, use_tucker=True
|
|
168
|
+
).to(device)
|
|
169
|
+
print(base)
|
|
170
|
+
test_input = torch.randn(1, 128, 16, 16).to(device).half()
|
|
171
|
+
test_output = base(test_input)
|
|
172
|
+
torch.sum(test_output).backward()
|
|
173
|
+
print(test_output.shape)
|
|
@@ -154,12 +154,12 @@ class LoConModule(LycorisBaseModule):
|
|
|
154
154
|
)
|
|
155
155
|
|
|
156
156
|
def make_weight(self, device=None):
|
|
157
|
-
wa = self.lora_up.weight
|
|
158
|
-
wb = self.lora_down.weight
|
|
157
|
+
wa = self.lora_up.weight
|
|
158
|
+
wb = self.lora_down.weight
|
|
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)
|
|
@@ -265,7 +265,7 @@ class LohaModule(LycorisBaseModule):
|
|
|
265
265
|
|
|
266
266
|
if self.wd:
|
|
267
267
|
weight = self.apply_weight_decompose(weight)
|
|
268
|
-
return self.op(x, weight
|
|
268
|
+
return self.op(x, weight, bias, **self.kw_dict)
|
|
269
269
|
|
|
270
270
|
|
|
271
271
|
if __name__ == "__main__":
|
|
@@ -72,7 +72,7 @@ class LokrModule(LycorisBaseModule):
|
|
|
72
72
|
bypass_mode,
|
|
73
73
|
)
|
|
74
74
|
if self.module_type not in self.support_module:
|
|
75
|
-
raise ValueError(f"{self.module_type} is not supported in
|
|
75
|
+
raise ValueError(f"{self.module_type} is not supported in LoKr algo.")
|
|
76
76
|
|
|
77
77
|
factor = int(factor)
|
|
78
78
|
self.lora_dim = lora_dim
|
|
@@ -396,7 +396,7 @@ class LokrModule(LycorisBaseModule):
|
|
|
396
396
|
|
|
397
397
|
if self.wd:
|
|
398
398
|
weight = self.apply_weight_decompose(weight)
|
|
399
|
-
return self.op(x, weight
|
|
399
|
+
return self.op(x, weight, bias, **self.kw_dict)
|
|
400
400
|
|
|
401
401
|
|
|
402
402
|
if __name__ == "__main__":
|
|
@@ -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.dev5
|
|
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.dev5",
|
|
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
|
-
)
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import torch
|
|
2
|
-
import torch.nn as nn
|
|
3
|
-
|
|
4
|
-
from .base import ModuleCustomSD
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class IA3Module(ModuleCustomSD):
|
|
8
|
-
"""
|
|
9
|
-
Hadamard product Implementaion for Low Rank Adaptation
|
|
10
|
-
"""
|
|
11
|
-
|
|
12
|
-
def __init__(
|
|
13
|
-
self,
|
|
14
|
-
lora_name,
|
|
15
|
-
org_module: nn.Module,
|
|
16
|
-
multiplier=1.0,
|
|
17
|
-
train_on_input=False,
|
|
18
|
-
**kwargs
|
|
19
|
-
):
|
|
20
|
-
"""if alpha == 0 or None, alpha is rank (no scaling)."""
|
|
21
|
-
super().__init__()
|
|
22
|
-
self.lora_name = lora_name
|
|
23
|
-
self.tucker = False
|
|
24
|
-
|
|
25
|
-
self.shape = org_module.weight.shape
|
|
26
|
-
if org_module.__class__.__name__ == "Conv2d":
|
|
27
|
-
in_dim = org_module.in_channels
|
|
28
|
-
out_dim = org_module.out_channels
|
|
29
|
-
if train_on_input:
|
|
30
|
-
train_dim = in_dim
|
|
31
|
-
else:
|
|
32
|
-
train_dim = out_dim
|
|
33
|
-
self.weight = nn.Parameter(torch.empty(1, train_dim, 1, 1))
|
|
34
|
-
else:
|
|
35
|
-
in_dim = org_module.in_features
|
|
36
|
-
out_dim = org_module.out_features
|
|
37
|
-
if train_on_input:
|
|
38
|
-
train_dim = in_dim
|
|
39
|
-
else:
|
|
40
|
-
train_dim = out_dim
|
|
41
|
-
|
|
42
|
-
self.weight = nn.Parameter(torch.empty(train_dim))
|
|
43
|
-
|
|
44
|
-
# Need more experiences on init method
|
|
45
|
-
torch.nn.init.constant_(self.weight, 0)
|
|
46
|
-
|
|
47
|
-
self.multiplier = multiplier
|
|
48
|
-
self.org_forward = None
|
|
49
|
-
self.org_module = [org_module] # remove in applying
|
|
50
|
-
self.grad_ckpt = False
|
|
51
|
-
self.train_input = train_on_input
|
|
52
|
-
self.register_buffer("on_input", torch.tensor(int(train_on_input)))
|
|
53
|
-
|
|
54
|
-
def apply_to(self):
|
|
55
|
-
self.org_forward = self.org_module[0].forward
|
|
56
|
-
self.org_module[0].forward = self.forward
|
|
57
|
-
|
|
58
|
-
@torch.enable_grad()
|
|
59
|
-
def forward(self, x):
|
|
60
|
-
if self.train_input:
|
|
61
|
-
x = x * (1 + self.weight * self.multiplier)
|
|
62
|
-
out = self.org_forward(x)
|
|
63
|
-
dtype = out.dtype
|
|
64
|
-
if not self.train_input:
|
|
65
|
-
out = out * (1 + self.weight * self.multiplier)
|
|
66
|
-
out = out.to(dtype)
|
|
67
|
-
return out
|
|
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.dev3 → lycoris_lora-3.0.0.dev5}/lycoris_lora.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|