autoregressive-diffusion-pytorch 0.2.1__tar.gz → 0.2.2__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.
- {autoregressive_diffusion_pytorch-0.2.1 → autoregressive_diffusion_pytorch-0.2.2}/PKG-INFO +37 -1
- {autoregressive_diffusion_pytorch-0.2.1 → autoregressive_diffusion_pytorch-0.2.2}/README.md +36 -0
- {autoregressive_diffusion_pytorch-0.2.1 → autoregressive_diffusion_pytorch-0.2.2}/autoregressive_diffusion_pytorch/__init__.py +6 -1
- autoregressive_diffusion_pytorch-0.2.2/autoregressive_diffusion_pytorch/autoregressive_flow.py +335 -0
- {autoregressive_diffusion_pytorch-0.2.1 → autoregressive_diffusion_pytorch-0.2.2}/pyproject.toml +1 -1
- {autoregressive_diffusion_pytorch-0.2.1 → autoregressive_diffusion_pytorch-0.2.2}/.github/workflows/python-publish.yml +0 -0
- {autoregressive_diffusion_pytorch-0.2.1 → autoregressive_diffusion_pytorch-0.2.2}/.gitignore +0 -0
- {autoregressive_diffusion_pytorch-0.2.1 → autoregressive_diffusion_pytorch-0.2.2}/LICENSE +0 -0
- {autoregressive_diffusion_pytorch-0.2.1 → autoregressive_diffusion_pytorch-0.2.2}/ar-diffusion.png +0 -0
- {autoregressive_diffusion_pytorch-0.2.1 → autoregressive_diffusion_pytorch-0.2.2}/autoregressive_diffusion_pytorch/autoregressive_diffusion.py +0 -0
- {autoregressive_diffusion_pytorch-0.2.1 → autoregressive_diffusion_pytorch-0.2.2}/autoregressive_diffusion_pytorch/image_trainer.py +0 -0
- {autoregressive_diffusion_pytorch-0.2.1 → autoregressive_diffusion_pytorch-0.2.2}/images/results.96600.png +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: autoregressive-diffusion-pytorch
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Autoregressive Diffusion - Pytorch
|
|
5
5
|
Project-URL: Homepage, https://pypi.org/project/autoregressive-diffusion-pytorch/
|
|
6
6
|
Project-URL: Repository, https://github.com/lucidrains/autoregressive-diffusion-pytorch
|
|
@@ -147,6 +147,42 @@ trainer = ImageTrainer(
|
|
|
147
147
|
trainer()
|
|
148
148
|
```
|
|
149
149
|
|
|
150
|
+
For an improvised version using flow matching, just import `ImageAutoregressiveFlow` and `AutoregressiveFlow` instead
|
|
151
|
+
|
|
152
|
+
The rest is the same
|
|
153
|
+
|
|
154
|
+
ex.
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
import torch
|
|
158
|
+
|
|
159
|
+
from autoregressive_diffusion_pytorch import (
|
|
160
|
+
ImageDataset,
|
|
161
|
+
ImageTrainer,
|
|
162
|
+
ImageAutoregressiveFlow,
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
dataset = ImageDataset(
|
|
166
|
+
'/path/to/your/images',
|
|
167
|
+
image_size = 128
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
model = ImageAutoregressiveFlow(
|
|
171
|
+
model = dict(
|
|
172
|
+
dim = 512
|
|
173
|
+
),
|
|
174
|
+
image_size = 128,
|
|
175
|
+
patch_size = 16
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
trainer = ImageTrainer(
|
|
179
|
+
model = model,
|
|
180
|
+
dataset = dataset
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
trainer()
|
|
184
|
+
```
|
|
185
|
+
|
|
150
186
|
## Citations
|
|
151
187
|
|
|
152
188
|
```bibtex
|
|
@@ -101,6 +101,42 @@ trainer = ImageTrainer(
|
|
|
101
101
|
trainer()
|
|
102
102
|
```
|
|
103
103
|
|
|
104
|
+
For an improvised version using flow matching, just import `ImageAutoregressiveFlow` and `AutoregressiveFlow` instead
|
|
105
|
+
|
|
106
|
+
The rest is the same
|
|
107
|
+
|
|
108
|
+
ex.
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
import torch
|
|
112
|
+
|
|
113
|
+
from autoregressive_diffusion_pytorch import (
|
|
114
|
+
ImageDataset,
|
|
115
|
+
ImageTrainer,
|
|
116
|
+
ImageAutoregressiveFlow,
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
dataset = ImageDataset(
|
|
120
|
+
'/path/to/your/images',
|
|
121
|
+
image_size = 128
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
model = ImageAutoregressiveFlow(
|
|
125
|
+
model = dict(
|
|
126
|
+
dim = 512
|
|
127
|
+
),
|
|
128
|
+
image_size = 128,
|
|
129
|
+
patch_size = 16
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
trainer = ImageTrainer(
|
|
133
|
+
model = model,
|
|
134
|
+
dataset = dataset
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
trainer()
|
|
138
|
+
```
|
|
139
|
+
|
|
104
140
|
## Citations
|
|
105
141
|
|
|
106
142
|
```bibtex
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
from autoregressive_diffusion_pytorch.autoregressive_diffusion import (
|
|
2
|
-
AutoregressiveDiffusion,
|
|
3
2
|
MLP,
|
|
3
|
+
AutoregressiveDiffusion,
|
|
4
4
|
ImageAutoregressiveDiffusion
|
|
5
5
|
)
|
|
6
6
|
|
|
7
|
+
from autoregressive_diffusion_pytorch.autoregressive_flow import (
|
|
8
|
+
AutoregressiveFlow,
|
|
9
|
+
ImageAutoregressiveFlow
|
|
10
|
+
)
|
|
11
|
+
|
|
7
12
|
from autoregressive_diffusion_pytorch.image_trainer import (
|
|
8
13
|
ImageDataset,
|
|
9
14
|
ImageTrainer
|
autoregressive_diffusion_pytorch-0.2.2/autoregressive_diffusion_pytorch/autoregressive_flow.py
ADDED
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import math
|
|
4
|
+
from math import sqrt
|
|
5
|
+
from typing import Literal
|
|
6
|
+
from functools import partial
|
|
7
|
+
|
|
8
|
+
import torch
|
|
9
|
+
from torch import nn, pi
|
|
10
|
+
import torch.nn.functional as F
|
|
11
|
+
from torch.nn import Module, ModuleList
|
|
12
|
+
|
|
13
|
+
from torchdiffeq import odeint
|
|
14
|
+
|
|
15
|
+
import einx
|
|
16
|
+
from einops import rearrange, repeat, reduce, pack, unpack
|
|
17
|
+
from einops.layers.torch import Rearrange
|
|
18
|
+
|
|
19
|
+
from tqdm import tqdm
|
|
20
|
+
|
|
21
|
+
from x_transformers import Decoder
|
|
22
|
+
|
|
23
|
+
from autoregressive_diffusion_pytorch.autoregressive_diffusion import MLP
|
|
24
|
+
|
|
25
|
+
# helpers
|
|
26
|
+
|
|
27
|
+
def exists(v):
|
|
28
|
+
return v is not None
|
|
29
|
+
|
|
30
|
+
def default(v, d):
|
|
31
|
+
return v if exists(v) else d
|
|
32
|
+
|
|
33
|
+
def divisible_by(num, den):
|
|
34
|
+
return (num % den) == 0
|
|
35
|
+
|
|
36
|
+
# tensor helpers
|
|
37
|
+
|
|
38
|
+
def log(t, eps = 1e-20):
|
|
39
|
+
return torch.log(t.clamp(min = eps))
|
|
40
|
+
|
|
41
|
+
def safe_div(num, den, eps = 1e-5):
|
|
42
|
+
return num / den.clamp(min = eps)
|
|
43
|
+
|
|
44
|
+
def right_pad_dims_to(x, t):
|
|
45
|
+
padding_dims = x.ndim - t.ndim
|
|
46
|
+
|
|
47
|
+
if padding_dims <= 0:
|
|
48
|
+
return t
|
|
49
|
+
|
|
50
|
+
return t.view(*t.shape, *((1,) * padding_dims))
|
|
51
|
+
|
|
52
|
+
def pack_one(t, pattern):
|
|
53
|
+
packed, ps = pack([t], pattern)
|
|
54
|
+
|
|
55
|
+
def unpack_one(to_unpack, unpack_pattern = None):
|
|
56
|
+
unpacked, = unpack(to_unpack, ps, default(unpack_pattern, pattern))
|
|
57
|
+
return unpacked
|
|
58
|
+
|
|
59
|
+
return packed, unpack_one
|
|
60
|
+
|
|
61
|
+
# sinusoidal embedding
|
|
62
|
+
|
|
63
|
+
class AdaptiveLayerNorm(Module):
|
|
64
|
+
def __init__(
|
|
65
|
+
self,
|
|
66
|
+
dim,
|
|
67
|
+
dim_condition = None
|
|
68
|
+
):
|
|
69
|
+
super().__init__()
|
|
70
|
+
dim_condition = default(dim_condition, dim)
|
|
71
|
+
|
|
72
|
+
self.ln = nn.LayerNorm(dim, elementwise_affine = False)
|
|
73
|
+
self.to_gamma = nn.Linear(dim_condition, dim, bias = False)
|
|
74
|
+
nn.init.zeros_(self.to_gamma.weight)
|
|
75
|
+
|
|
76
|
+
def forward(self, x, *, condition):
|
|
77
|
+
normed = self.ln(x)
|
|
78
|
+
gamma = self.to_gamma(condition)
|
|
79
|
+
return normed * (gamma + 1.)
|
|
80
|
+
|
|
81
|
+
class LearnedSinusoidalPosEmb(Module):
|
|
82
|
+
def __init__(self, dim):
|
|
83
|
+
super().__init__()
|
|
84
|
+
assert divisible_by(dim, 2)
|
|
85
|
+
half_dim = dim // 2
|
|
86
|
+
self.weights = nn.Parameter(torch.randn(half_dim))
|
|
87
|
+
|
|
88
|
+
def forward(self, x):
|
|
89
|
+
x = rearrange(x, 'b -> b 1')
|
|
90
|
+
freqs = x * rearrange(self.weights, 'd -> 1 d') * 2 * pi
|
|
91
|
+
fouriered = torch.cat((freqs.sin(), freqs.cos()), dim = -1)
|
|
92
|
+
fouriered = torch.cat((x, fouriered), dim = -1)
|
|
93
|
+
return fouriered
|
|
94
|
+
|
|
95
|
+
# gaussian diffusion
|
|
96
|
+
|
|
97
|
+
class Flow(Module):
|
|
98
|
+
def __init__(
|
|
99
|
+
self,
|
|
100
|
+
dim: int,
|
|
101
|
+
net: MLP,
|
|
102
|
+
*,
|
|
103
|
+
atol = 1e-5,
|
|
104
|
+
rtol = 1e-5,
|
|
105
|
+
method = 'midpoint'
|
|
106
|
+
):
|
|
107
|
+
super().__init__()
|
|
108
|
+
self.net = net
|
|
109
|
+
self.dim = dim
|
|
110
|
+
|
|
111
|
+
self.odeint_kwargs = dict(
|
|
112
|
+
atol = atol,
|
|
113
|
+
rtol = rtol,
|
|
114
|
+
method = method
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
@property
|
|
118
|
+
def device(self):
|
|
119
|
+
return next(self.net.parameters()).device
|
|
120
|
+
|
|
121
|
+
@torch.no_grad()
|
|
122
|
+
def sample(
|
|
123
|
+
self,
|
|
124
|
+
cond,
|
|
125
|
+
num_sample_steps = 16
|
|
126
|
+
):
|
|
127
|
+
|
|
128
|
+
batch = cond.shape[0]
|
|
129
|
+
|
|
130
|
+
sampled_data_shape = (batch, self.dim)
|
|
131
|
+
|
|
132
|
+
# start with random gaussian noise - y0
|
|
133
|
+
|
|
134
|
+
noise = torch.randn(sampled_data_shape, device = self.device)
|
|
135
|
+
|
|
136
|
+
# time steps
|
|
137
|
+
|
|
138
|
+
times = torch.linspace(0., 1., num_sample_steps, device = self.device)
|
|
139
|
+
|
|
140
|
+
# ode
|
|
141
|
+
|
|
142
|
+
def ode_fn(t, x):
|
|
143
|
+
t = repeat(t, '-> b', b = batch)
|
|
144
|
+
flow = self.net(x, times = t, cond = cond)
|
|
145
|
+
return flow
|
|
146
|
+
|
|
147
|
+
trajectory = odeint(ode_fn, noise, times, **self.odeint_kwargs)
|
|
148
|
+
|
|
149
|
+
sampled = trajectory[-1]
|
|
150
|
+
|
|
151
|
+
return sampled
|
|
152
|
+
|
|
153
|
+
# training
|
|
154
|
+
|
|
155
|
+
def forward(self, seq, *, cond):
|
|
156
|
+
batch_size, dim, device = *seq.shape, self.device
|
|
157
|
+
|
|
158
|
+
assert dim == self.dim, f'dimension of sequence being passed in must be {self.dim} but received {dim}'
|
|
159
|
+
|
|
160
|
+
times = torch.rand(batch_size, device = device)
|
|
161
|
+
noise = torch.randn_like(seq)
|
|
162
|
+
padded_times = right_pad_dims_to(seq, times)
|
|
163
|
+
|
|
164
|
+
flow = seq - noise
|
|
165
|
+
|
|
166
|
+
noised = (1.- padded_times) * noise + padded_times * seq
|
|
167
|
+
|
|
168
|
+
pred_flow = self.net(noised, times = times, cond = cond)
|
|
169
|
+
|
|
170
|
+
return F.mse_loss(pred_flow, flow)
|
|
171
|
+
|
|
172
|
+
# main model, a decoder with continuous wrapper + small denoising mlp
|
|
173
|
+
|
|
174
|
+
class AutoregressiveFlow(Module):
|
|
175
|
+
def __init__(
|
|
176
|
+
self,
|
|
177
|
+
dim,
|
|
178
|
+
*,
|
|
179
|
+
max_seq_len,
|
|
180
|
+
depth = 8,
|
|
181
|
+
dim_head = 64,
|
|
182
|
+
heads = 8,
|
|
183
|
+
mlp_depth = 3,
|
|
184
|
+
mlp_width = None,
|
|
185
|
+
dim_input = None,
|
|
186
|
+
decoder_kwargs: dict = dict(),
|
|
187
|
+
mlp_kwargs: dict = dict(),
|
|
188
|
+
flow_kwargs: dict = dict()
|
|
189
|
+
):
|
|
190
|
+
super().__init__()
|
|
191
|
+
|
|
192
|
+
self.start_token = nn.Parameter(torch.zeros(dim))
|
|
193
|
+
self.max_seq_len = max_seq_len
|
|
194
|
+
self.abs_pos_emb = nn.Embedding(max_seq_len, dim)
|
|
195
|
+
|
|
196
|
+
dim_input = default(dim_input, dim)
|
|
197
|
+
self.dim_input = dim_input
|
|
198
|
+
self.proj_in = nn.Linear(dim_input, dim)
|
|
199
|
+
|
|
200
|
+
self.transformer = Decoder(
|
|
201
|
+
dim = dim,
|
|
202
|
+
depth = depth,
|
|
203
|
+
heads = heads,
|
|
204
|
+
attn_dim_head = dim_head,
|
|
205
|
+
**decoder_kwargs
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
self.denoiser = MLP(
|
|
209
|
+
dim_cond = dim,
|
|
210
|
+
dim_input = dim_input,
|
|
211
|
+
depth = mlp_depth,
|
|
212
|
+
width = default(mlp_width, dim),
|
|
213
|
+
**mlp_kwargs
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
self.flow = Flow(
|
|
217
|
+
dim_input,
|
|
218
|
+
self.denoiser,
|
|
219
|
+
**flow_kwargs
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
@property
|
|
223
|
+
def device(self):
|
|
224
|
+
return next(self.transformer.parameters()).device
|
|
225
|
+
|
|
226
|
+
@torch.no_grad()
|
|
227
|
+
def sample(
|
|
228
|
+
self,
|
|
229
|
+
batch_size = 1,
|
|
230
|
+
prompt = None
|
|
231
|
+
):
|
|
232
|
+
self.eval()
|
|
233
|
+
|
|
234
|
+
start_tokens = repeat(self.start_token, 'd -> b 1 d', b = batch_size)
|
|
235
|
+
|
|
236
|
+
if not exists(prompt):
|
|
237
|
+
out = torch.empty((batch_size, 0, self.dim_input), device = self.device, dtype = torch.float32)
|
|
238
|
+
else:
|
|
239
|
+
out = prompt
|
|
240
|
+
|
|
241
|
+
cache = None
|
|
242
|
+
|
|
243
|
+
for _ in tqdm(range(self.max_seq_len - out.shape[1]), desc = 'tokens'):
|
|
244
|
+
|
|
245
|
+
cond = self.proj_in(out)
|
|
246
|
+
|
|
247
|
+
cond = torch.cat((start_tokens, cond), dim = 1)
|
|
248
|
+
cond = cond + self.abs_pos_emb(torch.arange(cond.shape[1], device = self.device))
|
|
249
|
+
|
|
250
|
+
cond, cache = self.transformer(cond, cache = cache, return_hiddens = True)
|
|
251
|
+
|
|
252
|
+
last_cond = cond[:, -1]
|
|
253
|
+
|
|
254
|
+
denoised_pred = self.flow.sample(cond = last_cond)
|
|
255
|
+
|
|
256
|
+
denoised_pred = rearrange(denoised_pred, 'b d -> b 1 d')
|
|
257
|
+
out = torch.cat((out, denoised_pred), dim = 1)
|
|
258
|
+
|
|
259
|
+
return out
|
|
260
|
+
|
|
261
|
+
def forward(
|
|
262
|
+
self,
|
|
263
|
+
seq
|
|
264
|
+
):
|
|
265
|
+
b, seq_len, dim = seq.shape
|
|
266
|
+
|
|
267
|
+
assert dim == self.dim_input
|
|
268
|
+
assert seq_len == self.max_seq_len
|
|
269
|
+
|
|
270
|
+
# break into seq and the continuous targets to be predicted
|
|
271
|
+
|
|
272
|
+
seq, target = seq[:, :-1], seq
|
|
273
|
+
|
|
274
|
+
# append start tokens
|
|
275
|
+
|
|
276
|
+
seq = self.proj_in(seq)
|
|
277
|
+
start_token = repeat(self.start_token, 'd -> b 1 d', b = b)
|
|
278
|
+
|
|
279
|
+
seq = torch.cat((start_token, seq), dim = 1)
|
|
280
|
+
seq = seq + self.abs_pos_emb(torch.arange(seq_len, device = self.device))
|
|
281
|
+
|
|
282
|
+
cond = self.transformer(seq)
|
|
283
|
+
|
|
284
|
+
# pack batch and sequence dimensions, so to train each token with different noise levels
|
|
285
|
+
|
|
286
|
+
target, _ = pack_one(target, '* d')
|
|
287
|
+
cond, _ = pack_one(cond, '* d')
|
|
288
|
+
|
|
289
|
+
return self.flow(target, cond = cond)
|
|
290
|
+
|
|
291
|
+
# image wrapper
|
|
292
|
+
|
|
293
|
+
def normalize_to_neg_one_to_one(img):
|
|
294
|
+
return img * 2 - 1
|
|
295
|
+
|
|
296
|
+
def unnormalize_to_zero_to_one(t):
|
|
297
|
+
return (t + 1) * 0.5
|
|
298
|
+
|
|
299
|
+
class ImageAutoregressiveFlow(Module):
|
|
300
|
+
def __init__(
|
|
301
|
+
self,
|
|
302
|
+
*,
|
|
303
|
+
image_size,
|
|
304
|
+
patch_size,
|
|
305
|
+
channels = 3,
|
|
306
|
+
model: dict = dict(),
|
|
307
|
+
):
|
|
308
|
+
super().__init__()
|
|
309
|
+
assert divisible_by(image_size, patch_size)
|
|
310
|
+
|
|
311
|
+
num_patches = (image_size // patch_size) ** 2
|
|
312
|
+
dim_in = channels * patch_size ** 2
|
|
313
|
+
|
|
314
|
+
self.image_size = image_size
|
|
315
|
+
self.patch_size = patch_size
|
|
316
|
+
|
|
317
|
+
self.to_tokens = Rearrange('b c (h p1) (w p2) -> b (h w) (c p1 p2)', p1 = patch_size, p2 = patch_size)
|
|
318
|
+
|
|
319
|
+
self.model = AutoregressiveFlow(
|
|
320
|
+
**model,
|
|
321
|
+
dim_input = dim_in,
|
|
322
|
+
max_seq_len = num_patches
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
self.to_image = Rearrange('b (h w) (c p1 p2) -> b c (h p1) (w p2)', p1 = patch_size, p2 = patch_size, h = int(math.sqrt(num_patches)))
|
|
326
|
+
|
|
327
|
+
def sample(self, batch_size = 1):
|
|
328
|
+
tokens = self.model.sample(batch_size = batch_size)
|
|
329
|
+
images = self.to_image(tokens)
|
|
330
|
+
return unnormalize_to_zero_to_one(images)
|
|
331
|
+
|
|
332
|
+
def forward(self, images):
|
|
333
|
+
images = normalize_to_neg_one_to_one(images)
|
|
334
|
+
tokens = self.to_tokens(images)
|
|
335
|
+
return self.model(tokens)
|
|
File without changes
|
{autoregressive_diffusion_pytorch-0.2.1 → autoregressive_diffusion_pytorch-0.2.2}/.gitignore
RENAMED
|
File without changes
|
|
File without changes
|
{autoregressive_diffusion_pytorch-0.2.1 → autoregressive_diffusion_pytorch-0.2.2}/ar-diffusion.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|