python - Python中的高精度词对齐算法
问题描述
我正在做一个项目,在句子和其他语言的翻译之间建立高精度的词对齐,以衡量翻译质量。我知道 Giza++ 和其他单词对齐工具被用作统计机器翻译管道的一部分,但这不是我想要的。我正在寻找一种算法,该算法可以将源句子中的单词映射到目标句子中的相应单词,并且在给定这些限制的情况下透明且准确地:
- 两种语言没有相同的词序,并且顺序不断变化
- 源句中的某些词在目标句中没有对应的词,反之亦然
- 有时源中的一个词对应目标中的多个词,反之亦然,并且可以存在多对多映射
- 可能有句子在句子中多次使用同一个词,因此需要对单词及其索引进行对齐,而不仅仅是单词
这是我所做的:
- 从句子对列表开始,比如英语-德语,每个句子都被标记为单词
- 索引每个句子中的所有单词,并为每个单词创建一个倒排索引(例如,单词“world”出现在句子#5、16、19、26 ...等中),用于源词和目标词
- 现在这个倒排索引可以预测任何源词和任何目标词之间的相关性,作为两个词之间的交集除以它们的并集。例如,如果 tagret 词“Welt”出现在句子 5、16、26,32 中,(world, Welt) 之间的相关性是交集 (3) 中的索引数除以联合中的索引数 ( 5),因此相关性为 0.6。使用联合可以降低高频词的相关性,例如“the”,以及其他语言中的对应词
- 再次遍历所有句子对,并使用给定句子对的源词和目标词的索引来创建相关矩阵
这是英语和德语句子之间的相关矩阵的示例。我们可以看到上面讨论的挑战。
在图像中,有一个英语和德语句子之间的对齐示例,显示了单词之间的相关性,绿色单元格是应该由单词对齐算法识别的正确对齐点。
这是我尝试的一些方法:
- 在某些情况下,预期的对齐可能只是在其各自的列和行中具有最高相关性的单词对,但在许多情况下并非如此。
- 我已经尝试过类似 Dijkstra 的算法来绘制连接对齐点的路径,但它似乎并不能以这种方式工作,因为由于词序,您似乎可以来回跳转到句子中较早的单词,并且那里跳过没有对齐的单词是不明智的。
- 我认为最佳解决方案将涉及诸如扩展矩形之类的东西,它从最可能的对应关系开始,跨越多对多对应关系,并跳过没有对齐的单词,但我不确定什么是实现的好方法这个
这是我正在使用的代码:
import random
src_words=["I","know","this"]
trg_words=["Ich","kenne","das"]
def match_indexes(word1,word2):
return random.random() #adjust this to get the actual correlation value
all_pairs_vals=[] #list for all the source (src) and taget (trg) indexes and the corresponding correlation values
for i in range(len(src_words)): #iterate over src indexes
src_word=src_words[i] #identify the correponding src word
for j in range(len(trg_words)): #iterate over trg indexes
trg_word=trg_words[j] #identify the correponding trg word
val=match_indexes(src_word,trg_word) #get the matching value from the inverted indexes of each word (or from the data provided in the speadsheet)
all_pairs_vals.append((i,j,val)) #add the sentence indexes for scr and trg, and the corresponding val
all_pairs_vals.sort(key=lambda x:-x[-1]) #sort the list in descending order, to get the pairs with the highest correlation first
selected_alignments=[]
used_i,used_j=[],[] #exclude the used rows and column indexes
for i0,j0,val0 in all_pairs_vals:
if i0 in used_i: continue #if the current column index i0 has been used before, exclude current pair-value
if j0 in used_j: continue #same if the current row was used before
selected_alignments.append((i0,j0)) #otherwise, add the current pair to the final alignment point selection
used_i.append(i0) #and include it in the used row and column indexes so that it will not be used again
used_j.append(j0)
for a in all_pairs_vals: #list all pairs and indicate which ones were selected
i0,j0,val0=a
if (i0,j0) in selected_alignments: print(a, "<<<<")
else: print(a)
这是有问题的,因为它不支持多对多,甚至是一对多的对齐方式,并且在开始时很容易出错,因为选择了具有最高相关性的错误对,将其行和列排除在未来的选择之外。一个好的算法会考虑到某个对在其各自的行/列中具有最高的相关性,但也会考虑与具有高相关性的其他对的接近度。
如果您愿意,可以尝试以下数据,它位于 Google 表格中: https ://docs.google.com/spreadsheets/d/1-eO47RH6SLwtYxnYygow1mvbqwMWVqSoAhW64aZrubo/edit?usp=sharing
解决方案
词对齐在某种程度上仍然是一个开放的研究课题。Giza++ 背后的概率模型相当重要,参见:http ://www.ee.columbia.edu/~sfchang/course/svia/papers/brown-machine-translate-93.pdf
您可以采取许多现有的方法,例如:
- 自己实现 Giza++ 使用的“IBM 模型”(或者如果你很勇敢,试试 NLTK 实现)
- 实现https://www.aclweb.org/anthology/N13-1073/背后的(简单得多的)算法
fast_align
- 实现某种形式的基于 HMM 的对齐方式https://www.aclweb.org/anthology/C96-2141/
- 使用深度学习,有多种可能性;这篇论文似乎包含一个很好的方法概述https://www.aclweb.org/anthology/P19-1124.pdf(通常人们试图利用神经 MT 模型的注意力机制来做到这一点)
这是一个非常困难的机器学习问题,虽然像您这样的简单方法可以工作并非不可能,但首先研究现有工作可能是一个好主意。话虽如此,我们已经看到该领域令人惊讶的简单技术取得了相当多的突破,所以谁知道:-)
推荐阅读
- c# - ASP.NET Core 2 - AD 组未映射到安全角色
- matplotlib - 放大 Cartopy 正交图
- javascript - 如何隐藏按钮?
- node.js - Jenkins 在构建时是否缓存依赖项和 Docker 层?
- angular - Angular 应用程序两次下载捆绑的 JS,这是一个错误吗?
- jquery - 动态重新加载表时,列样式未呈现
- python - 根据相同的 x 值绘制两个不同长度的 matplotlib 列表
- azure-active-directory - 自定义 AAD 身份验证逻辑
- javascript - 在材质 UI 中使用 withWidth HOC
- c# - 是否有可能更改 DataGridRowGroupHeader 控件的内容?