Usage¶
Installation¶
$ git clone https://github.com/facebookresearch/LA-MCTS.git
$ cd LA-MCTS
$ pip install -e .
API References¶
Function Interfaces¶
- class lamcts.Func¶
Bases:
abc.ABC
Function interface to be implemented by the client
- cleanup()¶
- compare(fx1: float, fx2: float, margin: float = 0.0) int ¶
To compare two outputs, based on if one is “better” than the other. :param fx1: output 1 :param fx2: output 2 :param margin: if two outputs are within margin, they are considered equal :return: < 0, if fx1 is worse than fx2; == 0 if equal; > 0 if better
- abstract property dims: int¶
Dimension of the input :return:
- empty_bag()¶
Create an empty bag based on the function properties :return:
- gen_random_inputs(num_inputs: int, lb: Optional[numpy.ndarray] = None, ub: Optional[numpy.ndarray] = None) numpy.ndarray ¶
To generate random inputs using latin hypercube
- Parameters
num_inputs – number of inputs to be generated
lb – if given, generated inputs are floored by lb
ub – if given, generated inputs are ceilinged by up
- Returns
- gen_sample_bag(xs: Optional[numpy.ndarray] = None) lamcts.type.Bag ¶
- input_equal(i1: numpy.ndarray, i2: numpy.ndarray) bool ¶
To test if two inputs are equal
- Parameters
i1 – input 1
i2 – input 2
- Returns
- property is_discrete: numpy.ndarray¶
Whether the input is discrete :return: bool or an array of bool
- property is_minimizing: bool¶
Whether the goal is to minimize or maximize the result :return:
- abstract property lb: numpy.ndarray¶
Lower bounds of each dimension :return: numpy array of shape (dims,)
- mcts_params(sampler: lamcts.config.config.SamplerEnum = SamplerEnum.RANDOM_SAMPLER, classifier: lamcts.config.config.ClassifierEnum = ClassifierEnum.KMEAN_SVM_CLASSIFIER) Dict ¶
- transform_input(xs: numpy.ndarray) numpy.ndarray ¶
- abstract property ub: numpy.ndarray¶
Upper bounds of each dimension :return: numpy array of shape (dims,)
- class lamcts.CheckPoint(call_mark, time_mark, x, fx)¶
- call_mark: int¶
Alias for field number 0
- fx: float¶
Alias for field number 3
- time_mark: float¶
Alias for field number 1
- x: Union[numpy.ndarray, List]¶
Alias for field number 2
- lamcts.CallHistory¶
alias of
List
[lamcts.func.CheckPoint
]
- class lamcts.FuncStats¶
Bases:
abc.ABC
Interface to track call statistics
- class Stats(is_minimizing: bool = True)¶
Bases:
object
- add_stat(xs: numpy.ndarray, fxs: numpy.ndarray, call_time: float)¶
- property call_history: List[lamcts.func.CheckPoint]¶
- property total_call_time: float¶
- property total_calls: int¶
- abstract property stats: lamcts.func.FuncStats.Stats¶
- class lamcts.StatsFuncWrapper(func: lamcts.func.Func)¶
Bases:
lamcts.func.FuncDecorator
,lamcts.func.FuncStats
A convenient wrapper of Func, to provide stats tracking
- cleanup()¶
- property stats: lamcts.func.FuncStats.Stats¶
MCTS¶
- class lamcts.MCTS(func: lamcts.func.Func, func_stats: lamcts.func.FuncStats, num_init_samples: int = 100, cp: float = 1.0, cb_base: lamcts.config.config.ConfidencyBase = ConfidencyBase.Mean, leaf_size: int = 20, num_samples_per_sampler: int = 200, classifier_factory: Optional[lamcts.type.ObjectFactory[lamcts.classifier.classifier.Classifier]] = None, num_split_worker: int = 1, sampler: Optional[lamcts.sampler.sampler.Sampler] = None, search_type: lamcts.config.config.SearchType = SearchType.Vertical, device: str = 'cpu')¶
Bases:
object
LaMCTS implementation, refer to the paper for more details
- Parameters
func – function to be optimized
func_stats – stats to track function calling history
num_init_samples – initial number of samples to draw
cp – parameter controlling exploration
cb_base – confident bound base - 0: mean, 1: best
leaf_size – number of samples hold by a leaf
num_samples_per_sampler – how many samples to draw at each iteration
classifier_factory – object factory to create classifiers
num_split_worker – number of workers to build search tree
sampler – sampler
search_type – Vertical - from root to leaf, horizontal - all leaves
device –
- DEFAULT_CB_BASE = 0¶
- DEFAULT_CP = 1.0¶
- DEFAULT_GAMMA_TYPE = 'auto'¶
- DEFAULT_KERNAL_TYPE = 'rbf'¶
- DEFAULT_KMEAN_SVM_CLASSIFIER_PARAM = {'gamma': 'auto', 'kernel': 'rbf', 'scaler': 'standard', 'use_features': False}¶
- DEFAULT_LEAF_SIZE = 20¶
- DEFAULT_NUM_INIT_SAMPLES = 100¶
- DEFAULT_NUM_SAMPLES_PER_SAMPLER = 200¶
- DEFAULT_SAMPLER_CONFIG = {'params': {'batch_size': 10, 'num_init_samples': 20}, 'type': 'turbo'}¶
- DEFAULT_SOLVER_TYPE = 'turbo'¶
- static create_mcts(func: lamcts.func.Func, func_stats: lamcts.func.FuncStats, params: Dict) lamcts.mcts.MCTS ¶
- init_tree()¶
- search(greedy: lamcts.config.config.GreedyType = GreedyType.ConfidencyBound, call_budget: float = inf) Tuple ¶
Search for optimal solution
- Parameters
greedy – < 0 random; == 0 using confidence bound; == 1 using mean; == 2 using best sample
call_budget –
- Returns
best sample found
- property stats: Tuple¶
Classifiers¶
- class lamcts.classifier.Classifier¶
A classifier to separate input bag into clusters
- abstract classify(bag: lamcts.type.Bag) Optional[numpy.ndarray] ¶
Classify input bag into clusters :param bag: input (rows, features) :return: label of each row of input (rows,)
- abstract predict(xs: numpy.ndarray) numpy.ndarray ¶
Predict which cluster input belongs to :param xs: (rows, features) :return: labels of each row of input (rows,)
- class lamcts.classifier.SvmClassifier(lb: numpy.ndarray, ub: numpy.ndarray, svm='svc', kernel='rbf', gamma='auto', scaler='', use_features=False)¶
Bases:
lamcts.classifier.classifier.Classifier
A classifier using SVM for boundary, refer: https://scikit-learn.org/0.24/modules/generated/sklearn.svm.SVC.html for parameter details
- Parameters
lb – lower bounds of the inputs
ub – upper bounds of the inputs
svm – “svr” or “svc”
kernel – “linear”, “poly”, “rbf”, “sigmoid” or “precomputed”
gamma – “scale” or “auto”
scaler – input preprocessing scaler, “standard” or “minmx” or empty for no scalers
- classify(bag: lamcts.type.Bag) numpy.ndarray ¶
Classify input bag into clusters :param bag: input (rows, features) :return: label of each row of input (rows,)
- predict(xs: numpy.ndarray) numpy.ndarray ¶
Predict which cluster input belongs to :param xs: (rows, features) :return: labels of each row of input (rows,)
- class lamcts.classifier.KmeanSvmClassifier(lb: numpy.ndarray, ub: numpy.ndarray, svm='svc', kernel='rbf', gamma='auto', scaler='', use_features=False)¶
Bases:
lamcts.classifier.svm_classifier.SvmClassifier
A classifier using KMean for cluster and SVM for boundary
- class lamcts.classifier.ThresholdSvmClassifier(lb: numpy.ndarray, ub: numpy.ndarray, threshold_type: lamcts.config.config.ThresholdType = ThresholdType.Median, svm='svc', kernel='rbf', gamma='auto', scaler='', use_features=False)¶
Bases:
lamcts.classifier.svm_classifier.SvmClassifier
A classifier using threshold (median or mean) to divide samples and SVM for boundary
- class lamcts.classifier.RegressionSvmClassifier(lb: numpy.ndarray, ub: numpy.ndarray, threshold_type: lamcts.config.config.ThresholdType = ThresholdType.Median, regressor: str = 'ridge', svm='svc', kernel='rbf', gamma='auto', scaler='', use_features=False)¶
Bases:
lamcts.classifier.svm_classifier.SvmClassifier
A classifier using a regressor to fit samples, then threshold (median or mean) to divide samples, and SVM for boundary
Samplers¶
- class lamcts.sampler.Sampler(func: lamcts.func.Func, func_stats: lamcts.func.FuncStats)¶
Bases:
abc.ABC
Interface for samplers, a.k.a, optimizers or solvers
- abstract sample(num_samples: int, path: Optional[lamcts.node.Path] = None, **kwargs) lamcts.type.Bag ¶
Generate num_samples samples, on the leaf node of the path (if not none) :param num_samples: :param path: path from root to leaf :param kwargs: :return: sample bag
- class lamcts.sampler.RandomSampler(func: lamcts.func.Func, func_stats: lamcts.func.FuncStats)¶
Bases:
lamcts.sampler.sampler.Sampler
- TOTAL_RETRIES: ClassVar[int] = 50¶
- sample(num_samples: int, path: Optional[lamcts.node.Path] = None, **kwargs) lamcts.type.Bag ¶
Randomly sample num_samples. If path is given, samples are filtered by all SVM regions along the path
- Parameters
num_samples –
path –
kwargs –
- Returns
- class lamcts.sampler.BOSampler(func: lamcts.func.Func, func_stats: lamcts.func.FuncStats, acquisition: str = 'ei', nu: float = 1.5, gp_num_cands: int = 0, gp_max_samples: int = 0, batch_size: int = 0)¶
Bases:
lamcts.sampler.random_sampler.RandomSampler
- sample(num_samples: int, path: Optional[lamcts.node.Path] = None, **kwargs) lamcts.type.Bag ¶
Randomly sample num_samples. If path is given, samples are filtered by all SVM regions along the path
- Parameters
num_samples –
path –
kwargs –
- Returns
- class lamcts.sampler.TuRBOSampler(func: lamcts.func.Func, func_stats: lamcts.func.FuncStats, acquisition: str = 'ei', nu: float = 1.5, gp_max_samples: int = 0, gp_num_cands: int = 0, gp_training_steps: int = 50, gp_max_cholesky_size: int = 2000, batch_size: int = 5, init_tr_length: float = 0.8, min_tr_length: float = 0.0078125, max_tr_length: float = 1.6, tr_length_multiplier: float = 2.0, fail_threshold: int = 3, succ_threshold: int = 3, device: str = 'cuda')¶
Bases:
lamcts.sampler.random_sampler.RandomSampler
- sample(num_samples: int, path: Optional[lamcts.node.Path] = None, **kwargs) lamcts.type.Bag ¶
Randomly sample num_samples. If path is given, samples are filtered by all SVM regions along the path
- Parameters
num_samples –
path –
kwargs –
- Returns
- class lamcts.sampler.CmaesSampler(func: lamcts.func.Func, func_stats: lamcts.func.FuncStats, **kwargs)¶
Bases:
lamcts.sampler.sampler.Sampler
- sample(num_samples: int, path: Optional[lamcts.node.Path] = None, **kwargs) lamcts.type.Bag ¶
Generate num_samples samples, on the leaf node of the path (if not none) :param num_samples: :param path: path from root to leaf :param kwargs: :return: sample bag
- class lamcts.sampler.NevergradSampler(func: lamcts.func.Func, func_stats: lamcts.func.FuncStats, sample_center: lamcts.config.config.SampleCenter = SampleCenter.Median)¶
Bases:
lamcts.sampler.random_sampler.RandomSampler
- sample(num_samples: int, path: Optional[lamcts.node.Path] = None, **kwargs) lamcts.type.Bag ¶
Randomly sample num_samples. If path is given, samples are filtered by all SVM regions along the path
- Parameters
num_samples –
path –
kwargs –
- Returns
Utilies¶
- class lamcts.Sample(x, fx, feature)¶
- feature: numpy.ndarray¶
Associated features (optional)
- fx: float¶
Function value
- x: numpy.ndarray¶
Input
- class lamcts.Bag(xs: Union[numpy.ndarray, int], fxs: numpy.ndarray = array([], dtype=float64), features: Optional[numpy.ndarray] = None, is_minimizing: bool = False, is_discrete: Optional[numpy.ndarray] = None)¶
Bases:
object
- append(sample: lamcts.type.Sample) bool ¶
- property best: lamcts.type.Sample¶
- clear() Any ¶
- clone() lamcts.type.Bag ¶
- property dims: int¶
- extend(other) bool ¶
- property features: Optional[numpy.ndarray]¶
- property fxs: numpy.ndarray¶
- property is_discrete: numpy.ndarray¶
- property is_minimizing: bool¶
- property mean: float¶
- remove_duplicate(xs: numpy.ndarray) Tuple[numpy.ndarray, numpy.ndarray] ¶
- trim(size: int) Any ¶
- property x_bounds: Tuple[numpy.ndarray, numpy.ndarray]¶
- x_confidence_bounds(z: float = 1.0) Tuple[numpy.ndarray, numpy.ndarray] ¶
- property xs: numpy.ndarray¶
Configuration¶
- class lamcts.config.SearchType(value)¶
Bases:
enum.Enum
Search type, depth first (Vertical) or breadth first (Horizontal)
- Horizontal = 1¶
- Vertical = 0¶
- class lamcts.config.SamplerEnum(value)¶
Bases:
enum.Enum
Enums for builtin samplers
- BO_SAMPLER = 'bo'¶
- CMAES_SAMPLER = 'cmaes'¶
- NEVERGRAD_SAMPLER = 'nevergrad'¶
- RANDOM_SAMPLER = 'random'¶
- TURBO_SAMPLER = 'turbo'¶
- class lamcts.config.ClassifierEnum(value)¶
Bases:
enum.Enum
Enums for builtin classifiers
- KMEAN_SVM_CLASSIFIER = 'kmean_svm'¶
- REGRESSION_SVM_CLASSIFIER = 'regression_svm'¶
- THRESHOLD_SVM_CLASSIFIER = 'threshold_svm'¶
- lamcts.config.get_mcts_params(sampler: lamcts.config.config.SamplerEnum = SamplerEnum.RANDOM_SAMPLER, classifier: lamcts.config.config.ClassifierEnum = ClassifierEnum.KMEAN_SVM_CLASSIFIER)¶
Generate a template for MCTS configuration
- Parameters
sampler – Sampler to use
classifier – Classifier to use
- Returns
MCTS configuration