PCA降维后调用sklearn cosine_similarity触发递归错误求助
解决cosine_similarity在PCA降维后矩阵上的RecursionError问题
首先,你遇到的核心问题是:PCA降维后的密集矩阵(转成DataFrame)调用cosine_similarity时触发了递归深度超出的错误,而原稀疏矩阵却能正常运行。这大概率是因为密集矩阵的内存占用过高,加上cosine_similarity处理密集矩阵的内部逻辑,导致了Windows下的栈溢出(错误码0xC00000FD就是栈溢出的典型标识)。
下面给你几个可行的解决办法:
1. 直接用numpy数组而非DataFrame传递给cosine_similarity
你当前把PCA降维后的numpy数组转成DataFrame完全没必要,反而会增加额外的内存开销和计算负担。cosine_similarity可以直接处理numpy数组,修改代码如下:
dtm = tdm.T # scale dtm in range [0:1] to better variance maximization scl = MinMaxScaler(feature_range=[0, 1]) data_rescaled = scl.fit_transform(dtm) # Fitting the PCA algorithm with our Data pca = PCA(n_components=n).fit(data_rescaled) data_reducted = pca.transform(data_rescaled) # 跳过转DataFrame步骤,直接用numpy数组计算 cs = cosine_similarity(data_reducted) cs_pd = pd.DataFrame(cs)
这个改动能减少DataFrame带来的额外内存消耗,很大概率能解决栈溢出问题。
2. 分块计算余弦相似度(针对超大矩阵场景)
如果9000×9000的相似度矩阵内存压力还是太大,可以分块计算,避免一次性加载整个矩阵:
from sklearn.metrics.pairwise import cosine_similarity import numpy as np # 定义分块大小,可根据内存情况调整 block_size = 1000 num_blocks = (data_reducted.shape[0] + block_size - 1) // block_size cs_blocks = [] for i in range(num_blocks): start_idx = i * block_size end_idx = min((i+1)*block_size, data_reducted.shape[0]) # 计算当前块与整个矩阵的余弦相似度 block_similarity = cosine_similarity(data_reducted[start_idx:end_idx], data_reducted) cs_blocks.append(block_similarity) # 拼接所有块得到完整的相似度矩阵 cs = np.vstack(cs_blocks) cs_pd = pd.DataFrame(cs)
分块计算能降低单次计算的内存占用,从根源上避免栈溢出。
3. 临时调整递归深度(不推荐,仅作应急)
如果上述方法都不行,可以尝试临时提高Python的递归深度限制,但这只是治标不治本,可能会引发其他内存问题:
import sys # 把递归深度调大,比如设置为10000 sys.setrecursionlimit(10000) # 然后再计算余弦相似度 cs = cosine_similarity(dtm_reducted) cs_pd = pd.DataFrame(cs)
注意:这个方法风险较高,若矩阵过大,可能会导致程序崩溃,优先推荐前两种方法。
补充说明
原稀疏矩阵能正常运行,是因为cosine_similarity对稀疏矩阵做了专门优化,采用了更高效的内存存储和计算方式;而密集矩阵(尤其是9000×200转成9000×9000的相似度矩阵)会占用大量连续内存,容易触发栈溢出错误。
内容的提问来源于stack exchange,提问作者MARCO LAGALLA
相关产品推荐
相关产品推荐

