def piecewiseexp_diffevol(x, y, breaks=1, minwindow=14): #prepare the bounds and guess vectors, and the other constants that will be used in the inner optimizer guess = [1, 1 / 7] #initial count and initial growth rate bounds = [(1e-1, 1e3), (-10 / 7, 10 / 7) ] #bounds for initial count and initial growth rate alpha = 1 for i in range(breaks): guess.append(1 / 7) #growth rate after breakpoint bounds.append((-10 / 7, 10 / 7)) constants = { 'minwindow': minwindow, 'x': x, 'y': y, 'guess': guess, 'bounds': bounds, 'alpha': alpha } #bounds for the auxiliary variables that will be used to set the breakpoints #these auxiliary variables are optimized by differential_evolution() auxBounds = [(0, 1)] * breaks #find the optimal breakpoints res = differential_evolution(func=piecewiseexp_diffevol_inner, bounds=auxBounds, args=[constants]) #print(res) #do the regression for the optimum breakpoints aux = res.x breakpoints = aux_to_breakpoints(aux, x[0], x[-1], minwindow) params, likelihood, fit = fit_model(x, y, model_func=piecewiseexp, constants={'breakpoints': breakpoints}, loglik_func=loglik_negbin, guess=guess, bounds=bounds, alpha=alpha) return params, breakpoints, likelihood, fit
def piecewiseexp_diffevol_inner(aux, constants): x = constants['x'] y = constants['y'] bounds = constants['bounds'] guess = constants['guess'] alpha = constants['alpha'] breakpoints = aux_to_breakpoints(aux, x[0], x[-1], constants['minwindow']) params, likelihood, fit = fit_model(x, y, model_func=piecewiseexp, constants={'breakpoints': breakpoints}, loglik_func=loglik_negbin, guess=guess, bounds=bounds, alpha=alpha) return likelihood
def test_piecewiseexp(): x = np.arange(100) guess = [1, 3 / 7, -1 / 7, 1.5 / 7] bounds = [(1e-2, 1e3), (-2, 2), (-2, 2), (-2, 2)] breakpoints = [20, 70] #create some data y = piecewiseexp(x, guess, {'breakpoints': breakpoints}) y = np.random.poisson(y) plt.plot(x, y, "x") plt.yscale('log') #regression knowing the breakpoints alpha = 0.1 params, likelihood, fit = fit_model(x, y, model_func=piecewiseexp, constants={'breakpoints': breakpoints}, loglik_func=loglik_negbin, guess=guess, bounds=bounds, alpha=alpha) plt.plot(x, fit, "r:") #grid search regression to find the breakpoints #min_params, min_likelihood, min_fit, min_breakpoints, res = piecewiseexp_gridsearch(x,y,breaks=2,minwindow=14) #plt.plot(x, min_fit, "g-") #differential evolution search regression to find the breakpoints min_params, min_breakpoints, min_likelihood, min_fit = piecewiseexp_diffevol( x, y, breaks=2, minwindow=14) plt.plot(x, min_fit, "g-") plt.show()
def piecewiseexp_gridsearch(x, y, breaks=1, minwindow=14): alpha = 0.1 breakpoints = [(i + 1) * minwindow for i in range(breaks)] guess = [1, 1 / 7] #initial count and initial growth rate bounds = [(1e-1, 1e3), (-10 / 7, 10 / 7) ] #bounds for initial count and initial growth rate for i in range(breaks): guess.append(1 / 7) #growth rate after breakpoint bounds.append((-10 / 7, 10 / 7)) def reset_breakpoints(i): if i <= breaks - 1: breakpoints[i] = breakpoints[i - 1] + minwindow reset_breakpoints(i + 1) def next_breakpoint(i): breakpoints[i] = breakpoints[i] + 1 reset_breakpoints(i + 1) if i >= 1 and breakpoints[-1] > x[-1] - minwindow: next_breakpoint(i - 1) res = [] isFirst = True min_params = None min_likelihood = None min_fit = None min_breakpoints = None while (True): params, likelihood, fit = fit_model( x, y, model_func=piecewiseexp, constants={'breakpoints': breakpoints}, loglik_func=loglik_negbin, guess=guess, bounds=bounds, alpha=alpha) res.append({ 'params': params, 'breakpoints': breakpoints, 'likelihood': likelihood, 'fit': fit }) if isFirst: isFirst = False min_params = params min_likelihood = likelihood min_fit = fit min_breakpoints = breakpoints.copy() else: if likelihood < min_likelihood: min_params = params min_likelihood = likelihood min_fit = fit min_breakpoints = breakpoints.copy() next_breakpoint(breaks - 1) if breakpoints[-1] > x[-1] - minwindow: break return min_params, min_likelihood, min_fit, min_breakpoints, res