| 102 | |
| 103 | |
| 104 | def DBI(X, M, R): |
| 105 | # ratio between sum of std deviations between 2 clusters / distance between cluster means |
| 106 | # lower is better |
| 107 | N, D = X.shape |
| 108 | K, _ = M.shape |
| 109 | |
| 110 | # get sigmas first |
| 111 | sigma = np.zeros(K) |
| 112 | for k in range(K): |
| 113 | diffs = X - M[k] # should be NxD |
| 114 | squared_distances = (diffs * diffs).sum(axis=1) # now just N |
| 115 | weighted_squared_distances = R[:,k]*squared_distances |
| 116 | sigma[k] = np.sqrt( weighted_squared_distances.sum() / R[:,k].sum() ) |
| 117 | |
| 118 | # calculate Davies-Bouldin Index |
| 119 | dbi = 0 |
| 120 | for k in range(K): |
| 121 | max_ratio = 0 |
| 122 | for j in range(K): |
| 123 | if k != j: |
| 124 | numerator = sigma[k] + sigma[j] |
| 125 | denominator = np.linalg.norm(M[k] - M[j]) |
| 126 | ratio = numerator / denominator |
| 127 | if ratio > max_ratio: |
| 128 | max_ratio = ratio |
| 129 | dbi += max_ratio |
| 130 | return dbi / K |
| 131 | |
| 132 | |
| 133 | def main(): |