在我的空闲时间,我正在转录一本非常古老且稀有的罗马尼亚语书籍(据我所知,这是唯一现存的副本)。这本书写于一百多年前,那时还没有电脑。因此,没有数字副本,我正在手动转录和数字化它。
这本书有数千页长,对于我来说,令人惊讶的是在打字时为每个单词添加变音和重音标记(ă/â/î/ş/ţ
)非常耗时。如果我省略这些标记,只打出基本字母(即a
而不是ă/â
),我能够打字的速度提高两倍以上,这是一个巨大的优势。目前,我直接将所有内容输入到.tex
文件中,以便为页面和插图应用特殊格式。
然而,我知道最终我将不得不将所有这些标记重新添加到文本中,手动完成这项工作似乎既繁琐又不必要,因为我已经有了所有的字母。我正在寻找某种方法来自动/半自动地添加变音/重音标记到大量文本中(不是删除 – 我在Stack Overflow上看到很多关于如何删除标记的问题)。
我尝试搜索罗马尼亚语的大型语料库(这个和这个是最有希望的两个),但我找到的所有内容都不够完善,在我输入的任何随机文本样本中至少缺少几个单词(我使用了一个简短的Python脚本)。这本书使用了许多古老/不常见的单词或单词的不常见拼写,这也无济于事。
有谁对我如何处理这个问题有任何想法吗?这里没有愚蠢的想法 – 任何你能想到的可能有帮助的文档格式、机器学习技术、编程语言、专业工具等都是受欢迎的。
我还应该指出,我有丰富的编程经验,并且不会认为自己构建一些东西是浪费时间。老实说,我认为这对社区可能是有益的,因为我在任何西方语言(法语、捷克语、塞尔维亚语等)中都找不到这样的工具。只是需要一些关于如何开始的指导。
回答:
Bob的回答是一种静态方法,其效果取决于词表的质量好坏。因此,如果某个单词不在这个列表中,它将永远不会被处理。
此外,像许多其他语言一样,有一些情况是两个(或更多)单词使用相同的字符但不同的变音符号。对于罗马尼亚语,我找到了以下例子:peste = 超过 vs. pesţe = 鱼。这些情况也不能以直接的方式处理。特别是,如果你转换的文本包含了当今语言中不再使用的单词,尤其是带有变音符号的单词,这是一个问题。
在本回答中,我将介绍一种使用机器学习的替代方法。唯一的缺点是,我找不到公开可用的训练模型来进行罗马尼亚语的变音符号恢复。你可能会有幸联系到我将提到的论文的作者,看看他们是否愿意发送他们的训练模型供你使用。否则,你将不得不自己训练,我会给出一些指导。我将尽量全面地概述以帮助你开始,但鼓励进一步阅读。
尽管这个过程可能很费力,但使用正确的工具可以达到99%的准确率。
语言模型
语言模型可以被认为是对语言有高层次“理解”的模型。它们通常在原始文本语料库上进行预训练。虽然你可以训练自己的模型,但要注意这些模型的预训练是相当昂贵的。
虽然可以使用多语言模型,但如果有足够的数据进行训练,特定语言的模型通常表现更好。幸运的是,罗马尼亚语有公开的语言模型可用,例如RoBERT。这个语言模型基于BERT,这是一种在自然语言处理中广泛使用的架构,并且由于在英语和其他语言中取得了最先进的结果,它在该领域已成为标准。
事实上,有三种变体:基础版、大型版和小型版。模型越大,结果越好,因为其表示能力更强。但更大的模型在内存占用方面也会更高。
使用transformers库加载这些模型非常简单。例如,基础模型:
from transformers import AutoModel, AutoTokenizer, AutoModeltokenizer = AutoTokenizer.from_pretrained("readerbench/RoBERT-base")model = AutoModel.from_pretrained("readerbench/RoBERT-base")inputs = tokenizer("exemplu de propoziție", return_tensors="pt")outputs = model(**inputs)
上面的outputs
将包含输入文本的向量表示,更常称为“词嵌入”。然后语言模型会针对下游任务进行微调——在你的案例中,是变音符号恢复——并将这些嵌入作为输入。
微调
我找不到任何公开可用的微调模型,所以除非你自己找到一个模型,否则你将不得不自己进行微调。
为了微调语言模型,我们需要构建一个特定任务的架构,并在某个数据集上进行训练。数据集用于告诉模型输入是什么以及我们希望输出是什么样的。
数据集
从使用BERT进行变音符号恢复的分析,关于捷克语,有一个公开可用的数据集,包括罗马尼亚语在内的多种语言。数据集的注释还会根据你使用的微调架构而有所不同(更多信息见下文)。
一般来说,你会选择一个你认为变音符号质量高的数据集。从这个文本中,你可以自动构建注释,通过生成单词的无变音变体以及相应的标签。
请记住,你使用的数据集或任何其他数据集都会包含偏见,特别是在注释文本来源的领域方面。根据你已经转录的数据量,你可能还想使用你的文本构建一个数据集。
架构
你选择的架构将影响你使用的下游性能以及你需要编写的自定义代码量。
词级
上述工作,使用BERT进行变音符号恢复的分析,关于捷克语,使用了一种标记级分类机制,其中每个单词都被标记为一组指示,指示在哪个字符索引处插入哪种类型的变音符号。例如,无变音单词“dite”带有指令集1:CARON;3:ACUTE
表示在索引1和索引3处添加适当的变音符号,结果为“dítě”。
由于这是一个标记级分类任务,你不需要编写太多自定义代码,因为你可以直接使用BertForTokenClassification
。参考作者的代码以获取更完整的示例。
一个附注是,作者使用了多语言语言模型。这可以很容易地替换为另一个语言模型,例如上面提到的RoBERT。
字符级
或者,RoBERT论文使用了一个字符级模型。根据论文,每个字符被注释为以下之一:
对当前字符不做修改(例如,a → a),添加抑扬符号(例如,a → â 和 i → î),添加短音符号(例如,a → ̆ă),以及两个用于添加下逗号的类别(例如,s → ş 和 t → ţ)
在这里,你将不得不构建自己的自定义模型(而不是上面的BertForTokenClassification
)。但是,训练代码的其余部分将大体相同。这里是一个可以使用transformers库的模型class
模板:
from transformers import BertModel, BertPreTrainedModelclass BertForDiacriticRestoration(BertPreTrainedModel): def __init__(self, config): super().__init__(config) self.bert = BertModel(config) ... def forward( self, input_ids=None, attention_mask=None, token_type_ids=None ): ...
评估
在每个部分中,你有许多选项可供选择。我提供的一点实用建议是,从简单开始,如果你想进一步改进,可以增加复杂性。保留一个测试集来衡量你所做的更改是否导致了改进或退化,相比于你之前的设置。
至关重要的是,我建议至少你的测试集的一部分是来自你自己转录的文本,你使用的越多越好。首先,这是你自己注释的数据,因此你对这些数据的质量比任何其他公开可用的来源更有把握。其次,当你在目标领域的数据上进行测试时,你更有可能更准确地评估你的系统,以更准确地适应你的目标任务,因为其他领域可能存在某些偏见。