|
| 1 | +from tools import * |
| 2 | + |
| 3 | +# https://en.wikipedia.org/wiki/Fuzzy_clustering |
| 4 | + |
| 5 | + |
| 6 | +class FuzzyCMeans: |
| 7 | + def __init__(self, n_clusters, initial_centers, data, max_iter=250, m=2, error=1e-5): |
| 8 | + assert m > 1 |
| 9 | + #assert initial_centers.shape[0] == n_clusters |
| 10 | + self.U = None |
| 11 | + self.centers = initial_centers |
| 12 | + self.max_iter = max_iter |
| 13 | + self.m = m |
| 14 | + self.error = error |
| 15 | + self.data = data |
| 16 | + |
| 17 | + def membership(self, data, centers): |
| 18 | + U_temp = cdist(data, centers, 'euclidean') |
| 19 | + U_temp = numpy.power(U_temp, 2/(self.m - 1)) |
| 20 | + denominator_ = U_temp.reshape( |
| 21 | + (data.shape[0], 1, -1)).repeat(U_temp.shape[-1], axis=1) |
| 22 | + denominator_ = U_temp[:, :, numpy.newaxis] / denominator_ |
| 23 | + return 1 / denominator_.sum(2) |
| 24 | + |
| 25 | + def Centers(self, data, U): |
| 26 | + um = U ** self.m |
| 27 | + return (data.T @ um / numpy.sum(um, axis=0)).T |
| 28 | + |
| 29 | + def newImage(self, U, centers, im): |
| 30 | + best = numpy.argmax(self.U, axis=-1) |
| 31 | + # print(best) |
| 32 | + # numpy.round() |
| 33 | + image = im.astype(int) |
| 34 | + for i in range(256): |
| 35 | + image = numpy.where(image == float(i), centers[best[i]][0], image) |
| 36 | + return image |
| 37 | + |
| 38 | + def compute(self): |
| 39 | + self.U = self.membership(self.data, self.centers) |
| 40 | + |
| 41 | + past_U = numpy.copy(self.U) |
| 42 | + begin_time = datetime.datetime.now() |
| 43 | + for i in range(self.max_iter): |
| 44 | + |
| 45 | + self.centers = self.Centers(self.data, self.U) |
| 46 | + self.U = self.membership(self.data, self.centers) |
| 47 | + |
| 48 | + if norm(self.U - past_U) < self.error: |
| 49 | + break |
| 50 | + past_U = numpy.copy(self.U) |
| 51 | + x = datetime.datetime.now() - begin_time |
| 52 | + return self.centers, self.U, x |
| 53 | + |
| 54 | +# that's how you run it, data being your data, and the other parameters being the basic FCM parameters such as numbe rof cluseters, degree of fuzziness and so on |
| 55 | +# f = FuzzyCMeans(n_clusters=C, initial_centers=Initial_centers, |
| 56 | +# data=data m=2, max_iter=1000, error=1e-5) |
| 57 | +# centers, U, time = f.compute() |
0 commit comments