def __init__(self, *args, **kwargs): # Run the constructors for the parent classes ModelFitterCore.__init__(self, *args, **kwargs) AbstractCrossValidator.__init__(self) # Handle case of deserialize if "observedTS" in self.__dict__.keys(): self.numPoint = len(self.observedTS)
def __init__(self, modelSpecification, observedTS, parametersToFit, trainIdxs=None, testIdxs=None, **kwargs): """ Parameters ---------- modelSpecification: str antimony model observedTS: NamedTimeseries parametersToFit: list-str/SBstoat.Parameter/None parameters in the model that you want to fit if None, no parameters are fit trainIdxs: list-int rows of observedData used for estimating parameters testIdxs: list-int rows of observedData used for scoring fit """ super().__init__() self.trainIdxs = trainIdxs self.testIdxs = testIdxs self.observedTS = observedTS if self.trainIdxs is None: self.trainIdxs = list(range(len(self.observedTS))) if self.testIdxs is None: self.testIdxs = list(range(len(self.observedTS))) self.trainTS = observedTS[self.trainIdxs] self.testTS = observedTS[self.testIdxs] self.modelFitter = ModelFitterCore(modelSpecification, self.trainTS, parametersToFit, **kwargs) self.columns = self.modelFitter.selectedColumns self.testObservedArr = self.testTS[self.columns]
def testNoneParameters(self): if IGNORE_TEST: return self._init() fitter = ModelFitterCore(th.ANTIMONY_MODEL, self.timeseries, None) fitter.fitModel() self.assertIsNone(fitter.params) self.assertGreater(len(fitter.fittedTS), 0)
def test(method): fitter = ModelFitterCore(th.ANTIMONY_MODEL, self.timeseries, list(th.PARAMETER_DCT.keys()), fitterMethods=method) fitter.fitModel() for parameter in ["k1", "k2", "k3", "k4", "k5"]: diff = np.abs(th.PARAMETER_DCT[parameter] - dct[parameter]) frac = diff/dct[parameter] self.assertLess(diff/dct[parameter], 5.0)
def calc(method, probNan=0.2): nanTimeseries = self.timeseries.copy() for col in self.timeseries.colnames: for idx in range(len(nanTimeseries)): if np.random.random() <= probNan: nanTimeseries[col][idx] = np.nan fitter = ModelFitterCore(th.ANTIMONY_MODEL, nanTimeseries, list(th.PARAMETER_DCT.keys()), fitterMethods=method) fitter.fitModel() diff = np.abs(th.PARAMETER_DCT[PARAMETER] - fitter.params.valuesdict()[PARAMETER]) return diff
def test(col, func, maxDifference=0.0): timeseries = self.timeseries.copy() timeseries[col] = func(timeseries) fittedDataTransformDct = {col: func} fitter = ModelFitterCore(th.ANTIMONY_MODEL, timeseries, list(th.PARAMETER_DCT.keys()), fittedDataTransformDct=fittedDataTransformDct) fitter.fitModel() for name in self.fitter.params.valuesdict().keys(): value1 = self.fitter.params.valuesdict()[name] value2 = fitter.params.valuesdict()[name] diff = np.abs(value1-value2) self.assertLessEqual(diff, maxDifference)
def test(method): compareDct = {} for numFitRepeat in NUM_FIT_REPEATS: fitter = ModelFitterCore(th.ANTIMONY_MODEL, self.timeseries, list(th.PARAMETER_DCT.keys()), fitterMethods=method, numFitRepeat=numFitRepeat) fitter.fitModel() compareDct[numFitRepeat] = self.checkParameterValues() for parameter in ["k1", "k2", "k3", "k4", "k5"]: first = NUM_FIT_REPEATS[0] last = NUM_FIT_REPEATS[1] self.assertLessEqual(compareDct[first][parameter], compareDct[last][parameter])
def testSelectCompatibleIndices(self): if IGNORE_TEST: return SIZE = 10 SUB_SIZE = 5 bigTimes = np.array(range(SIZE)) smallTimes = np.random.permutation(bigTimes)[:SUB_SIZE] smallTimes = np.sort(smallTimes) resultArr = ModelFitterCore.selectCompatibleIndices( bigTimes, smallTimes) np.testing.assert_array_equal(smallTimes, resultArr)
def testGetFittedModel(self): if IGNORE_TEST: return self._init() fitter1 = ModelFitterCore(th.ANTIMONY_MODEL, self.timeseries, list(th.PARAMETER_DCT.keys())) fitter1.fitModel() fittedModel = fitter1.getFittedModel() fitter2 = ModelFitterCore(fittedModel, self.timeseries, list(th.PARAMETER_DCT.keys())) fitter2.fitModel() # Should get same fit without changing the parameters std1 = np.var(fitter1.residualsTS.flatten()) std2 = np.var(fitter2.residualsTS.flatten()) if tcn.IGNORE_ACCURACY: return self.assertTrue(np.isclose(std1, std2, rtol=0.1))
def testrpConstruct(self): if IGNORE_TEST: return fitter = ModelFitterCore.rpConstruct() def updateAttr(attr): if not attr in fitter.__dict__.keys(): fitter.__setattr__(attr, None) # updateAttr("roadrunnerModel") updateAttr("observedTS") self.assertIsNone(self.fitter.roadrunnerModel) self.assertIsNone(fitter.observedTS)
def testInitializeParams(self): if IGNORE_TEST: return LOWER = -10 UPPER = -1 VALUE = -5 NEW_SPECIFICATION = mf.ParameterSpecification(lower=LOWER, upper=UPPER, value=VALUE) DEFAULT_SPECIFICATION = mf.ParameterSpecification( lower=mf.PARAMETER_LOWER_BOUND, upper=mf.PARAMETER_UPPER_BOUND, value=(mf.PARAMETER_LOWER_BOUND + mf.PARAMETER_UPPER_BOUND) / 2, ) def test(params, exceptions=[]): def check(parameter, specification): self.assertEqual(parameter.min, specification.lower) self.assertEqual(parameter.max, specification.upper) self.assertEqual(parameter.value, specification.value) # names = params.valuesdict().keys() for name in names: parameter = params.get(name) if name in exceptions: check(parameter, NEW_SPECIFICATION) else: check(parameter, DEFAULT_SPECIFICATION) # fitter = ModelFitterCore( self.fitter.modelSpecification, self.fitter.observedTS, #self.fitter.parametersToFit, parameterDct={"k1": NEW_SPECIFICATION}, ) params = fitter.mkParams() test(params, exceptions=["k1"]) # params = self.fitter.mkParams() test(params, []) # fitter = ModelFitterCore( self.fitter.modelSpecification, self.fitter.observedTS, parameterDct={"k1": (LOWER, UPPER, VALUE)}, ) params = fitter.mkParams() test(params, exceptions=["k1"])
class ModelFitterWrapper(AbstractFitter): def __init__(self, modelSpecification, observedTS, parametersToFit, trainIdxs=None, testIdxs=None, **kwargs): """ Parameters ---------- modelSpecification: str antimony model observedTS: NamedTimeseries parametersToFit: list-str/SBstoat.Parameter/None parameters in the model that you want to fit if None, no parameters are fit trainIdxs: list-int rows of observedData used for estimating parameters testIdxs: list-int rows of observedData used for scoring fit """ super().__init__() self.trainIdxs = trainIdxs self.testIdxs = testIdxs self.observedTS = observedTS if self.trainIdxs is None: self.trainIdxs = list(range(len(self.observedTS))) if self.testIdxs is None: self.testIdxs = list(range(len(self.observedTS))) self.trainTS = observedTS[self.trainIdxs] self.testTS = observedTS[self.testIdxs] self.modelFitter = ModelFitterCore(modelSpecification, self.trainTS, parametersToFit, **kwargs) self.columns = self.modelFitter.selectedColumns self.testObservedArr = self.testTS[self.columns] @property def parameters(self): """ Returns ------- lmfit.Parameters """ return self.modelFitter.params def fit(self): """ Estimates parameters. Parameters ---------- Returns ------- """ self.modelFitter.fitModel() def score(self): """ Returns an R^2 for predicting testData Parameters ---------- Returns ------- float """ fullFittedTS = self.modelFitter.runSimulation( parameters=self.modelFitter.params, modelSpecification=self.modelFitter.modelSpecification, endTime=self.observedTS.end, numPoint=len(self.observedTS), _logger=self.modelFitter.logger, _loggerPrefix=self.modelFitter._loggerPrefix, ) testFittedArr = fullFittedTS[self.modelFitter.selectedColumns] testFittedArr = testFittedArr[self.testIdxs, :] residualsArr = self.testObservedArr - testFittedArr rsq = 1 - np.var(residualsArr.flatten()) \ / np.var(self.testObservedArr.flatten()) return rsq
def test(parametersToFit): result = ModelFitterCore.mkParameters( parametersToFit=parametersToFit) self.assertTrue(isinstance(result, lmfit.Parameters)) self.assertEqual(len(result.valuesdict()), len(parametersToFit))