Specifying shape of parameter
kjdoore opened this issue · 1 comments
I was wondering if it is possible to specify the shape of a parameter to be more than a single value. Here is an example where I specify three parameters that all have the same prior hyperparameters.
import numpy as np
import spotpy
class spot_setup(object):
p1 = spotpy.parameter.Uniform(low=-10, high=10, optguess=1)
p2 = spotpy.parameter.Uniform(low=-10, high=10, optguess=1)
p3 = spotpy.parameter.Uniform(low=-10, high=10, optguess=1)
def __init__(self, nobs=1000, range=[-5, 5], p=[1, 2, 3]):
self.nobs = nobs
self.p = p
self.data_range = np.linspace(*range, nobs)
self.obs = np.polyval(self.p, self.data_range)
def simulation(self, x):
parameters = [x['p1'], x['p2'], x['p3']]
simulations = np.polyval(parameters, self.data_range)
return simulations
def evaluation(self):
return self.obs
def objectivefunction(self, simulation, evaluation):
objectivefunction = spotpy.objectivefunctions.rmse(
evaluation=evaluation, simulation=simulation
)
return objectivefunction
setup = spot_setup(nobs=50, p=[1, -5.2, 3])
sampler=spotpy.algorithms.sceua(setup, dbname='test_db', dbformat='csv')
sampler.sample(5000, ngs=20, kstop=3, peps=1e-10, pcento=1e-10)
What I am wanting is to be able to define one parameter p
that has three values that are solved for. This is possible in PyMC
with the shape
keyword in the prior (e.g., p = pymc.Uniform("p", lower=-10, upper=10, shape=(3))
) Is this something that can be done in spotpy
? If not, is there any idea of how to do something similar?
My actual problem utilizes an arbitrary number of parameters that vary with different runs. So, I am wanting a way to define each parameter automatically rather than having to define multiple lines of pX = spotpy.parameter.Uniform(low=-10, high=10, optguess=1)
, where pX is the Xth parameter. Thanks!
After looking at this some more, it appears that switching the parameters away from class variables and into the __init__
will work. It does not make a single parameter p
as I want, but it should suffice.
class spot_setup(object):
def __init__(self, nobs=1000, data_range=[-5, 5], p=[1, 2, 3]):
self.nobs = nobs
self.p = p
self.data_range = np.linspace(*data_range, nobs)
self.obs = np.polyval(self.p, self.data_range)
self.params = [spotpy.parameter.Uniform(name='p'+str(i), low=-10, high=10, optguess=0)
for i in range(len(self.p))]
# This is needed since parameters are defined in the init. Otherwise, if class
# variables (i.e., outside the init), they are generated automatically by the algorithm
def parameters(self):
return spotpy.parameter.generate(self.params)
def simulation(self, x):
parameters = [x['p'+str(i)] for i in range(len(self.p))]
simulations = np.polyval(parameters, self.data_range)
return simulations
def evaluation(self):
return self.obs
def objectivefunction(self, simulation, evaluation):
objectivefunction = spotpy.objectivefunctions.rmse(
evaluation=evaluation, simulation=simulation
)
return objectivefunction
setup = spot_setup(nobs=50, p=[1, -5.2, 3])
sampler=spotpy.algorithms.sceua(setup, dbname='test_db', dbformat='csv')
sampler.sample(5000, ngs=20, kstop=3, peps=1e-10, pcento=1e-10)