A basketball coach logs every free throw of a player as 1 (made) or 0 (missed). She models the shots as independent, each one made with the same unknown probability theta, and wants the value of theta that makes the recorded shots most probable.
Write best_rate(outcomes, steps) that tries every candidate theta = i / steps for i = 1, 2, ..., steps - 1 and returns a tuple (theta, loglik): the candidate under which the outcomes are most probable, and the natural logarithm of that probability. If two candidates tie exactly, return the smaller one.
The setup provides shot_log(n, rate, seed), which simulates n free throws of a player whose true success rate is rate. Try multiplying the probabilities of 2000 simulated shots with Run to see what goes wrong.
Examples
Input: outcomes = [1, 1, 0, 1, 1, 1, 0, 1, 0, 1], steps = 100
Output: (0.7, -6.108643020548935)
Explanation: 7 made and 3 missed. Under theta = 0.7 the probability of this exact
sequence is 0.7**7 * 0.3**3 = 0.00222, whose log is -6.1086; no other candidate
on the grid makes the sequence more probable.
Input: outcomes = [1, 0, 0], steps = 10
Output: (0.3, -1.917322692203401)
Explanation: the best candidate among 0.1, 0.2, ..., 0.9 is 0.3, close to 1/3.
Constraints
0 <= len(outcomes) <= 10**5, every outcome is0or12 <= steps <= 2000- floats are compared with a tolerance of
1e-6
Goals
- Write the log-likelihood of a Bernoulli model for a list of yes/no outcomes
- Maximise it over a grid of candidate parameters
- See why sums of logs replace products of probabilities