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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: autoregressive-diffusion-pytorch
3
- Version: 0.2.1
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
@@ -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)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "autoregressive-diffusion-pytorch"
3
- version = "0.2.1"
3
+ version = "0.2.2"
4
4
  description = "Autoregressive Diffusion - Pytorch"
5
5
  authors = [
6
6
  { name = "Phil Wang", email = "lucidrains@gmail.com" }