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