参考资料:https://blog.csdn.net/weixin_46713695/article/details/126385691?spm=1001.2014.3001.5502
最近在做一个序列聚类的项目,评价聚类优劣的时候,用到了 DBI 指数,根据自己的理解,梳理了网上看到的资料,以求步骤清晰公式易懂,给大家带来方便。
戴维森堡丁指数(Davies-Bouldin index,DBI) ,又称为分类适确性指标,是由 大卫L·戴维斯 和 唐纳德·Bouldin 提出的一种评估聚类算法优劣的指标。
综合考虑了类内样本相似度以及类间样本差异度 ,其值越小表征聚类有效性越高 ,假设我们有 m m m 个序列,将这些序列通过算法聚为 n n n 类,使用 DBI 聚类效果评价方法。具体定义如下:
D B I = 1 N ∑ i = 1 N max j ≠ i S i ‾ + S j ‾ ∥ w i − w j ∥ 2 DBI=\frac{1}{N}\sum^N_{i=1}\displaystyle \max_{j\neq i}\frac{\overline{S_i}+\overline{S_j}}{\left\| w_i-w_j\right\|_2} DBI=N1i=1∑Nj=imax∥wi−wj∥2Si+Sj
式中: D B I DBI DBI 表示 DBI 指标值; S i ‾ \overline{S_i} Si 为第 i i i 类样本到其类中心的平均欧氏距离; ∥ w i − w j ∥ 2 \left\| w_i-w_j\right\|_2 ∥wi−wj∥2为第 i i i 和第 j j j 类的类中心欧氏距离。
1)计算 S i S_i Si
2)计算 M i j M_{ij} Mij
分子之和计算完后,需计算分母 M i j M_{ij} Mij,DBI 定义了一个距离值 M i j M_{ij} Mij:表示第 i i i 类与第 j j j 类的距离,计算公式为:
M i j = ∥ A i − A j ∥ p = ( ∑ k = 1 N ∣ a k i − a k j ∣ p ) 1 / p M_{ij}=\left\| A_i-A_j\right\|_p=\left(\sum^{N}_{k=1}\left |a_{ki}-a_{kj}\right|^p\right)^{1/p} Mij=∥Ai−Aj∥p=(k=1∑N∣aki−akj∣p)1/p
a k i a_{ki} aki 表示第 i i i 类的质心点的第 K K K 个值, M i j M_{ij} Mij 则就是第 i i i 类与第 j j j 类质心的距离(两个点的距离)。
3)计算 R i j R_{ij} Rij
计算了分子与分母后,DBI 定义了一个衡量相似度的值 R i j R_{ij} Rij,计算公式为:
R i j = S i + S j M i j R_{ij}=\frac{S_i+S_j}{M_{ij}} Rij=MijSi+Sj
衡量第 i i i 类与第 j j j 类的相似度。
4)计算DBI
有了以上公式的基础,我们做一个基于簇类数 n n n 的 n 2 n^2 n2 的嵌套循环,对每一个簇类 i i i 计算最大值的 R i j R_{ij} Rij,记为 D i D_i Di,即:
D i = max j ≠ i R i , j D_i=\displaystyle \max_{j\neq i}R_{i,j} Di=j=imaxRi,j
也即簇类 i i i 与其他类的最大相似度值,也就是取出最差结果。然后对所有类的最大相似度取均值就得到了 DBI 指数,计算公式为:
D B I = D ‾ = 1 N ∑ i = 1 N D i DBI=\overline{D}=\frac{1}{N}\sum^N_{i=1}D_i DBI=D=N1i=1∑NDi
分类个数的不同可以导致不同的值,DBI 值越小,分类效果越好(说明分散程度越低)。
图例:
左图表示不同簇类数目下数据点的分类情况,右图表示在不同的簇类数目下(q=1),DBI 值的变化。
总的来说,这个 DBI 就是计算类内距离之和与类间距离之比,来优化 k 值的选择,避免 K-means 算法中由于只计算目标函数Wn而导致局部最优的情况。
# -*- coding: utf-8 -*-
class evalution:
@classmethod
def vector_distance(cls, v1, v2):
"""
this function calculates de euclidean distance between two vectors.
params:
v1: vector v1
v2: vector v2
"""
sum = 0
for i in range(len(v1)):
sum += (v1[i] - v2[i]) ** 2
return sum ** 0.5
@classmethod
def compute_si(cls, i, x, clusters, nc):
"""
Average distance from within-class data to cluster centroids
params:
clusters: 某一聚类中心点,例如 clusters[j],具体内容取决于 j 的值。
x: 分类结果中,某一类数据集合。
i: label_的索引, 若为 1,则 x[1]表示 label 为 clusters[j] 的数据的集合
nc: nc is number of clusters
"""
norm_c = nc
s = 0
for t in x[i]: # 遍历标签为 i 的数据
s += cls.vector_distance(t, clusters) # 遍历每个点 t 与质心clusters的距离,然后累加
return s / norm_c
@classmethod
def compute_rij(cls, i, j, x, clusters, nc):
"""
先计算 Mij,再计算 Rij
params:
clusters: cluster centroids
i, j: 两个聚类结果的索引
nc: nc is number of clusters
"""
m_ij = cls.vector_distance(clusters[i], clusters[j]) # 计算质心 i 和 j 的距离 Mij (分母)
r_ij = (cls.compute_si(i, x, clusters[i], nc) + cls.compute_si(j, x, clusters[j], nc)) / m_ij # 衡量 i 和 j 的相似度
return r_ij
@classmethod
def compute_di(cls, i, x, clusters, nc):
"""
Calculates the max similarity between cluster i and other clusters
params:
i: 聚类结果中某一label_
x: 聚类结果数据,x[1]表示label为1的数据的集合
clusters: cluster centroids(聚类中心)
nc: nc is number of clusters
return:
max(list_r): max similarity between cluster i and other clusters
"""
list_r = []
for j in range(nc):
if i != j:
temp = cls.compute_rij(i, j, x, clusters, nc)
list_r.append(temp)
return max(list_r)
@classmethod
def compute_db_index(cls, x, clusters, nc):
"""
params:
x:
clusters:
nc: nc is number of clusters
"""
sigma_r = 0.0
for i in range(nc):
sigma_r = sigma_r + cls.compute_di(i, x, clusters, nc)
db_index = float(sigma_r) / float(nc)
return db_index
if __name__ == '__main__':
db_index = evalution.compute_db_index(x, clusters, nc)
参考资料
[1] Davies-Bouldin指数(DBI) 2020.11
[2] Python实现DBI(davies_bouldin_score)评价指标 2020.3
[3] 聚类算法评价指标——Davies-Bouldin指数(Dbi) 2018.5
[4] 聚类算法内部度量-si,ch,dbi 2022.2