![](/img/trans.png)
[英]Python: How can I make this function for calculating distances faster?
[英]How can I make this python function faster?
我编写的以下代码包含68,000个项目,并尝试根据字符串中的文本位置查找相似的项目。 这个过程在我暂时用来编码的i3 4130上花了点时间-有什么方法可以加快速度吗? 我的意思是“你是说吗?” 功能,因此我需要对用户输入的内容进行排序。
我不是要在已经使用关键字创建的字典中通过相似性进行比较,而是要在用户输入的动态输入与所有现有键之间进行相似性比较。 用户可能会键入错误的键,这就是为什么它会像Google搜索一样显示“您是不是要输入?”的原因。
根据平均测试,排序不会影响时间。
def similar_movies(movie):
start=time.clock()
movie=capitalize(movie)
similarmovies={}
allmovies=all_movies() #returns set of all 68000 movies
for item in allmovies:
'''if similar(movie.lower(),item.lower())>.5 or movie in item: #older algorithm
similarmovies[item]=similar(movie.lower(),item.lower())'''
if movie in item: #newer algorithm,
similarmovies[item]=1.0
print item
else:
similarmovies[item]=similar(movie.lower(),item.lower())
similarmovieshigh=sorted(similarmovies, key=similarmovies.get, reverse=True)[:10]
print time.clock()-start
return similarmovieshigh
使用的其他功能:
from difflib import SequenceMatcher
def similar(a, b):
output=SequenceMatcher(None, a, b).ratio()
return output
def all_movies(): #returns set of all keys in sub dicts(movies)
people=list(ratings.keys())
allmovies=[]
for item in people:
for i in ratings[item]:
allmovies.append(i)
allmovies=set(allmovies)
return allmovies
字典采用这种格式,但有数千个名称:
rating = {'Shane':{'Avatar':4.2,'127 Hours':4.7},'Joe':{'Into The Wild':4.5,'Unstoppable':3.0}}
您的算法将为O(n 2 ),因为在每个标题中, in
运算符必须检查标题的每个子字符串,以确定输入的文本是否在其中。 是的,我可以理解为什么您希望它运行得更快。
i3不能提供太多的计算能力,因此唯一的解决方案是尽可能地进行预计算,而再次运行该功能,则运行额外的软件(例如数据库)可能会产生较差的结果。
您可能会考虑使用标题词词典(可能通过预先计算的语音变化来消除最常见的拼写错误-Porter Stemmer算法应提供一些有用的归约规则,例如,允许“不停”匹配“不停”)。
因此,例如,词典中的一个键将是“ wild”(或语音调整),并且与该键关联的值将是包含“ wild”的所有标题的列表; 在68,000个标题列表中,“ the”,“ into”,“ avatar”,“ hours”,“ 127”以及所有其他单词的含义相同。 举例来说,字典的“ wild”条目可能类似于:
"wild": ["Into The Wild", "Wild Wild West", "Wild Things"]
(是的,我只是在IMDB上搜索“ wild”,所以此列表中可能有更多条目-可能不是最佳选择,但是其中没有“ avatar”,“ unstoppable”或“ hours”的标题很少)。
诸如“ the”之类的常用词可能有足够多的条目,您希望将它们排除在外,因此,词典的持久副本可能有助于您进行特定的调整,尽管这不是必需的,并且计算时间应该是启动相对较快。
当用户键入某些文本时,您将文本拆分为多个单词,如果选择使用它们,则应用任何语音简化,然后将用户的所有单词的所有标题列表(包括重复项)串联起来。
然后,计算重复项并按标题匹配的次数排序。 如果用户键入“ The Wild”,则您在“ Into The Wild”中将有两个匹配项(“ the”和“ wild”),因此它的排序应比仅包含“ the”或“ wild”的标题更高,在他们中。
您可以在建立最终排序列表之后搜索等级列表,并将等级附加到每个条目上; 此操作应该很快,因为您的评分已在字典中,并以名称为关键字。
对于输入的每个单词,这会将O(n 2 )搜索转换为O(log(n))搜索,如果适合您的需求,这将在性能上产生很大的不同。
在all_movies()
不是附加到一个列表中,您可以添加一组,而不是投键()到一个列表:
def all_movies():
allmovies = set()
for item in ratings.keys():
for i in ratings[item]:
allmovies.add(i)
return allmovies
编辑:或者只能用一个for循环:
def all_movies():
result = []
for rating_dict in ratings.values()
result += rating_dict.keys()
return result
我看similar_movies
。
也可以看看celery: http : //docs.celeryproject.org/en/latest/用于多处理,
尤其是chunks
的概念: http://docs.celeryproject.org/en/latest/userguide/canvas.html#chunks
如果您正在为生产系统进行开发,建议您使用全文搜索引擎,如Whoosh(Python) , Elastic Search(Java)或Apache Solr(Java) 。 全文搜索引擎是一种服务器,它构建索引以有效地实现包括模糊或接近搜索在内的全文搜索。 许多流行的数据库系统还具有完整的搜索文本引擎,例如PostgreSQL FTS和MySQL FTS ,如果您已经在使用这些数据库引擎,它们可能是可接受的替代方法。
如果此代码主要是为自学而开发的,并且您想学习如何实现模糊搜索,则可能需要查看将索引和搜索字词中的电影标题标准化。 诸如Soundex和Metaphone之类的方法可以根据其在英语中的发音方式对搜索词进行归一化,并且可以使用此归一化的词来创建搜索索引。 PostgreSQL已经实现了这些算法 。 请注意,这些算法是非常基本的构建块,适当的全文本搜索引擎将考虑拼写错误,同义词,停用词,特定于语言的怪癖以及诸如并行/分布式处理等优化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.