docs: def smart_initialize(self):
          '''Use k-means++ to initialize a good set of centroids'''
          if self.seed is not None: # useful for obtaining consistent results
              np.random.seed(self.seed)
          centroids = np.zeros((self.k, self.data.shape[1]))
          # Randomly choose the first centroid.
          # Since we have no prior knowledge, choose uniformly at random
          idx = np.random.randint(self.data.shape[0])
          centroids[0] = self.data[idx,:].toarray()
          # Compute distances from the first centroid chosen to all the other data points
          squared_distances = pairwise_distances(self.data, centroids[0:1], metric='euclidean').flatten()**2
          for i in range(1, self.k):
              # Choose the next centroid randomly, so that the probability for each data point to be chosen
              # is directly proportional to its squared distance from the nearest centroid.
              # Roughtly speaking, a new centroid should be as far as from ohter centroids as possible.
              idx = np.random.choice(self.data.shape[0], 1, p=squared_distances/sum(squared_distances))
              centroids[i] = self.data[idx,:].toarray()
              # Now compute distances from the centroids to all data points
              squared_distances = np.min(pairwise_distances(self.data, centroids[0:i+1], metric='euclidean')**2,axis=1)
          self.centroids=centroids
          return centroids