【发布时间】:2012-08-05 17:13:57
【问题描述】:
编辑解决方案 这是解决方案,感谢@mprivat:
from mysql_wrapper2 import Mysql
import Levenshtein
import time
db = Mysql()
fields = [...]
records = db.query('SELECT *, CONCAT(%s) as `string`, SOUNDEX(CONCAT(%s)) as `soundsLike` FROM records ORDER BY `soundsLike`' % (','.join(fields), ','.join(fields)))
print len(records)
matches = []
start = time.clock()
for k,v in enumerate(records):
if k+1 == len(records):
break
if Levenshtein.ratio(records[k]['string'],records[k+1]['string']) >= .98:
matches.append((records[k],records[k+1]))
print time.clock() - start
print len(matches)
最终解决方案
我有一个用于 Web 应用程序的 MySQL 数据库,其中可能(或可能没有)有重复记录。这些记录代表人(即姓名、地址等)。
目前,我们有一个 python 脚本,它可以提取所有记录,将它们与带状疱疹进行比较,然后向管理用户展示潜在的重复记录。此脚本在
该方法使用 pygraph 记录数据,并使用 shingles 查找重复项。它仍然停留在图表中 - 所以我假设这意味着它甚至还没有完成查看记录!
我们希望能够比较“相似”匹配项,因此字段的差异(如“St.”和“Street”)不会成为唯一性的依据。我们可能不会处理简单的同义词,因此仅替换同义词不是一种选择。所以我猜我们正在寻找模糊匹配。
我尝试了一些简单的解决方案,但速度不够快。
虽然在这种情况下,哈希构建速度很快(当前的带状疱疹示例没有......它构建了大约 8 个小时并且没有完成),但它的比较速度是可怕的(但这是算法效率低下,而不是解释器速度)
我也在尽可能多地研究选项。我已经被Nearest Neighbor Search 卡住了一段时间了,DNlog(n) 搜索的命中承诺。
最近邻搜索有两个问题,你可能很清楚如何克服,但我一直没能解决:
- 并非所有键都是数字键
- 我们当前系统的限制是我们只需要一组 [K-Nearest Neighbor] 中的两个匹配项,但前提是它们是非常明确的匹配项(固定半径最近邻)
我也很幸运地找到了某种集群解决方案。我还没有找到一个可用的 python 库,其中包含可变数量的集群。我找到但无法实施的每个解决方案都需要提前了解最终要拥有的集群数量。
- 我们应该只在它们实际上相似时才具有匹配项
- 我们不知道会有多少,如果有的话。
对于#2,我们当然可以在得到答案后进行过滤,但哪个更好?但这只有在 #1 可以被克服的情况下。
由于我们要比较的数据受到限制,我还不能实现神经网络或聚类解决方案,并且不得不转向普通的旧比较。这样做时,为了删除比较域的数量,我连接了所有记录的值,并对字符串与所有其他字符串进行了 Levenshtein 比较。这个解决方案也不够快。它不会在大约 20 分钟内完成一条记录(我当时停止计时)。
我想出了一个简单的例子:
from mysql_wrapper2 import Mysql
import Levenshtein
db = Mysql()
# Get 89k records from the database
records = db.query(""""
SELECT *
FROM records
""")
# Build a dictionary where the keys are our records, and their IDs are our data
# Only passing ID, we only use about 3GB of memory, instead of
# > 16GB with the actual dictionaries
records_hash = {}
for i in records:
key = []
for k in i.values():
key.append(str(i))
records_hash['-'.join(key)] = i['id']
# Compare every key to every key with the Levenshtein ratio
for i in records_hash.keys():
print 'once...'
for j in records_hash.keys():
if Levenshtein.ratio(i,j) >= .75:
pass
再一次,这是一个简单的例子,如果实际实施,将确保没有两条记录被检查两次,等等。
有什么解决办法吗?有没有一种方法可以实现 NN 或 Clustering 来解决我的问题?有没有其他我不考虑的模式可以提供帮助?我是 SOL 吗?
【问题讨论】:
标签: python mysql algorithm data-mining bigdata