def test_mean_squared_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.MeanSquaredError(p) self.assertEqual(e.n_parameters(), 2) float(e([1, 2])) self.assertEqual(e([1, 2]), 0) # 0 self.assertEqual(e([2, 2]), 0.5) # (3*(1^2+0^2)) / 6 = (1^2+0^2) / 2 self.assertEqual(e([2, 3]), 2.5) # (1^2+2^2) / 2 = 2.5 self.assertEqual(e([3, 4]), 10) # (2^2+4^2) / 2 = 10 # Derivatives values = np.array([[1, 4], [2, 7], [3, 10]]) p = pints.MultiOutputProblem(model, times, values) e = pints.MeanSquaredError(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) / 6) # 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 / nt / no) * (0 - 1 - 2) * 1 = (1 / 3) * -3 * 1 = -1 # dex2 is: (2 / nt / no) * (0 - 3 - 6) * 1 = (1 / 3) * -9 * 1 = -3 self.assertEqual(dex[0], -1) self.assertEqual(dex[1], -3)
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.MeanSquaredError(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] * mean(input[0] - 1), # weight[1] * 2 * mean(2 * input[1] - 4)] self.assertEqual(deriv[0], weights[0] * (test_parameters[0] - 1)) self.assertEqual(deriv[1], weights[1] * 2 * (2 * test_parameters[1] - 4))
def test_mean_squared_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.MeanSquaredError(p) self.assertEqual(e.n_parameters(), 1) float(e([1])) self.assertEqual(e([1]), 0) self.assertEqual(e([2]), 1) self.assertEqual(e([0]), 1) self.assertEqual(e([3]), 4) # Derivatives for x in [1, 2, 3, 4]: y, dy = e.evaluateS1([x]) r = x - 1 self.assertEqual(y, e([x])) self.assertEqual(dy.shape, (1, )) self.assertTrue(np.all(dy == 2 * r))
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.MeanSquaredError(problem) # Evaluate likelihood for test parameters test_parameters = [3, 4] score = error(test_parameters) # Check that error returns expected value # exp = (mean(input[0] - 1) ** 2 + mean(2 * input[1] - 4) ** 2) / 2 self.assertEqual(score, 10)
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.MeanSquaredError(problem) # Evaluate likelihood for test parameters test_parameters = [3] score = error(test_parameters) # Check that error returns expected value # Expected = mean(input - 1) ** 2 self.assertEqual(score, 4)
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.MeanSquaredError(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 * mean(input - 1) self.assertEqual(deriv, 2 * (test_parameters[0] - 1))
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_mean_squared_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.MeanSquaredError(p, weights=[1, 2]) self.assertRaisesRegex(ValueError, 'Number of weights', pints.MeanSquaredError, 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]), 0.5) # (3*(1^2*1+0^2*2)) / 6 = 1 / 2 self.assertEqual(e([2, 3]), 4.5) # (1^2*1+2^2*2) / 2 = 4.5 self.assertEqual(e([3, 4]), 18) # (2^2*1+4^2*2) / 2 = 18 # Derivatives values = np.array([[1, 4], [2, 7], [3, 10]]) p = pints.MultiOutputProblem(model, times, values) w = np.array([1, 2]) e = pints.MeanSquaredError(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) / 6) # 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, 2]] # dex1 is: (2 / nt / no) * (0 - 1 - 2) * 1 * 1 # = (1 / 3) * -3 * 1 * 1 # = -1 # dex2 is: (2 / nt / no) * (0 - 3 - 6) * 1 * 2 # = (1 / 3) * -9 * 1 * 2 # = -6 self.assertEqual(dex[0], -1) self.assertEqual(dex[1], -6)