01-kmeans-assignment answered "given wherever the centroids currently sit, which one is each point closest to." That answer is only ever as good as the guessed centroids it started from — if the centroids are in the wrong place, the assignment is wrong too. The fix is the obvious one: now that you know which points think they belong to which centroid, move each centroid to where those points actually are.
That "move to where your assigned points actually are" step is the same centroid computation 04-nearest-centroid did for labeled classes — average the points in a group to get the group's center — just applied to a group defined by "current assignment" instead of "true class." Alternate this with the assignment step and the two together are the whole K-Means algorithm.
Implement kmeans_update_centroids(input, assignments, centroids): for each cluster index, average the rows of input currently assigned to it, and use that average as the cluster's new centroid. The one piece of theory that isn't just "average a group" is what to do when a group is empty — that's called out separately in Constraints and Theory below.
input: shape (n_samples, n_features).assignments: shape (n_samples,), integer cluster index per sample, as produced by 01-kmeans-assignment's kmeans_assign.centroids: shape (k, n_features), the current centroids.(k, n_features).0/0 is undefined).centroids array must not be mutated in place; callers may still hold a reference to it.Open one at a time. Each gives away a little more than the last.
Start from a copy of centroids, not the original — you're going to overwrite rows, and the caller's array shouldn't change underneath them.
For a given cluster index, input[assignments == cluster] selects exactly the rows currently assigned to it. Before you call .mean(axis=0) on that selection, check whether it has any rows at all.
No results yet
Run your code to check it against the examples, or submit to run every test.