The k-means++ initialization algorithm returns a set of initial clusers, with the advantage that: - it generates better clusters than k-means(seed=RANDOM) on most data sets, - it runs faster than standard k-means, - it has a theoretical approximation guarantee.
(vectors, k, distance=COSINE)
| 1512 | kmeans = k_means |
| 1513 | |
| 1514 | def kmpp(vectors, k, distance=COSINE): |
| 1515 | """ The k-means++ initialization algorithm returns a set of initial clusers, |
| 1516 | with the advantage that: |
| 1517 | - it generates better clusters than k-means(seed=RANDOM) on most data sets, |
| 1518 | - it runs faster than standard k-means, |
| 1519 | - it has a theoretical approximation guarantee. |
| 1520 | """ |
| 1521 | # Cache the distance calculations between vectors (up to 4x faster). |
| 1522 | map = DistanceMap(method=distance); distance = map.distance |
| 1523 | # David Arthur, 2006, http://theory.stanford.edu/~sergei/slides/BATS-Means.pdf |
| 1524 | # Based on: |
| 1525 | # http://www.stanford.edu/~darthur/kmpp.zip |
| 1526 | # http://yongsun.me/2008/10/k-means-and-k-means-with-python |
| 1527 | # Choose one center at random. |
| 1528 | # Calculate the distance between each vector and the nearest center. |
| 1529 | centroids = [choice(vectors)] |
| 1530 | d = [distance(v, centroids[0]) for v in vectors] |
| 1531 | s = sum(d) |
| 1532 | for _ in range(int(k) - 1): |
| 1533 | # Choose a random number y between 0 and d1 + d2 + ... + dn. |
| 1534 | # Find vector i so that: d1 + d2 + ... + di >= y > d1 + d2 + ... + dj. |
| 1535 | # Perform a number of local tries so that y yields a small distance sum. |
| 1536 | i = 0 |
| 1537 | for _ in range(int(2 + log(k))): |
| 1538 | y = random() * s |
| 1539 | for i1, v1 in enumerate(vectors): |
| 1540 | if y <= d[i1]: |
| 1541 | break |
| 1542 | y -= d[i1] |
| 1543 | s1 = sum(min(d[j], distance(v1, v2)) for j, v2 in enumerate(vectors)) |
| 1544 | if s1 < s: |
| 1545 | s, i = s1, i1 |
| 1546 | # Add vector i as a new center. |
| 1547 | # Repeat until we have chosen k centers. |
| 1548 | centroids.append(vectors[i]) |
| 1549 | d = [min(d[i], distance(v, centroids[-1])) for i, v in enumerate(vectors)] |
| 1550 | s = sum(d) |
| 1551 | # Assign points to the nearest center. |
| 1552 | clusters = [[] for i in xrange(int(k))] |
| 1553 | for v1 in vectors: |
| 1554 | d = [distance(v1, v2) for v2 in centroids] |
| 1555 | clusters[d.index(min(d))].append(v1) |
| 1556 | return clusters |
| 1557 | |
| 1558 | #--- HIERARCHICAL ---------------------------------------------------------------------------------- |
| 1559 | # Hierarchical clustering is slow but the optimal solution guaranteed in O(len(vectors) ** 3). |