morphml 1.0.0__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.

Potentially problematic release.


This version of morphml might be problematic. Click here for more details.

Files changed (158) hide show
  1. morphml/__init__.py +14 -0
  2. morphml/api/__init__.py +26 -0
  3. morphml/api/app.py +326 -0
  4. morphml/api/auth.py +193 -0
  5. morphml/api/client.py +338 -0
  6. morphml/api/models.py +132 -0
  7. morphml/api/rate_limit.py +192 -0
  8. morphml/benchmarking/__init__.py +36 -0
  9. morphml/benchmarking/comparison.py +430 -0
  10. morphml/benchmarks/__init__.py +56 -0
  11. morphml/benchmarks/comparator.py +409 -0
  12. morphml/benchmarks/datasets.py +280 -0
  13. morphml/benchmarks/metrics.py +199 -0
  14. morphml/benchmarks/openml_suite.py +201 -0
  15. morphml/benchmarks/problems.py +289 -0
  16. morphml/benchmarks/suite.py +318 -0
  17. morphml/cli/__init__.py +5 -0
  18. morphml/cli/commands/experiment.py +329 -0
  19. morphml/cli/main.py +457 -0
  20. morphml/cli/quickstart.py +312 -0
  21. morphml/config.py +278 -0
  22. morphml/constraints/__init__.py +19 -0
  23. morphml/constraints/handler.py +205 -0
  24. morphml/constraints/predicates.py +285 -0
  25. morphml/core/__init__.py +3 -0
  26. morphml/core/crossover.py +449 -0
  27. morphml/core/dsl/README.md +359 -0
  28. morphml/core/dsl/__init__.py +72 -0
  29. morphml/core/dsl/ast_nodes.py +364 -0
  30. morphml/core/dsl/compiler.py +318 -0
  31. morphml/core/dsl/layers.py +368 -0
  32. morphml/core/dsl/lexer.py +336 -0
  33. morphml/core/dsl/parser.py +455 -0
  34. morphml/core/dsl/search_space.py +386 -0
  35. morphml/core/dsl/syntax.py +199 -0
  36. morphml/core/dsl/type_system.py +361 -0
  37. morphml/core/dsl/validator.py +386 -0
  38. morphml/core/graph/__init__.py +40 -0
  39. morphml/core/graph/edge.py +124 -0
  40. morphml/core/graph/graph.py +507 -0
  41. morphml/core/graph/mutations.py +409 -0
  42. morphml/core/graph/node.py +196 -0
  43. morphml/core/graph/serialization.py +361 -0
  44. morphml/core/graph/visualization.py +431 -0
  45. morphml/core/objectives/__init__.py +20 -0
  46. morphml/core/search/__init__.py +33 -0
  47. morphml/core/search/individual.py +252 -0
  48. morphml/core/search/parameters.py +453 -0
  49. morphml/core/search/population.py +375 -0
  50. morphml/core/search/search_engine.py +340 -0
  51. morphml/distributed/__init__.py +76 -0
  52. morphml/distributed/fault_tolerance.py +497 -0
  53. morphml/distributed/health_monitor.py +348 -0
  54. morphml/distributed/master.py +709 -0
  55. morphml/distributed/proto/README.md +224 -0
  56. morphml/distributed/proto/__init__.py +74 -0
  57. morphml/distributed/proto/worker.proto +170 -0
  58. morphml/distributed/proto/worker_pb2.py +79 -0
  59. morphml/distributed/proto/worker_pb2_grpc.py +423 -0
  60. morphml/distributed/resource_manager.py +416 -0
  61. morphml/distributed/scheduler.py +567 -0
  62. morphml/distributed/storage/__init__.py +33 -0
  63. morphml/distributed/storage/artifacts.py +381 -0
  64. morphml/distributed/storage/cache.py +366 -0
  65. morphml/distributed/storage/checkpointing.py +329 -0
  66. morphml/distributed/storage/database.py +459 -0
  67. morphml/distributed/worker.py +549 -0
  68. morphml/evaluation/__init__.py +5 -0
  69. morphml/evaluation/heuristic.py +237 -0
  70. morphml/exceptions.py +55 -0
  71. morphml/execution/__init__.py +5 -0
  72. morphml/execution/local_executor.py +350 -0
  73. morphml/integrations/__init__.py +28 -0
  74. morphml/integrations/jax_adapter.py +206 -0
  75. morphml/integrations/pytorch_adapter.py +530 -0
  76. morphml/integrations/sklearn_adapter.py +206 -0
  77. morphml/integrations/tensorflow_adapter.py +230 -0
  78. morphml/logging_config.py +93 -0
  79. morphml/meta_learning/__init__.py +66 -0
  80. morphml/meta_learning/architecture_similarity.py +277 -0
  81. morphml/meta_learning/experiment_database.py +240 -0
  82. morphml/meta_learning/knowledge_base/__init__.py +19 -0
  83. morphml/meta_learning/knowledge_base/embedder.py +179 -0
  84. morphml/meta_learning/knowledge_base/knowledge_base.py +313 -0
  85. morphml/meta_learning/knowledge_base/meta_features.py +265 -0
  86. morphml/meta_learning/knowledge_base/vector_store.py +271 -0
  87. morphml/meta_learning/predictors/__init__.py +27 -0
  88. morphml/meta_learning/predictors/ensemble.py +221 -0
  89. morphml/meta_learning/predictors/gnn_predictor.py +552 -0
  90. morphml/meta_learning/predictors/learning_curve.py +231 -0
  91. morphml/meta_learning/predictors/proxy_metrics.py +261 -0
  92. morphml/meta_learning/strategy_evolution/__init__.py +27 -0
  93. morphml/meta_learning/strategy_evolution/adaptive_optimizer.py +226 -0
  94. morphml/meta_learning/strategy_evolution/bandit.py +276 -0
  95. morphml/meta_learning/strategy_evolution/portfolio.py +230 -0
  96. morphml/meta_learning/transfer.py +581 -0
  97. morphml/meta_learning/warm_start.py +286 -0
  98. morphml/optimizers/__init__.py +74 -0
  99. morphml/optimizers/adaptive_operators.py +399 -0
  100. morphml/optimizers/bayesian/__init__.py +52 -0
  101. morphml/optimizers/bayesian/acquisition.py +387 -0
  102. morphml/optimizers/bayesian/base.py +319 -0
  103. morphml/optimizers/bayesian/gaussian_process.py +635 -0
  104. morphml/optimizers/bayesian/smac.py +534 -0
  105. morphml/optimizers/bayesian/tpe.py +411 -0
  106. morphml/optimizers/differential_evolution.py +220 -0
  107. morphml/optimizers/evolutionary/__init__.py +61 -0
  108. morphml/optimizers/evolutionary/cma_es.py +416 -0
  109. morphml/optimizers/evolutionary/differential_evolution.py +556 -0
  110. morphml/optimizers/evolutionary/encoding.py +426 -0
  111. morphml/optimizers/evolutionary/particle_swarm.py +449 -0
  112. morphml/optimizers/genetic_algorithm.py +486 -0
  113. morphml/optimizers/gradient_based/__init__.py +22 -0
  114. morphml/optimizers/gradient_based/darts.py +550 -0
  115. morphml/optimizers/gradient_based/enas.py +585 -0
  116. morphml/optimizers/gradient_based/operations.py +474 -0
  117. morphml/optimizers/gradient_based/utils.py +601 -0
  118. morphml/optimizers/hill_climbing.py +169 -0
  119. morphml/optimizers/multi_objective/__init__.py +56 -0
  120. morphml/optimizers/multi_objective/indicators.py +504 -0
  121. morphml/optimizers/multi_objective/nsga2.py +647 -0
  122. morphml/optimizers/multi_objective/visualization.py +427 -0
  123. morphml/optimizers/nsga2.py +308 -0
  124. morphml/optimizers/random_search.py +172 -0
  125. morphml/optimizers/simulated_annealing.py +181 -0
  126. morphml/plugins/__init__.py +35 -0
  127. morphml/plugins/custom_evaluator_example.py +81 -0
  128. morphml/plugins/custom_optimizer_example.py +63 -0
  129. morphml/plugins/plugin_system.py +454 -0
  130. morphml/reports/__init__.py +30 -0
  131. morphml/reports/generator.py +362 -0
  132. morphml/tracking/__init__.py +7 -0
  133. morphml/tracking/experiment.py +309 -0
  134. morphml/tracking/logger.py +301 -0
  135. morphml/tracking/reporter.py +357 -0
  136. morphml/utils/__init__.py +6 -0
  137. morphml/utils/checkpoint.py +189 -0
  138. morphml/utils/comparison.py +390 -0
  139. morphml/utils/export.py +407 -0
  140. morphml/utils/progress.py +392 -0
  141. morphml/utils/validation.py +392 -0
  142. morphml/version.py +7 -0
  143. morphml/visualization/__init__.py +50 -0
  144. morphml/visualization/analytics.py +423 -0
  145. morphml/visualization/architecture_diagrams.py +353 -0
  146. morphml/visualization/architecture_plot.py +223 -0
  147. morphml/visualization/convergence_plot.py +174 -0
  148. morphml/visualization/crossover_viz.py +386 -0
  149. morphml/visualization/graph_viz.py +338 -0
  150. morphml/visualization/pareto_plot.py +149 -0
  151. morphml/visualization/plotly_dashboards.py +422 -0
  152. morphml/visualization/population.py +309 -0
  153. morphml/visualization/progress.py +260 -0
  154. morphml-1.0.0.dist-info/METADATA +434 -0
  155. morphml-1.0.0.dist-info/RECORD +158 -0
  156. morphml-1.0.0.dist-info/WHEEL +4 -0
  157. morphml-1.0.0.dist-info/entry_points.txt +3 -0
  158. morphml-1.0.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,286 @@
1
+ """Warm-starting from past experiments.
2
+
3
+ Accelerates search by initializing from similar past tasks.
4
+
5
+ Author: Eshan Roy <eshanized@proton.me>
6
+ Organization: TONMOY INFRASTRUCTURE & VISION
7
+ """
8
+
9
+ import random
10
+ from typing import Any, Dict, List, Optional, Tuple
11
+
12
+ import numpy as np
13
+
14
+ from morphml.core.dsl import SearchSpace
15
+ from morphml.core.graph import ModelGraph
16
+ from morphml.logging_config import get_logger
17
+ from morphml.meta_learning.architecture_similarity import (
18
+ ArchitectureSimilarity,
19
+ compute_task_similarity,
20
+ )
21
+ from morphml.meta_learning.experiment_database import ExperimentDatabase, TaskMetadata
22
+
23
+ logger = get_logger(__name__)
24
+
25
+
26
+ class WarmStarter:
27
+ """
28
+ Initialize search from past successful experiments.
29
+
30
+ Strategies:
31
+ 1. **Similarity-based**: Find similar past tasks
32
+ 2. **Performance-based**: Transfer top-k architectures
33
+ 3. **Diversity-aware**: Ensure population diversity
34
+
35
+ Args:
36
+ knowledge_base: Experiment database
37
+ config: Configuration dict
38
+ - transfer_ratio: Fraction of population from transfer (default: 0.5)
39
+ - min_similarity: Minimum task similarity for transfer (default: 0.6)
40
+ - similarity_method: Task similarity method (default: 'meta_features')
41
+ - diversity_weight: Weight for diversity (default: 0.3)
42
+
43
+ Example:
44
+ >>> kb = ExperimentDatabase(db_manager)
45
+ >>> warm_starter = WarmStarter(kb, {'transfer_ratio': 0.5})
46
+ >>>
47
+ >>> current_task = TaskMetadata(
48
+ ... task_id='new_task',
49
+ ... dataset_name='CIFAR-100',
50
+ ... num_samples=50000,
51
+ ... num_classes=100,
52
+ ... input_size=(3, 32, 32)
53
+ ... )
54
+ >>>
55
+ >>> population = warm_starter.generate_initial_population(
56
+ ... current_task,
57
+ ... population_size=50,
58
+ ... search_space=space
59
+ ... )
60
+ """
61
+
62
+ def __init__(self, knowledge_base: ExperimentDatabase, config: Optional[Dict[str, Any]] = None):
63
+ """Initialize warm-starter."""
64
+ self.kb = knowledge_base
65
+ self.config = config or {}
66
+
67
+ self.transfer_ratio = self.config.get("transfer_ratio", 0.5)
68
+ self.min_similarity = self.config.get("min_similarity", 0.6)
69
+ self.similarity_method = self.config.get("similarity_method", "meta_features")
70
+ self.diversity_weight = self.config.get("diversity_weight", 0.3)
71
+
72
+ logger.info(
73
+ f"Initialized WarmStarter (transfer_ratio={self.transfer_ratio}, "
74
+ f"min_similarity={self.min_similarity})"
75
+ )
76
+
77
+ def generate_initial_population(
78
+ self,
79
+ current_task: TaskMetadata,
80
+ population_size: int,
81
+ search_space: SearchSpace,
82
+ ) -> List[ModelGraph]:
83
+ """
84
+ Generate initial population with warm-starting.
85
+
86
+ Combines:
87
+ - Transferred architectures from similar tasks
88
+ - Random architectures from search space
89
+
90
+ Args:
91
+ current_task: Current task metadata
92
+ population_size: Desired population size
93
+ search_space: Search space definition
94
+
95
+ Returns:
96
+ Initial population of architectures
97
+ """
98
+ logger.info(
99
+ f"Generating initial population for task {current_task.task_id} "
100
+ f"(size={population_size})"
101
+ )
102
+
103
+ # Find similar past tasks
104
+ similar_tasks = self._find_similar_tasks(current_task)
105
+
106
+ if not similar_tasks:
107
+ logger.info("No similar tasks found, using pure random initialization")
108
+ return [search_space.sample() for _ in range(population_size)]
109
+
110
+ # Determine transfer count
111
+ num_transfer = int(population_size * self.transfer_ratio)
112
+ num_random = population_size - num_transfer
113
+
114
+ logger.info(
115
+ f"Found {len(similar_tasks)} similar tasks, "
116
+ f"transferring {num_transfer} architectures"
117
+ )
118
+
119
+ # Get best architectures from similar tasks
120
+ transferred = self._transfer_architectures(similar_tasks, num_transfer)
121
+
122
+ # Fill rest with random
123
+ random_archs = [search_space.sample() for _ in range(num_random)]
124
+
125
+ # Combine
126
+ population = transferred + random_archs
127
+
128
+ # Ensure diversity
129
+ if self.diversity_weight > 0:
130
+ population = self._ensure_diversity(population, search_space)
131
+
132
+ logger.info(
133
+ f"Generated population: {len(transferred)} transferred, " f"{len(random_archs)} random"
134
+ )
135
+
136
+ return population
137
+
138
+ def _find_similar_tasks(
139
+ self, current_task: TaskMetadata, top_k: int = 5
140
+ ) -> List[Tuple[TaskMetadata, float]]:
141
+ """
142
+ Find similar tasks from knowledge base.
143
+
144
+ Args:
145
+ current_task: Current task
146
+ top_k: Number of similar tasks to return
147
+
148
+ Returns:
149
+ List of (task, similarity_score) tuples
150
+ """
151
+ all_tasks = self.kb.get_all_tasks()
152
+
153
+ if not all_tasks:
154
+ return []
155
+
156
+ # Compute similarities
157
+ similarities = []
158
+ for task in all_tasks:
159
+ # Skip same task
160
+ if task.task_id == current_task.task_id:
161
+ continue
162
+
163
+ sim = compute_task_similarity(current_task, task, method=self.similarity_method)
164
+
165
+ if sim >= self.min_similarity:
166
+ similarities.append((task, sim))
167
+
168
+ # Sort by similarity
169
+ similarities.sort(key=lambda x: x[1], reverse=True)
170
+
171
+ return similarities[:top_k]
172
+
173
+ def _transfer_architectures(
174
+ self,
175
+ similar_tasks: List[Tuple[TaskMetadata, float]],
176
+ num_transfer: int,
177
+ ) -> List[ModelGraph]:
178
+ """
179
+ Transfer best architectures from similar tasks.
180
+
181
+ Architectures are weighted by task similarity.
182
+
183
+ Args:
184
+ similar_tasks: List of (task, similarity) tuples
185
+ num_transfer: Number of architectures to transfer
186
+
187
+ Returns:
188
+ List of transferred architectures
189
+ """
190
+ transferred = []
191
+
192
+ # Calculate weights
193
+ total_similarity = sum(sim for _, sim in similar_tasks)
194
+
195
+ for task, similarity in similar_tasks:
196
+ # Number to transfer from this task (weighted by similarity)
197
+ weight = similarity / total_similarity
198
+ num_from_task = max(1, int(num_transfer * weight))
199
+
200
+ # Get top architectures from this task
201
+ top_archs = self.kb.get_top_architectures(task.task_id, top_k=20)
202
+
203
+ if not top_archs:
204
+ continue
205
+
206
+ # Sample architectures
207
+ num_sample = min(num_from_task, len(top_archs))
208
+ sampled = random.sample(top_archs, num_sample)
209
+
210
+ transferred.extend(sampled)
211
+
212
+ logger.debug(
213
+ f"Transferred {num_sample} architectures from {task.task_id} "
214
+ f"(similarity={similarity:.3f})"
215
+ )
216
+
217
+ if len(transferred) >= num_transfer:
218
+ break
219
+
220
+ # Trim to exact size
221
+ return transferred[:num_transfer]
222
+
223
+ def _ensure_diversity(
224
+ self, population: List[ModelGraph], search_space: SearchSpace
225
+ ) -> List[ModelGraph]:
226
+ """
227
+ Ensure population diversity.
228
+
229
+ Replaces very similar architectures with random ones.
230
+
231
+ Args:
232
+ population: Current population
233
+ search_space: Search space for sampling replacements
234
+
235
+ Returns:
236
+ Diversified population
237
+ """
238
+ if len(population) < 2:
239
+ return population
240
+
241
+ # Compute pairwise similarities
242
+ n = len(population)
243
+ similarities = np.zeros((n, n))
244
+
245
+ for i in range(n):
246
+ for j in range(i + 1, n):
247
+ sim = ArchitectureSimilarity.compute(
248
+ population[i], population[j], method="operation_distribution"
249
+ )
250
+ similarities[i, j] = sim
251
+ similarities[j, i] = sim
252
+
253
+ # Find very similar pairs (threshold = 0.95)
254
+ threshold = 0.95
255
+ replaced = set()
256
+
257
+ for i in range(n):
258
+ if i in replaced:
259
+ continue
260
+
261
+ for j in range(i + 1, n):
262
+ if j in replaced:
263
+ continue
264
+
265
+ if similarities[i, j] > threshold:
266
+ # Replace j with random
267
+ population[j] = search_space.sample()
268
+ replaced.add(j)
269
+
270
+ if replaced:
271
+ logger.info(f"Replaced {len(replaced)} similar architectures for diversity")
272
+
273
+ return population
274
+
275
+ def get_statistics(self) -> Dict[str, Any]:
276
+ """Get warm-starting statistics."""
277
+ kb_stats = self.kb.get_statistics()
278
+
279
+ return {
280
+ "knowledge_base": kb_stats,
281
+ "config": {
282
+ "transfer_ratio": self.transfer_ratio,
283
+ "min_similarity": self.min_similarity,
284
+ "similarity_method": self.similarity_method,
285
+ },
286
+ }
@@ -0,0 +1,74 @@
1
+ """Optimization algorithms for neural architecture search.
2
+
3
+ Phase 1 (Evolutionary):
4
+ - GeneticAlgorithm, RandomSearch, HillClimbing, SimulatedAnnealing, DifferentialEvolution
5
+
6
+ Phase 2 (Advanced):
7
+ - Bayesian: GaussianProcessOptimizer, TPEOptimizer, SMACOptimizer
8
+ - Gradient-based: DARTS, ENAS
9
+ - Multi-objective: NSGA2Optimizer
10
+ - Advanced Evolutionary: CMAESOptimizer, ParticleSwarmOptimizer, DifferentialEvolutionOptimizer
11
+ """
12
+
13
+ # Phase 1: Core evolutionary algorithms
14
+ # Phase 2: Bayesian Optimization
15
+ from morphml.optimizers.bayesian import (
16
+ GaussianProcessOptimizer,
17
+ SMACOptimizer,
18
+ TPEOptimizer,
19
+ )
20
+ from morphml.optimizers.differential_evolution import DifferentialEvolution
21
+ from morphml.optimizers.genetic_algorithm import GeneticAlgorithm
22
+ from morphml.optimizers.hill_climbing import HillClimbing
23
+ from morphml.optimizers.random_search import RandomSearch
24
+ from morphml.optimizers.simulated_annealing import SimulatedAnnealing
25
+
26
+ # Phase 2: Gradient-based NAS (requires PyTorch)
27
+ try:
28
+ from morphml.optimizers.gradient_based import DARTS, ENAS
29
+
30
+ _GRADIENT_BASED_AVAILABLE = True
31
+ except ImportError:
32
+ DARTS = None # type: ignore[misc]
33
+ ENAS = None # type: ignore[misc]
34
+ _GRADIENT_BASED_AVAILABLE = False
35
+
36
+ # Phase 2: Multi-objective (canonical NSGA-II from multi_objective module)
37
+ # Phase 2: Advanced Evolutionary
38
+ from morphml.optimizers.evolutionary import (
39
+ CMAESOptimizer,
40
+ DifferentialEvolutionOptimizer,
41
+ ParticleSwarmOptimizer,
42
+ )
43
+ from morphml.optimizers.multi_objective import NSGA2Optimizer
44
+
45
+ # Legacy alias for backward compatibility
46
+ from morphml.optimizers.nsga2 import NSGA2 as NSGA2Legacy
47
+
48
+ # Primary exports
49
+ __all__ = [
50
+ # Phase 1
51
+ "GeneticAlgorithm",
52
+ "RandomSearch",
53
+ "HillClimbing",
54
+ "SimulatedAnnealing",
55
+ "DifferentialEvolution",
56
+ # Phase 2: Bayesian
57
+ "GaussianProcessOptimizer",
58
+ "TPEOptimizer",
59
+ "SMACOptimizer",
60
+ # Phase 2: Gradient-based
61
+ "DARTS",
62
+ "ENAS",
63
+ # Phase 2: Multi-objective
64
+ "NSGA2Optimizer",
65
+ # Phase 2: Advanced Evolutionary
66
+ "CMAESOptimizer",
67
+ "ParticleSwarmOptimizer",
68
+ "DifferentialEvolutionOptimizer",
69
+ # Legacy
70
+ "NSGA2Legacy",
71
+ ]
72
+
73
+ # Convenience alias: NSGA2 points to canonical multi-objective implementation
74
+ NSGA2 = NSGA2Optimizer