繁体   English   中英

解析Moses配置文件

[英]Parsing a Moses config file

Moses Machine Translation Toolkit中获得这样的配置文件:

#########################
### MOSES CONFIG FILE ###
#########################

# input factors
[input-factors]
0

# mapping steps
[mapping]
0 T 0

[distortion-limit]
6

# feature functions
[feature]
UnknownWordPenalty
WordPenalty
PhrasePenalty
PhraseDictionaryMemory name=TranslationModel0 num-features=4 path=/home/gillin/jojomert/phrase-jojo/work.src-ref/training/model/phrase-table.gz input-factor=0 output-factor=0
LexicalReordering name=LexicalReordering0 num-features=6 type=wbe-msd-bidirectional-fe-allff input-factor=0 output-factor=0 path=/home/gillin/jojomert/phrase-jojo/work.src-ref/training/model/reordering-table.wbe-msd-bidirectional-fe.gz
Distortion
KENLM lazyken=0 name=LM0 factor=0 path=/home/gillin/jojomert/ru.kenlm order=5

# dense weights for feature functions
[weight]
UnknownWordPenalty0= 1
WordPenalty0= -1
PhrasePenalty0= 0.2
TranslationModel0= 0.2 0.2 0.2 0.2
LexicalReordering0= 0.3 0.3 0.3 0.3 0.3 0.3
Distortion0= 0.3
LM0= 0.5

我需要从[weights]部分读取参数:

UnknownWordPenalty0= 1
WordPenalty0= -1
PhrasePenalty0= 0.2
TranslationModel0= 0.2 0.2 0.2 0.2
LexicalReordering0= 0.3 0.3 0.3 0.3 0.3 0.3
Distortion0= 0.3
LM0= 0.5

我一直在这样做:

def read_params_from_moses_ini(mosesinifile):
    parameters_string = ""
    for line in reversed(open(mosesinifile, 'r').readlines()):
        if line.startswith('[weight]'):
            return parameters_string
        else:
            parameters_string+=line.strip() + ' ' 

获得此输出:

LM0= 0.5 Distortion0= 0.3 LexicalReordering0= 0.3 0.3 0.3 0.3 0.3 0.3 TranslationModel0= 0.2 0.2 0.2 0.2 PhrasePenalty0= 0.2 WordPenalty0= -1 UnknownWordPenalty0= 1 

然后使用解析输出

moses_param_pattern = re.compile(r'''([^\s=]+)=\s*((?:[^\s=]+(?:\s|$))*)''')

def parse_parameters(parameters_string):
    return dict((k, list(map(float, v.split())))
                   for k, v in moses_param_pattern.findall(parameters_string))


 mosesinifile = 'mertfiles/moses.ini'

 print (parse_parameters(read_params_from_moses_ini(mosesinifile)))

要得到:

{'UnknownWordPenalty0': [1.0], 'PhrasePenalty0': [0.2], 'WordPenalty0': [-1.0], 'Distortion0': [0.3], 'LexicalReordering0': [0.3, 0.3, 0.3, 0.3, 0.3, 0.3], 'TranslationModel0': [0.2, 0.2, 0.2, 0.2], 'LM0': [0.5]}

当前的解决方案包括从配置文件中读取一些疯狂的反转行,然后读取相当复杂的正则表达式以获取参数。

有没有更简单或更简洁的方法来读取文件并实现所需的参数字典输出?

是否可以更改configparser以使其读取moses配置文件? 这很困难,因为它实际上有一些错误的部分是参数,例如[distortion-limit]并且没有值6键。 在经过验证的可配置文件中,该文件将为distortion-limit = 6


注意:本机python configparser无法处理moses.ini配置文件。 如何使用Python3读取和写入INI文件的答案? 不管用。

您可以简单地做到这一点。

x="""#########################
### MOSES CONFIG FILE ###
#########################

# input factors 
[input-factors]
0

# mapping steps
[mapping]
0 T 0

[distortion-limit]
6

# feature functions
[feature]
UnknownWordPenalty
WordPenalty
PhrasePenalty
PhraseDictionaryMemory name=TranslationModel0 num-features=4 path=/home    /gillin/jojomert/phrase-jojo/work.src-ref/training/model/phrase-table.gz input-factor=0 output-factor=0
LexicalReordering name=LexicalReordering0 num-features=6 type=wbe-msd-bidirectional-fe-allff input-factor=0 output-factor=0 path=/home/gillin/jojomert/phrase-jojo/work.src-ref/training/model/reordering-table.wbe-msd-bidirectional-fe.gz
Distortion
KENLM lazyken=0 name=LM0 factor=0 path=/home/gillin/jojomert/ru.kenlm      order=5

# dense weights for feature functions
[weight]
UnknownWordPenalty0= 1
WordPenalty0= -1
PhrasePenalty0= 0.2
TranslationModel0= 0.2 0.2 0.2 0.2
LexicalReordering0= 0.3 0.3 0.3 0.3 0.3 0.3
Distortion0= 0.3
LM0= 0.5"""

print [(i,j.split()) for i,j in re.findall(r"([^\s=]+)=\s*([\d.\s]+(?<!\s))",re.findall(r"\[weight\]([\s\S]*?)(?:\n\[[^\]]*\]|$)",x)[0])]

输出: [('UnknownWordPenalty0', ['1']), ('PhrasePenalty0', ['0.2']), ('TranslationModel0', ['0.2', '0.2', '0.2', '0.2']), ('LexicalReordering0', ['0.3', '0.3', '0.3', '0.3', '0.3', '0.3']), ('Distortion0', ['0.3']), ('LM0', ['0.5'])] `

这是另一个基于正则表达式的简短解决方案,该解决方案返回类似于您的输出的值的字典:

import re
from collections import defaultdict

dct = {}

str="MOSES_INI_FILE_CONTENTS"

#get [weight] section
match_weight = re.search(r"\[weight][^\n]*(?:\n(?!$|\n)[^\n]*)*", str) # Regex is identical to "(?s)\[weight].*?(?:$|\n\n)"
if match_weight:
    weight = match_weight.group() # get the [weight] text
    dct = dict([(x[0], [float(x) for x in x[1].split(" ")]) for x in  re.findall(r"(\w+)\s*=\s*(.*)\s*", weight)])

print dct

IDEONE演示

产生的字典内容:

{'UnknownWordPenalty0': [1.0], 'LexicalReordering0': [0.3, 0.3, 0.3, 0.3, 0.3, 0.3], 'LM0': [0.5], 'PhrasePenalty0': [0.2], 'TranslationModel0': [0.2, 0.2, 0.2, 0.2], 'Distortion0': [0.3], 'WordPenalty0': [-1.0]}

逻辑:

  • 从文件中获取[weight]块。 它可以用做r"\\[weight][^\\n]*(?:\\n(?!$|\\n)[^\\n]*)*"匹配正则表达式[weight]从字面上来看,那么它匹配每个字符多次,直到出现双\\n符号为止(正则表达式使用展开循环技术,并且对于跨越几行的较长文本来说是很好的选择)。 相同的基于懒点的正则表达式为[ r"(?s)\\[weight].*?(?:$|\\n\\n)" ],但效率不高(第一个正则表达式为62个步骤,第528个为第二个正则表达式可在当前MOSES.ini文件中找到匹配项),但绝对更易读。
  • 运行搜索后,请检查匹配项。 如果找到匹配项,请运行re.findall(r"(\\w+)\\s*=\\s*(.*)\\s*", weight)方法来收集所有键值对。 使用的正则表达式是简单的(\\w+)\\s*=\\s*(.*)\\s*匹配并捕获到第1组中的一个或多个字母数字符号( (\\w+) ),后跟任意数量的空格= ,再次使用任意数量的空格( \\s*=\\s* ),然后将除换行符之外的所有符号匹配并捕获到组2中,直到字符串末尾。 尾随空格的尾随换行符用最后的\\s*修剪。
  • 收集键和值时,可以使用comprehension将后者作为解析为浮点值的数字列表返回。

没有正则表达式,您可以执行以下操作:

flag = False
result = dict()

with open('moses.ini', 'rb') as fh:
    for line in fh:
        if flag:
            parts = line.rstrip().split('= ')
            if len(parts) == 2:
                result[parts[0]] = [float(x) for x in parts[1].split()]
            else:
                break
        elif line.startswith('[weight]'):
            flag = True

print(result)

在循环中逐行读取文件,当达到[weight]时,将标志设置为True并为接下来的所有行提取键/值,直到空白行或文件末尾。

这样,仅将当前行加载到内存中,并且一旦到达[weight]块的末尾,程序就会停止读取文件。


使用itertools的另一种方式:

from itertools import *

result = dict()

with open('moses.ini', 'rb') as fh:
    a = dropwhile(lambda x: not(x.startswith('[weight]')), fh)
    a.next()
    for k,v in takewhile(lambda x: len(x)==2, [y.rstrip().split('= ') for y in a]):
        result[k] = [float(x) for x in v.split()]

print(result)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM