使Python Gensim搜索功能高效

时间:2019-02-13 15:37:31

标签: python python-3.x pandas gensim

我有一个带有文本列的DataFrame。我根据另一列中的值将DataFrame分为两部分。这些部分之一被索引到gensim相似性模型中。然后将另一部分输入模型中,以找到最相似的索引文本。这涉及几个搜索功能,以枚举索引部分中的每个项目。对于玩具数据,速度很快,但是对于我的真实数据,使用apply的速度太慢了。这是代码示例:

import pandas as pd
import gensim
import nltk
from nltk.tokenize import word_tokenize
nltk.download('punkt')

d = {'number': [1,2,3,4,5], 'text': ['do you like python', 'do you hate python','do you like apples','who is nelson mandela','i am not interested'], 'answer':['no','yes','no','no','yes']}
df = pd.DataFrame(data=d)

df_yes = df[df['answer']=='yes']

df_no = df[df['answer']=='no']
df_no = df_no.reset_index()

docs = df_no['text'].tolist()
genDocs = [[w.lower() for w in word_tokenize(text)] for text in docs]
dictionary = gensim.corpora.Dictionary(genDocs)
corpus = [dictionary.doc2bow(genDoc) for genDoc in genDocs]
tfidf = gensim.models.TfidfModel(corpus)
sims = gensim.similarities.MatrixSimilarity(tfidf[corpus], num_features=len(dictionary))

def search(row):
    query = [w.lower() for w in word_tokenize(row)]
    query_bag_of_words = dictionary.doc2bow(query)
    query_tfidf = tfidf[query_bag_of_words]
    return query_tfidf

def searchAll(row):
    max_similarity = max(sims[search(row)])
    index = [i for i, j in enumerate(sims[search(row)]) if j == max_similarity]
    return max_similarity, index

df_yes = df_yes.copy()

df_yes['max_similarity'], df_yes['index'] = zip(*df_yes['text'].apply(searchAll))

我曾尝试将操作转换为dask数据帧,但无济于事,并且尝试了python多处理。我如何使这些功能更有效率?是否可以对部分/全部功能进行矢量化处理?

1 个答案:

答案 0 :(得分:1)

您的代码的意图和操作尚不清楚。假设它可行,解释最终目标,并显示更多示例数据,更多示例查询以及您问题中的预期结果可能会有所帮助。

也许可以改进它,以免一遍又一遍地重复某些操作。一些想法可能包括:

  • 仅对每行令牌化一次,并缓存令牌化
  • 每行仅doc2bow()一次,并缓存BOW表示形式
  • 请勿在{{1​​}}内两次致电sims(search[row])
  • 不要重复两次–一次找到最大值,然后再次找到索引–只需一次

(不过,通常来说,高效的文本关键字搜索通常使用专门的反向索引来提高效率,以避免对每个文档进行昂贵的迭代。)