如何基于距离矩阵和KMedoids为新增观测分配所属聚类簇
问题解决方法
错误原因
- 你调用
fit()时输入的是5个原始文档的5×5距离矩阵,KMedoids模型的输入特征维度对应「样本到所有原始训练样本的距离」,维度固定为5 - 你调用
predict()时传入的是包含新文档的6列距离矩阵,多了新文档到自身的距离列,维度变为6和训练时的5不匹配,因此抛出维度错误。
小提示:如果你训练KMedoids时用的是预计算的距离矩阵,一定要在初始化时指定metric='precomputed',否则模型会把输入的距离矩阵当成普通特征矩阵处理,结果会出错。
无需重新聚类的实现方法
这个需求完全可以实现,不需要每次新增数据都重新训练聚类,有两种可行方案:
方案1:手动计算归属簇(更简单,不需要调用模型接口)
KMedoids的预测逻辑本身就是把新样本划分到「距离最近的簇中心(medoid)」所在的簇,你可以直接手动计算:
- 首先从训练好的模型中提取簇中心对应的原始样本索引:
# 获取原始训练集中作为簇中心的样本索引(对应你原始距离矩阵的行/列名) medoid_ids = distance.index[kmed.medoid_indices_].tolist()
- 从新的距离矩阵中提取新增文档(示例中为第6个)到所有簇中心的距离,取距离最小的簇即为归属:
# 示例提取新文档6到所有簇中心的距离 new_doc_dist = new_distance.loc[6, medoid_ids] # 得到归属簇 assigned_cluster = new_doc_dist.idxmin()
就你给出的示例数据而言,新文档6到中心3的距离只有0.01,是所有距离里最小的,直接划入3所在的簇即可。
方案2:修正输入维度后调用predict()接口
如果要使用模型自带的predict()方法,你只需要传入新文档到原始5个训练样本的距离,也就是去掉新矩阵里新增的第6列即可:
# 提取新文档行,仅保留前5列(对应到原始5个训练样本的距离) predict_input = new_distance.loc[[6], new_distance.columns[:5]] # 调用预测 assigned_cluster = kmed.predict(predict_input)
什么时候需要重新聚类?
只有当你新增的样本量足够大、或者观察到原有簇的结构已经发生明显偏移时,才需要重新用全量数据训练KMedoids,单条或者少量新增数据直接按上述方法增量分配即可。
内容的提问来源于stack exchange,提问作者mjoy
相关产品推荐
相关产品推荐

