You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Sklearn KMeans手动修改聚类中心后,序列化反序列化结果不一致

问题描述

我正在使用Sklearn 0.24.2版本的KMeans模型进行向量量化,通过Kiefer-Wolfowitz算法的变体手动修改聚类中心以实现优化。提取聚类中心调整后重新赋值给模型,但使用Pickle(也尝试过Joblib)保存并重新加载模型后,量化器的评估结果出现差异。

用于获取和设置聚类中心的方法:

def getWeights():
   return self.kmeans.cluster_centers_.flatten()
def setWeights(weights):
   kmeans.cluster_centers_ = weights.reshape(self.clusters, self.dim)

模型保存与加载代码:

# 保存
with open(os.path.join(savepath, savename + '.pkl'), 'wb') as f:
            pickle.dump(self.kmeans, f)

# 加载
with open(os.path.join(savepath, savename + '.pkl'), 'rb') as f:
            self.kmeans  = pickle.load(f)

通过np.sum(cc1 - cc2)对比加载前后的聚类中心,得到差异值:[-23657.44412046 -27826.84822967 -34863.87009913 -22867.6671942 -31120.73019114]。

请问该差异的原因是什么?是Pickle未保存全精度,还是版本问题?当前使用Python 3.6,因依赖限制无法升级。


原因分析与验证建议

可能的核心原因

  • Sklearn模型序列化的状态同步问题:Sklearn的KMeans模型除了cluster_centers_,还有内部维护的状态变量(如_n_features_in_、_fit_status_等)。手动修改cluster_centers_后,这些衍生状态并未同步更新,导致保存后加载的模型在执行评估、预测时,内部逻辑依赖了未同步的状态,最终出现结果偏差。
  • NumPy数组的类型/形状异常:检查保存前后cluster_centers_的dtype和形状是否一致。如果手动修改时误将数组类型从float64转为float32(或反之),或reshape时维度匹配错误,会导致序列化后数值出现大幅偏差——你给出的差异值量级很大,更倾向于这类问题。
  • 旧版本Sklearn的序列化bug:Sklearn 0.24.2对Python 3.6的支持虽存在,但针对手动修改模型属性的场景,__getstate__/__setstate__序列化逻辑可能存在疏漏,导致手动赋值的cluster_centers_未被完整保存。

验证步骤

  1. 排除模型本身的临时状态问题:保存前连续两次调用评估,看结果是否一致。如果一致,说明问题确实出在保存加载环节。
  2. 直接对比数组二进制:打印保存前和加载后cluster_centers_.tobytes(),若二进制不一致,说明序列化过程中数组被篡改。
  3. 单独序列化聚类中心:用np.save/np.load单独保存cluster_centers_,加载后重新赋值给模型,再评估。如果结果正常,说明是Pickle对整个模型序列化的问题,而非数组本身的精度问题。

内容的提问来源于stack exchange,提问作者Blinski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 11:15:44