Package: pyepal
Continuous integrationCode healthDocumentation and tutorialSocialPythonLicenseCitationGeneralized Python implementation of a modified version of the ε-PAL algorithm [1,2].For more detailed docsgo here.InstallationTo install the latest stable release usepip install pyepalto install the latest development version from the head usepip install git+https://github.com/kjappelbaum/pyepal.gitDevelopers can install the extras[testing, docs, pre-commit]. Installation should take only a few minutes.Additional NotesOn MacOS you might need to installlibomp(e.g.,brew install libomp) for multithreading in some of the models.We currently support Python 3.7 and 3.8.UsageThe main logic is implemented in thePALBaseclass. There are some prebuilt classes for common use cases (GPy,sklearn) that inherit from this class.
For more details about how to use the code and notes about the tutorialssee the docs.Pre-Built classesscikit-learnIf you want to use a list ofsklearnmodels, you can use thePALSklearnclass. To use it for one step,
you can follow the following code snippet. The basic principle is the same for all the differentPALclasses.frompyepalimportPALSklearnfromsklearn.gaussian_processimportGaussianProcessRegressorfromsklearn.gaussian_process.kernelsimportRBF,Matern# For each objective, initialize a modelgpr_objective_0=GaussianProcessRegressor(RBF())gpr_objective_1=GaussianProcessRegressor(RBF())# The minimal input to create a PAL instance is a list of models,# the design space (X, in ML terms "feature matrix") and the number of objectivespalsklearn_instance=PALSklearn(X,[gpr_objective_0,gpr_objective_1],2)# the next step is to provide some initial measurements.# You can do this with the update_train_set function, which you# can use throughout the active learning process to update the training set.# For this, provide a numpy array of indices in your design space# and the corresponding measurementssampled_indices=np.array([1,2,3])measurements=np.array([[1,2],[0.8,1],[7,1]])palsklearn_instance.update_train_set(sampled_indices,measurements)# Now, you're ready to run the first iteration.# This will return the next index to sample and update all the attributes# If there are no unclassified samples left, it will return None and# print a statement saying that the classification is completedindex_to_sample=palsklearn_instance.run_one_step()GPyIf you want to use a list ofGPymodels, you can use thePALGPyclass.Coregionalized GPRCoregionalized GPR models can utilize correlations between the objectives and also work in the cases in which some of the objectives are not measured for all samples.Custom classesYou will need to implement the_train()and_predict()functions if you inherit fromPALBase. If you want to tune the hyperparameters of your models while new training points are added, you can implement a schedule by setting the_should_optimize_hyperparameters()function and the_set_hyperparameters()function, which sets the hyperparameters for the model(s).If you need to train a model, useself.design_spaceas the feature matrix andself.yas the target vector. Note that inself.yall objectives are turned into maximization problems. That is, if one of your problems is a minimization problem, PyePAL will flip its sign inself.y.A basic example of how a custom class can be implemented is thePALSklearnclass:classPALSklearn(PALBase):"""PAL class for a list of Sklearn (GPR) models, with one model per objective"""def__init__(self,*args,**kwargs):super().__init__(*args,**kwargs)validate_number_models(self.models,self.ndim)def_train(self):fori,modelinenumerate(self.models):model.fit(self.design_space[self.sampled],self.y[self.sampled,i].reshape(-1,1))def_predict(self):means,stds=[],[]formodelinself.models:mean,std=model.predict(self.design_space,return_std=True)means.append(mean.reshape(-1,1))stds.append(std.reshape(-1,1))self.means=np.hstack(mean)self.std=np.hstack(stds)For scheduling of the hyperparameter optimization, we have some predefined schedules in thepyepal.pal.schedulesmodule.Test the algorithmsIf the full design space is known, you can use a while loop to fully explore the space with PyePAL.
For the theoretical guarantees of PyePAL to hold, you'll need to sample until all uncertainties are below epsilon. In practice, it is usually enough to require as a termination criterion that there are no unclassified samples left. For this you can use the following snippetfrompyepal.utilsimportexhaust_loopfrompyepal.models.gprimportbuild_model# indices for initializationsample_idx=np.array([0,1,2,3,4,5,6,7,8,9,10,50,60,70])# build one model per objectivemodel_0=build_model(X[sample_idx],y[sample_idx],0)model_1=build_model(X[sample_idx],y[sample_idx],1)# initialize the PAL instancepalinstance=PALGPy(X,[model_0,model_1],2,beta_scale=1)palinstance.update_train_set(sample_idx,y[sample_idx])# This will run the sampling and training as long as there# are unclassified samplesexhaust_loop(palinstance,y)To measure the performance, you can use theget_hypervolumefunction frompyepal.pal.utils. More indicators are implemented in packages likedeap,pagmo, orpymoo.ReferencesZuluaga, M.; Krause, A.; Püschel, M. E-PAL: An Active Learning Approach to the Multi-Objective Optimization Problem. Journal of Machine Learning Research 2016, 17 (104), 1–32.Zuluaga, M.; Sergent, G.; Krause, A.; Püschel, M. Active Learning for Multi-Objective Optimization; Dasgupta, S., McAllester, D., Eds.; Proceedings of machine learning research; PMLR: Atlanta, Georgia, USA, 2013; Vol. 28, pp 462–470.CitationIf you find this code useful for your work, please cite:Our paper that describes the implementation and an application to materials discovery:Jablonka, K. M.; Giriprasad, M. J.; Wang, S.; Smit, B.; Yoo, B. Bias Free Multiobjective Active Learning for Materials Design and Discovery, ChemRxiv 2020 (10.26434/chemrxiv.13200197.v1).The original paper that describes the ε-PAL algorithm:Zuluaga, M.; Krause, A.; Püschel, M. E-PAL: An Active Learning Approach to the Multi-Objective Optimization Problem. Journal of Machine Learning Research 2016, 17 (104), 1–32.AcknowledgmentsThe research was supported by the European Research Council (ERC) under the European Union’s Horizon 2020 research and innovation programme (grant agreement 666983, MaGic), by theNCCR-MARVEL, funded by the Swiss National Science Foundation, and by the Swiss National Science Foundation (SNSF) under Grant 200021_172759. Part of the work was performed as part of theExplore Together internship program at BASF.