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

Windows环境下Sklearn凝聚聚类触发MemoryError内存不足问题求助

解决凝聚聚类(Agglomerative Clustering)的内存不足问题

你的问题根源很明确:AgglomerativeClustering使用ward linkage时,默认会计算全量的两两样本距离矩阵,对于406829个样本来说,这个矩阵的元素数量是n*(n-1)/2≈8.27e10个,每个float64类型占8字节,总内存需求高达617GiB——这显然远远超出了你16GB物理内存的承载能力。修改Jupyter的max_buffer_size没用,因为这个参数管的是Jupyter的缓存,解决不了Python进程本身需要的巨量内存问题。

下面给你几个可行的解决方案,按优先级排序:

1. 用稀疏连接矩阵优化凝聚聚类

sklearn的AgglomerativeClustering支持通过connectivity参数限制只计算样本与邻近样本的距离,避免生成全量距离矩阵,能大幅降低内存占用。具体来说,我们可以用k近邻图来定义样本间的连接关系,只让每个样本和它的k个邻居参与聚类计算:

import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import AgglomerativeClustering
from sklearn.neighbors import kneighbors_graph

# 先标准化数据(ward linkage对尺度敏感,建议先做标准化)
scaler = StandardScaler()
data_scaled = scaler.fit_transform(data)

# 生成k近邻连接矩阵,k值可以根据你的数据调整,比如先试10
connectivity = kneighbors_graph(data_scaled, n_neighbors=10, include_self=False)

# 传入connectivity参数进行聚类
aggloclust = AgglomerativeClustering(
    affinity='euclidean',
    linkage='ward',
    n_clusters=5,
    connectivity=connectivity
).fit(data_scaled)

labels = aggloclust.labels_
plt.scatter(data_scaled[:,0], data_scaled[:,1], c=labels)
plt.show()

这个方法能把内存需求从数百GiB降到几百MB级别,同时保留ward linkage的聚类特性。

2. 先降维再聚类

你的数据集是8维,先通过降维算法(比如PCA)把特征维度压缩到2-3维,再进行凝聚聚类。虽然样本数还是40万,但降维后聚类计算的速度会大幅提升,同时如果降维保留了足够多的原始数据信息,聚类结果也不会有太大偏差:

from sklearn.decomposition import PCA

# 标准化+PCA降维
scaler = StandardScaler()
data_scaled = scaler.fit_transform(data)
pca = PCA(n_components=2)  # 降到2维,方便后续可视化
data_pca = pca.fit_transform(data_scaled)

# 对降维后的数据做聚类
aggloclust = AgglomerativeClustering(
    affinity='euclidean',
    linkage='ward',
    n_clusters=5
).fit(data_pca)

labels = aggloclust.labels_
plt.scatter(data_pca[:,0], data_pca[:,1], c=labels)
plt.show()

注意:这个方法本身不会解决全距离矩阵的内存问题,但降维后可以和上面的connectivity方法结合,进一步优化性能。

3. 换用适合大数据集的聚类算法

凝聚聚类(层次聚类)的时间和空间复杂度都是O(n²),天生不适合超大规模数据集。如果可以接受非层次聚类的结果,MiniBatchKMeans是更好的选择——它用小批量样本迭代计算,内存占用极低,速度极快,适合百万级别的数据集:

from sklearn.cluster import MiniBatchKMeans

# 标准化数据
scaler = StandardScaler()
data_scaled = scaler.fit_transform(data)

# MiniBatchKMeans聚类,batch_size可以根据内存调整
mbk = MiniBatchKMeans(n_clusters=5, batch_size=10000, random_state=42)
labels = mbk.fit_predict(data_scaled)

plt.scatter(data_scaled[:,0], data_scaled[:,1], c=labels)
plt.show()

4. 临时方案:扩大虚拟内存(不推荐)

如果你一定要坚持用原始的ward linkage凝聚聚类,可以尝试扩大Windows的虚拟内存(页面文件):

  • 右键「此电脑」→「属性」→「高级系统设置」→「高级」→「性能」→「设置」→「高级」→「虚拟内存」→「更改」
  • 取消「自动管理所有驱动器的分页文件大小」,然后把系统盘的分页文件设为「自定义大小」,比如初始大小设为32GB,最大值设为64GB或更大

这个方法能让系统把部分数据放到硬盘上,但速度会非常慢(硬盘读写速度远低于内存),可能要运行几个小时甚至更久,只适合紧急场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 17:37:43