xMillion条目的匿名化-需要性能提示



编辑:在每次调用时初始化名称数据集(将黑名单名称数据集加载到内存中(是一个巨大的错误。刚刚将m=NameData((移到主函数。没有测量,但现在至少快了100倍。


我开发了一个(多语言(快速搜索的数据库和数据表。我想匿名化MySQL数据库中的一些数据(名称等(。在第一个例子中,我使用了spaCy,但因此字典没有经过训练,结果有太多的误报。现在我对名称数据集非常满意。当然,它的工作方式完全不同,而且与spaCy慢得多,这得益于GPU的强大功能。

因此,自定义名称数据库变得相当大(350.000行(,而目标数据库则非常庞大-在循环中使用regex.finditer处理每个找到的单词将永远耗时(Ryzen 7 3700X(。我们可以说是5个案例/秒,这使得>100个小时的百万行。因此,每个进程只消耗大约10%的CPU功率,我启动了几个(最多10个(python进程——最终它仍然需要很长时间。

我希望,我再也不用这样做了——但我害怕,我不得不这样做。我想问的是,你对以下动作有什么技巧吗?

  • main((中的outer for循环-它在管道对象(DB行(中循环,并调用三次(=3项/列(anonymize((
  • 它还有一个for循环,它贯穿找到的每个单词

重写它们、使用CUDA/numba(RTX 2070可用(等是否有意义。?还有其他的表演技巧吗?谢谢

import simplejson as json
import sys, regex, logging, os
from names_dataset import NameDataset
def anonymize(sourceString, col):
replacement = 'xxx'
output = ''
words = sourceString.split(' ')
#and this second loop for each word (will run three times per row)
for word in words:
newword = word
#regex for findind/splitting the words
fRegExStr = r'(?=[^srn|(|)])(w+)(?=[.?:,!-/s()]|$)'
pattern = regex.compile(fRegExStr)
regx = pattern.finditer(word)
if regx is None:
if m.search_first_name(word, use_upper_Row=True):
output += replacement
elif m.search_last_name(word, use_upper_Row=True):
output += replacement
else:
output += word
else:
for eachword in regx:
if m.search_first_name(eachword.group(), use_upper_Row=True):
newword = newword.replace(eachword.group(), replacement)
elif m.search_last_name(eachword.group(), use_upper_Row=True):
newword = newword.replace(eachword.group(), replacement)
output += newword
output += ' '
return output
def main():
#object with data is been piped to the python script, data structure:
#MyRows: {
#   [Text_A: 'some text', Text_B: 'some more text', Text_C: 'still text'],
#   [Text_A: 'some text', Text_B: 'some more text', Text_C: 'still text'],
#   ....several thousand rows
#   }
MyRows = json.load(sys.stdin, 'utf-8')
#this is the first outer loop for each row
for Row in MyRows:
xText_A = Row['Text_A']
if Row['Text_A'] and len(Row['Text_A']) > 30:
Row['Text_A'] = anonymize(xText_A, 'Text_A')
xText_B = Row['Text_B']
if xText_B and len(xText_B) > 10:
Row['Text_B'] = anonymize(xText_B, 'Text_B')
xMyRowText_C = Row['MyRowText_C']
if xMyRowText_C and len(xMyRowText_C) > 10:
Row['MyRowText_C'] = anonymize(xMyRowText_C, 'MyRowText_C')
retVal = json.dumps(MyRows, 'utf-8')
return retVal
if __name__ == '__main__':
m = NameDataset() ## Right here is good - THIS WAS THE BOTTLENECK ##
retVal = main()
sys.stdout.write(str(retVal))

您正在进行

for word in words:
newword = word
#regex for findind/splitting the words
fRegExStr = r'(?=[^srn|(|)])(w+)(?=[.?:,!-/s()]|$)'
pattern = regex.compile(fRegExStr)
regx = pattern.finditer(word)

这意味着你在循环的每一个回合中regex.compile都是完全相同的东西,而你可以在循环开始前这样做,并得到相同的结果。

我没有看到其他明显的优化,所以我建议对代码进行分析,找出最耗时的部分。

最新更新