【问题标题】:Replace all collocations in a text file with a dictionary of collocations in python用python中的搭配字典替换文本文件中的所有搭配
【发布时间】: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代码(由于corpussub的大小,使用了多处理)

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)

我添加了已经初始化的corpussub 变量(在上面的sn-p 中)来显示代码是如何工作的。 corpus.txtsub.txt 在实际设置中都包含数百万(分别为 200M+ 和 4M+)行。我需要一个可以有效完成任务的代码,我已经尝试过Multiprocessingpool,但这需要几周时间才能完成。还有其他高效快捷的方法来完成这项任务吗?

【问题讨论】:

  • 很酷的项目。我不知道答案,但是您是否考虑过使用 NLTK 或类似方法?
  • 想知道您是否可以组合模式来进行不那么频繁的解析。 IE。正则表达式_ = re.compile(pat1|pat2|pat3...)。在命中查找时,匹配在字典中的替换,或者甚至可能不需要给定您的样本。不,不是 4M concats,但即使是 10-20 个 可能 的块也有帮助。有一种 re.split 的味道,可以保留分隔符。
  • 我现在看到你了。但考虑使用拆分、添加、重新加入而不是直接输出。我相信拆分保持分隔符是(&lt;pat&gt;) 而不是&lt;pat&gt;。即只是额外的包装括号。更少的字符串操作导致更少的内存搅动。

标签: python python-3.x nlp nltk information-retrieval


【解决方案1】:

你正在为每个句子重新编译你的模式。这需要相当多的时间。 相反,您可以在全局范围内编译您的模式一次:

sbsx = { " "+ng+" " : " <bop> "+ng+" <eop> " for ng  in sub }
pattern = re.compile("|".join([re.escape(k) for k in sorted(sbsx,key=len,reverse=True)]), flags=re.DOTALL)

def multiple_replace(string):
     print("replaced = ")
     return pattern.sub(lambda x: sbsx[x.group(0)], string)

我用你的例句测试了 100 万次,我从 52 秒缩短到只有 13 秒。

我希望我没有遗漏任何内容,这将有助于加快您的代码速度。

【讨论】:

  • 有趣。我以为re 默认缓存了大约 100 个模式,但你在这里取得了不错的结果。
  • 很好的观察和解决方案在这里@chefhose。我现在有了很大的进步! Errrm,你对代码的多处理部分有什么要说的吗?
猜你喜欢
  • 2011-12-27
  • 1970-01-01
  • 1970-01-01
  • 2019-06-25
  • 1970-01-01
  • 1970-01-01
  • 2017-06-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多