class BootstrapRunner(AbstractRunner): def __init__(self, runnerArgument): """ Parameters ---------- runnerArgument: RunnerArgument Notes ----- 1. Uses METHOD_LEASTSQ for fitModel iterations. """ super().__init__() # self.lastErr = "" self.fitter = runnerArgument.fitter self.numIteration = runnerArgument.numIteration self.kwargs = runnerArgument.kwargs self.synthesizerClass = runnerArgument.synthesizerClass if "logger" in self.fitter.__dict__.keys(): self.logger = self.fitter.logger else: self.logger = Logger() self._isDone = not self._fitInitial() self.columns = self.fitter.selectedColumns # Initializations for bootstrap loop if not self.isDone: fittedTS = self.fitter.fittedTS.subsetColumns(self.columns, isCopy=False) self.synthesizer = self.synthesizerClass( observedTS=self.fitter.observedTS.subsetColumns(self.columns, isCopy=False), fittedTS=fittedTS, **self.kwargs) self.numSuccessIteration = 0 if self.fitter.minimizerResult is None: self.fitter.fitModel() self.baseChisq = self.fitter.minimizerResult.redchi self.curIteration = 0 self.fd = self.logger.getFileDescriptor() self.baseFittedStatistic = TimeseriesStatistic( self.fitter.observedTS.subsetColumns( self.fitter.selectedColumns, isCopy=False)) def report(self, id=None): if True: return if id is None: self._startTime = time.time() else: elapsed = time.time() - self._startTime print("%s: %2.3f" % (id, elapsed)) @property def numWorkUnit(self): return self.numIteration @property def isDone(self): return self._isDone def run(self): """ Runs the bootstrap. Returns ------- BootstrapResult """ def mkNullResult(): fittedStatistic = TimeseriesStatistic( self.fitter.observedTS[self.fitter.selectedColumns]) return BootstrapResult(self.fitter, 0, {}, fittedStatistic) # if self.isDone: return # Set up logging for this run if self.fd is not None: sys.stderr = self.fd sys.stdout = self.fd isSuccess = False bootstrapError = 0 self.report() for _ in range(ITERATION_MULTIPLIER): newObservedTS = self.synthesizer.calculate() self.report("newObservedTS") # Update fitter to use the new observed data _ = self.fitter._updateObservedTS(newObservedTS, isCheck=False) self.report("updated fitter") # Try fitting try: self.fitter.fitModel(params=self.fitter.params) self.report("fitter.fit") except Exception as err: # Problem with the fit. msg = "modelFitterBootstrap. Fit failed on iteration %d." \ % iteration self.logger.error(msg, err) bootstrapError += 1 continue # Verify that there is a result if self.fitter.minimizerResult is None: continue # Check if the fit is of sufficient quality if self.fitter.minimizerResult.redchi > MAX_CHISQ_MULT * self.baseChisq: continue if self.fitter.params is None: continue isSuccess = True self.report("break") break # Create the result if isSuccess: self.numSuccessIteration += 1 parameterDct = { k: [v] for k, v in self.fitter.params.valuesdict().items() } fittedStatistic = self.baseFittedStatistic.copy() fittedStatistic.accumulate( self.fitter.fittedTS.subsetColumns(self.fitter.selectedColumns, isCopy=False)) bootstrapResult = BootstrapResult(self.fitter, self.numSuccessIteration, parameterDct, fittedStatistic, bootstrapError=bootstrapError) else: bootstrapResult = mkNullResult() self._isDone = True # Close the logging file if self.fd is not None: if not self.fd.closed: self.fd.close() # See if completed work if self.numSuccessIteration >= self.numIteration: self._isDone = True return bootstrapResult def _fitInitial(self): """ Do the initial fit. Returns ------- bool successful fit """ isSuccess = False for _ in range(MAX_TRIES): try: self.fitter.fitModel() # Initialize model isSuccess = True break except Exception as err: self.lastErr = err msg = "Could not do initial fit" self.logger.error(msg, err) return isSuccess
class TestNamedTimeseries(unittest.TestCase): def setUp(self): self.timeseries = SIMPLE_TS self.statistic = TimeseriesStatistic(self.timeseries) def testConstructor(self): if IGNORE_TEST: return colnames = list(COLNAMES) colnames.remove(TIME) diff = set(self.statistic.colnames).symmetric_difference(colnames) self.assertEqual(len(diff), 0) def testAccumulate(self): if IGNORE_TEST: return self.statistic.accumulate(SIMPLE_TS) self.assertTrue(self.statistic.sumTS.equals(SIMPLE_TS)) def testCalculate1(self): if IGNORE_TEST: return for _ in range(SIMPLE_CNT): self.statistic.accumulate(SIMPLE_TS) self.statistic.calculate() self.assertEqual(self.statistic.count, SIMPLE_CNT) self.assertTrue(self.statistic.meanTS.equals(SIMPLE_TS)) stdTS = SIMPLE_TS.copy(isInitialize=True) self.assertTrue(self.statistic.stdTS.equals(stdTS)) def mkStatistics(self, count): result = [] for _ in range(count): statistic = TimeseriesStatistic(UNIFORM_TS) for _ in range(UNIFORM_CNT): statistic.accumulate( mkTimeseries(UNIFORM_LEN, COLNAMES, isRandom=True)) result.append(statistic) return result def evaluateStatistic(self, statistic, count=1): statistic.calculate() self.assertEqual(statistic.count, count * UNIFORM_CNT) mean = np.mean(statistic.meanTS.flatten()) self.assertLess(np.abs(mean - UNIFORM_MEAN), 0.1) std = np.mean(statistic.stdTS.flatten()) self.assertLess(np.abs(std - UNIFORM_STD), 0.1) for percentile in self.statistic.percentiles: value = np.mean(statistic.percentileDct[percentile].flatten()) self.assertLess(np.abs(value - 0.01 * percentile), 0.01) def testCalculate2(self): if IGNORE_TEST: return statistic = self.mkStatistics(1)[0] self.evaluateStatistic(statistic) def testEquals(self): if IGNORE_TEST: return statistic = TimeseriesStatistic(self.timeseries) self.assertTrue(self.statistic.equals(statistic)) # statistic.accumulate(SIMPLE_TS) self.assertFalse(self.statistic.equals(statistic)) def testCopy(self): if IGNORE_TEST: return statistic = self.statistic.copy() self.assertTrue(self.statistic.equals(statistic)) # statistic = self.mkStatistics(1)[0] self.assertTrue(statistic.equals(statistic)) def testMerge(self): if IGNORE_TEST: return NUM = 4 statistics = self.mkStatistics(NUM) statistic = TimeseriesStatistic.merge(statistics) statistic.calculate() self.evaluateStatistic(statistic, count=NUM) def testRpickleInterface(self): if IGNORE_TEST: return serialization = rpickle.Serialization(self.statistic) statistic = serialization.deserialize() self.assertTrue(statistic.meanTS.equals(self.statistic.meanTS))