DBA K-means计算Davies-Bouldin Index报list不可调用错误
问题描述
通过循环遍历聚类数K=1到9的场景,运行DBA优化的DTW时序K-means算法,结合肘部法、轮廓系数、Davies-Bouldin指数三类指标确定最优聚类数。目前肘部法、轮廓系数的计算逻辑可正常运行,计算Davies-Bouldin指数时触发报错,相关实现代码如下:
inertias = [] silhouette = [] davies_bouldin = [] clusters_range = range(1, 10) for K in clusters_range: dba_km = TimeSeriesKMeans(n_clusters=K, n_init=2, metric="dtw", verbose=True, max_iter_barycenter=10, random_state=seed) y_pred = dba_km.fit_predict(scaled_ts) inertias.append(dba_km.inertia_) if K > 1: silhouette.append(silhouette_score(scaled_ts, dba_km.labels_)) davies_bouldin.append(davies_bouldin_score(scaled_ts, dba_km.labels_))
报错详情
- 触发位置:
davies_bouldin.append所在代码行 - 错误输出:
TypeError: 'list' object is not callable.
错误原因
这是Python动态类型机制下非常典型的命名覆盖问题:
- 绝大多数场景是因为你在Jupyter Notebook、IPython、IDE交互控制台这类保留内存变量的环境中跑代码时,之前的错误执行记录已经把
davies_bouldin_score这个评估函数名绑定成了列表对象。当你在append()的参数位置写davies_bouldin_score(...)时,本质是在尝试“调用一个列表”,自然会抛出类型错误,而解释器标记错误行时会把整行davies_bouldin.append标为触发位置,很容易误导排查方向。 - 少数情况是导入函数时写了别名,和你定义的存储结果的列表
davies_bouldin重名,列表赋值直接覆盖了函数对象,触发同类错误。
修复方案
- 先更改变量名规避冲突:把存储DBI结果的列表从
davies_bouldin改成语义更明确的名字,比如dbi_scores,同步修改对应的append语句,从根源上避免和函数名撞车:
# 替换原代码的davies_bouldin = [] dbi_scores = [] # ... # 循环内对应append行同步替换 dbi_scores.append(davies_bouldin_score(scaled_ts, dba_km.labels_))
- 重启运行环境的Python内核/解释器,清空内存里残留的错误变量绑定——很多时候改完代码还是报错,就是因为之前把函数覆盖成列表的绑定还在内存里没清掉。
- 确认DBI函数的导入语句正确,不要写错函数名,建议和轮廓系数函数一起导入:
from sklearn.metrics import silhouette_score, davies_bouldin_score
补充提示:你用的是DTW作为距离度量的时序K-means,默认的
davies_bouldin_score是基于欧氏距离计算的,和聚类用的度量不一致,评估结果参考性会打折扣,更严谨的做法是先预计算所有样本间的DTW距离矩阵,调用评分函数时传入metric="precomputed"参数。
内容的提问来源于stack exchange,提问作者Kabir
相关产品推荐
相关产品推荐

