【发布时间】:2020-10-17 20:46:45
【问题描述】:
我正在尝试使用 python 将文本文件 [corpus.txt] 中的子字符串替换为其他一些子字符串 [collocation|ngram]。我在包含以下内容的文件 sub.txt 中有可能的子字符串列表:
dogs chase
birds eat
chase birds
chase cat
chase birds .
还有一个corpus.txt,其中包含如下一些文本:
dogs chase cats around
dogs bark
cats meow
dogs chase birds
cats chase birds , birds eat grains
dogs chase the cats
the birds chirp
具有所需的输出
<bop> dogs chase <eop> cats around
dogs bark
cats meow
<bop> dogs chase <eop> birds
cats <bop> chase birds <eop> , <bop> birds eat <eop> grains
<bop> dogs chase <eop> the cats
the birds chirp
还有我的带有多处理的python代码(由于corpus和sub的大小,使用了多处理)
import sys
import string
import time
from multiprocessing import Pool
import re
import itertools
flatten = itertools.chain.from_iterable
#corpus_dir = sys.argv[1]
#ngram_dir = sys.argv[2]
#f = open(corpus_dir) # Open file on read mode
#corpus = f.read().split("\n") # Create a list containing all lines
#f.close() # Close file
#f2 = open(ngram_dir) # Open file on read mode
#sub = f2.read().split("\n") # Create a list containing all lines
#f2.close() # Close file
sub = ['dogs chase', 'birds eat', 'chase birds', 'chase cat', 'chase birds .']
corpus = [' dogs chase cats around ', ' dogs bark ', ' cats meow ', ' dogs chase birds ', ' cats chase birds , birds eat grains ', ' dogs chase the cats ', ' the birds chirp ']
print("The corpus has ", len(corpus))
sbsx = { " "+ng+" " : " <bop> "+ng+" <eop> " for ng in sub }
def multiple_replace(string, rep_dict):
pattern = re.compile("|".join([re.escape(k) for k in sorted(rep_dict,key=len,reverse=True)]), flags=re.DOTALL)
print("replaced = ")
return pattern.sub(lambda x: rep_dict[x.group(0)], string)
def f(a_list):
out = [multiple_replace(sent, sbsx) for sent in a_list]
'''out = []
for sent in a_list:
c = multiple_replace(sent, sbsx)
out.append(c)
#print(c)
time.sleep(0.01)
'''
return out
def f_amp(a_list):
#chunks = [a_list[i::5] for i in range(5)]
chunks = [a_list[x:x+5] for x in range(0, len(a_list), 5)]
print(len(chunks))
pool = Pool(processes=10)
result = pool.map_async(f, chunks)
while not result.ready():
print("Running...")
time.sleep(0.5)
return list(flatten(result.get()))
final_anot = f_amp(corpus)
print(final_anot)
我添加了已经初始化的corpus 和sub 变量(在上面的sn-p 中)来显示代码是如何工作的。 corpus.txt 和 sub.txt 在实际设置中都包含数百万(分别为 200M+ 和 4M+)行。我需要一个可以有效完成任务的代码,我已经尝试过Multiprocessing 和pool,但这需要几周时间才能完成。还有其他高效快捷的方法来完成这项任务吗?
【问题讨论】:
-
很酷的项目。我不知道答案,但是您是否考虑过使用 NLTK 或类似方法?
-
想知道您是否可以组合模式来进行不那么频繁的解析。 IE。正则表达式_ = re.compile(pat1|pat2|pat3...)。在命中查找时,匹配在字典中的替换,或者甚至可能不需要给定您的样本。不,不是 4M concats,但即使是 10-20 个 可能 的块也有帮助。有一种 re.split 的味道,可以保留分隔符。
-
我现在看到你了。但考虑使用拆分、添加、重新加入而不是直接输出。我相信拆分保持分隔符是
(<pat>)而不是<pat>。即只是额外的包装括号。更少的字符串操作导致更少的内存搅动。
标签: python python-3.x nlp nltk information-retrieval