def testThompsonSamplerValidation(self): generator = ThompsonSampler(min_weight=0.01) # all Xs are not the same with self.assertRaises(ValueError): generator.fit( Xs=[[[1, 1], [2, 2], [3, 3], [4, 4]], [[1, 1], [2, 2], [4, 4]]], Ys=self.Ys, Yvars=self.Yvars, parameter_values=self.parameter_values, outcome_names=self.outcome_names, ) # multiple observations per parameterization with self.assertRaises(ValueError): generator.fit( Xs=[[[1, 1], [2, 2], [2, 2]]], Ys=self.Ys, Yvars=self.Yvars, parameter_values=self.parameter_values, outcome_names=self.outcome_names, ) # these are not the same observations, so should not error generator.fit( Xs=[[[1, 1], [2.0, 2], [2, 2]]], Ys=self.Ys, Yvars=self.Yvars, parameter_values=self.parameter_values, outcome_names=self.outcome_names, ) # requires objective weights with self.assertRaises(ValueError): generator.gen(5, self.parameter_values, objective_weights=None)
def testThompsonSamplerOutcomeConstraints(self): generator = ThompsonSampler(min_weight=0.0) generator.fit( Xs=self.multiple_metrics_Xs, Ys=self.multiple_metrics_Ys, Yvars=self.multiple_metrics_Yvars, parameter_values=self.parameter_values, outcome_names=self.outcome_names, ) arms, weights, _ = generator.gen( n=4, parameter_values=self.parameter_values, objective_weights=np.array([1, 0]), outcome_constraints=( # pass in multiples of the same constraint # to ensure that shapes are correct for multiple constraints np.array([[0, 1], [0, 1], [0, 1]]), np.array([[1], [1], [1]]), ), ) self.assertEqual(arms, [[3, 3], [4, 4], [2, 2], [1, 1]]) for weight, expected_weight in zip( weights, [4 * i for i in [0.4, 0.4, 0.15, 0.05]] ): self.assertAlmostEqual(weight, expected_weight, delta=0.1)
def testThompsonSamplerUniformWeights(self): generator = ThompsonSampler(min_weight=0.0, uniform_weights=True) generator.fit( Xs=self.Xs, Ys=self.Ys, Yvars=self.Yvars, parameter_values=self.parameter_values, outcome_names=self.outcome_names, ) arms, weights, _ = generator.gen( n=3, parameter_values=self.parameter_values, objective_weights=np.ones(1) ) self.assertEqual(arms, [[4, 4], [3, 3], [2, 2]]) for weight, expected_weight in zip(weights, [1.0, 1.0, 1.0]): self.assertAlmostEqual(weight, expected_weight, 1)
def testThompsonSamplerMinWeight(self): generator = ThompsonSampler(min_weight=0.01) generator.fit( Xs=self.Xs, Ys=self.Ys, Yvars=self.Yvars, parameter_values=self.parameter_values, outcome_names=self.outcome_names, ) arms, weights = generator.gen( n=5, parameter_values=self.parameter_values, objective_weights=np.ones(1) ) self.assertEqual(arms, [[4, 4], [3, 3], [2, 2]]) for weight, expected_weight in zip(weights, [0.725, 0.225, 0.05]): self.assertAlmostEqual(weight, expected_weight, 1)
def testThompsonSampler(self): generator = ThompsonSampler(min_weight=0.0) generator.fit( Xs=self.Xs, Ys=self.Ys, Yvars=self.Yvars, parameter_values=self.parameter_values, outcome_names=self.outcome_names, ) arms, weights, gen_metadata = generator.gen( n=3, parameter_values=self.parameter_values, objective_weights=np.ones(1) ) self.assertEqual(arms, [[4, 4], [3, 3], [2, 2]]) for weight, expected_weight in zip( weights, [3 * i for i in [0.725, 0.225, 0.05]] ): self.assertAlmostEqual(weight, expected_weight, 1) self.assertEqual(len(gen_metadata["arms_to_weights"]), 4)
def testThompsonSamplerPredict(self): generator = ThompsonSampler(min_weight=0.0) generator.fit( Xs=self.Xs, Ys=self.Ys, Yvars=self.Yvars, parameter_values=self.parameter_values, outcome_names=self.outcome_names, ) f, cov = generator.predict([[1, 1], [3, 3]]) self.assertTrue(np.array_equal(f, np.array([[1], [3]]))) self.assertTrue(np.array_equal(cov, np.ones((2, 1, 1)))) with self.assertRaises(ValueError): generator.predict([[1, 2]])
def testThompsonSamplerInfeasible(self): generator = ThompsonSampler(min_weight=0.9) generator.fit( Xs=self.Xs, Ys=self.Ys, Yvars=self.Yvars, parameter_values=self.parameter_values, outcome_names=self.outcome_names, ) with self.assertRaises(ModelError): generator.gen( n=3, parameter_values=self.parameter_values, objective_weights=np.ones(1), )
def testThompsonSamplerOutcomeConstraintsInfeasible(self): generator = ThompsonSampler(min_weight=0.0) generator.fit( Xs=self.multiple_metrics_Xs, Ys=self.multiple_metrics_Ys, Yvars=self.multiple_metrics_Yvars, parameter_values=self.parameter_values, outcome_names=self.outcome_names, ) with self.assertRaises(ValueError): generator.gen( n=3, parameter_values=self.parameter_values, objective_weights=np.ones(2), outcome_constraints=(np.array([[0, 1]]), np.array([[-10]])), )
def get_thompson( experiment: Experiment, data: Data, search_space: Optional[SearchSpace] = None, num_samples: int = 10000, min_weight: Optional[float] = None, uniform_weights: bool = False, ) -> DiscreteModelBridge: """Instantiates a Thompson sampling model.""" if data.df.empty: # pragma: no cover raise ValueError("Thompson sampler requires non-empty data.") model = ThompsonSampler(num_samples=num_samples, min_weight=min_weight, uniform_weights=uniform_weights) return DiscreteModelBridge( experiment=experiment, search_space=search_space if search_space is not None else experiment.search_space, data=data, model=model, transforms=TS_trans, )