从 scikit-learn/numpy 中的聚类中心计算标签?
Compute labels from cluster centers in scikit-learn/numpy?
我需要从另一个聚类器生成的聚类中心计算标签在不同的数据集中没有原始聚类器对象。
我知道我可以像这样在 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())
但它在 kmeans2.predict(datapoints2)
中引发了 sklearn.exceptions.NotFittedError
异常,我尝试在 kmeans kwargs 中设置 max_iter=0
,但它也引发了异常。
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
只是
的补充
广义函数(带有虚拟静态变量):
def compute_labels(centers,datapoints):
compute_labels.dummy.cluster_centers_=centers
return compute_labels.dummy.predict(datapoints)
compute_labels.dummy=KMeans()
我需要从另一个聚类器生成的聚类中心计算标签在不同的数据集中没有原始聚类器对象。
我知道我可以像这样在 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())
但它在 kmeans2.predict(datapoints2)
中引发了 sklearn.exceptions.NotFittedError
异常,我尝试在 kmeans kwargs 中设置 max_iter=0
,但它也引发了异常。
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
只是
广义函数(带有虚拟静态变量):
def compute_labels(centers,datapoints):
compute_labels.dummy.cluster_centers_=centers
return compute_labels.dummy.predict(datapoints)
compute_labels.dummy=KMeans()