| 98 | return cost |
| 99 | |
| 100 | def plot_k_means(X, K, index_word_map, max_iter=20, beta=1.0, show_plots=True): |
| 101 | N, D = X.shape |
| 102 | M = np.zeros((K, D)) |
| 103 | R = np.zeros((N, K)) |
| 104 | exponents = np.empty((N, K)) |
| 105 | |
| 106 | # initialize M to random |
| 107 | for k in range(K): |
| 108 | M[k] = X[np.random.choice(N)] |
| 109 | |
| 110 | costs = np.zeros(max_iter) |
| 111 | for i in range(max_iter): |
| 112 | # step 1: determine assignments / resposibilities |
| 113 | # is this inefficient? |
| 114 | for k in range(K): |
| 115 | for n in range(N): |
| 116 | # R[n,k] = np.exp(-beta*d(M[k], X[n])) / np.sum( np.exp(-beta*d(M[j], X[n])) for j in range(K) ) |
| 117 | exponents[n,k] = np.exp(-beta*d(M[k], X[n])) |
| 118 | |
| 119 | R = exponents / exponents.sum(axis=1, keepdims=True) |
| 120 | |
| 121 | # step 2: recalculate means |
| 122 | for k in range(K): |
| 123 | M[k] = R[:,k].dot(X) / R[:,k].sum() |
| 124 | |
| 125 | costs[i] = cost(X, R, M) |
| 126 | if i > 0: |
| 127 | if np.abs(costs[i] - costs[i-1]) < 10e-5: |
| 128 | break |
| 129 | |
| 130 | if show_plots: |
| 131 | # plt.plot(costs) |
| 132 | # plt.title("Costs") |
| 133 | # plt.show() |
| 134 | |
| 135 | random_colors = np.random.random((K, 3)) |
| 136 | colors = R.dot(random_colors) |
| 137 | plt.figure(figsize=(80.0, 80.0)) |
| 138 | plt.scatter(X[:,0], X[:,1], s=300, alpha=0.9, c=colors) |
| 139 | annotate1(X, index_word_map) |
| 140 | # plt.show() |
| 141 | plt.savefig("test.png") |
| 142 | |
| 143 | |
| 144 | # print out the clusters |
| 145 | hard_responsibilities = np.argmax(R, axis=1) # is an N-size array of cluster identities |
| 146 | # let's "reverse" the order so it's cluster identity -> word index |
| 147 | cluster2word = {} |
| 148 | for i in range(len(hard_responsibilities)): |
| 149 | word = index_word_map[i] |
| 150 | cluster = hard_responsibilities[i] |
| 151 | if cluster not in cluster2word: |
| 152 | cluster2word[cluster] = [] |
| 153 | cluster2word[cluster].append(word) |
| 154 | |
| 155 | # print out the words grouped by cluster |
| 156 | for cluster, wordlist in cluster2word.items(): |
| 157 | print("cluster", cluster, "->", wordlist) |