hypergan 2.0.0a1__py3-none-any.whl

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.
Files changed (140) hide show
  1. hypergan/__init__.py +39 -0
  2. hypergan/__main__.py +5 -0
  3. hypergan/_build_provenance.json +1 -0
  4. hypergan/_file_lock.py +32 -0
  5. hypergan/api.py +2221 -0
  6. hypergan/artifacts.py +334 -0
  7. hypergan/autoencoder_components.py +60 -0
  8. hypergan/background_poll.py +74 -0
  9. hypergan/bounded_cli_output.py +562 -0
  10. hypergan/bounded_observer.py +278 -0
  11. hypergan/checkpoint_compatibility.py +203 -0
  12. hypergan/checkpoints.py +902 -0
  13. hypergan/cli.py +2165 -0
  14. hypergan/color_words.py +288 -0
  15. hypergan/colorization_components.py +360 -0
  16. hypergan/colorization_data.py +256 -0
  17. hypergan/colorization_metrics.py +168 -0
  18. hypergan/config.py +1041 -0
  19. hypergan/console_settings.py +87 -0
  20. hypergan/cpu_worker_service.py +575 -0
  21. hypergan/cpu_workers.py +125 -0
  22. hypergan/data.py +429 -0
  23. hypergan/datasets.py +6 -0
  24. hypergan/diff_augment.py +131 -0
  25. hypergan/distributed.py +110 -0
  26. hypergan/distributed_checkpoints.py +558 -0
  27. hypergan/distributed_commit.py +297 -0
  28. hypergan/distributed_training.py +733 -0
  29. hypergan/diversity_metrics.py +175 -0
  30. hypergan/evaluation_cli.py +22 -0
  31. hypergan/evaluation_snapshot.py +28 -0
  32. hypergan/event_views.py +500 -0
  33. hypergan/execution.py +360 -0
  34. hypergan/execution_preflight.py +264 -0
  35. hypergan/execution_profiles.py +142 -0
  36. hypergan/gpu_inventory.py +687 -0
  37. hypergan/hndl_augmentation.py +40 -0
  38. hypergan/hndl_networks.py +42 -0
  39. hypergan/image_cache.py +66 -0
  40. hypergan/image_components.py +326 -0
  41. hypergan/image_data.py +96 -0
  42. hypergan/image_grids.py +151 -0
  43. hypergan/image_metrics.py +121 -0
  44. hypergan/inspection.py +1956 -0
  45. hypergan/interval_evaluation.py +294 -0
  46. hypergan/item_data.py +165 -0
  47. hypergan/metric_evaluation.py +425 -0
  48. hypergan/metric_evaluation_worker.py +136 -0
  49. hypergan/metric_examples.py +81 -0
  50. hypergan/metric_plugins.py +339 -0
  51. hypergan/metrics.py +407 -0
  52. hypergan/metrics_reducer/__init__.py +12 -0
  53. hypergan/model_description.py +651 -0
  54. hypergan/model_file.py +1014 -0
  55. hypergan/models/gaussian-grid.toml +48 -0
  56. hypergan/network_config.py +131 -0
  57. hypergan/networks/autoencoder_offset.hndl +1 -0
  58. hypergan/networks/colorization_conv_head.hndl +6 -0
  59. hypergan/networks/colorization_dcgan256.hndl +14 -0
  60. hypergan/networks/colorization_dinov3_multidepth.hndl +20 -0
  61. hypergan/networks/colorization_dinov3_patch_tokens.hndl +19 -0
  62. hypergan/networks/colorization_encoder_features.hndl +19 -0
  63. hypergan/networks/colorization_feature_concat.hndl +2 -0
  64. hypergan/networks/colorization_feature_project.hndl +3 -0
  65. hypergan/networks/colorization_generator16.hndl +69 -0
  66. hypergan/networks/colorization_generator32.hndl +69 -0
  67. hypergan/networks/colorization_joint_score.hndl +2 -0
  68. hypergan/networks/colorization_linear_head.hndl +3 -0
  69. hypergan/networks/colorization_multidepth_projection.hndl +18 -0
  70. hypergan/networks/colorization_multiscale_score.hndl +2 -0
  71. hypergan/networks/colorization_pixel_features.hndl +8 -0
  72. hypergan/networks/colorization_pixel_head.hndl +17 -0
  73. hypergan/networks/colorization_query.hndl +2 -0
  74. hypergan/networks/colorization_random_project.hndl +2 -0
  75. hypergan/networks/colorization_scale_head16.hndl +8 -0
  76. hypergan/networks/colorization_scale_head32.hndl +10 -0
  77. hypergan/networks/colorization_scale_head4.hndl +4 -0
  78. hypergan/networks/colorization_scale_head8.hndl +6 -0
  79. hypergan/networks/image_attention.hndl +15 -0
  80. hypergan/networks/image_critic_score.hndl +6 -0
  81. hypergan/networks/image_encoder.hndl +17 -0
  82. hypergan/networks/image_feature_head.hndl +9 -0
  83. hypergan/networks/image_generator.hndl +13 -0
  84. hypergan/networks/image_pixel.hndl +7 -0
  85. hypergan/networks/image_pixel_block.hndl +16 -0
  86. hypergan/networks/image_resnet_stage1.hndl +7 -0
  87. hypergan/networks/image_resnet_stage2.hndl +2 -0
  88. hypergan/networks/image_resnet_stage3.hndl +2 -0
  89. hypergan/networks/reference.hndl +6 -0
  90. hypergan/numerical_policy.py +95 -0
  91. hypergan/objective_program.py +425 -0
  92. hypergan/observation_io.py +150 -0
  93. hypergan/particlegan_integration.py +134 -0
  94. hypergan/plugin_functions.py +94 -0
  95. hypergan/ports.py +9 -0
  96. hypergan/pretrained_providers.py +104 -0
  97. hypergan/preview_snapshot.py +229 -0
  98. hypergan/preview_worker.py +128 -0
  99. hypergan/previews.py +590 -0
  100. hypergan/provenance.py +187 -0
  101. hypergan/queue.py +819 -0
  102. hypergan/recipe_generator.py +691 -0
  103. hypergan/recipes.py +279 -0
  104. hypergan/registry.py +1337 -0
  105. hypergan/replicated_execution.py +487 -0
  106. hypergan/replicated_worker.py +184 -0
  107. hypergan/run_controller.py +990 -0
  108. hypergan/run_events.py +185 -0
  109. hypergan/run_requests.py +277 -0
  110. hypergan/run_signals.py +42 -0
  111. hypergan/run_state.py +80 -0
  112. hypergan/single_execution.py +225 -0
  113. hypergan/snapshot_renderer.py +71 -0
  114. hypergan/summary.py +336 -0
  115. hypergan/toml_writer.py +125 -0
  116. hypergan/training.py +543 -0
  117. hypergan/web_assets/THIRD_PARTY_LICENSES.txt +289 -0
  118. hypergan/web_assets/__init__.py +25 -0
  119. hypergan/web_assets/app.js +22 -0
  120. hypergan/web_assets/index.html +225 -0
  121. hypergan/web_assets/logo.png +0 -0
  122. hypergan/web_assets/runs.css +75 -0
  123. hypergan/web_assets/runs.js +203 -0
  124. hypergan/web_assets/style.css +871 -0
  125. hypergan/web_assets/view-worker.js +204 -0
  126. hypergan/web_autostart.py +1283 -0
  127. hypergan/web_dev.py +132 -0
  128. hypergan/web_files.py +83 -0
  129. hypergan/web_launch.py +272 -0
  130. hypergan/web_schema.py +165 -0
  131. hypergan/web_server.py +1323 -0
  132. hypergan/web_service.py +651 -0
  133. hypergan/web_session.py +191 -0
  134. hypergan/workspace.py +325 -0
  135. hypergan-2.0.0a1.dist-info/METADATA +328 -0
  136. hypergan-2.0.0a1.dist-info/RECORD +140 -0
  137. hypergan-2.0.0a1.dist-info/WHEEL +5 -0
  138. hypergan-2.0.0a1.dist-info/entry_points.txt +2 -0
  139. hypergan-2.0.0a1.dist-info/licenses/LICENSE +21 -0
  140. hypergan-2.0.0a1.dist-info/top_level.txt +1 -0
hypergan/recipes.py ADDED
@@ -0,0 +1,279 @@
1
+ """Small torch component registry and explicit forward bindings."""
2
+ import importlib
3
+ import torch
4
+ from torch import nn
5
+ from .data import ImageFolder
6
+
7
+
8
+ class MLP(nn.Module):
9
+ """Legacy argument adapter; every layer is compiled by HNDL."""
10
+ def __init__(self, input_dim=None, output_dim=None, hidden=(64, 64), negative_slope=0.2,
11
+ source=None, input_shape=None, output_shape=None, **kwargs):
12
+ super().__init__()
13
+ from .hndl_networks import build_network
14
+ if source is None:
15
+ source = '\n'.join(f'linear({width})\nleaky_relu({negative_slope!r})' for width in hidden)
16
+ source += '\nlinear()'
17
+ self.network = build_network(source, input_shape=input_shape or ('B', input_dim),
18
+ output_shape=output_shape or ('B', output_dim), **kwargs)
19
+
20
+ def forward(self, x, **inputs):
21
+ return self.network(x=x, **inputs) if inputs else self.network(x)
22
+
23
+
24
+ def linear(in_features, out_features, bias=True):
25
+ from .hndl_networks import HNDLNetwork
26
+ return HNDLNetwork(f'linear(bias={bias!r})', ('B', in_features), ('B', out_features))
27
+
28
+
29
+ class Identity(nn.Module):
30
+ """Shape-polymorphic binding adapter for legacy identity components."""
31
+ def forward(self, input):
32
+ # Identity carries no architecture or parameters.
33
+ return input
34
+
35
+
36
+ class GaussianGrid:
37
+ def __init__(self, side=10, noise=0.015):
38
+ if type(side) is not int or side < 1 or noise < 0:
39
+ raise ValueError("gaussian_grid requires positive side and nonnegative noise")
40
+ self.centers = torch.cartesian_prod(torch.linspace(-1, 1, side), torch.linspace(-1, 1, side))
41
+ self.noise = noise
42
+
43
+ def __call__(self, batch_size, *, generator):
44
+ ids = torch.randint(len(self.centers), (batch_size,), generator=generator)
45
+ return {"real": self.centers[ids] + self.noise * torch.randn(batch_size, 2, generator=generator)}
46
+
47
+
48
+ class PairedLinear:
49
+ """Synthetic paired-input fixture; deliberately makes no application claim."""
50
+ def __init__(self, dimensions=2, scale=2.0, offset=0.0):
51
+ self.dimensions, self.scale, self.offset = dimensions, scale, offset
52
+
53
+ def __call__(self, batch_size, *, generator):
54
+ condition = torch.randn(batch_size, self.dimensions, generator=generator)
55
+ return {"condition": condition, "real": condition * self.scale + self.offset}
56
+
57
+
58
+ BUILTINS = {"mlp": MLP, "linear": linear, "identity": Identity, "mse": nn.MSELoss, "l1": nn.L1Loss, "gaussian_grid": GaussianGrid, "paired_linear": PairedLinear, "image_folder": ImageFolder}
59
+
60
+
61
+ def execution_device(value, fallback=True):
62
+ """Resolve an explicit native device; falls back to visible device on unavailable hardware."""
63
+ device = torch.device(value)
64
+ if device.type not in ('cpu', 'cuda'):
65
+ raise ValueError('Native execution requires cpu or cuda[:index]')
66
+ if device.type == 'cuda':
67
+ if not torch.cuda.is_available():
68
+ if fallback:
69
+ from .checkpoint_compatibility import HyperGANHardwareWarning
70
+ import warnings
71
+ warnings.warn(
72
+ f"CUDA device requested ({value!r}) but CUDA is unavailable on this host; falling back to cpu",
73
+ HyperGANHardwareWarning,
74
+ stacklevel=2,
75
+ )
76
+ return torch.device('cpu')
77
+ raise ValueError('CUDA was requested but is unavailable; install a CUDA-enabled PyTorch build and check the NVIDIA driver, or explicitly select cpu')
78
+ index = 0 if device.index is None else device.index
79
+ if not 0 <= index < torch.cuda.device_count():
80
+ if fallback and torch.cuda.device_count() > 0:
81
+ from .checkpoint_compatibility import HyperGANHardwareWarning
82
+ import warnings
83
+ warnings.warn(
84
+ f"CUDA device index {index} is unavailable; falling back to cuda:0",
85
+ HyperGANHardwareWarning,
86
+ stacklevel=2,
87
+ )
88
+ return torch.device('cuda', 0)
89
+ elif fallback:
90
+ from .checkpoint_compatibility import HyperGANHardwareWarning
91
+ import warnings
92
+ warnings.warn(
93
+ f"CUDA device index {index} is unavailable; falling back to cpu",
94
+ HyperGANHardwareWarning,
95
+ stacklevel=2,
96
+ )
97
+ return torch.device('cpu')
98
+ raise ValueError(f'CUDA device index {index} is unavailable')
99
+ device = torch.device('cuda', index)
100
+ return device
101
+
102
+
103
+
104
+ def move_tensors(value, device):
105
+ if isinstance(value, torch.Tensor):
106
+ return value.to(device)
107
+ if isinstance(value, dict):
108
+ return {key: move_tensors(item, device) for key, item in value.items()}
109
+ if isinstance(value, (tuple, list)):
110
+ return type(value)(move_tensors(item, device) for item in value)
111
+ return value
112
+
113
+
114
+ def make_prior(spec, *, device=None, recipe=None):
115
+ from particlegan import GaussianPrior, MoGParticlePrior, ParticlePrior, calibrate_mog_sigma
116
+ args = dict(spec['args'])
117
+ initial_device = 'cpu' if spec.get('initialization_device') == 'cpu' else device
118
+ if initial_device is not None:
119
+ args['device'] = initial_device
120
+ if spec.get('initialization_seed') is not None:
121
+ args['generator'] = torch.Generator(device=initial_device or 'cpu').manual_seed(spec['initialization_seed'])
122
+ if spec['kind'] == 'mog':
123
+ sigma_rel = args.pop('sigma_rel', .025)
124
+ sigma = args.pop('sigma', None)
125
+ if spec.get('fixed_sigma') is not None:
126
+ if sigma is not None:
127
+ raise ValueError('Choose prior.fixed_sigma or prior.args.sigma, not both')
128
+ sigma = spec['fixed_sigma']
129
+ prior = MoGParticlePrior(sigma=0.0 if sigma is None else sigma, **args)
130
+ if sigma is None:
131
+ # Preserve historical relative-noise recipes explicitly. Fixed-noise
132
+ # recipes never search neighbors, including during checkpoint setup.
133
+ value, distance = calibrate_mog_sigma(prior.means(), sigma_rel)
134
+ prior.set_sigma(value)
135
+ prior.d0.copy_(distance)
136
+ prior.sigma_rel = float(sigma_rel)
137
+ else:
138
+ prior = {"particles": ParticlePrior, "gaussian": GaussianPrior}[spec["kind"]](**args)
139
+ prior = prior.to(device) if device is not None else prior
140
+ if recipe:
141
+ # Inference workers must reconstruct persistent recipe-owned buffers
142
+ # before strict loading, including initial prior reference buffers.
143
+ from particlegan import Recipe
144
+ Recipe(**recipe).apply_prior_policy(prior)
145
+ return prior
146
+
147
+
148
+ def construct(spec):
149
+ name = spec["factory"]
150
+ if name == "hndl":
151
+ from .hndl_networks import HNDLNetwork
152
+ return HNDLNetwork(**spec["args"])
153
+ if name in BUILTINS:
154
+ constructor = BUILTINS[name]
155
+ else:
156
+ module, attribute = name.split(":")
157
+ try:
158
+ constructor = importlib.import_module(module)
159
+ for part in attribute.split("."):
160
+ constructor = getattr(constructor, part)
161
+ except (ImportError, AttributeError) as exc:
162
+ raise ValueError(f"Unavailable custom constructor {name}: {exc}") from exc
163
+ try:
164
+ return constructor(**spec.get("args", {}))
165
+ except TypeError as exc:
166
+ raise ValueError(f"Invalid constructor arguments for {name}: {exc}") from exc
167
+
168
+
169
+ def detach(value):
170
+ if isinstance(value, torch.Tensor):
171
+ return value.detach()
172
+ if isinstance(value, dict):
173
+ return {k: detach(v) for k, v in value.items()}
174
+ if isinstance(value, (list, tuple)):
175
+ return type(value)(detach(v) for v in value)
176
+ return value
177
+
178
+
179
+ def generation_output(graph, context, sampling):
180
+ """Select inference output without changing the adversarial generated binding."""
181
+ return graph.resolve(sampling.get('generated', 'generated'), context)
182
+
183
+
184
+ def generation_particle_ids(graph, context, prior_ids, sampling):
185
+ """Resolve explicitly declared routed IDs without reporting unused prior draws."""
186
+ if 'particle_ids' not in sampling:
187
+ return prior_ids
188
+ ids = graph.resolve(sampling['particle_ids'], context)
189
+ if (not isinstance(ids, torch.Tensor) or ids.ndim != 1
190
+ or len(ids) != len(generation_output(graph, context, sampling))
191
+ or ids.dtype not in (torch.int32, torch.int64) or (ids < 0).any()):
192
+ raise ValueError('sampling.particle_ids must produce one nonnegative integer per generated sample')
193
+ return ids
194
+
195
+
196
+ class ComponentGraph(nn.Module):
197
+ """Auxiliary components execute on demand; all trainable auxiliaries belong to G.
198
+
199
+ A discriminator sees detached conditioning. Only its candidate is differentiated
200
+ during a generator update or candidate-only gradient penalty.
201
+ """
202
+ def __init__(self, specs):
203
+ super().__init__()
204
+ self.specs = specs
205
+ modules = {}
206
+ order = [name for name in ('generator', 'discriminator') if name in specs]
207
+ order += sorted(set(specs) - set(order))
208
+ for name in order:
209
+ spec = specs[name]
210
+ if 'reuse' in spec:
211
+ continue
212
+ module = construct(spec)
213
+ if not isinstance(module, nn.Module):
214
+ raise ValueError(f"Component {name} must construct a torch.nn.Module")
215
+ if not spec["trainable"]:
216
+ module.requires_grad_(False)
217
+ module.eval()
218
+ modules[name] = module
219
+ self.models = nn.ModuleDict(modules)
220
+
221
+ def resolve(self, path, context, active=None):
222
+ parts = path.split(".")
223
+ if parts[0] == 'prior' and parts[1] not in context['prior']:
224
+ prior = context.get('_prior')
225
+ if prior is None:
226
+ raise ValueError('This component binding requires the current prior')
227
+ context['prior'][parts[1]] = prior.means() if parts[1] == 'means' else prior.sigma
228
+ if parts[0] == "components" and parts[1] not in context["components"]:
229
+ self.call(parts[1], context, active)
230
+ value = context
231
+ try:
232
+ for part in parts:
233
+ value = value[int(part)] if isinstance(value, (list, tuple)) else value[part]
234
+ except (KeyError, IndexError, TypeError, ValueError) as exc:
235
+ raise ValueError(f"Unavailable I/O binding '{path}'") from exc
236
+ return value
237
+
238
+ def call(self, name, context, active=None):
239
+ active = set() if active is None else active
240
+ if name in active:
241
+ raise ValueError(f"Cyclic component binding at {name}")
242
+ active.add(name)
243
+ try:
244
+ kwargs = {arg: self.resolve(path, context, active) for arg, path in self.specs[name]["inputs"].items()}
245
+ spec = self.specs[name]
246
+ model = self.models[spec.get('reuse', name)]
247
+ flags = [parameter.requires_grad for parameter in model.parameters()]
248
+ if spec.get('freeze_parameters', False):
249
+ model.requires_grad_(False)
250
+ try:
251
+ value = model(**kwargs)
252
+ finally:
253
+ if spec.get('freeze_parameters', False):
254
+ for parameter, flag in zip(model.parameters(), flags):
255
+ parameter.requires_grad_(flag)
256
+ context["components"][name] = value
257
+ return value
258
+ finally:
259
+ active.remove(name)
260
+
261
+ def generate(self, latent, batch, *, prior=None):
262
+ context = {"latent": latent, "batch": batch, "components": {}, 'prior': {}, '_prior': prior}
263
+ context["generated"] = self.call("generator", context)
264
+ return context
265
+
266
+ def critic(self, candidate, context, module=None):
267
+ # Auxiliary conditioning runs with detached inputs and contributes no D loss
268
+ # gradients to G/encoder parameters. The candidate path remains attached.
269
+ # ``module`` replaces the discriminator (the penalty passes its EMA).
270
+ fixed = detach(context)
271
+ fixed["candidate"] = candidate
272
+ kwargs = {}
273
+ for arg, path in self.specs["discriminator"]["inputs"].items():
274
+ value = self.resolve(path, fixed)
275
+ kwargs[arg] = value if path == "candidate" else detach(value)
276
+ return (self.models["discriminator"] if module is None else module)(**kwargs)
277
+
278
+ def generator_parameters(self):
279
+ return [p for name, model in self.models.items() if name != "discriminator" for p in model.parameters() if p.requires_grad]