'Compute labels and inertia using mini batches.
This is slightly slower than doing everything at once but preventes
memory errors / segfaults.
Parameters
X : array-like, shape (n_samples, n_features)
Input data.
Returns
labels : array, shap (n_samples,)
Cluster labels for each point.
inertia : float
Sum of squared distances of points to nearest cluster.'

def _labels_inertia_minibatch(self, X):

    if self.verbose:
        print 'Computing    label    assignment    and    total    inertia'
    x_squared_norms = row_norms(X, squared=True)
    slices = gen_batches(X.shape[0], self.batch_size)
    results = [_labels_inertia(X[s], x_squared_norms[s], self.cluster_centers_) for s in slices]
    (labels, inertia) = zip(*results)
    return (np.hstack(labels), np.sum(inertia))
