使用肘部法确定k-medoids聚类数时运行代码报内存错误如何解决
内存错误根因
你遇到的内存错误是由KMedoids的PAM算法特性导致的:PAM算法的空间复杂度为O(n²),运行时需要预计算所有样本两两之间的距离矩阵,当你的words_vector样本量较大时,距离矩阵的内存占用会指数级上升,直接触发内存溢出。同时你循环运行6次不同k值的训练,未及时释放的内存也会加剧占用问题。
另外你原有代码的肘部法逻辑存在错误:inertia_(平方损失)会随着聚类数增加持续降低,用np.argmin找最小值只会得到最大的k值,完全不符合肘部法找拐点的核心逻辑。
修复方案
- 降采样确定k值:不需要用全量词向量跑肘部法,随机抽取10%-30%的代表性样本即可得到准确的拐点位置,确定最优k后再用全量数据训练聚类模型,可大幅降低计算压力
- 更换低内存算法:将
method="pam"替换为method="alternate",该实现不需要预计算完整距离矩阵,空间复杂度大幅降低,适合大样本场景 - 循环内主动释放内存:每次完成单个k值的训练后,手动删除模型对象并回收内存,避免内存累积
- 修正肘部法逻辑:手动判断曲线拐点,或使用拐点检测工具定位最优聚类数
修复后代码
import numpy as np import matplotlib.pyplot as plt from sklearn_extra.cluster import KMedoids import gc def elbowKMediod(words_vector, sample_ratio=0.2): # 可选:降采样减少计算量 if sample_ratio < 1: sample_size = int(len(words_vector) * sample_ratio) idx = np.random.choice(len(words_vector), sample_size, replace=False) words_vector = words_vector[idx] num_cluster = list(range(2,8)) squared_errors = [] for cluster in num_cluster: print(cluster, "Done") # 更换为alternate方法降低内存占用 kmediods = KMedoids(n_clusters = cluster, random_state=0, method="alternate") kmediods.fit(words_vector) squared_errors.append(kmediods.inertia_) # 主动释放内存 del kmediods gc.collect() # 绘制肘部曲线,手动观察拐点取最优k,不要用argmin plt.plot(num_cluster, squared_errors) plt.title("Elbow Curve to find the no. of clusters.") plt.xlabel("Number of clusters.") plt.ylabel("Squared Loss.") plt.grid(True) plt.show() # 示例:简单拐点检测逻辑,也可手动指定拐点对应的k值 diffs = np.diff(squared_errors) diff_ratios = diffs[:-1] / diffs[1:] optimal_idx = np.argmax(diff_ratios) + 1 optimal_clusters = num_cluster[optimal_idx] return optimal_clusters
内容的提问来源于stack exchange,提问作者Dharshitha
相关产品推荐
相关产品推荐

