def test_sum_of_squares_error_multi(self): """ Tests :class:`pints.MeanSquaredError` with multiple outputs. """ # Set up problem model = pints.toy.ConstantModel(2) times = [1, 2, 3] values = [[1, 4], [1, 4], [1, 4]] p = pints.MultiOutputProblem(model, times, values) # Test e = pints.SumOfSquaresError(p) self.assertEqual(e.n_parameters(), 2) float(e([1, 2])) self.assertEqual(e([1, 2]), 0) # 0 self.assertEqual(e([2, 2]), 3) # 3*(1^2+0^2) = 3 self.assertEqual(e([2, 3]), 15) # 3*(1^2+2^2) = 15 self.assertEqual(e([3, 4]), 60) # 3*(2^2+4^2) = 60 # Derivatives values = np.array([[1, 4], [2, 7], [3, 10]]) p = pints.MultiOutputProblem(model, times, values) e = pints.SumOfSquaresError(p) x = [1, 2] # Model outputs are 3 times [1,4] # Model derivatives are 3 times [[1, 0], [0, 1]] y, dy = p.evaluateS1(x) self.assertTrue(np.all(y == p.evaluate(x))) self.assertTrue(np.all(y[0, :] == [1, 4])) self.assertTrue(np.all(y[1, :] == [1, 4])) self.assertTrue(np.all(y[2, :] == [1, 4])) self.assertTrue(np.all(dy[0, :] == [[1, 0], [0, 1]])) self.assertTrue(np.all(dy[1, :] == [[1, 0], [0, 1]])) self.assertTrue(np.all(dy[2, :] == [[1, 0], [0, 1]])) # Check residuals rx = y - np.array(values) self.assertTrue(np.all(rx == np.array([[-0, -0], [-1, -3], [-2, -6]]))) self.assertAlmostEqual(e(x), np.sum(rx**2)) # Now with derivatives ex, dex = e.evaluateS1(x) # Check error self.assertTrue(np.all(ex == e(x))) # Check derivatives. Shape is (parameters, ) self.assertEqual(dex.shape, (2, )) # Residuals are: [[0, 0], [-1, -3], [-2, -6]] # Derivatives are: [[1, 0], [0, 1]] # dex1 is: 2 * (0 - 1 - 2) * 1 = 2 * -3 * 1 = -6 # dex2 is: 2 * (0 - 3 - 6) * 2 = 2 * -9 * 1 = -18 self.assertEqual(dex[0], -6) self.assertEqual(dex[1], -18)
def optimise(self, data, sigma_fac=0.001, method="minimisation"): cmaes_problem = pints.MultiOutputProblem(self, self.frequency_range, data) if method == "likelihood": score = pints.GaussianLogLikelihood(cmaes_problem) sigma = sigma_fac * np.sum(data) / 2 * len(data) lower_bound = [self.param_bounds[x][0] for x in self.params] + [0.1 * sigma] * 2 upper_bound = [self.param_bounds[x][1] for x in self.params] + [10 * sigma] * 2 CMAES_boundaries = pints.RectangularBoundaries( lower_bound, upper_bound) random_init = abs(np.random.rand(self.n_parameters())) x0 = self.change_norm_group(random_init, "un_norm", "list") + [sigma] * 2 cmaes_fitting = pints.OptimisationController( score, x0, sigma0=None, boundaries=CMAES_boundaries, method=pints.CMAES) elif method == "minimisation": score = pints.SumOfSquaresError(cmaes_problem) lower_bound = [self.param_bounds[x][0] for x in self.params] upper_bound = [self.param_bounds[x][1] for x in self.params] CMAES_boundaries = pints.RectangularBoundaries( lower_bound, upper_bound) random_init = abs(np.random.rand(self.n_parameters())) x0 = self.change_norm_group(random_init, "un_norm", "list") cmaes_fitting = pints.OptimisationController( score, x0, sigma0=None, boundaries=CMAES_boundaries, method=pints.CMAES) cmaes_fitting.set_max_unchanged_iterations(iterations=200, threshold=1e-7) #cmaes_fitting.set_log_to_screen(False) cmaes_fitting.set_parallel(True) found_parameters, found_value = cmaes_fitting.run() if method == "likelihood": sim_params = found_parameters[:-2] sim_data = self.simulate(sim_params, self.frequency_range) else: found_value = -found_value sim_params = found_parameters sim_data = self.simulate(sim_params, self.frequency_range) """ log_score = pints.GaussianLogLikelihood(cmaes_problem) stds=self.get_std(data, sim_data) sigma=sigma_fac*np.sum(data)/2*len(data) score_params=list(found_parameters)+[sigma]*2 found_value=log_score(score_params) print(stds, found_value, "stds")""" #DOITDIMENSIONALLY#NORMALISE DEFAULT TO BOUND return found_parameters, found_value, cmaes_fitting._optimiser._es.sm.C, sim_data
def test_stopping_on_ill_conditioned_covariance_matrix(self): # Tests that ill conditioned covariance matrices are detected. from scipy.integrate import odeint #TODO: A quicker test-case for this would be great! def OnePopControlODE(y, t, p): a, b, c = p dydt = np.zeros(y.shape) k = (a - b) / c * (y[0] + y[1]) dydt[0] = a * y[0] - b * y[0] - k * y[0] dydt[1] = k * y[0] - b * y[1] return dydt class Model(pints.ForwardModel): def simulate(self, parameters, times): y0 = [2000000, 0] solution = odeint( OnePopControlODE, y0, times, args=(parameters,)) return np.sum(np.array(solution), axis=1) def n_parameters(self): return 3 model = Model() times = [0, 0.5, 2, 4, 8, 24] values = [2e6, 3.9e6, 3.1e7, 3.7e8, 1.6e9, 1.6e9] problem = pints.SingleOutputProblem(model, times, values) score = pints.SumOfSquaresError(problem) x = [3.42, -0.21, 5e6] opt = pints.OptimisationController(score, x, method=method) with StreamCapture() as c: opt.run() self.assertTrue('Ill-conditioned covariance matrix' in c.text())
def test_evaluateS1_two_dim_array_multi_weighted(self): # Create an object with links to the model and time series problem = pints.MultiOutputProblem(self.model_multi, self.times, self.data_multi) # Create error measure with weighted inputs weights = [1, 2] error = pints.SumOfSquaresError(problem, weights=weights) # Evaluate likelihood for test parameters test_parameters = [3, 4] score, deriv = error.evaluateS1(test_parameters) # Check that returned error is correct self.assertEqual(score, error(test_parameters)) # Check that partial derivatives are returned for each parameter self.assertEqual(deriv.shape, (2, )) # Check that partials are correct # Expectation = [weight [0] * 2 * sum(input[0] - 1), # weight[1] * 4 * sum(2 * input[1] - 4)] self.assertEqual(deriv[0], weights[0] * 2 * 3 * (test_parameters[0] - 1)) self.assertEqual(deriv[1], weights[1] * 4 * 3 * (2 * test_parameters[1] - 4))
def _problem(self): import numpy as np import pints import pints.toy # Load a forward model model = pints.toy.LogisticModel() # Create some toy data xtrue = [0.015, 500] times = np.linspace(0, 1000, 1000) values = model.simulate(xtrue, times) # Add noise values += np.random.normal(0, 10, values.shape) # Create problem problem = pints.SingleOutputProblem(model, times, values) score = pints.SumOfSquaresError(problem) # Select some boundaries boundaries = pints.RectangularBoundaries([0, 400], [0.03, 600]) # Select a random starting point x0 = boundaries.sample(1)[0] # Select an initial sigma sigma0 = (1 / 6) * boundaries.range() return score, xtrue, x0, sigma0, boundaries
def test_sum_of_squares_error_single(self): """ Tests :class:`pints.MeanSquaredError` with a single output. """ # Set up problem model = pints.toy.ConstantModel(1) times = [1, 2, 3] values = [1, 1, 1] p = pints.SingleOutputProblem(model, times, values) # Test e = pints.SumOfSquaresError(p) self.assertEqual(e.n_parameters(), 1) float(e([1])) self.assertEqual(e([1]), 0) self.assertEqual(e([2]), 3) self.assertEqual(e([0]), 3) self.assertEqual(e([3]), 12) # Derivatives for x in [1, 2, 3, 4]: ex, dex = e.evaluateS1([x]) r = x - 1 self.assertEqual(ex, e([x])) self.assertEqual(dex.shape, (1, )) self.assertEqual(dex[0], 2 * 3 * r)
def setUpClass(cls): """ Prepare problem for tests. """ # Load a forward model model = pints.toy.LogisticModel() # Create some toy data real_parameters = [0.015, 500] times = np.linspace(0, 1000, 1000) org_values = model.simulate(real_parameters, times) # Add noise noise = 10 values = org_values + np.random.normal(0, noise, org_values.shape) real_parameters = np.array(real_parameters + [noise]) # Create an object with links to the model and time series problem = pints.SingleOutputProblem(model, times, values) # Create an error measure cls.score = pints.SumOfSquaresError(problem) cls.boundaries = pints.RectangularBoundaries([0, 400], [0.05, 600]) # Create a log-likelihood function (adds an extra parameter!) log_likelihood = pints.GaussianLogLikelihood(problem) # Create a uniform prior over both the parameters and the new noise cls.log_prior = pints.UniformLogPrior([0.01, 400, noise * 0.1], [0.02, 600, noise * 100]) # Create a posterior log-likelihood (log(likelihood * prior)) cls.log_posterior = pints.LogPosterior(log_likelihood, cls.log_prior)
def _problem(self): import numpy as np import pints import pints.toy # Load a forward model model = pints.toy.ActionPotentialModel() # Create some toy data xtrue = model.suggested_parameters() times = model.suggested_times() values = model.simulate(xtrue, times) # Add noise values[:, 0] += np.random.normal(0, 1, values[:, 0].shape) values[:, 1] += np.random.normal(0, 5e-7, values[:, 1].shape) # Create problem and a weighted score function problem = pints.MultiOutputProblem(model, times, values) weights = [1 / 70, 1 / 0.000006] score = pints.SumOfSquaresError(problem, weights=weights) # Select some boundaries lower = xtrue - 2 upper = xtrue + 2 boundaries = pints.RectangularBoundaries(lower, upper) # Select a random starting point x0 = boundaries.sample(1)[0] # Select an initial sigma sigma0 = (1 / 6) * boundaries.range() return score, xtrue, x0, sigma0, boundaries
def __init__(self, name): super(TestCMAES, self).__init__(name) # Create toy model self.model = toy.LogisticModel() self.real_parameters = [0.015, 500] self.times = np.linspace(0, 1000, 1000) self.values = self.model.simulate(self.real_parameters, self.times) # Create an object with links to the model and time series self.problem = pints.SingleSeriesProblem(self.model, self.times, self.values) # Select a score function self.score = pints.SumOfSquaresError(self.problem) # Select some boundaries self.boundaries = pints.Boundaries([0, 400], [0.03, 600]) # Set an initial position self.x0 = 0.014, 499 # Set a guess for the standard deviation around the initial position # (in both directions) self.sigma0 = 0.01 # Minimum score function value to obtain self.cutoff = 1e-9 # Maximum tries before it counts as failed self.max_tries = 3
def _problem(self): import numpy as np import pints import pints.toy # Create a model model = pints.toy.FitzhughNagumoModel() # Run a simulation xtrue = [0.1, 0.5, 3] times = np.linspace(0, 20, 200) values = model.simulate(xtrue, times) # Add some noise sigma = 0.5 noisy = values + np.random.normal(0, sigma, values.shape) # Create problem problem = pints.MultiOutputProblem(model, times, noisy) score = pints.SumOfSquaresError(problem) # Select boundaries boundaries = pints.RectangularBoundaries([0, 0, 0], [10, 10, 10]) # Select a random starting point x0 = boundaries.sample(1)[0] # Select an initial sigma sigma0 = (1 / 6) * boundaries.range() return score, xtrue, x0, sigma0, boundaries
def main(): #constants timeRangesToUse = [[1, 2499], [2549, 2999], [3049, 4999], [5049, 14999], [15049, 19999], [20049, 29999], [30049, 64999], [65049, 69999], [70049, -1]] true_parameters = [ 2.26E-04, 0.0699, 3.45E-05, 0.05462, 0.0873, 8.92E-03, 5.150E-3, 0.03158, 0.1524 ] model = ChannelModelPintsWrapper() data = pd.read_csv("data/averaged-data.txt", delim_whitespace=True) dat = extract_time_ranges(data.values, timeRangesToUse) times = dat[:, 0] values = dat[:, 1] current = model.simulate(true_parameters, times) plt.plot(times, values) plt.plot(times, current) plt.show() problem = pints.SingleOutputProblem(model, times, values) error = pints.SumOfSquaresError(problem) boundaries = MarkovModelBoundaries() x0 = np.array([0.1] * 9) found_parameters, found_value = pints.optimise(error, true_parameters, boundaries=boundaries) print(found_parameters, found_value)
def __init__(self, models: List[m.MultiOutputModel], times: List[np.ndarray], values: List[np.ndarray]): """Initialises a multi-output inference problem with default objective function pints.SumOfSquaresError and default optimiser pints.CMAES. Standard deviation in initial starting point of optimisation as well as restricted domain of support for inferred parameters is disabled by default. Arguments: models {List[m.MultiOutputModel]} -- Models, which parameters are to be inferred. times {List[np.ndarray]} -- Times of data points for the different models. values {List[np.ndarray]} -- State values of data points for the different models. Return: None """ # initialise problem container self.problem_container = [] for model_id, model in enumerate(models): self.problem_container.append(pints.MultiOutputProblem(model, times[model_id], values[model_id])) # initialise error function container self.error_function_container = [] for problem in self.problem_container: self.error_function_container.append(pints.SumOfSquaresError(problem)) # initialise optimiser self.optimiser = pints.CMAES # initialise fluctuations around starting point of optimisation self.initial_parameter_uncertainty = None # initialise parameter constraints self.parameter_boundaries = None # initialise outputs self.estimated_parameters = None self.objective_score = None
def optimise(self, x, parallel=False): """ Runs the optimisation, this method: (1) generates simulated data and adds noise (2) sets up the optimiser with the method given, trying to optimise the function f(x) = sum of squared error (3) runs the optimisation (4) returns: - the found parameters x, - the ratio of f(x) / f(x_0), where x_0 are the real parameters - time total time taken divided by the time taken to evaluate a single evaluation of f(x) """ the_model = self.model() print('model = ', the_model) values = the_model.simulate(self.real_parameters, self.times) value_range = np.max(values) - np.min(values) values += np.random.normal(0, self.noise * value_range, values.shape) problem = pints.MultiOutputProblem(the_model, self.times, values) score = pints.SumOfSquaresError(problem) middle = [0.5 * (u + l) for l, u in zip(self.lower, self.upper)] sigma = [(1.0/6.0)*(u - l) for l, u in zip(self.lower, self.upper)] print('sigma = ', sigma) boundaries = pints.RectangularBoundaries(self.lower, self.upper) optimisation = pints.Optimisation( score, middle, sigma0=sigma, boundaries=boundaries, method=self.method ) optimisation.optimiser().set_hyper_parameters(x) if parallel: optimisation.set_parallel(int(os.environ['OMP_NUM_THREADS'])) else: optimisation.set_parallel(False) start = timer() found_parameters, found_value = optimisation.run() end = timer() N = 10 start_score = timer() for i in range(N): minimum_value = score(self.real_parameters) end_score = timer() score_duration = (end_score - start_score) / N return found_parameters, \ found_value / minimum_value, \ (end - start) / score_duration
def setUpClass(cls): # Define objective function model = pints.toy.ConstantModel(1) times = np.linspace(1, 10) cls.true_params = [2.5] values = model.simulate(cls.true_params, times) problem = pints.SingleOutputProblem(model, times, values) cls.error = pints.SumOfSquaresError(problem) # Define initial parameters cls.params = [[3]] # Define boundaries cls.boundaries = pints.RectangularBoundaries(1, 5)
def test_call_two_dim_array_multi(self): # Create an object with links to the model and time series problem = pints.MultiOutputProblem(self.model_multi, self.times, self.data_multi) # Create error measure error = pints.SumOfSquaresError(problem) # Evaluate likelihood for test parameters test_parameters = [3, 4] score = error(test_parameters) # Check that error returns expected value # Exp = sum((input[0] - 1) ** 2) + sum((2 * input[1] - 4) ** 2) self.assertEqual(score, 60)
def main(): #constants timeRangesToUse = [[1,2499], [2549,2999], [3049,4999], [5049,14999], [15049,19999], [20049,29999], [30049,64999], [65049,69999], [70049,-1]] starting_parameters = [3.87068845e-04, 5.88028759e-02, 6.46971727e-05, 4.87408447e-02, 8.03073893e-02, 7.36295506e-03, 5.32908518e-03, 3.32254316e-02, 6.56614672e-02] model = ChannelModelPintsWrapper() data = pd.read_csv("data/averaged-data.txt", delim_whitespace=True) dat = extract_time_ranges(data.values, timeRangesToUse) times=dat[:,0] values=dat[:,1] current = model.simulate(starting_parameters, times) problem = pints.SingleOutputProblem(model, times, values) error = pints.SumOfSquaresError(problem) boundaries = MarkovModelBoundaries() x0 = np.array([0.1]*9) found_parameters, found_value = pints.optimise(error, starting_parameters, boundaries=boundaries) print(found_parameters, found_value)
def test_call_two_dim_array_single(self): # Convert data to array of shape (n_times, 1) values = np.reshape(self.data_single, (self.n_times, 1)) # Create an object with links to the model and time series problem = pints.SingleOutputProblem(self.model_single, self.times, values) # Create error measure error = pints.SumOfSquaresError(problem) # Evaluate likelihood for test parameters test_parameters = [3] score = error(test_parameters) # Check that error returns expected value # Expected = sum((input - 1) ** 2) self.assertEqual(score, 12)
def optimise(self): """ Parameter inference using SNES (Seperable Natural Evolution Strategy). Returns: --------------- found_parameters: - found optimal parameters """ #Define a score function, i.e the sum of squares error score = pints.SumOfSquaresError(self.problem) #Define the boundaries for F and k according to literature boundaries = pints.RectangularBoundaries([0.01, 0.01], [1.0, 1.0]) #Starting point within the boundaries x0 = [0.05, 0.05] #Run SNES found_parameters, found_value = pints.optimise(score, x0, boundaries=boundaries, method=pints.SNES) return found_parameters
def test_evaluateS1_two_dim_array_single(self): # Convert data to array of shape (n_times, 1) values = np.reshape(self.data_single, (self.n_times, 1)) # Create an object with links to the model and time series problem = pints.SingleOutputProblem(self.model_single, self.times, values) # Create error measure error = pints.SumOfSquaresError(problem) # Evaluate likelihood for test parameters test_parameters = [3] score, deriv = error.evaluateS1(test_parameters) # Check that returned error is correct self.assertEqual(score, error(test_parameters)) # Check that partial derivatives are returned for each parameter self.assertEqual(deriv.shape, (1, )) # Check that partials are correct # Expected = 2 * sum(input - 1) self.assertEqual(deriv, 2 * 3 * (test_parameters[0] - 1))
plt.ylabel('Vm (mV)') plt.plot(times, noisy_values[:, 0]) plt.plot(times, values[:, 0]) plt.subplot(2, 1, 2) plt.xlabel('Time (ms)') plt.ylabel('[Ca]i (mol/L)') plt.plot(times, noisy_values[:, 1]) plt.plot(times, values[:, 1]) #plt.show() # Create an object with links to the model and time series problem = pints.MultiOutputProblem(model, times, noisy_values) # Create a score function weights = [1 / 70, 1 / 0.000006] score = pints.SumOfSquaresError(problem, weights=weights) # Select some boundaries lower = x_true / 2 upper = x_true * 2 boundaries = pints.RectangularBoundaries(lower, upper) # Perform an optimization x0 = x_true * 1.2 optimiser = pints.OptimisationController(score, x0, boundaries=boundaries, method=pints.CMAES) print('Running...') x_found, score_found = optimiser.run()
def test_best_vs_guessed(self): # Tests tracking and logging of best and guessed values # Set up a problem model = pints.toy.LogisticModel() real = model.suggested_parameters() times = model.suggested_times() values = model.simulate(real, times) values += np.random.normal(0, 10, values.shape) problem = pints.SingleOutputProblem(model, times, values) f = pints.SumOfSquaresError(problem) b = pints.RectangularBoundaries([0, 200], [1, 1000]) x = [0, 700] # Check getting and setting tracking method np.random.seed(123) opt = pints.OptimisationController( f, x, boundaries=b, method=pints.SNES) self.assertFalse(opt.f_guessed_tracking()) opt.set_f_guessed_tracking(True) self.assertTrue(opt.f_guessed_tracking()) opt.set_f_guessed_tracking(False) self.assertFalse(opt.f_guessed_tracking()) # Check f_best and f_guessed with callback fb, fg = [], [] def cb(i, opt): fb.append(opt.f_best()) fg.append(opt.f_guessed()) # Run and check the logged values opt.set_callback(cb) opt.set_log_to_screen(False) opt.set_log_interval(1) with TemporaryDirectory() as d: p = d.path('out.csv') opt.set_log_to_file(p, csv=True) x1, f1 = opt.run() csv = np.genfromtxt(p, delimiter=',', skip_header=1)[:-1] lb = csv[:, 2] lg = csv[:, 3] del(csv) fb, fg = np.array(fb), np.array(fg) if debug: import matplotlib.pyplot as plt plt.figure() plt.semilogy() plt.plot(fb, label='best, callback') plt.plot(fg, label='guessed, callback') plt.plot(lb, '--', label='best, logged') plt.plot(lg, '--', label='guessed, logged') plt.legend() plt.show() self.assertTrue(np.all(fb == lb)) self.assertTrue(np.all(fg == lg)) self.assertFalse(np.all(lb == lg)) # Run again, but checking on f_guessed np.random.seed(123) opt2 = pints.OptimisationController( f, x, boundaries=b, method=pints.SNES) opt2.set_log_to_screen(False) opt2.set_f_guessed_tracking(True) x2, f2 = opt2.run() self.assertNotEqual(opt.iterations(), opt2.iterations()) self.assertAlmostEqual(f1, f2)
abs_vals=[0.12267918433476588, 0.10000001217777187, 110.7217695311136, 6.436119838423983e-09, 9.015056846897231, 2.300030530938936, 5.0949078241522905, 0.599999988589617] abs_vals=[0.1942552896092487, 1.6396496330592818, 53.46929098380687, 2.745723906710015e-09, 9.015061323815008, 4.022601263585928, 3.2663583722003433, 0.4804444355077191] cmaes_abs=LPMO.test_vals(abs_vals, "timeseries") plot_harmonics(LPMO.t_nondim(time_results), h_class, abs_time_series=LPMO.i_nondim(cmaes_abs), data_time_series=LPMO.i_nondim(current_results), xaxis=LPMO.e_nondim(voltage_results)) LPMO.def_optim_list(["E_0","k0_shape", "k0_scale","Ru","gamma","omega","cap_phase","phase", "alpha"]) true_data=current_results#LPMO.add_noise(cmaes_time, 0.0*max(cmaes_time)) exp_harms=h_class.generate_harmonics(LPMO.t_nondim(time_results), LPMO.i_nondim(true_data)) fourier_arg=LPMO.top_hat_filter(true_data) plot_harmonics(LPMO.t_nondim(time_results), h_class, noisy_time_series=true_data, base_time_series=cmaes_time, xaxis=voltage_results) if LPMO.simulation_options["likelihood"]=="timeseries": cmaes_problem=pints.SingleOutputProblem(LPMO, time_results, true_data) elif LPMO.simulation_options["likelihood"]=="fourier": dummy_times=np.linspace(0, 1, len(fourier_arg)) cmaes_problem=pints.SingleOutputProblem(LPMO, dummy_times, fourier_arg) score = pints.SumOfSquaresError(cmaes_problem) CMAES_boundaries=pints.RectangularBoundaries(list(np.zeros(len(LPMO.optim_list))), list(np.ones(len(LPMO.optim_list)))) num_runs=5 for i in range(0, num_runs): x0=abs(np.random.rand(LPMO.n_parameters())) starting_point=[orig_cmaes_results[ts_results_optim_list.index((param))] if param in ts_results_optim_list else LPMO.dim_dict[param] for param in LPMO.optim_list] print(starting_point) #x0=LPMO.change_norm_group(starting_point, "norm") print(len(x0), cmaes_problem.n_parameters(), CMAES_boundaries.n_parameters(), score.n_parameters()) cmaes_fitting=pints.OptimisationController(score, x0, sigma0=None, boundaries=CMAES_boundaries, method=pints.CMAES) cmaes_fitting.set_max_unchanged_iterations(iterations=200, threshold=1e-7) cmaes_fitting.set_parallel(not LPMO.simulation_options["test"])# found_parameters, found_value=cmaes_fitting.run() print(found_parameters) cmaes_results=LPMO.change_norm_group(found_parameters[:], "un_norm") print(list(cmaes_results))
def test_sum_of_errors(self): # Tests :class:`pints.SumOfErrors`. e1 = pints.SumOfSquaresError(MiniProblem()) e2 = pints.MeanSquaredError(MiniProblem()) e3 = pints.RootMeanSquaredError(BigMiniProblem()) e4 = pints.SumOfSquaresError(BadMiniProblem()) # Basic use e = pints.SumOfErrors([e1, e2]) x = [0, 0, 0] self.assertEqual(e.n_parameters(), 3) self.assertEqual(e(x), e1(x) + e2(x)) e = pints.SumOfErrors([e1, e2], [3.1, 4.5]) x = [0, 0, 0] self.assertEqual(e.n_parameters(), 3) self.assertEqual(e(x), 3.1 * e1(x) + 4.5 * e2(x)) e = pints.SumOfErrors([e1, e1, e1, e1, e1, e1], [1, 2, 3, 4, 5, 6]) self.assertEqual(e.n_parameters(), 3) self.assertEqual(e(x), e1(x) * 21) self.assertNotEqual(e(x), 0) with np.errstate(all='ignore'): e = pints.SumOfErrors([e4, e1, e1, e1, e1, e1], [10, 1, 1, 1, 1, 1]) self.assertEqual(e.n_parameters(), 3) self.assertEqual(e(x), float('inf')) e = pints.SumOfErrors([e4, e1, e1, e1, e1, e1], [0, 2, 0, 2, 0, 2]) self.assertEqual(e.n_parameters(), 3) self.assertTrue(e(x), 6 * e1(x)) e5 = pints.SumOfSquaresError(BadMiniProblem(float('-inf'))) e = pints.SumOfErrors([e1, e5, e1], [2.1, 3.4, 6.5]) self.assertTrue(np.isinf(e(x))) e = pints.SumOfErrors([e4, e5, e1], [2.1, 3.4, 6.5]) self.assertTrue(np.isinf(e(x))) e5 = pints.SumOfSquaresError(BadMiniProblem(float('nan'))) e = pints.SumOfErrors( [BadErrorMeasure(float('inf')), BadErrorMeasure(float('inf'))], [1, 1]) self.assertEqual(e(x), float('inf')) e = pints.SumOfErrors([ BadErrorMeasure(float('inf')), BadErrorMeasure(float('-inf')) ], [1, 1]) self.assertTrue(np.isnan(e(x))) e = pints.SumOfErrors( [BadErrorMeasure(5), BadErrorMeasure(float('nan'))], [1, 1]) self.assertTrue(np.isnan(e(x))) e = pints.SumOfErrors([e1, e5, e1], [2.1, 3.4, 6.5]) self.assertTrue(np.isnan(e(x))) e = pints.SumOfErrors([e4, e5, e1], [2.1, 3.4, 6.5]) self.assertTrue(np.isnan(e(x))) # Wrong number of ErrorMeasures self.assertRaises(ValueError, pints.SumOfErrors, [], []) # Wrong argument types self.assertRaises(TypeError, pints.SumOfErrors, [e1, e1], [e1, 1]) self.assertRaises(ValueError, pints.SumOfErrors, [e1, 3], [2, 1]) # Mismatching sizes self.assertRaises(ValueError, pints.SumOfErrors, [e1, e1, e1], [1, 1]) # Mismatching problem dimensions self.assertRaises(ValueError, pints.SumOfErrors, [e1, e1, e3], [1, 2, 3]) # Single-output derivatives model = pints.toy.ConstantModel(1) times = [1, 2, 3] p1 = pints.SingleOutputProblem(model, times, [1, 1, 1]) p2 = pints.SingleOutputProblem(model, times, [2, 2, 2]) e1 = pints.SumOfSquaresError(p1) e2 = pints.SumOfSquaresError(p2) e = pints.SumOfErrors([e1, e2], [1, 2]) x = [4] y, dy = e.evaluateS1(x) self.assertEqual(y, e(x)) self.assertEqual(dy.shape, (1, )) y1, dy1 = e1.evaluateS1(x) y2, dy2 = e2.evaluateS1(x) self.assertTrue(np.all(dy == dy1 + 2 * dy2)) # Multi-output derivatives model = pints.toy.ConstantModel(2) times = [1, 2, 3] p1 = pints.MultiOutputProblem(model, times, [[3, 2], [1, 7], [3, 2]]) p2 = pints.MultiOutputProblem(model, times, [[2, 3], [3, 4], [5, 6]]) e1 = pints.SumOfSquaresError(p1) e2 = pints.SumOfSquaresError(p2) e = pints.SumOfErrors([e1, e2], [1, 2]) x = [4, -2] y, dy = e.evaluateS1(x) self.assertEqual(y, e(x)) self.assertEqual(dy.shape, (2, )) y1, dy1 = e1.evaluateS1(x) y2, dy2 = e2.evaluateS1(x) self.assertTrue(np.all(dy == dy1 + 2 * dy2))
def test_sum_of_squares_error_weighted(self): """ Tests :class:`pints.MeanSquaredError` with weighted outputs. """ # Set up problem model = pints.toy.ConstantModel(2) times = [1, 2, 3] values = [[1, 4], [1, 4], [1, 4]] p = pints.MultiOutputProblem(model, times, values) # Test e = pints.SumOfSquaresError(p, weights=[1, 2]) self.assertRaisesRegex(ValueError, 'Number of weights', pints.SumOfSquaresError, p, weights=[1, 2, 3]) self.assertEqual(e.n_parameters(), 2) float(e([1, 2])) self.assertEqual(e([1, 2]), 0) # 0 self.assertEqual(e([2, 2]), 3) # 3*(1^2*1+0^2*2) = 3 self.assertEqual(e([2, 3]), 27) # 3*(1^2*1+2^2*2) = 27 self.assertEqual(e([3, 4]), 108) # 3*(2^2*1+4^2*2) = 108 # Derivatives values = np.array([[1, 4], [2, 7], [3, 10]]) p = pints.MultiOutputProblem(model, times, values) w = np.array([1, 2]) e = pints.SumOfSquaresError(p, weights=w) x = [1, 2] # Model outputs are 3 times [1, 4] # Model derivatives are 3 times [[1, 0], [0, 1]] y, dy = p.evaluateS1(x) self.assertTrue(np.all(y == p.evaluate(x))) self.assertTrue(np.all(y[0, :] == [1, 4])) self.assertTrue(np.all(y[1, :] == [1, 4])) self.assertTrue(np.all(y[2, :] == [1, 4])) self.assertTrue(np.all(dy[0, :] == [[1, 0], [0, 1]])) self.assertTrue(np.all(dy[1, :] == [[1, 0], [0, 1]])) self.assertTrue(np.all(dy[2, :] == [[1, 0], [0, 1]])) # Check residuals rx = y - np.array(values) self.assertTrue(np.all(rx == np.array([[-0, -0], [-1, -3], [-2, -6]]))) self.assertAlmostEqual(e(x), np.sum(np.sum(rx**2, axis=0) * w)) # Now with derivatives ex, dex = e.evaluateS1(x) # Check error self.assertAlmostEqual(ex, e(x)) # Check derivatives. Shape is (parameters, ) self.assertEqual(dex.shape, (2, )) # Residuals are: [[0, 0], [-1, -3], [-2, -6]] # Derivatives are: [[1, 0], [0, 1]] # dex1 is: 2 * (0 - 1 - 2) * 1 * 1 # = 2 * -3 * 1 * 1 # = -6 # dex2 is: 2 * (0 - 3 - 6) * 2 * 1 # = 2 * -9 * 2 * 1 # = -36 self.assertEqual(dex[0], -6) self.assertEqual(dex[1], -36)
def main(args, output_dir="", ms_to_remove_after_spike=50): output_dir = os.path.join(args.output, output_dir) if not os.path.exists(output_dir): os.mkdir(output_dir) # Constants if ms_to_remove_after_spike == 0: indices_to_remove = None else: spikes = [2500, 3000, 5000, 15000, 20000, 30000, 65000, 70000] indices_to_remove = [[spike, spike + ms_to_remove_after_spike*10] for spike in spikes] indices_to_use = remove_indices(list(range(80000)), indices_to_remove) # indices_to_use = [[1,2499], [2549,2999], [3049,4999], [5049,14999], [15049,19999], [20049,29999], [30049,64999], [65049,69999], [70049,-1]] starting_parameters = [3.87068845e-04, 5.88028759e-02, 6.46971727e-05, 4.87408447e-02, 8.03073893e-02, 7.36295506e-03, 5.32908518e-03, 3.32254316e-02, 6.56614672e-02] plt.rcParams['axes.axisbelow'] = True data = pd.read_csv(args.data_file_path, delim_whitespace=True) print("outputting to {}".format(args.output)) if not os.path.exists(args.data_file_path): print("Input file not provided. Doing nothing.") return par = Params() skip = int(par.timestep/0.1) dat = data.values[indices_to_use] times=dat[:,0] values=dat[:,1] model = PintsWrapper(par, args, times) current = model.simulate(starting_parameters, times) if args.plot: plt.plot(times, values) plt.plot(model.times_to_use, current) plt.show() problem = pints.SingleOutputProblem(model, times, values) error = pints.SumOfSquaresError(problem) boundaries = Boundaries() x0 = starting_parameters found_parameters, found_value = pints.optimise(error, starting_parameters, boundaries=boundaries) # found_parameters = np.array([2.26E-04, 0.0699, 3.45E-05, 0.05462, 0.0873, 8.92E-03, 5.150E-3, 0.03158, 0.1524]) # found_value = 100 print("finished! found parameters : {} ".format(found_parameters, found_value)) # Find error sensitivities funcs = model.funcs current, sens = funcs.SimulateForwardModelSensitivities(found_parameters) sens = (sens * found_parameters[None,:]).T for i, vec in enumerate(sens): plt.plot(times, vec, label="state_variable".format(i)) plt.title("Output sensitivities for four gate Markov Model") if args.plot: plt.show() else: plt.savefig(os.path.join(output_dir, "output_sensitivities")) plt.clf() # Estimate the various of the i.i.d Gaussian noise nobs = len(times) sigma2 = sum((current - values)**2)/(nobs-1) # Compute the Fischer information matrix FIM = sens @ sens.T/sigma2 cov = FIM**-1 eigvals = np.linalg.eigvals(FIM) for i in range(0, par.n_params): for j in range(i+1, par.n_params): parameters_to_view = np.array([i,j]) sub_cov = cov[parameters_to_view[:,None], parameters_to_view] eigen_val, eigen_vec = np.linalg.eigh(sub_cov) eigen_val=eigen_val.real if eigen_val[0] > 0 and eigen_val[1] > 0: print("COV_{},{} : well defined".format(i, j)) cov_ellipse(sub_cov, q=[0.75, 0.9, 0.99]) plt.ylabel("parameter {}".format(i)) plt.xlabel("parameter {}".format(j)) if args.plot: plt.show() else: plt.savefig(os.path.join(output_dir, "covariance_for_parameters_{}_{}".format(i,j))) plt.clf() else: print("COV_{},{} : negative eigenvalue".format(i,j)) print('Eigenvalues of FIM:\n{}'.format(eigvals)) print("Covariance matrix is: \n{}".format(cov)) plt.plot(data["time"], data["current"], label="averaged data") plt.plot(times, current, label="current") plt.legend() if args.plot: plt.show() else: plt.savefig(os.path.join(output_dir, "fit")) plt.clf() return times, found_parameters
model, prot, script = myokit.load('./PKPD_linear.mmt') s = myokit.Simulation(model, prot) # Format the values list to use it in PINTS fit_values = values[0] + values[1] # Calling PINTS library # Parameters : [CL, Vc, Qp1, Vp1, Qp2, Vp2] initial_point = [5.4, 8.5, 18.6, 8.3, 1.7, 32.8] problem = pints.SingleOutputProblem(model=MyModel(), times=np.linspace(0, 24, 10), values=fit_values) boundaries = pints.RectangularBoundaries([3, 5, 7, 5, 0.5, 30], [15, 15, 30, 20, 5, 60]) error_measure = pints.SumOfSquaresError(problem) found_parameters, found_value = pints.optimise(error_measure, initial_point, boundaries=boundaries, method=pints.XNES) #%% Running the simulation with found parameters # Reset the variables to initial state for the plot s.reset() # Use parameters returned from optimisation or user-defined parameters set parameters = [6.7, 10.1, 17.8, 9.4, 1.4, 18.3] plot_parameters = found_parameters s.set_constant('constants.CL', plot_parameters[0]) s.set_constant('plasma.Vc', plot_parameters[1]) s.set_constant('constants.kp1', plot_parameters[2])
def infer_params(initial_point, data_exp, boundaries_low, boundaries_high, pints_method=pints.XNES, parallel=False): """ Infers parameters using PINTS library pnits.optimise() function, using method pints.XNES, and rectangular boundaries. :param initial_point: list Starting point for optimisation. It has to match the length of fitting parameters annotations. :param data_exp: Data_exp Contains the data that the model is fitted too. See documentation for sabs_pkpd.load_data for further info :param boundaries_low: list List of lower boundaries for the fitted parameters. It has to match the length of fitting parameters annotations :param boundaries_high: list List of lower boundaries for the fitted parameters. It has to match the length of fitting parameters annotations :return: found_parameters : numpy.array List of parameters values after optimisation routine. """ if len(initial_point) != \ len(data_exp.fitting_instructions.fitted_params_annot): raise ValueError('The initial point should have the same length as ' 'the fitted parameters annotations ' '(defined in data_exp.fitting_instructions') if len(boundaries_low) != \ len(data_exp.fitting_instructions.fitted_params_annot): raise ValueError('The lower boundaries should have the same length as ' 'the fitted parameters annotations ' '(defined in data_exp.fitting_instructions') if len(boundaries_high) != \ len(data_exp.fitting_instructions.fitted_params_annot): raise ValueError('The higher boundaries should have the same length ' 'as the fitted parameters annotations ' '(defined in data_exp.fitting_instructions') fit_values = np.concatenate(data_exp.values) sabs_pkpd.constants.n = len( sabs_pkpd.constants.data_exp.fitting_instructions.fitted_params_annot) problem = pints.SingleOutputProblem( model=MyModel(), times=np.linspace(0, 1, len(fit_values)), values=fit_values) boundaries = pints.RectangularBoundaries(boundaries_low, boundaries_high) error_measure = pints.SumOfSquaresError(problem) optimiser = pints.OptimisationController(error_measure, initial_point, boundaries=boundaries, method=pints_method) optimiser.set_parallel(parallel=parallel) found_parameters, found_value = optimiser.run() print(data_exp.fitting_instructions.fitted_params_annot) print(found_parameters) return found_parameters, found_value