03-probability's correlation measures whether two variables move together LINEARLY, and can be exactly zero even when two variables are strongly, deterministically related in a curved way (y = x^2, say). What you actually want, much of the time, is a measure of "how much does knowing X tell you about Y," with no assumption about linearity at all. That's mutual information: it's zero if and only if X and Y are genuinely, completely independent (knowing one tells you literally nothing about the other), and it grows the more knowing X narrows down what Y could be, no matter what shape that relationship takes.
The elegant part, and the reason this question sits at the very end of both the Probability and Information Theory tracks: mutual information is built entirely from tools you've already implemented, it is literally 03-kl-divergence's KL divergence, applied to compare the real joint distribution against what that same joint distribution WOULD look like if X and Y had no relationship at all.
Theory defines mutual information as KL(P(X,Y) || P(X)*P(Y)): the real joint distribution, compared against the "independent" joint you'd get by multiplying the two marginals together (03-probability/04-conditional-probability's marginal_x/marginal_y). Build that hypothetical independent joint via an outer product, then measure the KL divergence between the two, flattened into matching 1D distributions.
Implement mutual_information(joint, base=2.0) against that reasoning. The signature and docstring are already in the editor.
joint is a 2D array, joint[i, j] = P(X=i, Y=j), summing to 1.0.marginal_x/marginal_y (already imported) to build the independent joint, not compute it any other way.kl_divergence (already imported), not reimplement its formula.Open one at a time. Each gives away a little more than the last.
np.outer(px, py) builds exactly the (len(px), len(py)) table you'd expect from two independent variables with those marginals.
kl_divergence expects two flat distributions of matching shape. .flatten() both 2D tables before passing them in.
Click "Run Tests" to test your implementation