One step of cosine k-means

mediumEmbeddings~30 min · 7 tests

Vector indexes like IVF split the space into clusters, then search only the clusters closest to the query. The clusters come from k-means. Each round has two halves: assign every vector to a centroid, then move every centroid to the middle of its vectors. Write one round.

Write kmeans_step(vectors, centroids):

  • vectors and centroids are lists of float lists, all the same length. There is at least one centroid.
  • Assign: each vector goes to the centroid with the highest cosine similarity. Break ties by the lower centroid index. A zero vector has similarity 0 with everything.
  • Update: each new centroid is the element-wise mean of the vectors assigned to it. A centroid with no vectors keeps its old position.
  • Return {"assignments": [...], "centroids": [...]}: one centroid index per vector, and the new centroids as lists of floats.

No numpy. Plain Python only.

>>> kmeans_step([[1, 0], [3, 1], [0, 2]], [[1, 0], [0, 1]])
{'assignments': [0, 0, 1], 'centroids': [[2.0, 0.5], [0.0, 2.0]]}
Learn the ideaRead the post →
solution.pyPython 3.14 · Pyodide

Press ⌘ ↵ or Run to check the visible tests. Submit runs the hidden ones too. Everything runs in your browser.

⌘ ↵ to run