Skip to main content

Advanced hyperparameter optimization using Iterative Decision Tree - Random (IDT-R) algorithm

Project description

IDT-R Optimizer: Iterative Decision Tree - Random Optimization

A professional, production-ready Python package for advanced hyperparameter optimization based on the IDT-R (Iterative Decision Tree - Random) algorithm.

Overview

IDT-R is a novel hyperparameter optimization algorithm that combines:

  • Decision Tree Surrogate Models: Learn patterns in the objective function landscape
  • Intelligent Node Extraction: Identify promising hyperparameter regions from tree leaves
  • Constrained Random Sampling: Efficiently explore within high-potential regions
  • Iterative Refinement: Progressively narrow down the search space

This approach bridges the gap between simple random/grid search and expensive Bayesian optimization, offering:

  • ✅ Fast convergence on realistic problems
  • ✅ Interpretable optimization dynamics (see tree structure and leaf regions)
  • ✅ Robust sampling within identified promising regions
  • ✅ Minimal computational overhead

Installation

From PyPI (Recommended)

pip install idt-r-optimizer

From Source

git clone https://github.com/Narith-Saum/idt_r_optimizer.git
cd idt_r_optimizer
pip install -e .

Requirements

  • Python 3.9+
  • NumPy >= 1.20.0
  • scikit-learn >= 1.0.0

Quick Start

from idt_r_optimizer import IDTROptimizer
from sklearn.datasets import make_classification
from sklearn.svm import SVC
from sklearn.model_selection import cross_val_score

# Define search space
search_space = {
    "C": (0.1, 10.0),           # Continuous
    "kernel": ["linear", "rbf"],  # Categorical
    "gamma": (0.001, 1.0),      # Continuous
}

# Define objective function
def objective(params):
    X, y = make_classification(n_samples=100, n_features=20, random_state=42)
    model = SVC(**params)
    score = cross_val_score(model, X, y, cv=3, scoring='accuracy').mean()
    return score

# Create optimizer
optimizer = IDTROptimizer(
    search_space=search_space,
    max_iterations=15,
    n_random_init=5,
    n_top_leaves=3,
    n_samples_per_leaf=2,
    verbose=True,
    maximize=True,  # Maximize accuracy
)

# Run optimization
best_params, best_score = optimizer.optimize(objective)

print(f"\n✅ Best Score: {best_score:.4f}")
print(f"✅ Best Params: {best_params}")

Algorithm Details

1. Initialization Phase

  • Generate n_random_init random samples from the search space
  • Evaluate each using the objective function

2. Iterative Optimization Loop

Step 1: Train Surrogate Model

Train a Decision Tree regressor on all previously evaluated points.

Input: {(params, score), ...}
Output: DecisionTreeRegressor fitted on objective landscape

Step 2: Extract Leaf Nodes

Extract all leaf nodes from the trained tree, identifying their hyperparameter bounds.

For each leaf:

  • Determine interval bounds: param_i ∈ [lower_i, upper_i]
  • Record predicted average performance in that region

Step 3: Select Best Leaves

Rank leaves by predicted performance and select top n_top_leaves.

Step 4: Random Sampling Within Leaves

For each selected leaf, randomly sample n_samples_per_leaf points:

for leaf in top_leaves:
    for _ in range(n_samples_per_leaf):
        for param in leaf.bounds:
            value = random_uniform(leaf.bounds[param])
        candidates.append(new_point)

Step 5: Evaluate & Update

  • Filter duplicates and already-evaluated points
  • Evaluate new candidates
  • Update history

Step 6: Repeat

Continue until max_iterations or no new candidates remain.

Why IDT-R Works

Aspect Random Search Grid Search Bayesian Opt IDT-R
Convergence Slow Poor for continuous Excellent Very Good
Interpretability None None Black box Tree structure visible
Computational Cost Low Medium High Low
Scaling Poor Very poor OK Good
Local Optima Not stuck Not stuck Exploits Balanced

API Reference

IDTROptimizer

optimizer = IDTROptimizer(
    search_space,              # Dict with parameter ranges
    max_iterations=20,         # Max optimization iterations
    n_random_init=5,           # Initial random samples
    n_top_leaves=3,            # Leaves to sample from per iteration
    n_samples_per_leaf=2,      # Samples per leaf
    tree_max_depth=5,          # Max depth of surrogate tree
    verbose=True,              # Print progress
    maximize=True,             # Maximize or minimize
    seed=None,                 # Random seed
)

Methods

optimize(objective_function) → (best_params, best_score)

Run optimization. Objective function takes param dict, returns float score.

get_best() → (params, score)

Returns best parameters and score found.

get_history() → OptimizationHistory

Returns detailed optimization history with all evaluations.

get_summary() → Dict

Returns summary statistics.

SearchSpace

Define your search space flexibly:

from idt_r_optimizer import SearchSpace

search_space = SearchSpace({
    "learning_rate": (0.0001, 0.1),     # Continuous
    "batch_size": (8, 256),              # Discrete (integer bounds)
    "optimizer": ["adam", "sgd", "rmsprop"],  # Categorical
    "dropout": (0.0, 0.5),               # Continuous
})

OptimizationHistory

Track and analyze results:

history = optimizer.get_history()

# Access records
best_record = history.get_best()
all_scores = history.get_all_scores()
best_params = history.get_best_params()

# Summary statistics
summary = history.get_summary()
print(summary)  # {'n_evaluations': 50, 'best_score': 0.95, 'mean_score': 0.87, ...}

Examples

Example 1: SVM Hyperparameter Tuning

from idt_r_optimizer import IDTROptimizer
from sklearn.svm import SVC
from sklearn.datasets import load_iris
from sklearn.model_selection import cross_val_score

# Load data
X, y = load_iris(return_X_y=True)

# Search space
search_space = {
    "C": (0.1, 100.0),
    "kernel": ["linear", "poly", "rbf"],
    "gamma": (0.001, 1.0),
}

# Objective function
def objective(params):
    model = SVC(**params)
    cv_scores = cross_val_score(model, X, y, cv=5, scoring='accuracy')
    return cv_scores.mean()

# Optimize
optimizer = IDTROptimizer(
    search_space,
    max_iterations=20,
    n_top_leaves=2,
    verbose=True,
)
best_params, best_score = optimizer.optimize(objective)

Example 2: Random Forest Tuning

from idt_r_optimizer import IDTROptimizer
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score

# Generate data
X, y = make_classification(n_samples=1000, n_features=50, n_informative=30)

# Search space
search_space = {
    "n_estimators": (10, 200),
    "max_depth": (3, 30),
    "min_samples_split": (2, 10),
    "min_samples_leaf": (1, 5),
    "criterion": ["gini", "entropy"],
}

# Objective function
def objective(params):
    rf = RandomForestClassifier(n_jobs=-1, **params)
    scores = cross_val_score(rf, X, y, cv=3, scoring='accuracy')
    return scores.mean()

# Optimize
optimizer = IDTROptimizer(
    search_space,
    max_iterations=25,
    n_random_init=10,
    n_top_leaves=3,
    n_samples_per_leaf=3,
    verbose=True,
)
best_params, best_score = optimizer.optimize(objective)

Configuration Guide

Tuning Hyperparameters

n_random_init: Number of initial random samples

  • Small (3-5): Fast startup, requires good surrogate early
  • Large (10-20): Better initial understanding, slower start

n_top_leaves: Number of leaves to sample from per iteration

  • Small (1-2): Exploitative, focuses on best regions
  • Large (5-10): Explorative, broader coverage

n_samples_per_leaf: Samples per selected leaf

  • Small (1-2): Fewer evaluations, lower computation
  • Large (5-10): More evaluations, better coverage per region

tree_max_depth: Decision tree complexity

  • Shallow (2-3): Rough surrogate, general patterns
  • Deep (6-10): Complex surrogate, overfitting risk

For Different Problem Types

Fast/Cheap Objective (~seconds)

IDTROptimizer(
    search_space,
    max_iterations=50,
    n_random_init=5,
    n_top_leaves=3,
    n_samples_per_leaf=3,
)

Expensive Objective (~hours)

IDTROptimizer(
    search_space,
    max_iterations=10,
    n_random_init=20,
    n_top_leaves=2,
    n_samples_per_leaf=1,
)

Features

Type Support

  • Continuous (float) parameters
  • Discrete (integer) parameters
  • Categorical (choice) parameters
  • Mixed spaces

Robustness

  • Duplicate detection and removal
  • History tracking
  • Graceful error handling
  • Reproducible (seed support)

Interpretability

  • Tree structure visible
  • Leaf intervals accessible
  • Full evaluation history
  • Feature importance available

Performance

  • Vectorized operations
  • Efficient tree extraction
  • Memory-conscious design
  • Scales to large parameter spaces

Advantages

vs. Random Search

  • 4-10x faster convergence on typical problems
  • Identifies promising regions automatically
  • Leverages past evaluations

vs. Grid Search

  • Handles continuous spaces naturally
  • No combinatorial explosion from many parameters
  • Adaptive grid refinement

vs. Bayesian Optimization

  • Simpler, more interpretable
  • Faster: no GP posterior sampling
  • More robust: tree structure visible
  • Lower computational overhead

Performance Considerations

Memory Usage: O(n_evaluations × n_params)

Time Complexity per Iteration:

  • Tree training: O(n_evaluations × log n_params)
  • Leaf extraction: O(tree_depth)
  • Sampling: O(n_top_leaves × n_samples_per_leaf)

Typical Evaluation Counts:

  • Initial random: ~5-10 evaluations
  • Per iteration: ~5-20 new evaluations
  • Total (20 iterations): 100-410 evaluations

Contributing

Contributions welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Submit a pull request

Citation

If you use IDT-R in your research, please cite the software and the related research paper:

Software Citation

@software{idt_r_2024,
  title={IDT-R Optimizer: Iterative Decision Tree - Random Hyperparameter Optimization},
  author={{IDT-R Development Team}},
  year={2024},
  url={https://github.com/Narith-Saum/idt_r_optimizer},
  version={0.1.2},
  howpublished={Python Package Index (PyPI)}
}

Related Research

This implementation is based on the IDT (Iterative Decision Tree) algorithm. For the foundational work, please refer to:

@article{saum2022hyperparameter,
  title={Hyperparameter Optimization Using Iterative Decision Tree (IDT)},
  author={Saum, Narith and Sugiura, Satoshi and Piantanakulchai, Mongkut},
  journal={IEEE Access},
  volume={10},
  pages={106812--106827},
  year={2022},
  doi={10.1109/ACCESS.2022.3212387},
  publisher={IEEE}
}

For comprehensive citation formats (APA, Chicago, etc.) and additional references, see CITATIONS.md.

License

MIT License - see LICENSE file for details.

Support

Changelog

v0.1.0 (2024)

  • Initial release
  • Core IDT-R algorithm implementation
  • Support for continuous, discrete, categorical parameters
  • Full history tracking
  • Comprehensive examples

Happy Optimizing! 🚀

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

idt_r_optimizer-0.1.5.tar.gz (44.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

idt_r_optimizer-0.1.5-py3-none-any.whl (18.9 kB view details)

Uploaded Python 3

File details

Details for the file idt_r_optimizer-0.1.5.tar.gz.

File metadata

  • Download URL: idt_r_optimizer-0.1.5.tar.gz
  • Upload date:
  • Size: 44.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for idt_r_optimizer-0.1.5.tar.gz
Algorithm Hash digest
SHA256 00a0a72b04d5c7b4e760a18e47becef541ffc7b00c525358ee9fd1f1b3cc3369
MD5 939c7311ffa4b639330268275fbe85f7
BLAKE2b-256 9b4206dbef7a7e0097b1bd1416b3c385278947336b7b5425dd3a330faaf8fc2f

See more details on using hashes here.

File details

Details for the file idt_r_optimizer-0.1.5-py3-none-any.whl.

File metadata

File hashes

Hashes for idt_r_optimizer-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 28536daf3713b3dd7f18688375ba11cf046584cc522e77166976d1f656b594f1
MD5 0c5834b94b2cd73ef7875eafb16f27a4
BLAKE2b-256 cbb1e691bdcd148fb70d7710910312b2dc951cd9cb6111ca314aae94f897963f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page