Skip to content

Commit 58d3b60

Browse files
authored
chore: delete dead code from efficient kmeans (apple#23)
1 parent de5803b commit 58d3b60

1 file changed

Lines changed: 9 additions & 123 deletions

File tree

src/coreai_opt/palettization/kmeans/_efficient_kmeans.py

Lines changed: 9 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,6 @@
55

66
import numpy as _np
77
import torch as _torch
8-
import torch.distributed as _dist
9-
from coremltools._deps import _kmeans1d
10-
11-
from coreai_opt._utils.import_utils import lazy_import_module
128

139

1410
class _EfficientKMeans:
@@ -19,21 +15,18 @@ class _EfficientKMeans:
1915
def __init__(
2016
self,
2117
n_clusters: int,
22-
init: str | _torch.Tensor,
18+
init: str,
2319
n_init: int = 0,
24-
labels=None,
2520
max_iter: int = 100,
2621
tol: float = 0.0001,
27-
error_bnd: float = 0.0,
2822
):
2923
self.n_clusters = n_clusters
3024
self.n_init = n_init
3125
self.max_iter = max_iter
3226
self.tol = tol
33-
self.labels_ = labels
27+
self.labels_ = None
3428
self.inertia_ = None
3529
self.cluster_centers_ = init
36-
self.error_bnd = error_bnd
3730

3831
assert self.max_iter > 0
3932
assert self.n_clusters > 0
@@ -69,21 +62,9 @@ def _get_cluster_avg(
6962

7063
return v_avg.to(vals.dtype)
7164

72-
@staticmethod
73-
def x_c_dist(params: _torch.Tensor, clusters: _torch.Tensor) -> _torch.Tensor:
74-
"""
75-
Calculate the distance between weights and clusters.
76-
"""
77-
clusters = clusters.contiguous()
78-
79-
if _torch.finfo(params.dtype).bits > _torch.finfo(clusters.dtype).bits:
80-
return _torch.cdist(params.to(clusters.dtype), clusters).square()
81-
else:
82-
return _torch.cdist(params, clusters.to(params.dtype)).square()
83-
8465
def _kmeans_pp(
8566
self, parameters: _torch.Tensor, sample_weight: _torch.Tensor | None = None
86-
) -> "_EfficientKMeans":
67+
) -> None:
8768
assert len(parameters) >= self.n_clusters
8869

8970
num_update_list = []
@@ -166,8 +147,6 @@ def _kmeans_pp(
166147
if len(num_update_list) >= INIT_EXIT and sum(num_update_list[-INIT_EXIT:]) == 0:
167148
break
168149

169-
return self
170-
171150
def fit(
172151
self, X: _torch.Tensor, sample_weight: _torch.Tensor | None = None
173152
) -> "_EfficientKMeans":
@@ -178,106 +157,13 @@ def fit(
178157

179158
assert N >= self.n_clusters, f"too many clusters {self.n_clusters} for {N} samples"
180159

181-
if isinstance(self.cluster_centers_, str):
182-
if "kmeans++" in self.cluster_centers_:
183-
if _dist.is_available() and _dist.is_initialized():
184-
rank = _dist.get_rank()
185-
else:
186-
rank = 0
187-
188-
if "cpu" in self.cluster_centers_:
189-
190-
def _import_sklearn():
191-
import sklearn as sk # noqa: PLC0415
192-
193-
return sk
194-
195-
sk = lazy_import_module(
196-
_import_sklearn,
197-
"sklearn is required. Install it with: pip install scikit-learn",
198-
)
199-
200-
if "minibatch" in self.cluster_centers_:
201-
clustering_method = sk.cluster.MiniBatchKMeans
202-
else:
203-
clustering_method = sk.cluster.KMeans
204-
205-
kmeans = clustering_method(
206-
n_init=self.n_init,
207-
n_clusters=self.n_clusters,
208-
max_iter=self.max_iter,
209-
random_state=rank + 1,
210-
tol=self.tol,
211-
).fit(X.float().cpu().numpy(), sample_weight=sample_weight)
212-
self.inertia_ = _torch.Tensor([kmeans.inertia_]).to(X.device)
213-
self.labels_ = _torch.from_numpy(kmeans.labels_).int().to(X.device)
214-
self.cluster_centers_ = None
215-
else:
216-
self._kmeans_pp(X.float(), sample_weight=sample_weight)
217-
218-
self.cluster_centers_ = _EfficientKMeans._get_cluster_avg(
219-
self.n_clusters, self.labels_, X, sample_weight=sample_weight
220-
)
221-
222-
elif self.cluster_centers_ == "opt1d":
223-
self.labels_, self.cluster_centers_ = _kmeans1d.cluster(
224-
X, self.n_clusters, weights=sample_weight
225-
)
226-
227-
self.n_clusters = len(self.cluster_centers_)
228-
self.cluster_centers_ = (
229-
_torch.Tensor(self.cluster_centers_)
230-
.to(device=X.device, dtype=X.dtype)
231-
.view(-1, 1)
232-
)
233-
self.labels_ = _torch.Tensor(self.labels_).int().to(X.device)
234-
235-
min_error, _ = _EfficientKMeans.x_c_dist(X, self.cluster_centers_).min(dim=-1)
236-
self.inertia_ = min_error.sum()
237-
else:
238-
self.inertia_ = None
239-
240-
for _ in range(self.max_iter):
241-
self.cluster_centers_ = _EfficientKMeans._get_cluster_avg(
242-
self.n_clusters, self.labels_, X, sample_weight=sample_weight
243-
)
160+
if self.cluster_centers_ != "kmeans++":
161+
raise ValueError(f"init must be 'kmeans++'; got {self.cluster_centers_!r}")
244162

245-
# remove empty clusters perhaps due to pruning
246-
nan_centers = self.cluster_centers_.isnan()
247-
if nan_centers.any():
248-
self._kmeans_pp(X, sample_weight=sample_weight)
249-
continue
163+
self._kmeans_pp(X.float(), sample_weight=sample_weight)
250164

251-
x_c_dist = _EfficientKMeans.x_c_dist(X, self.cluster_centers_)
252-
min_error, self.labels_ = x_c_dist.min(dim=-1)
253-
cur_inertia = min_error.sum()
254-
255-
if self.error_bnd and _torch.sqrt(cur_inertia / N) < self.error_bnd:
256-
unique, counts = _torch.unique(self.labels_, return_counts=True)
257-
idx = unique[counts.argmin()]
258-
259-
reduce_cluster_centers_ = self.cluster_centers_.clone()
260-
reduce_cluster_centers_[idx] = _np.nan
261-
262-
reduce_cluster_centers_ = reduce_cluster_centers_[
263-
~_torch.isnan(reduce_cluster_centers_)
264-
].view(-1, 1)
265-
reduce_min_error, reduce_labels_ = _EfficientKMeans.x_c_dist(
266-
X, reduce_cluster_centers_
267-
).min(dim=-1)
268-
reduce_inertia = reduce_min_error.sum()
269-
rmse_error = _torch.sqrt(reduce_inertia / N)
270-
271-
if rmse_error < self.error_bnd:
272-
self.cluster_centers_ = reduce_cluster_centers_
273-
self.labels_ = reduce_labels_
274-
self.n_clusters = len(self.cluster_centers_)
275-
continue
276-
277-
if self.inertia_ is None or abs(self.inertia_ - cur_inertia) > self.tol:
278-
self.inertia_ = cur_inertia
279-
else:
280-
self.inertia_ = cur_inertia
281-
break
165+
self.cluster_centers_ = _EfficientKMeans._get_cluster_avg(
166+
self.n_clusters, self.labels_, X, sample_weight=sample_weight
167+
)
282168

283169
return self

0 commit comments

Comments
 (0)