gpt4 book ai didi

python - 我的 Davies-Bouldin 索引的 python 实现是否正确?

转载 作者:太空宇宙 更新时间:2023-11-03 10:52:18 24 4
gpt4 key购买 nike

我正在尝试计算 Davies-Bouldin Index在 Python 中。

下面是代码尝试重现的步骤。

5 个步骤:

  1. 对于每个簇,计算每个点到质心之间的欧氏距离
  2. 对于每个集群,计算这些距离的平均值
  3. 对于每对簇,计算它们质心之间的欧氏距离

然后,

  1. 对于每对簇,计算到它们各自质心的平均距离(在第 2 步计算)的总和,然后除以它们之间的距离(在第 3 步计算)。

最后,

  1. 计算所有这些分区的平均值(=所有索引)以获得整个聚类的 Davies-Bouldin 索引

代码

def daviesbouldin(X, labels, centroids):

import numpy as np
from scipy.spatial.distance import pdist, euclidean

nbre_of_clusters = len(centroids) #Get the number of clusters
distances = [[] for e in range(nbre_of_clusters)] #Store intra-cluster distances by cluster
distances_means = [] #Store the mean of these distances
DB_indexes = [] #Store Davies_Boulin index of each pair of cluster
second_cluster_idx = [] #Store index of the second cluster of each pair
first_cluster_idx = 0 #Set index of first cluster of each pair to 0

# Step 1: Compute euclidean distances between each point of a cluster to their centroid
for cluster in range(nbre_of_clusters):
for point in range(X[labels == cluster].shape[0]):
distances[cluster].append(euclidean(X[labels == cluster][point], centroids[cluster]))

# Step 2: Compute the mean of these distances
for e in distances:
distances_means.append(np.mean(e))

# Step 3: Compute euclidean distances between each pair of centroid
ctrds_distance = pdist(centroids)

# Tricky step 4: Compute Davies-Bouldin index of each pair of cluster
for i, e in enumerate(e for start in range(1, nbre_of_clusters) for e in range(start, nbre_of_clusters)):
second_cluster_idx.append(e)
if second_cluster_idx[i-1] == nbre_of_clusters - 1:
first_cluster_idx += 1
DB_indexes.append((distances_means[first_cluster_idx] + distances_means[e]) / ctrds_distance[i])

# Step 5: Compute the mean of all DB_indexes
print("DAVIES-BOULDIN Index: %.5f" % np.mean(DB_indexes))

在参数中:

  • X是数据
  • labels,是由聚类算法计算的标签(即:kmeans)
  • centroids 是每个簇的质心坐标(即:cluster_centers_)

另外,请注意我使用的是 Python 3

问题 1:每对质心之间的欧氏距离计算是否正确(第 3 步)?

问题 2:我对第 4 步的实现是否正确?

问题 3:我是否需要归一化簇内和簇间距离?


关于第 4 步的进一步解释

假设我们有 10 个集群。循环应该计算每对集群的数据库索引。

在第一次迭代时:

  • 将簇 1 的内距离平均值(distances_means 的索引 0)和簇 2 的内距离平均值(distances_means 的索引 1)相加
  • 将此总和除以 2 个聚类之间的距离(ctrds_distance 的索引 0)

在第二次迭代时:

  • 将簇 1 的内距离平均值(distances_means 的索引 0)和簇 3 的内距离平均值(distances_means 的索引 2)相加
  • 将此总和除以 2 个聚类之间的距离(ctrds_distance 的索引 1)

等等……

以 10 个集群为例,完整的迭代过程应该是这样的:

intra-cluster distance intra-cluster distance       distance between their
of cluster: of cluster: centroids(storage num):
0 + 1 / 0
0 + 2 / 1
0 + 3 / 2
0 + 4 / 3
0 + 5 / 4
0 + 6 / 5
0 + 7 / 6
0 + 8 / 7
0 + 9 / 8
1 + 2 / 9
1 + 3 / 10
1 + 4 / 11
1 + 5 / 12
1 + 6 / 13
1 + 7 / 14
1 + 8 / 15
1 + 9 / 16
2 + 3 / 17
2 + 4 / 18
2 + 5 / 19
2 + 6 / 20
2 + 7 / 21
2 + 8 / 22
2 + 9 / 23
3 + 4 / 24
3 + 5 / 25
3 + 6 / 26
3 + 7 / 27
3 + 8 / 28
3 + 9 / 29
4 + 5 / 30
4 + 6 / 31
4 + 7 / 32
4 + 8 / 33
4 + 9 / 34
5 + 6 / 35
5 + 7 / 36
5 + 8 / 37
5 + 9 / 38
6 + 7 / 39
6 + 8 / 40
6 + 9 / 41
7 + 8 / 42
7 + 9 / 43
8 + 9 / 44

这里的问题是我不太确定 distances_means 的索引是否与 ctrds_distance 的索引匹配。

换句话说,我不确定计算的第一个簇间距离是否对应于簇 1 和簇 2 之间的距离。计算的第二个簇间距离是否对应于簇 3 和簇 1 之间的距离... 依此类推,遵循上述模式。

简而言之:恐怕我将成对的簇内距离除以不对应的簇间距离。

最佳答案

这里是上面 Davies-Bouldin 索引朴素实现的更短、更正后更快的版本。

def DaviesBouldin(X, labels):
n_cluster = len(np.bincount(labels))
cluster_k = [X[labels == k] for k in range(n_cluster)]
centroids = [np.mean(k, axis = 0) for k in cluster_k]
variances = [np.mean([euclidean(p, centroids[i]) for p in k]) for i, k in enumerate(cluster_k)]
db = []

for i in range(n_cluster):
for j in range(n_cluster):
if j != i:
db.append((variances[i] + variances[j]) / euclidean(centroids[i], centroids[j]))

return(np.max(db) / n_cluster)

回答我自己的问题:

  • 初稿(第 4 步)的反驳是正确的,但不相关
  • 无需标准化簇内和簇间距离
  • 计算欧氏距离时出错

请注意,您可以找到尝试改进该指数的创新方法,特别是“New Version of Davies-Bouldin Index ”,它用柱面距离代替欧氏距离。

关于python - 我的 Davies-Bouldin 索引的 python 实现是否正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48036593/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com