为什么Whoosh Search在sklearn中的表现比tfidfvectorizer差?

时间:2019-08-26 11:02:19

标签: python whoosh

我实现了一个基于TF-IDF矢量化器(sklearn)的基本(几乎所有默认选项)的搜索程序,以根据用户查询来搜索某些文档。

我还尝试使用python中的Whoosh实现相同的功能。尽管独立的tfidfvectorizer实现针对同一查询返回许多直观结果,但whoosh查询仅返回一个查询。 (当我尝试在更多字段中搜索并归结为0个结果时,该结果就消失了)。我想知道我在做什么错?

我已经尝试根据Whoosh文档在Whoosh搜索器中适当设置得分。 with myindex.searcher(weighting=scoring.TF_IDF()) as s:

有了这个,我认为它应该给出与TF-IDF矢量化器的sklearn实现有些相似的结果,但是只返回一个匹配。我如何获得类似的结果,即如何在飞快移动中使用类似于sklearns TF-IDF矢量化器的实现。

当我使用多个字段进行搜索时 MultifieldParser(["title", "content", "tags", "categories"], ix.schema) 与仅单个字段“内容”相反,结果是没有点击。

模式:

schema = Schema(id = NUMERIC,
                title = TEXT(field_boost=2.0, stored=True, analyzer = StandardAnalyzer(minsize = 1)),              
                content = TEXT(stored=False, analyzer = StemmingAnalyzer(minsize = 1)),
                permalink = ID(stored=True),
                tags = KEYWORD(field_boost=2.0,lowercase=True, commas=True, scorable=True, stored = True),
                categories = KEYWORD(field_boost=2.0,lowercase=True, commas=True, scorable=True, stored = True),
                pub_date = DATETIME(stored = True),
                creator = TEXT(stored=False)
                )

搜索:

writer = ix.writer()
for i in range(len(df)):
    writer.add_document(id = df["ID"][i], title = df["Title"][i],  content=df["Content"][i],
                    permalink = df["Permalink"][i], tags = df["Tag"][i], categories = df["Category"][i],
                    pub_date = df["PubDate"][i], creator = df["Creator"][i])
writer.commit()

with ix.searcher(weighting=scoring.TF_IDF()) as searcher:
    parser = MultifieldParser(["title", "content", "tags", "categories"], ix.schema)
    query_string = sys.argv[2]
    myquery = parser.parse(query_string)
    results = searcher.search(myquery, limit = 10, terms = True)
    print(len(results))
    for i in range(results.scored_length()):
        print(results[i])
        print()
    print("\n")

该代码可以正常工作,也可以获取结果。我所面临的唯一问题是,与TF-IDF实现相比,它们似乎缺乏,而且在大多数情况下返回的结果也更少(问题不是飞速搜索中的limit属性)。我想知道如何在飞快移动中获得更好的结果或对结果进行评分,以及为什么它比正常实现返回的结果更少。

查询“如何编码?”的输出示例 TF-IDF(sklearn):

30 Tips to Become Super Effective Software Developers
(Cosine Similarity of 0.3783876779183675 ):

Automation and Continuous Delivery are the bedrock of DevOps
(Cosine Similarity of 0.1476918570123896 ):

Practical Implementation of DevOps Step by Step
(Cosine Similarity of 0.1469115686911894 ):

10 Software Development Frustrations & What You Can Do To Avoid Them!
(Cosine Similarity of 0.13241987064219532 ):

WHOOSH(仅在内容字段中搜索时,否则返回0次匹配):

<Hit {'title': 'Ultimate List of 110 Must Read Software Development Books'}>

编辑:我只是再次运行代码,发现如果删除“?”从查询“如何编码?”并仅在“标题”和“内容”中搜索,它会返回很多结果,而且看起来也更好。尽管我一开始在要搜索的字段中包含“标签”和“类别”,但结果将变为0。为什么?

1 个答案:

答案 0 :(得分:0)

?被视为通配符。我现在正在玩飞快移动,并注意到:

query = QueryParser("content", ix.schema).parse("one")

我得到:

<Top 1 Results for Term('content', 'one') runtime=0.0006002392619848251>

同时搜索一个吗?:

query = QueryParser("content", ix.schema).parse("one?")

我得到:

<Top 0 Results for Wildcard('content', 'one?') runtime=0.0002482738345861435>

在第二个示例中可以看到,返回的对象是通配符。在此处阅读更多信息:https://whoosh.readthedocs.io/en/latest/querylang.html#inexact-terms