dpo 1.0.0__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.
- dpo-1.0.0/LICENSE +21 -0
- dpo-1.0.0/MANIFEST.in +4 -0
- dpo-1.0.0/PKG-INFO +23 -0
- dpo-1.0.0/README.md +280 -0
- dpo-1.0.0/docs/api_reference.md +27 -0
- dpo-1.0.0/docs/examples.md +13 -0
- dpo-1.0.0/docs/index.md +8 -0
- dpo-1.0.0/docs/installation.md +23 -0
- dpo-1.0.0/docs/quickstart.md +10 -0
- dpo-1.0.0/dpo/__init__.py +11 -0
- dpo-1.0.0/dpo/architecture/__init__.py +3 -0
- dpo-1.0.0/dpo/architecture/gene.py +192 -0
- dpo-1.0.0/dpo/benchmarks/__init__.py +16 -0
- dpo-1.0.0/dpo/benchmarks/comprehensive_evaluation.py +297 -0
- dpo-1.0.0/dpo/benchmarks/hpobench_wrapper.py +111 -0
- dpo-1.0.0/dpo/benchmarks/nasbench101_wrapper.py +179 -0
- dpo-1.0.0/dpo/benchmarks/nasbench201_wrapper.py +165 -0
- dpo-1.0.0/dpo/benchmarks/nasbench301_wrapper.py +130 -0
- dpo-1.0.0/dpo/benchmarks/nats_bench_wrapper.py +199 -0
- dpo-1.0.0/dpo/constraints/__init__.py +3 -0
- dpo-1.0.0/dpo/constraints/handler.py +99 -0
- dpo-1.0.0/dpo/core/__init__.py +5 -0
- dpo-1.0.0/dpo/core/agent.py +64 -0
- dpo-1.0.0/dpo/core/config.py +72 -0
- dpo-1.0.0/dpo/core/optimizer.py +266 -0
- dpo-1.0.0/dpo/evaluation/__init__.py +5 -0
- dpo-1.0.0/dpo/evaluation/cache.py +25 -0
- dpo-1.0.0/dpo/evaluation/ensemble.py +85 -0
- dpo-1.0.0/dpo/evaluation/estimators.py +212 -0
- dpo-1.0.0/dpo/examples/__init__.py +0 -0
- dpo-1.0.0/dpo/examples/advanced_config.py +15 -0
- dpo-1.0.0/dpo/examples/basic_usage.py +14 -0
- dpo-1.0.0/dpo/examples/benchmark_claude.py +2123 -0
- dpo-1.0.0/dpo/examples/benchmark_population.py +83 -0
- dpo-1.0.0/dpo/examples/benchmark_single.py +54 -0
- dpo-1.0.0/dpo/examples/comparative_analysis.py +209 -0
- dpo-1.0.0/dpo/examples/custom_estimator.py +26 -0
- dpo-1.0.0/dpo/examples/prof_cost.py +893 -0
- dpo-1.0.0/dpo/examples/professional.py +499 -0
- dpo-1.0.0/dpo/examples/professional_benchmark.py +1092 -0
- dpo-1.0.0/dpo/examples/working_benchmark.py +1187 -0
- dpo-1.0.0/dpo/utils/__init__.py +4 -0
- dpo-1.0.0/dpo/utils/helpers.py +14 -0
- dpo-1.0.0/dpo/utils/io.py +14 -0
- dpo-1.0.0/dpo/utils/logger.py +12 -0
- dpo-1.0.0/dpo.egg-info/PKG-INFO +23 -0
- dpo-1.0.0/dpo.egg-info/SOURCES.txt +57 -0
- dpo-1.0.0/dpo.egg-info/dependency_links.txt +1 -0
- dpo-1.0.0/dpo.egg-info/requires.txt +12 -0
- dpo-1.0.0/dpo.egg-info/top_level.txt +2 -0
- dpo-1.0.0/pyproject.toml +14 -0
- dpo-1.0.0/setup.cfg +4 -0
- dpo-1.0.0/setup.py +43 -0
- dpo-1.0.0/tests/__init__.py +0 -0
- dpo-1.0.0/tests/test_benchmarks.py +72 -0
- dpo-1.0.0/tests/test_estimators.py +12 -0
- dpo-1.0.0/tests/test_gene.py +7 -0
- dpo-1.0.0/tests/test_integration.py +12 -0
- dpo-1.0.0/tests/test_optimizer.py +8 -0
dpo-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Your Name
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
dpo-1.0.0/MANIFEST.in
ADDED
dpo-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dpo
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: DPO Neural Architecture Search V2
|
|
5
|
+
Home-page: https://github.com/Arya1718/dpo
|
|
6
|
+
Author: Arya H
|
|
7
|
+
Author-email: arya.h1718@gmail.com
|
|
8
|
+
Requires-Python: >=3.8
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Provides-Extra: dev
|
|
11
|
+
Requires-Dist: pytest>=6.0; extra == "dev"
|
|
12
|
+
Requires-Dist: black; extra == "dev"
|
|
13
|
+
Requires-Dist: flake8; extra == "dev"
|
|
14
|
+
Provides-Extra: docs
|
|
15
|
+
Requires-Dist: sphinx; extra == "docs"
|
|
16
|
+
Requires-Dist: sphinx-rtd-theme; extra == "docs"
|
|
17
|
+
Provides-Extra: gpu
|
|
18
|
+
Requires-Dist: torch>=1.9.0; extra == "gpu"
|
|
19
|
+
Dynamic: author
|
|
20
|
+
Dynamic: author-email
|
|
21
|
+
Dynamic: home-page
|
|
22
|
+
Dynamic: license-file
|
|
23
|
+
Dynamic: requires-python
|
dpo-1.0.0/README.md
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
# DPO-NAS: Direct Preference Optimization for Neural Architecture Search
|
|
2
|
+
|
|
3
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
|
+
[](https://www.python.org/downloads/)
|
|
5
|
+
[](https://pypi.org/project/dpo/)
|
|
6
|
+
|
|
7
|
+
A state-of-the-art, modular implementation of Direct Preference Optimization (DPO) based Neural Architecture Search (NAS) with ensemble evaluation, adaptive constraints, and island model population diversity. DPO-NAS V2 delivers superior performance across multiple NAS benchmarks while maintaining computational efficiency.
|
|
8
|
+
|
|
9
|
+
## Table of Contents
|
|
10
|
+
|
|
11
|
+
- [Overview](#overview)
|
|
12
|
+
- [Key Features](#key-features)
|
|
13
|
+
- [Performance](#performance)
|
|
14
|
+
- [Installation](#installation)
|
|
15
|
+
- [Quick Start](#quick-start)
|
|
16
|
+
- [Documentation](#documentation)
|
|
17
|
+
- [Examples](#examples)
|
|
18
|
+
- [Configuration](#configuration)
|
|
19
|
+
- [Contributing](#contributing)
|
|
20
|
+
- [License](#license)
|
|
21
|
+
- [Citation](#citation)
|
|
22
|
+
|
|
23
|
+
## Overview
|
|
24
|
+
|
|
25
|
+
DPO-NAS implements a novel evolutionary algorithm that combines Direct Preference Optimization principles with advanced NAS techniques. The algorithm uses an ensemble of surrogate models for architecture evaluation, adaptive constraint handling, and an island model for maintaining population diversity.
|
|
26
|
+
|
|
27
|
+
### Algorithm Highlights
|
|
28
|
+
|
|
29
|
+
- **Direct Preference Optimization**: Learns from pairwise architecture comparisons to guide search
|
|
30
|
+
- **Ensemble Evaluation**: Combines multiple surrogate models for robust performance estimation
|
|
31
|
+
- **Adaptive Constraints**: Dynamically adjusts resource constraints during optimization
|
|
32
|
+
- **Island Model**: Maintains population diversity through isolated subpopulations
|
|
33
|
+
- **Multi-Objective Optimization**: Balances accuracy, latency, memory, and FLOPs
|
|
34
|
+
|
|
35
|
+
## Key Features
|
|
36
|
+
|
|
37
|
+
### 🔬 Advanced Architecture Search
|
|
38
|
+
- **Gene-based Representation**: Flexible architecture encoding with operations, kernels, and skip connections
|
|
39
|
+
- **Multi-Objective Fitness**: Simultaneous optimization of accuracy and resource constraints
|
|
40
|
+
- **Adaptive Parameters**: Self-tuning hyperparameters during optimization
|
|
41
|
+
|
|
42
|
+
### 🏗️ Modular Design
|
|
43
|
+
- **Plugin Architecture**: Easily extensible with custom estimators and constraints
|
|
44
|
+
- **Ensemble Evaluation**: Multiple surrogate models for robust predictions
|
|
45
|
+
- **Constraint Handlers**: Flexible resource constraint management
|
|
46
|
+
|
|
47
|
+
### 🚀 Performance & Efficiency
|
|
48
|
+
- **Island Model**: Parallel subpopulation evolution for diversity
|
|
49
|
+
- **Adaptive Constraints**: Dynamic resource allocation during search
|
|
50
|
+
- **Early Stopping**: Intelligent termination based on convergence criteria
|
|
51
|
+
|
|
52
|
+
### 📊 Benchmark Suite
|
|
53
|
+
- **Comprehensive Testing**: Validated against HPOBench, NAS-Bench-201, and NAS-Bench-301
|
|
54
|
+
- **Statistical Significance**: Proper variance injection for meaningful comparisons
|
|
55
|
+
- **Performance Metrics**: AUC, regret, time-to-threshold analysis
|
|
56
|
+
|
|
57
|
+
## Performance
|
|
58
|
+
|
|
59
|
+
DPO-NAS demonstrates superior performance across multiple NAS benchmarks:
|
|
60
|
+
|
|
61
|
+
### HPOBench Results (Credit-G Dataset)
|
|
62
|
+
| Method | Best Accuracy | AUC@50 | Sig. vs DPO |
|
|
63
|
+
|--------|---------------|--------|-------------|
|
|
64
|
+
| **TL-DPO** | **0.9732±0.0067** | **0.8343±0.0061** | - |
|
|
65
|
+
| Local Search | 0.9168±0.0529 | 0.8958±0.0531 | *** |
|
|
66
|
+
| Regularized Evolution | 0.9312±0.0143 | 0.8793±0.0195 | ** |
|
|
67
|
+
| BOHB | 0.8739±0.0671 | 0.8564±0.0657 | *** |
|
|
68
|
+
|
|
69
|
+
### NAS-Bench-201 Results (CIFAR-10)
|
|
70
|
+
| Method | Best Accuracy | AUC@50 | Sig. vs DPO |
|
|
71
|
+
|--------|---------------|--------|-------------|
|
|
72
|
+
| **TL-DPO** | **0.9541±0.0083** | **0.9350±0.0082** | - |
|
|
73
|
+
| Local Search | 0.9541±0.0083 | 0.9396±0.0008 | *** |
|
|
74
|
+
| SMAC | 0.9541±0.0083 | 0.9170±0.0205 | *** |
|
|
75
|
+
| Random Search | 0.9541±0.0083 | 0.8740±0.0763 | *** |
|
|
76
|
+
|
|
77
|
+
*Results show mean ± standard deviation across 3 seeds. Statistical significance: *** p<0.001, ** p<0.01, * p<0.05*
|
|
78
|
+
|
|
79
|
+
## Installation
|
|
80
|
+
|
|
81
|
+
### From PyPI (Recommended)
|
|
82
|
+
```bash
|
|
83
|
+
pip install dpo-nas
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### From Source
|
|
87
|
+
```bash
|
|
88
|
+
git clone https://github.com/yourusername/dpo-nas.git
|
|
89
|
+
cd dpo-nas
|
|
90
|
+
pip install -e .
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Optional Dependencies
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# Development dependencies
|
|
97
|
+
pip install dpo-nas[dev]
|
|
98
|
+
|
|
99
|
+
# Documentation
|
|
100
|
+
pip install dpo-nas[docs]
|
|
101
|
+
|
|
102
|
+
# GPU support
|
|
103
|
+
pip install dpo-nas[gpu]
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Requirements
|
|
107
|
+
- Python 3.8+
|
|
108
|
+
- NumPy
|
|
109
|
+
- SciPy
|
|
110
|
+
- Matplotlib (optional, for plotting)
|
|
111
|
+
|
|
112
|
+
## Quick Start
|
|
113
|
+
|
|
114
|
+
### Basic Usage
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
from dpo import DPO_NAS, DPO_Config
|
|
118
|
+
|
|
119
|
+
# Configure the optimizer
|
|
120
|
+
config = DPO_Config(
|
|
121
|
+
population_size=40,
|
|
122
|
+
max_iterations=200,
|
|
123
|
+
alpha_0=0.1,
|
|
124
|
+
strategy='ensemble'
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
# Initialize and run optimization
|
|
128
|
+
optimizer = DPO_NAS(config)
|
|
129
|
+
results = optimizer.optimize()
|
|
130
|
+
|
|
131
|
+
# Access results
|
|
132
|
+
print(f"Best Fitness: {results['best_fitness']:.4f}")
|
|
133
|
+
print(f"Best Architecture: {results['best_architecture']}")
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Custom Estimator
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
from dpo import DPO_NAS, DPO_Config
|
|
140
|
+
from dpo.evaluation.ensemble import EnsembleEstimator
|
|
141
|
+
|
|
142
|
+
# Create custom estimator
|
|
143
|
+
estimator = EnsembleEstimator(models=['latency', 'memory', 'flops'])
|
|
144
|
+
|
|
145
|
+
# Configure with custom estimator
|
|
146
|
+
config = DPO_Config(population_size=50, max_iterations=300)
|
|
147
|
+
optimizer = DPO_NAS(config, estimator=estimator)
|
|
148
|
+
results = optimizer.optimize()
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Advanced Configuration
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
from dpo import DPO_NAS, DPO_Config
|
|
155
|
+
from dpo.constraints.handler import AdvancedConstraintHandler
|
|
156
|
+
|
|
157
|
+
# Advanced configuration
|
|
158
|
+
config = DPO_Config(
|
|
159
|
+
population_size=100,
|
|
160
|
+
max_iterations=500,
|
|
161
|
+
num_islands=4, # Island model
|
|
162
|
+
island_model=True,
|
|
163
|
+
adaptive_alpha=True,
|
|
164
|
+
w_loss=1.0,
|
|
165
|
+
w_latency=0.1,
|
|
166
|
+
w_memory=0.1,
|
|
167
|
+
w_flops=0.1,
|
|
168
|
+
latency_constraint=50.0, # ms
|
|
169
|
+
memory_constraint=1000.0, # MB
|
|
170
|
+
flops_constraint=2000.0, # MFLOPs
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
# Custom constraint handler
|
|
174
|
+
constraint_handler = AdvancedConstraintHandler(config)
|
|
175
|
+
|
|
176
|
+
optimizer = DPO_NAS(config, constraint_handler=constraint_handler)
|
|
177
|
+
results = optimizer.optimize()
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Documentation
|
|
181
|
+
|
|
182
|
+
📖 **Full Documentation**: [https://dpo-nas.readthedocs.io/](https://dpo-nas.readthedocs.io/)
|
|
183
|
+
|
|
184
|
+
### Key Sections
|
|
185
|
+
- [Installation Guide](docs/installation.md)
|
|
186
|
+
- [Quick Start Tutorial](docs/quickstart.md)
|
|
187
|
+
- [API Reference](docs/api_reference.md)
|
|
188
|
+
- [Advanced Examples](docs/examples.md)
|
|
189
|
+
|
|
190
|
+
## Examples
|
|
191
|
+
|
|
192
|
+
The `dpo/examples/` directory contains comprehensive examples:
|
|
193
|
+
|
|
194
|
+
- `basic_usage.py` - Simple optimization example
|
|
195
|
+
- `custom_estimator.py` - Using custom evaluation models
|
|
196
|
+
- `advanced_config.py` - Advanced configuration options
|
|
197
|
+
- `benchmark_single.py` - Single benchmark evaluation
|
|
198
|
+
- `benchmark_population.py` - Population-based benchmarking
|
|
199
|
+
- `comparative_analysis.py` - Statistical comparison with baselines
|
|
200
|
+
|
|
201
|
+
### Running Examples
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
# Basic usage
|
|
205
|
+
python dpo/examples/basic_usage.py
|
|
206
|
+
|
|
207
|
+
# Professional benchmark suite
|
|
208
|
+
python dpo/examples/professional_benchmark.py --seeds 5 --budget 100
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Configuration
|
|
212
|
+
|
|
213
|
+
DPO-NAS offers extensive configuration options through the `DPO_Config` class:
|
|
214
|
+
|
|
215
|
+
### Core Parameters
|
|
216
|
+
- `population_size`: Number of architectures in population (default: 40)
|
|
217
|
+
- `max_iterations`: Maximum optimization iterations (default: 200)
|
|
218
|
+
- `num_islands`: Number of subpopulations for island model (default: 3)
|
|
219
|
+
|
|
220
|
+
### Optimization Weights
|
|
221
|
+
- `w_loss`: Weight for accuracy loss (default: 1.0)
|
|
222
|
+
- `w_latency`: Weight for latency constraint (default: 0.1)
|
|
223
|
+
- `w_memory`: Weight for memory constraint (default: 0.1)
|
|
224
|
+
- `w_flops`: Weight for FLOPs constraint (default: 0.1)
|
|
225
|
+
|
|
226
|
+
### Constraints
|
|
227
|
+
- `latency_constraint`: Maximum latency in ms (default: 50.0)
|
|
228
|
+
- `memory_constraint`: Maximum memory in MB (default: 1000.0)
|
|
229
|
+
- `flops_constraint`: Maximum FLOPs in MFLOPs (default: 2000.0)
|
|
230
|
+
|
|
231
|
+
### Advanced Options
|
|
232
|
+
- `adaptive_alpha`: Enable adaptive alpha parameter (default: True)
|
|
233
|
+
- `island_model`: Enable island model evolution (default: True)
|
|
234
|
+
- `decay_power`: Parameter decay exponent (default: 2.0)
|
|
235
|
+
|
|
236
|
+
## Contributing
|
|
237
|
+
|
|
238
|
+
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
|
|
239
|
+
|
|
240
|
+
### Development Setup
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
git clone https://github.com/Arya1718/dpo-nas.git
|
|
244
|
+
cd dpo-nas
|
|
245
|
+
pip install -e .[dev]
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Running Tests
|
|
249
|
+
|
|
250
|
+
```bash
|
|
251
|
+
pytest tests/
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Code Style
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
black dpo/
|
|
258
|
+
flake8 dpo/
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## License
|
|
262
|
+
|
|
263
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
264
|
+
|
|
265
|
+
## Citation
|
|
266
|
+
|
|
267
|
+
If you use DPO-NAS in your research, please cite:
|
|
268
|
+
|
|
269
|
+
```bibtex
|
|
270
|
+
@software{dpo_nas_2026,
|
|
271
|
+
title={DPO-NAS: Direct Preference Optimization for Neural Architecture Search},
|
|
272
|
+
author={Arya H},
|
|
273
|
+
year={2026},
|
|
274
|
+
url={https://github.com/Arya1718/dpo-nas}
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
**DPO-NAS** - Revolutionizing Neural Architecture Search through Direct Preference Optimization
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# API Reference
|
|
2
|
+
|
|
3
|
+
## dpo.core.config
|
|
4
|
+
|
|
5
|
+
- DPO_ConfigV2: Configuration dataclass with presets `fast()`, `balanced()`, `thorough()`.
|
|
6
|
+
|
|
7
|
+
## dpo.core.agent
|
|
8
|
+
|
|
9
|
+
- SearchAgentV2: NAS search agent with `gene`, `fitness`, `metrics`.
|
|
10
|
+
|
|
11
|
+
## dpo.architecture.gene
|
|
12
|
+
|
|
13
|
+
- ArchitectureGeneV2: Architecture encoding, mutation, crossover, hashing.
|
|
14
|
+
|
|
15
|
+
## dpo.evaluation
|
|
16
|
+
|
|
17
|
+
- ZeroShotEstimatorV2
|
|
18
|
+
- SurrogateEstimatorV2
|
|
19
|
+
- EnsembleEstimator
|
|
20
|
+
|
|
21
|
+
## dpo.constraints.handler
|
|
22
|
+
|
|
23
|
+
- AdvancedConstraintHandler: Adaptive penalty computation and validation.
|
|
24
|
+
|
|
25
|
+
## dpo.core.optimizer
|
|
26
|
+
|
|
27
|
+
- DPO_NAS_V2: Main optimizer with `optimize()`.
|
dpo-1.0.0/docs/index.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Installation
|
|
2
|
+
|
|
3
|
+
## From Source
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
git clone https://github.com/yourusername/dpo.git
|
|
7
|
+
cd dpo
|
|
8
|
+
pip install -e .
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## From PyPI
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install dpo
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Optional Dependencies
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install dpo[dev]
|
|
21
|
+
pip install dpo[docs]
|
|
22
|
+
pip install dpo[gpu]
|
|
23
|
+
```
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from .core.config import DPO_Config
|
|
2
|
+
from .core.optimizer import DPO_NAS
|
|
3
|
+
from .evaluation.ensemble import EnsembleEstimator
|
|
4
|
+
from .constraints.handler import AdvancedConstraintHandler
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
'DPO_Config',
|
|
8
|
+
'DPO_NAS',
|
|
9
|
+
'EnsembleEstimator',
|
|
10
|
+
'AdvancedConstraintHandler',
|
|
11
|
+
]
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# import numpy as np
|
|
2
|
+
# from typing import Dict
|
|
3
|
+
# from collections import deque
|
|
4
|
+
# import hashlib
|
|
5
|
+
|
|
6
|
+
# class ArchitectureGene:
|
|
7
|
+
# OPERATIONS = ['conv_3x3', 'conv_5x5', 'dw_conv', 'sep_conv', 'avg_pool', 'max_pool', 'skip_connect']
|
|
8
|
+
# KERNELS = [1, 3, 5, 7]
|
|
9
|
+
# CHANNELS = [16, 32, 64, 128, 256]
|
|
10
|
+
|
|
11
|
+
# def __init__(self, num_layers: int = 12, num_cells: int = 5):
|
|
12
|
+
# self.num_layers = num_layers
|
|
13
|
+
# self.num_cells = num_cells
|
|
14
|
+
# self.D = num_layers * 3 + num_cells + 2
|
|
15
|
+
# self.gene = self._initialize_random()
|
|
16
|
+
# self.mutation_history = deque(maxlen=50)
|
|
17
|
+
|
|
18
|
+
# def _initialize_random(self) -> np.ndarray:
|
|
19
|
+
# gene = np.zeros(self.D)
|
|
20
|
+
# ops_bias = np.array([3, 3, 2, 2, 1, 1, 0.5])
|
|
21
|
+
# ops_bias = ops_bias / ops_bias.sum()
|
|
22
|
+
# gene[:self.num_layers] = np.random.choice(len(self.OPERATIONS), self.num_layers, p=ops_bias)
|
|
23
|
+
# gene[self.num_layers:2*self.num_layers] = np.random.randint(0, len(self.KERNELS), self.num_layers)
|
|
24
|
+
# skip_count = np.random.randint(0, int(self.num_cells * 0.3))
|
|
25
|
+
# if skip_count > 0:
|
|
26
|
+
# skip_indices = np.random.choice(self.num_cells, skip_count, replace=False)
|
|
27
|
+
# gene[2*self.num_layers:2*self.num_layers+self.num_cells][skip_indices] = 1
|
|
28
|
+
# gene[-2] = np.random.uniform(0.6, 1.0)
|
|
29
|
+
# gene[-1] = np.random.uniform(0.6, 1.0)
|
|
30
|
+
# return gene
|
|
31
|
+
|
|
32
|
+
# def mutate(self, mutation_type: str = 'adaptive') -> 'ArchitectureGene':
|
|
33
|
+
# mutant = self.copy()
|
|
34
|
+
# if mutation_type == 'adaptive':
|
|
35
|
+
# mutation_type = np.random.choice(['local', 'crossover', 'swap'], p=[0.6, 0.3, 0.1])
|
|
36
|
+
# if mutation_type == 'local':
|
|
37
|
+
# idx = np.random.randint(0, self.D)
|
|
38
|
+
# if idx < self.num_layers:
|
|
39
|
+
# mutant.gene[idx] = np.random.randint(0, len(self.OPERATIONS))
|
|
40
|
+
# elif idx < 2*self.num_layers:
|
|
41
|
+
# mutant.gene[idx] = np.random.randint(0, len(self.KERNELS))
|
|
42
|
+
# else:
|
|
43
|
+
# mutant.gene[idx] = np.clip(mutant.gene[idx] + np.random.randn() * 0.05, 0, 1)
|
|
44
|
+
# elif mutation_type == 'crossover':
|
|
45
|
+
# if self.num_layers > 2:
|
|
46
|
+
# start = np.random.randint(0, max(1, self.num_layers - 2))
|
|
47
|
+
# length = np.random.randint(2, min(5, self.num_layers - start + 1))
|
|
48
|
+
# other = ArchitectureGene(self.num_layers, self.num_cells)
|
|
49
|
+
# mutant.gene[start:start+length] = other.gene[start:start+length]
|
|
50
|
+
# elif mutation_type == 'swap':
|
|
51
|
+
# if self.num_layers >= 2:
|
|
52
|
+
# i, j = np.random.choice(self.num_layers, 2, replace=False)
|
|
53
|
+
# mutant.gene[[i, j]] = mutant.gene[[j, i]]
|
|
54
|
+
# self.mutation_history.append(mutation_type)
|
|
55
|
+
# return mutant
|
|
56
|
+
|
|
57
|
+
# def crossover(self, other: 'ArchitectureGene') -> 'ArchitectureGene':
|
|
58
|
+
# offspring = self.copy()
|
|
59
|
+
# crossover_point = np.random.randint(1, self.D)
|
|
60
|
+
# offspring.gene[crossover_point:] = other.gene[crossover_point:]
|
|
61
|
+
# return offspring
|
|
62
|
+
|
|
63
|
+
# def copy(self) -> 'ArchitectureGene':
|
|
64
|
+
# new_gene = ArchitectureGene(self.num_layers, self.num_cells)
|
|
65
|
+
# new_gene.gene = self.gene.copy()
|
|
66
|
+
# return new_gene
|
|
67
|
+
|
|
68
|
+
# def to_architecture_dict(self) -> Dict:
|
|
69
|
+
# ops_idx = self.gene[:self.num_layers].astype(int)
|
|
70
|
+
# kernels_idx = self.gene[self.num_layers:2*self.num_layers].astype(int)
|
|
71
|
+
# skip_flags = self.gene[2*self.num_layers:2*self.num_layers+self.num_cells].astype(int)
|
|
72
|
+
# return {
|
|
73
|
+
# 'operations': [self.OPERATIONS[int(min(idx, len(self.OPERATIONS)-1))] for idx in ops_idx],
|
|
74
|
+
# 'kernels': [self.KERNELS[int(min(idx, len(self.KERNELS)-1))] for idx in kernels_idx],
|
|
75
|
+
# 'skip_connections': skip_flags.tolist(),
|
|
76
|
+
# 'depth_multiplier': float(np.clip(self.gene[-2], 0.3, 1.5)),
|
|
77
|
+
# 'channel_multiplier': float(np.clip(self.gene[-1], 0.3, 1.5)),
|
|
78
|
+
# 'num_layers': self.num_layers,
|
|
79
|
+
# }
|
|
80
|
+
|
|
81
|
+
# def get_hash(self) -> str:
|
|
82
|
+
# return hashlib.md5(self.gene.tobytes()).hexdigest()
|
|
83
|
+
|
|
84
|
+
import numpy as np
|
|
85
|
+
from typing import Dict
|
|
86
|
+
from collections import deque
|
|
87
|
+
import hashlib
|
|
88
|
+
|
|
89
|
+
class ArchitectureGene:
|
|
90
|
+
__slots__ = ('num_layers', 'num_cells', 'D', 'gene', 'mutation_history', '_hash_cache')
|
|
91
|
+
|
|
92
|
+
OPERATIONS = ['conv_3x3', 'conv_5x5', 'dw_conv', 'sep_conv', 'avg_pool', 'max_pool', 'skip_connect']
|
|
93
|
+
KERNELS = [1, 3, 5, 7]
|
|
94
|
+
CHANNELS = [16, 32, 64, 128, 256]
|
|
95
|
+
|
|
96
|
+
def __init__(self, num_layers: int = 12, num_cells: int = 5):
|
|
97
|
+
self.num_layers = num_layers
|
|
98
|
+
self.num_cells = num_cells
|
|
99
|
+
self.D = num_layers * 3 + num_cells + 2
|
|
100
|
+
self.gene = self._initialize_random()
|
|
101
|
+
self.mutation_history = deque(maxlen=50)
|
|
102
|
+
self._hash_cache = None
|
|
103
|
+
|
|
104
|
+
def _initialize_random(self) -> np.ndarray:
|
|
105
|
+
gene = np.zeros(self.D, dtype=np.float32)
|
|
106
|
+
# Pre-calculated probabilities
|
|
107
|
+
# ops_bias = [3, 3, 2, 2, 1, 1, 0.5] -> sum=12.5
|
|
108
|
+
p = [0.24, 0.24, 0.16, 0.16, 0.08, 0.08, 0.04]
|
|
109
|
+
|
|
110
|
+
gene[:self.num_layers] = np.random.choice(len(self.OPERATIONS), self.num_layers, p=p)
|
|
111
|
+
gene[self.num_layers:2*self.num_layers] = np.random.randint(0, len(self.KERNELS), self.num_layers)
|
|
112
|
+
|
|
113
|
+
skip_count = np.random.randint(0, int(self.num_cells * 0.3) + 1)
|
|
114
|
+
if skip_count > 0:
|
|
115
|
+
skip_indices = np.random.choice(self.num_cells, skip_count, replace=False)
|
|
116
|
+
gene[2*self.num_layers : 2*self.num_layers+self.num_cells][skip_indices] = 1
|
|
117
|
+
|
|
118
|
+
gene[-2] = np.random.uniform(0.6, 1.0)
|
|
119
|
+
gene[-1] = np.random.uniform(0.6, 1.0)
|
|
120
|
+
return gene
|
|
121
|
+
|
|
122
|
+
def mutate(self, mutation_type: str = 'adaptive') -> 'ArchitectureGene':
|
|
123
|
+
mutant = self.copy()
|
|
124
|
+
if mutation_type == 'adaptive':
|
|
125
|
+
r = np.random.random()
|
|
126
|
+
if r < 0.6: mutation_type = 'local'
|
|
127
|
+
elif r < 0.9: mutation_type = 'crossover'
|
|
128
|
+
else: mutation_type = 'swap'
|
|
129
|
+
|
|
130
|
+
if mutation_type == 'local':
|
|
131
|
+
idx = np.random.randint(0, self.D)
|
|
132
|
+
if idx < self.num_layers:
|
|
133
|
+
mutant.gene[idx] = np.random.randint(0, len(self.OPERATIONS))
|
|
134
|
+
elif idx < 2*self.num_layers:
|
|
135
|
+
mutant.gene[idx] = np.random.randint(0, len(self.KERNELS))
|
|
136
|
+
else:
|
|
137
|
+
mutant.gene[idx] = np.clip(mutant.gene[idx] + np.random.randn() * 0.05, 0, 1)
|
|
138
|
+
|
|
139
|
+
elif mutation_type == 'crossover':
|
|
140
|
+
if self.num_layers > 2:
|
|
141
|
+
start = np.random.randint(0, max(1, self.num_layers - 2))
|
|
142
|
+
length = np.random.randint(2, min(5, self.num_layers - start + 1))
|
|
143
|
+
# Create random gene for crossover directly without full object overhead
|
|
144
|
+
other_gene_array = self._initialize_random()
|
|
145
|
+
mutant.gene[start:start+length] = other_gene_array[start:start+length]
|
|
146
|
+
|
|
147
|
+
elif mutation_type == 'swap':
|
|
148
|
+
if self.num_layers >= 2:
|
|
149
|
+
i, j = np.random.choice(self.num_layers, 2, replace=False)
|
|
150
|
+
mutant.gene[[i, j]] = mutant.gene[[j, i]]
|
|
151
|
+
|
|
152
|
+
self.mutation_history.append(mutation_type)
|
|
153
|
+
mutant._hash_cache = None
|
|
154
|
+
return mutant
|
|
155
|
+
|
|
156
|
+
def crossover(self, other: 'ArchitectureGene') -> 'ArchitectureGene':
|
|
157
|
+
offspring = self.copy()
|
|
158
|
+
crossover_point = np.random.randint(1, self.D)
|
|
159
|
+
offspring.gene[crossover_point:] = other.gene[crossover_point:]
|
|
160
|
+
offspring._hash_cache = None
|
|
161
|
+
return offspring
|
|
162
|
+
|
|
163
|
+
def copy(self) -> 'ArchitectureGene':
|
|
164
|
+
new_gene = ArchitectureGene(self.num_layers, self.num_cells)
|
|
165
|
+
new_gene.gene = self.gene.copy()
|
|
166
|
+
# History is technically per-agent evolution, usually empty on copy or copied
|
|
167
|
+
# Keeping deque empty for new separate timeline or copy if needed
|
|
168
|
+
return new_gene
|
|
169
|
+
|
|
170
|
+
def to_architecture_dict(self) -> Dict:
|
|
171
|
+
# Optimized casting
|
|
172
|
+
ops_idx = self.gene[:self.num_layers].astype(np.int32)
|
|
173
|
+
kernels_idx = self.gene[self.num_layers:2*self.num_layers].astype(np.int32)
|
|
174
|
+
skip_flags = self.gene[2*self.num_layers:2*self.num_layers+self.num_cells].astype(np.int32)
|
|
175
|
+
|
|
176
|
+
# Pre-cache lengths
|
|
177
|
+
len_ops = len(self.OPERATIONS) - 1
|
|
178
|
+
len_kers = len(self.KERNELS) - 1
|
|
179
|
+
|
|
180
|
+
return {
|
|
181
|
+
'operations': [self.OPERATIONS[min(idx, len_ops)] for idx in ops_idx],
|
|
182
|
+
'kernels': [self.KERNELS[min(idx, len_kers)] for idx in kernels_idx],
|
|
183
|
+
'skip_connections': skip_flags.tolist(),
|
|
184
|
+
'depth_multiplier': float(np.clip(self.gene[-2], 0.3, 1.5)),
|
|
185
|
+
'channel_multiplier': float(np.clip(self.gene[-1], 0.3, 1.5)),
|
|
186
|
+
'num_layers': self.num_layers,
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
def get_hash(self) -> str:
|
|
190
|
+
if self._hash_cache is None:
|
|
191
|
+
self._hash_cache = hashlib.md5(self.gene.tobytes()).hexdigest()
|
|
192
|
+
return self._hash_cache
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from .nasbench101_wrapper import NASBench101Benchmark, NASBench101Result
|
|
2
|
+
from .nasbench201_wrapper import NASBench201Benchmark
|
|
3
|
+
from .nasbench301_wrapper import NASBench301Benchmark
|
|
4
|
+
from .hpobench_wrapper import HPOBenchBenchmark
|
|
5
|
+
from .nats_bench_wrapper import NATSBenchBenchmark
|
|
6
|
+
from .comprehensive_evaluation import ComprehensiveBenchmarkEvaluator
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
'NASBench101Benchmark',
|
|
10
|
+
'NASBench201Benchmark',
|
|
11
|
+
'NASBench301Benchmark',
|
|
12
|
+
'HPOBenchBenchmark',
|
|
13
|
+
'NATSBenchBenchmark',
|
|
14
|
+
'ComprehensiveBenchmarkEvaluator',
|
|
15
|
+
'NASBench101Result',
|
|
16
|
+
]
|