A simple parameter exploration
This notebook demonstrates a very simple parameter exploration of a custom function that we have defined. It is a simple function that returns the distance to a unit circle, so we expect our parameter exploration to resemble a circle.
# change to the root directory of the project
import os
if os.getcwd().split("/")[-1] == "examples":
os.chdir('..')
# This will reload all imports as soon as the code changes
%load_ext autoreload
%autoreload 2
try:
import matplotlib.pyplot as plt
except ImportError:
import sys
!{sys.executable} -m pip install matplotlib
import matplotlib.pyplot as plt
import numpy as np
from neurolib.utils.parameterSpace import ParameterSpace
from neurolib.optimize.exploration import BoxSearch
Define the evaluation function
Here we define a very simple evaluation function. The function needs to take in traj
as an argument, which is the pypet trajectory. This is how the function knows what parameters were assigned to it. Using the builtin function search.getParametersFromTraj(traj)
we can then retrieve the parameters for this run. They are returned as a dictionary and can be accessed in the function.
In the last step, we use search.saveToPypet(result_dict, traj)
to save the results to the pypet trajectory and to an HDF. In between, the computational magic happens!
def explore_me(traj):
pars = search.getParametersFromTraj(traj)
# let's calculate the distance to a circle
computation_result = abs((pars['x']**2 + pars['y']**2) - 1)
result_dict = {"distance" : computation_result}
search.saveToPypet(result_dict, traj)
Define the parameter space and exploration
Here we define which space we want to cover. For this, we use the builtin class ParameterSpace
which provides a very easy interface to the exploration. To initialize the exploration, we simply pass the evaluation function and the parameter space to the BoxSearch
class.
parameters = ParameterSpace({"x": np.linspace(-2, 2, 2), "y": np.linspace(-2, 2, 2)})
# info: chose np.linspace(-2, 2, 40) or more, values here are low for testing
search = BoxSearch(evalFunction = explore_me, parameterSpace = parameters, filename="example-1.1.hdf")
Run
And off we go!
search.run()
Get results
We can easily obtain the results from pypet. First we call search.loadResults()
to make sure that the results are loaded from the hdf file to our instance.
search.loadResults()
print("Number of results: {}".format(len(search.results)))
The runs are also ordered in a simple pandas dataframe called search.dfResults
. We cycle through all results by calling search.results[i]
and loading the desired result (here the distance to the circle) into the dataframe
for i in search.dfResults.index:
search.dfResults.loc[i, 'distance'] = search.results[i]['distance']
search.dfResults
And of course a plot can visualize the results very easily.
plt.imshow(search.dfResults.pivot_table(values='distance', index = 'x', columns='y'), \
extent = [min(search.dfResults.x), max(search.dfResults.x),
min(search.dfResults.y), max(search.dfResults.y)], origin='lower')
plt.colorbar(label='Distance to the unit circle')