如何应用 KMeans 使用具有多个特征的数据框获取质心

How to apply KMeans to get the centroid using dataframe with multiple features

我正在关注这个详细的 KMeans 教程:https://github.com/python-engineer/MLfromscratch/blob/master/mlfromscratch/kmeans.py 它使用具有 2 个特征的数据集。

但是我有一个包含 5 个特征(列)的数据框,所以我没有使用教程中的 def euclidean_distance(x1, x2): 函数,而是按如下方式计算欧氏距离。

def euclidean_distance(df):
    n = df.shape[1]
    distance_matrix = np.zeros((n,n))
    for i in range(n):
        for j in range(n):
            distance_matrix[i,j] = np.sqrt(np.sum((df.iloc[:,i] - df.iloc[:,j])**2))
    return distance_matrix

接下来我想实现教程中计算质心的部分,如下所示;

def _closest_centroid(self, sample, centroids):
    distances = [euclidean_distance(sample, point) for point in centroids]

由于我的 def euclidean_distance(df): 函数只接受 1 个参数 df,我怎样才能最好地实现它以获得质心?

我的样本数据集df如下:

col1,col2,col3,col4,col5
0.54,0.68,0.46,0.98,-2.14
0.52,0.44,0.19,0.29,30.44
1.27,1.15,1.32,0.60,-161.63
0.88,0.79,0.63,0.58,-49.52
1.39,1.15,1.32,0.41,-188.52
0.86,0.80,0.65,0.65,-45.27

[添加:plot() 函数]

你包含的 plot 函数给出了一个错误 TypeError: object of type 'itertools.combinations' has no len(),我通过将 len(combinations) 更改为len(list(combinations))。但是输出 不是散点图。知道我需要在这里修复什么吗?

读取数据并对其进行聚类不应引发任何错误,即使您增加了数据集中的特征数量。 事实上,当您重新定义 euclidean_distance 函数时,您只会在该部分代码中遇到错误。

这个 asnwer 解决了您得到的绘图函数的实际错误。

   def plot(self):
      fig, ax = plt.subplots(figsize=(12, 8))

       for i, index in enumerate(self.clusters):
           point = self.X[index].T
           ax.scatter(*point)

获取给定集群中的所有点并尝试绘制散点图。

ax.scatter(*point)中的星号表示该点已解包。

这里的隐含假设(这就是为什么这可能很难发现)是 point 应该是二维的。然后,各个部分被解释为要绘制的 x、y 值。

但是因为你有 5 个特征,所以点是 5 维的。

正在查看the docs of ax.scatter

matplotlib.axes.Axes.scatter
Axes.scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None, vmin=None, vmax=None, alpha=None, linewidths=None,
verts=<deprecated parameter>, edgecolors=None, *, plotnonfinite=False,
data=None, **kwargs)

所以,ax.scatter 采用的前几个参数(self 除外)是:

x 
y
s (i.e. the markersize)
c (i.e. the color)
marker (i.e. the markerstyle)

前四个,即 x、y、s 和 c 允许浮点数,但您的数据集是 5 维的,因此第五个特征被解释为标记,它需要一个 MarkerStyle。由于它得到一个浮点数,它会抛出错误。

要做什么:

一次只看2或3个维度,或使用降维(例如主成分分析)将数据投影到较低维度space。

对于第一个选项,您可以在 KMeans 中重新定义 plot 方法 class:

def plot(self):
    

    import itertools
    combinations = itertools.combinations(range(self.K), 2) # generate all combinations of features
    
    fig, axes = plt.subplots(figsize=(12, 8), nrows=len(combinations), ncols=1) # initialise one subplot for each feature combination

    for (x,y), ax in zip(combinations, axes.ravel()): # loop through combinations and subpltos
        
        
        for i, index in enumerate(self.clusters):
            point = self.X[index].T
            
            # only get the coordinates for this combination:
            px, py = point[x], point[y]
            ax.scatter(px, py)

        for point in self.centroids:
            
            # only get the coordinates for this combination:
            px, py = point[x], point[y]
            
            ax.scatter(px, py, marker="x", color='black', linewidth=2)

        ax.set_title('feature {} vs feature {}'.format(x,y))
    plt.show()