使用ward法执行AgglomerativeClustering时内存不足问题求助
解决方案:AgglomerativeClustering处理大数据集的内存问题
问题根源
你的报错是因为scipy的linkage函数计算ward聚类时,需要预计算全样本的距离矩阵,这是O(n²)的内存开销。根据报错里的数组形状(8979943105,),可以算出你的样本量约为13.4万条,每个float64元素占8字节,总内存需求约71GB,远超过你8GB的物理内存,直接触发MemoryError。
可行解决方案
1. 用sklearn的AgglomerativeClustering做聚类(无全距离矩阵)
如果核心需求是完成聚类而非生成完整树状图,直接用scikit-learn的实现,它不需要预计算全距离矩阵,内存效率极高:
from sklearn.cluster import AgglomerativeClustering # 初始化聚类器,指定聚类数和ward方法 cluster = AgglomerativeClustering(n_clusters=5, linkage='ward') # 直接拟合数据并得到聚类标签 labels = cluster.fit_predict(data_scaled)
sklearn的实现采用增量式合并策略,仅维护必要的聚类间距离信息,内存占用远低于scipy的linkage。
2. 若需生成树状图:用抽样或截断方式
完整树状图需要存储所有样本的合并路径,内存开销依然巨大,可通过以下方式折中:
- 抽样生成树状图:从全量数据中抽取少量样本(比如1000-5000条),用这部分数据生成树状图,大致体现聚类结构:
# 随机抽样1000条数据 sample = data_scaled.sample(n=1000, random_state=42) # 生成linkage矩阵并绘制树状图 wardlink = linkage(sample, method='ward') dend_wardlink = dendrogram(wardlink) - 截断树状图:如果能生成完整的
linkage矩阵(比如抽样后),用scipy的dendrogram参数截断显示,只保留关键聚类分支:# 只显示最后20个聚类的合并过程 dendrogram(wardlink, truncate_mode='lastp', p=20)
3. 临时内存优化技巧
- 降低数据精度:将数据从
float64转为float32,内存占用直接减半(需验证精度是否满足需求):data_scaled = data_scaled.astype('float32') - 关闭后台不必要程序,释放物理内存;或开启Windows虚拟内存(但会大幅降低计算速度,仅作应急)
内容的提问来源于stack exchange,提问作者user2779095
相关产品推荐
相关产品推荐

