Вычислить метки из кластерных центров в scikit-learn / numpy? - PullRequest
1 голос
/ 10 марта 2020

Мне нужно вычислить метки из центров кластеризации, сгенерированных другим кластеризатором в другом наборе данных без исходного объекта кластеризатора .

Я знаю, что могу жестко закодировать его в python вроде так

def compute_labels(centers,datapoints):
    ans=[]
    for point in datapoints:
        ans.append(
            min(
                ((i,np.linalg.norm(point-center)) for i,center in enumerate(centers)),
                key=lambda t:t[1]
            )[0]
        )
    return ans

однако для моего приложения это было бы медленно, мне нужна его реализация на более низком уровне, поэтому мне было интересно, можно ли было бы просто использовать scikit-learn или numpy.

что я пробовал:

from sklearn.cluster import KMeans
import numpy as np

np.random.seed(42)

datapoints1=np.random.rand(200,38)
datapoints2=np.random.rand(200,38)

kmeans1=KMeans(
    init="k-means++",
    random_state=42,
    n_init=100
 )
kmeans1=kmeans1.fit(datapoints1)

kmeans2=KMeans(
    init=kmeans1.cluster_centers_,
    max_iter=1,
    n_init=1
)
kmeans2.predict(datapoints2)
print((kmeans1.cluster_centers_==kmeans2.cluster_centers_).all())

но это вызывает sklearn.exceptions.NotFittedError исключение в kmeans2.predict(datapoints2), я пытался установить max_iter=0 в kmeans kwargs, но это также вызывает исключение.

Ответы [ 2 ]

1 голос
/ 10 марта 2020

sklearn проверяет функцию с именем check_is_fitted, которая просматривает атрибуты модели. В вашем случае, как вы никогда не вызывали fit, некоторые атрибуты не существуют, что вызывает ошибку. Вы можете подделать его, создав их вручную, например:

from sklearn.cluster import KMeans
import numpy as np

np.random.seed(42)

datapoints1=np.random.rand(200,38)
datapoints2=np.random.rand(200,38)

kmeans1=KMeans(
    init="k-means++",
    random_state=42,
    n_init=100
 )
kmeans1=kmeans1.fit(datapoints1)

kmeans2=KMeans(
    init=kmeans1.cluster_centers_,
    max_iter=1,
    n_init=1
)

kmeans2.cluster_centers_ = kmeans1.cluster_centers_                # you have it
kmeans2.labels_ = kmeans1.labels_                                  # to test if required, no difference found
print([v for v in vars(kmeans2)
       if v.endswith("_") and not v.startswith("__")])             # if this list is empty, the model if not fitted, you can compare it to kmeans1

pred = kmeans2.predict(datapoints2)
print(pred)                                                        # [3 7 1 ... 2]
print((kmeans1.cluster_centers_== kmeans2.cluster_centers_).all()) # True
0 голосов
/ 13 марта 2020

Просто дополнение к Николас М. ответ

Обобщенная функция (с фиктивной переменной c):

def compute_labels(centers,datapoints):
    compute_labels.dummy.cluster_centers_=centers
    return compute_labels.dummy.predict(datapoints)
compute_labels.dummy=KMeans()
...