我有一个训练集包含两种类型的NLP解析树(PSG和CCG),它们有一个共同的源句子。我的目标是只使用一种类型的解析树,使用从训练数据中学习的一组规则,将给定类型转换为另一种类型的解析树。
例如,给定两种类型的解析树i和ii,比如说:
i: (S (N John) (VP (V hit) (NP (D the) (N ball) ) ) )
ii: (S (NP John) (S\NP ((S\NP)/NP hit) (NP (NP/NP the) (NP ball) ) ) )
它们都具有相同的叶节点,但具有不同的句法标签(分别为POS标签和CCG标签)。
我的方法是在每棵树的相应节点之间创建一个映射:
pos_cat_map = defaultdict(int) # A map from (POS tags, CCG tags) to their counts
cat_map = defaultdict(int) # A map from CCG tags to its counts
# Generate a hierarchical tree structure,
# @para: psg_sent is the sentence i, ccg_sent is ii.
psg_tree = generate_psg_tree(psg_sent)
ccg_tree = generate_ccg_tree(ccg_sent)
# Updating the container iteratively.
update_mapping(psg_tree, ccg_tree, pos_cat_map, cat_map)
函数update_mapping
定义如下:
def update_mapping(psg_tree, ccg_tree, pos_cat_map, cat_map):
...
if isinstance(psg_tree, PSGTree):
# Update the root node
pos_cat_map[(psg_tree.root, ccg_tree.cat)] += 1
cat_map[ccg_tree.cat] += 1
if ...
update_mapping(psg_tree.left_child, ccg_tree.head, pos_cat_map, cat_map)
update_mapping(psg_tree.right_child, ccg_tree.sister, pos_cat_map, cat_map)
...
elif isinstance(psg_tree, PSGLeafNode):
# Update the leaf node
...
try:
if psg_tree.word == ccg_tree.word:
pos_cat_map[(psg_tree.syn, ccg_tree.cat)] += 1
cat_map[ccg_tree.cat] += 1
else:
raise TransException("Two types of words are not matching: %s %s" % (tct_tree.word, ccg_tree.word))
...
...
执行此操作后,我得到了一个包含从PSG叶节点到CCG叶节点的映射的映射,例如:
==============
== p(pos|cat)
==============
v|S{sub}\NP 0.341598
vN|SP/SP 0.034783
a|[S/S]/[S/S] 0.014184
vN|NP 0.041867
p|[S/S]/[S{obj}\NP] 1.000000
...
然后我需要使用这个规则将PSG树转换为CCG树(或反向),但我发现这可能是不可能的,因为对于每个POS标签,从它生成了很多可能的CCG标签。可能的CCG树数量巨大。如何限制CCG树的空间以找到有效的空间?