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.
- morphml/__init__.py +14 -0
- morphml/api/__init__.py +26 -0
- morphml/api/app.py +326 -0
- morphml/api/auth.py +193 -0
- morphml/api/client.py +338 -0
- morphml/api/models.py +132 -0
- morphml/api/rate_limit.py +192 -0
- morphml/benchmarking/__init__.py +36 -0
- morphml/benchmarking/comparison.py +430 -0
- morphml/benchmarks/__init__.py +56 -0
- morphml/benchmarks/comparator.py +409 -0
- morphml/benchmarks/datasets.py +280 -0
- morphml/benchmarks/metrics.py +199 -0
- morphml/benchmarks/openml_suite.py +201 -0
- morphml/benchmarks/problems.py +289 -0
- morphml/benchmarks/suite.py +318 -0
- morphml/cli/__init__.py +5 -0
- morphml/cli/commands/experiment.py +329 -0
- morphml/cli/main.py +457 -0
- morphml/cli/quickstart.py +312 -0
- morphml/config.py +278 -0
- morphml/constraints/__init__.py +19 -0
- morphml/constraints/handler.py +205 -0
- morphml/constraints/predicates.py +285 -0
- morphml/core/__init__.py +3 -0
- morphml/core/crossover.py +449 -0
- morphml/core/dsl/README.md +359 -0
- morphml/core/dsl/__init__.py +72 -0
- morphml/core/dsl/ast_nodes.py +364 -0
- morphml/core/dsl/compiler.py +318 -0
- morphml/core/dsl/layers.py +368 -0
- morphml/core/dsl/lexer.py +336 -0
- morphml/core/dsl/parser.py +455 -0
- morphml/core/dsl/search_space.py +386 -0
- morphml/core/dsl/syntax.py +199 -0
- morphml/core/dsl/type_system.py +361 -0
- morphml/core/dsl/validator.py +386 -0
- morphml/core/graph/__init__.py +40 -0
- morphml/core/graph/edge.py +124 -0
- morphml/core/graph/graph.py +507 -0
- morphml/core/graph/mutations.py +409 -0
- morphml/core/graph/node.py +196 -0
- morphml/core/graph/serialization.py +361 -0
- morphml/core/graph/visualization.py +431 -0
- morphml/core/objectives/__init__.py +20 -0
- morphml/core/search/__init__.py +33 -0
- morphml/core/search/individual.py +252 -0
- morphml/core/search/parameters.py +453 -0
- morphml/core/search/population.py +375 -0
- morphml/core/search/search_engine.py +340 -0
- morphml/distributed/__init__.py +76 -0
- morphml/distributed/fault_tolerance.py +497 -0
- morphml/distributed/health_monitor.py +348 -0
- morphml/distributed/master.py +709 -0
- morphml/distributed/proto/README.md +224 -0
- morphml/distributed/proto/__init__.py +74 -0
- morphml/distributed/proto/worker.proto +170 -0
- morphml/distributed/proto/worker_pb2.py +79 -0
- morphml/distributed/proto/worker_pb2_grpc.py +423 -0
- morphml/distributed/resource_manager.py +416 -0
- morphml/distributed/scheduler.py +567 -0
- morphml/distributed/storage/__init__.py +33 -0
- morphml/distributed/storage/artifacts.py +381 -0
- morphml/distributed/storage/cache.py +366 -0
- morphml/distributed/storage/checkpointing.py +329 -0
- morphml/distributed/storage/database.py +459 -0
- morphml/distributed/worker.py +549 -0
- morphml/evaluation/__init__.py +5 -0
- morphml/evaluation/heuristic.py +237 -0
- morphml/exceptions.py +55 -0
- morphml/execution/__init__.py +5 -0
- morphml/execution/local_executor.py +350 -0
- morphml/integrations/__init__.py +28 -0
- morphml/integrations/jax_adapter.py +206 -0
- morphml/integrations/pytorch_adapter.py +530 -0
- morphml/integrations/sklearn_adapter.py +206 -0
- morphml/integrations/tensorflow_adapter.py +230 -0
- morphml/logging_config.py +93 -0
- morphml/meta_learning/__init__.py +66 -0
- morphml/meta_learning/architecture_similarity.py +277 -0
- morphml/meta_learning/experiment_database.py +240 -0
- morphml/meta_learning/knowledge_base/__init__.py +19 -0
- morphml/meta_learning/knowledge_base/embedder.py +179 -0
- morphml/meta_learning/knowledge_base/knowledge_base.py +313 -0
- morphml/meta_learning/knowledge_base/meta_features.py +265 -0
- morphml/meta_learning/knowledge_base/vector_store.py +271 -0
- morphml/meta_learning/predictors/__init__.py +27 -0
- morphml/meta_learning/predictors/ensemble.py +221 -0
- morphml/meta_learning/predictors/gnn_predictor.py +552 -0
- morphml/meta_learning/predictors/learning_curve.py +231 -0
- morphml/meta_learning/predictors/proxy_metrics.py +261 -0
- morphml/meta_learning/strategy_evolution/__init__.py +27 -0
- morphml/meta_learning/strategy_evolution/adaptive_optimizer.py +226 -0
- morphml/meta_learning/strategy_evolution/bandit.py +276 -0
- morphml/meta_learning/strategy_evolution/portfolio.py +230 -0
- morphml/meta_learning/transfer.py +581 -0
- morphml/meta_learning/warm_start.py +286 -0
- morphml/optimizers/__init__.py +74 -0
- morphml/optimizers/adaptive_operators.py +399 -0
- morphml/optimizers/bayesian/__init__.py +52 -0
- morphml/optimizers/bayesian/acquisition.py +387 -0
- morphml/optimizers/bayesian/base.py +319 -0
- morphml/optimizers/bayesian/gaussian_process.py +635 -0
- morphml/optimizers/bayesian/smac.py +534 -0
- morphml/optimizers/bayesian/tpe.py +411 -0
- morphml/optimizers/differential_evolution.py +220 -0
- morphml/optimizers/evolutionary/__init__.py +61 -0
- morphml/optimizers/evolutionary/cma_es.py +416 -0
- morphml/optimizers/evolutionary/differential_evolution.py +556 -0
- morphml/optimizers/evolutionary/encoding.py +426 -0
- morphml/optimizers/evolutionary/particle_swarm.py +449 -0
- morphml/optimizers/genetic_algorithm.py +486 -0
- morphml/optimizers/gradient_based/__init__.py +22 -0
- morphml/optimizers/gradient_based/darts.py +550 -0
- morphml/optimizers/gradient_based/enas.py +585 -0
- morphml/optimizers/gradient_based/operations.py +474 -0
- morphml/optimizers/gradient_based/utils.py +601 -0
- morphml/optimizers/hill_climbing.py +169 -0
- morphml/optimizers/multi_objective/__init__.py +56 -0
- morphml/optimizers/multi_objective/indicators.py +504 -0
- morphml/optimizers/multi_objective/nsga2.py +647 -0
- morphml/optimizers/multi_objective/visualization.py +427 -0
- morphml/optimizers/nsga2.py +308 -0
- morphml/optimizers/random_search.py +172 -0
- morphml/optimizers/simulated_annealing.py +181 -0
- morphml/plugins/__init__.py +35 -0
- morphml/plugins/custom_evaluator_example.py +81 -0
- morphml/plugins/custom_optimizer_example.py +63 -0
- morphml/plugins/plugin_system.py +454 -0
- morphml/reports/__init__.py +30 -0
- morphml/reports/generator.py +362 -0
- morphml/tracking/__init__.py +7 -0
- morphml/tracking/experiment.py +309 -0
- morphml/tracking/logger.py +301 -0
- morphml/tracking/reporter.py +357 -0
- morphml/utils/__init__.py +6 -0
- morphml/utils/checkpoint.py +189 -0
- morphml/utils/comparison.py +390 -0
- morphml/utils/export.py +407 -0
- morphml/utils/progress.py +392 -0
- morphml/utils/validation.py +392 -0
- morphml/version.py +7 -0
- morphml/visualization/__init__.py +50 -0
- morphml/visualization/analytics.py +423 -0
- morphml/visualization/architecture_diagrams.py +353 -0
- morphml/visualization/architecture_plot.py +223 -0
- morphml/visualization/convergence_plot.py +174 -0
- morphml/visualization/crossover_viz.py +386 -0
- morphml/visualization/graph_viz.py +338 -0
- morphml/visualization/pareto_plot.py +149 -0
- morphml/visualization/plotly_dashboards.py +422 -0
- morphml/visualization/population.py +309 -0
- morphml/visualization/progress.py +260 -0
- morphml-1.0.0.dist-info/METADATA +434 -0
- morphml-1.0.0.dist-info/RECORD +158 -0
- morphml-1.0.0.dist-info/WHEEL +4 -0
- morphml-1.0.0.dist-info/entry_points.txt +3 -0
- morphml-1.0.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
"""Ensemble predictor combining multiple methods.
|
|
2
|
+
|
|
3
|
+
Author: Eshan Roy <eshanized@proton.me>
|
|
4
|
+
Organization: TONMOY INFRASTRUCTURE & VISION
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any, Dict, List, Optional
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
from morphml.core.graph import ModelGraph
|
|
12
|
+
from morphml.logging_config import get_logger
|
|
13
|
+
|
|
14
|
+
logger = get_logger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class EnsemblePredictor:
|
|
18
|
+
"""
|
|
19
|
+
Ensemble of multiple performance predictors.
|
|
20
|
+
|
|
21
|
+
Combines predictions from:
|
|
22
|
+
- Proxy metric predictor
|
|
23
|
+
- Learning curve predictor
|
|
24
|
+
- GNN predictor (if available)
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
predictors: List of predictor instances
|
|
28
|
+
weights: Weights for each predictor (default: equal)
|
|
29
|
+
aggregation: How to combine ('weighted_average', 'max', 'min')
|
|
30
|
+
|
|
31
|
+
Example:
|
|
32
|
+
>>> from morphml.meta_learning.predictors import (
|
|
33
|
+
... ProxyMetricPredictor,
|
|
34
|
+
... EnsemblePredictor
|
|
35
|
+
... )
|
|
36
|
+
>>>
|
|
37
|
+
>>> # Create predictors
|
|
38
|
+
>>> proxy_pred = ProxyMetricPredictor()
|
|
39
|
+
>>> proxy_pred.train(training_data)
|
|
40
|
+
>>>
|
|
41
|
+
>>> # Ensemble
|
|
42
|
+
>>> ensemble = EnsemblePredictor(
|
|
43
|
+
... predictors=[proxy_pred],
|
|
44
|
+
... weights=[1.0]
|
|
45
|
+
... )
|
|
46
|
+
>>>
|
|
47
|
+
>>> prediction = ensemble.predict(new_graph)
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
def __init__(
|
|
51
|
+
self,
|
|
52
|
+
predictors: List[Any],
|
|
53
|
+
weights: Optional[List[float]] = None,
|
|
54
|
+
aggregation: str = "weighted_average",
|
|
55
|
+
):
|
|
56
|
+
"""Initialize ensemble predictor."""
|
|
57
|
+
self.predictors = predictors
|
|
58
|
+
|
|
59
|
+
# Default: equal weights
|
|
60
|
+
if weights is None:
|
|
61
|
+
weights = [1.0 / len(predictors)] * len(predictors)
|
|
62
|
+
|
|
63
|
+
# Normalize weights
|
|
64
|
+
total = sum(weights)
|
|
65
|
+
self.weights = [w / total for w in weights]
|
|
66
|
+
|
|
67
|
+
self.aggregation = aggregation
|
|
68
|
+
|
|
69
|
+
logger.info(
|
|
70
|
+
f"Initialized EnsemblePredictor with {len(predictors)} predictors "
|
|
71
|
+
f"(aggregation={aggregation})"
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
def predict(self, graph: ModelGraph, **predictor_kwargs) -> float:
|
|
75
|
+
"""
|
|
76
|
+
Predict using ensemble.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
graph: Architecture to evaluate
|
|
80
|
+
**predictor_kwargs: Additional kwargs for specific predictors
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
Ensemble prediction
|
|
84
|
+
"""
|
|
85
|
+
predictions = []
|
|
86
|
+
|
|
87
|
+
for i, predictor in enumerate(self.predictors):
|
|
88
|
+
try:
|
|
89
|
+
# Get prediction
|
|
90
|
+
if hasattr(predictor, "predict"):
|
|
91
|
+
pred = predictor.predict(graph, **predictor_kwargs)
|
|
92
|
+
predictions.append(pred)
|
|
93
|
+
else:
|
|
94
|
+
logger.warning(f"Predictor {i} has no predict method, skipping")
|
|
95
|
+
except Exception as e:
|
|
96
|
+
logger.warning(f"Predictor {i} failed: {e}")
|
|
97
|
+
|
|
98
|
+
if not predictions:
|
|
99
|
+
logger.warning("No valid predictions, returning 0.5")
|
|
100
|
+
return 0.5
|
|
101
|
+
|
|
102
|
+
# Aggregate
|
|
103
|
+
if self.aggregation == "weighted_average":
|
|
104
|
+
# Use weights corresponding to valid predictions
|
|
105
|
+
valid_weights = self.weights[: len(predictions)]
|
|
106
|
+
total_weight = sum(valid_weights)
|
|
107
|
+
valid_weights = [w / total_weight for w in valid_weights]
|
|
108
|
+
|
|
109
|
+
result = sum(w * p for w, p in zip(valid_weights, predictions))
|
|
110
|
+
|
|
111
|
+
elif self.aggregation == "max":
|
|
112
|
+
result = max(predictions)
|
|
113
|
+
|
|
114
|
+
elif self.aggregation == "min":
|
|
115
|
+
result = min(predictions)
|
|
116
|
+
|
|
117
|
+
elif self.aggregation == "median":
|
|
118
|
+
result = np.median(predictions)
|
|
119
|
+
|
|
120
|
+
else:
|
|
121
|
+
raise ValueError(f"Unknown aggregation: {self.aggregation}")
|
|
122
|
+
|
|
123
|
+
return float(result)
|
|
124
|
+
|
|
125
|
+
def batch_predict(self, graphs: List[ModelGraph], **predictor_kwargs) -> np.ndarray:
|
|
126
|
+
"""
|
|
127
|
+
Batch prediction for efficiency.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
graphs: List of architectures
|
|
131
|
+
**predictor_kwargs: Additional kwargs
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
Array of predictions
|
|
135
|
+
"""
|
|
136
|
+
# Try batch prediction if available
|
|
137
|
+
all_predictions = []
|
|
138
|
+
|
|
139
|
+
for predictor in self.predictors:
|
|
140
|
+
try:
|
|
141
|
+
if hasattr(predictor, "batch_predict"):
|
|
142
|
+
preds = predictor.batch_predict(graphs, **predictor_kwargs)
|
|
143
|
+
else:
|
|
144
|
+
# Fallback to sequential
|
|
145
|
+
preds = np.array([predictor.predict(g, **predictor_kwargs) for g in graphs])
|
|
146
|
+
|
|
147
|
+
all_predictions.append(preds)
|
|
148
|
+
except Exception as e:
|
|
149
|
+
logger.warning(f"Batch prediction failed for predictor: {e}")
|
|
150
|
+
|
|
151
|
+
if not all_predictions:
|
|
152
|
+
return np.full(len(graphs), 0.5)
|
|
153
|
+
|
|
154
|
+
# Aggregate
|
|
155
|
+
all_predictions = np.array(all_predictions) # Shape: (n_predictors, n_graphs)
|
|
156
|
+
|
|
157
|
+
if self.aggregation == "weighted_average":
|
|
158
|
+
weights = np.array(self.weights[: len(all_predictions)])
|
|
159
|
+
weights = weights / weights.sum()
|
|
160
|
+
result = np.average(all_predictions, axis=0, weights=weights)
|
|
161
|
+
|
|
162
|
+
elif self.aggregation == "max":
|
|
163
|
+
result = np.max(all_predictions, axis=0)
|
|
164
|
+
|
|
165
|
+
elif self.aggregation == "min":
|
|
166
|
+
result = np.min(all_predictions, axis=0)
|
|
167
|
+
|
|
168
|
+
elif self.aggregation == "median":
|
|
169
|
+
result = np.median(all_predictions, axis=0)
|
|
170
|
+
|
|
171
|
+
else:
|
|
172
|
+
raise ValueError(f"Unknown aggregation: {self.aggregation}")
|
|
173
|
+
|
|
174
|
+
return result
|
|
175
|
+
|
|
176
|
+
def get_individual_predictions(self, graph: ModelGraph, **predictor_kwargs) -> Dict[str, float]:
|
|
177
|
+
"""
|
|
178
|
+
Get predictions from each individual predictor.
|
|
179
|
+
|
|
180
|
+
Useful for debugging and analysis.
|
|
181
|
+
|
|
182
|
+
Args:
|
|
183
|
+
graph: Architecture to evaluate
|
|
184
|
+
**predictor_kwargs: Additional kwargs
|
|
185
|
+
|
|
186
|
+
Returns:
|
|
187
|
+
Dictionary mapping predictor name to prediction
|
|
188
|
+
"""
|
|
189
|
+
predictions = {}
|
|
190
|
+
|
|
191
|
+
for i, predictor in enumerate(self.predictors):
|
|
192
|
+
name = predictor.__class__.__name__
|
|
193
|
+
try:
|
|
194
|
+
pred = predictor.predict(graph, **predictor_kwargs)
|
|
195
|
+
predictions[f"{name}_{i}"] = pred
|
|
196
|
+
except Exception as e:
|
|
197
|
+
logger.warning(f"Predictor {name} failed: {e}")
|
|
198
|
+
predictions[f"{name}_{i}"] = None
|
|
199
|
+
|
|
200
|
+
# Add ensemble prediction
|
|
201
|
+
predictions["ensemble"] = self.predict(graph, **predictor_kwargs)
|
|
202
|
+
|
|
203
|
+
return predictions
|
|
204
|
+
|
|
205
|
+
def update_weights(self, new_weights: List[float]) -> None:
|
|
206
|
+
"""
|
|
207
|
+
Update predictor weights.
|
|
208
|
+
|
|
209
|
+
Useful for adaptive weighting based on performance.
|
|
210
|
+
|
|
211
|
+
Args:
|
|
212
|
+
new_weights: New weights (will be normalized)
|
|
213
|
+
"""
|
|
214
|
+
if len(new_weights) != len(self.predictors):
|
|
215
|
+
raise ValueError(f"Expected {len(self.predictors)} weights, got {len(new_weights)}")
|
|
216
|
+
|
|
217
|
+
# Normalize
|
|
218
|
+
total = sum(new_weights)
|
|
219
|
+
self.weights = [w / total for w in new_weights]
|
|
220
|
+
|
|
221
|
+
logger.info(f"Updated weights: {self.weights}")
|