我正在处理十万 (100,000) 个文档(平均文档长度约为 500 个术语)。对于每个文档,我想通过余弦相似度获得前 k(例如 k = 5)个相似文档。那么如何通过Python高效做到这一点。
这是我做的:
- 对每个文档进行文本分割,去除停用词,统计词频(tf)
- 所以我们得到 tf 矩阵,大约 100,000 个文档 * 600000 个术语
- 做 1 - pairwise_distances (tf_matrix, metric = "余弦")
- 对于每个文档,获取前k个相似的文档。
我在 i5-2.5GHz 上运行我的代码,12 小时过去了,但它仍然有效。所以我想知道如何优化我的代码或过程。
这是我的想法:
- 对每个文档,做特征选择,只保留tf > 1的词
- 先进行聚类,然后计算每个聚类内的余弦相似度
- 因为我只需要前 k 个相似的文档,我是否需要计算所有成对的余弦相似度?
- python GPU 编程还是并行编程?
那么,你有什么好主意吗?
非常感谢。
我知道有一个 similar question ,但这不是我想要的。
更新1
感谢@orange ,经过profiling,我发现第2步是瓶颈!这是示例代码:
def construct_dt_matrix():
dt_matrix = pd.DataFrame(columns=['docid'])
docid = 0
for f in files:
# text segmentation for f
# remove stop words
# word count store in cleaned_dict = {'word': tf}
dt_matrix.loc[docid] = [0] * dt_matrix.shape[1] # add one row, init all 0
dt_matrix.set_value(docid, 'docid', docid)
for key, value in cleaned_dict.items():
if key not in dt_matrix.columns.values:
dt_matrix[key] = 0 # add one column, init all 0
dt_matrix.set_value(docid, key, value) # bottleneck
docid += 1
因此,瓶颈在于向 pandas 添加新的行和列。有什么想法吗?
最佳答案
Pandas DataFrames(和底层的 numpy)只有在您一次分配数据数组时才会非常快。 set_value
需要为矩阵中的每个单元调用一次!
您可以执行 dt_matrix = pd.DataFrame(cleaned_dict)
并且您有一个带有一个函数调用的 DataFrame(忽略 Pandas 内部调用)。
改为尝试:
dt_matrix = pd.DataFrame()
for docid, f in enumerate(files):
dt_matrix_file = pd.DataFrame(cleaned_dict)
dt_matrix_file['docid'] = docid
dt_matrix = dt_matrix.append(dt_matrix_file)
这应该快几个数量级。
如果您要求 NaN 单元格为零,您可以执行 dt_matrix.fillna(0)
(再次调用一次,而不是潜在的 n * m)。
关于python - 如何使用python通过余弦相似度有效地检索前K个相似文档?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34446985/