k均值可能不总能找到“正确”的簇个数,每个簇仅由其中心定义,这意味着每个簇都是凸形。因此,k均值只能找到相对简单的形状。k均值还假设所有簇在某种程度上具有相同的“直径”,它总是将簇之间的边界刚好画在簇中心的之间位置。有时,这会导致令人惊讶的结果。
比如下面这个例子:
import mglearn.plots
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans
X_varied,y_varied=make_blobs(n_samples=200,
cluster_std=[1.0,2.5,0.5],
random_state=170)
y_pred=KMeans(n_clusters=3,random_state=0).fit_predict(X_varied)
mglearn.discrete_scatter(X_varied[:,0],X_varied[:,1],y_pred)
plt.legend(['簇0,','簇1','簇2'],loc='best')
plt.xlabel('特征0')
plt.ylabel('特征1')
plt.show()
图中可以看到,簇0和1都包含一些远离簇中其他点的点。
k均值还假设所有方向对每个簇都同等重要。
下面这个例子里显示了一个二维数据点,数据中包含明确分开的三部分。但是这三部分被沿着对角线方向拉长。由于k均值仅考虑到最近簇中心的距离,所以它无法处理这种数据:
import mglearn.plots
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans
import numpy as np
X,y=make_blobs(random_state=170,n_samples=600)
rng=np.random.RandomState(74)
transformation=rng.normal(size=(2,2))
X=np.dot(X,transformation)
kmeans=KMeans(n_clusters=3)
kmeans.fit(X)
y_pred=kmeans.predict(X)
plt.scatter(X[:,0],X[:,1],c=y_pred,cmap=mglearn.cm3)
plt.scatter(kmeans.cluster_centers_[:,0],kmeans.cluster_centers_[:,1],marker='^',c=[0,1,2],s=100,linewidths=2,cmap=mglearn.cm3)
plt.xlabel('Feature 0')
plt.ylabel('Feature 1')
plt.show()
如果簇的形状更复杂,比如之前用到的two_moons数据:
import mglearn.plots
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs,make_moons
from sklearn.cluster import KMeans
import numpy as np
X,y=make_moons(random_state=0,noise=0.05,n_samples=200)
kmeans=KMeans(n_clusters=2)
kmeans.fit(X)
y_pred=kmeans.predict(X)
plt.scatter(X[:,0],X[:,1],c=y_pred,cmap=mglearn.cm2,s=60)
plt.scatter(kmeans.cluster_centers_[:,0],kmeans.cluster_centers_[:,1],marker='^',c=[mglearn.cm2(0),mglearn.cm2(1)],s=100,linewidths=2)
plt.xlabel('Feature 0')
plt.ylabel('Feature 1')
plt.show()