许可证: apache-2.0
语言:
- 越南语
任务标签: 词元分类
标签:
- 越南语
- 声调标注器
- 变音符号
指标:
- 准确率
越南语声调标注的Transformer模型
该模型用于为未标注声调(或部分词汇有声调而部分没有)的越南语文本添加声调符号(变音符号)。
示例输入: Nhin nhung mua thu di
目标输出: Nhìn những mùa thu đi
模型训练
该问题被建模为一个词元分类任务。对于每个输入词元,目标是分配一个"标签",将其转换为带声调的词元。
该模型基于XLM-Roberta Large进行微调。关于训练过程的更多细节,请参考这篇博客文章。
如何使用该模型
只需几个步骤:
- 第一步:将模型加载为词元分类模型(
AutoModelForTokenClassification
)。
- 第二步:将输入文本通过模型运行,获取每个输入词元的标签索引。
- 第三步:使用标签索引从文件
selected_tags_names.txt
中检索实际标签。然后,根据标签指示的转换规则,将每个词元转换为带声调的词元。
第一步:加载模型
注意:请先安装transformers、torch、numpy包。
from transformers import AutoTokenizer, AutoModelForTokenClassification
import torch
import numpy as np
def load_trained_transformer_model():
model_path = "peterhung/vietnamese-accent-marker-xlm-roberta"
tokenizer = AutoTokenizer.from_pretrained(model_path, add_prefix_space=True)
model = AutoModelForTokenClassification.from_pretrained(model_path)
return model, tokenizer
model, tokenizer = load_trained_transformer_model()
第二步:将输入文本通过模型运行
device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")
model.to(device)
model.eval()
def insert_accents(text, model, tokenizer):
our_tokens = text.strip().split()
inputs = tokenizer(our_tokens,
is_split_into_words=True,
truncation=True,
padding=True,
return_tensors="pt"
)
input_ids = inputs['input_ids']
tokens = tokenizer.convert_ids_to_tokens(input_ids[0])
tokens = tokens[1:-1]
with torch.no_grad():
inputs.to(device)
outputs = model(**inputs)
predictions = outputs["logits"].cpu().numpy()
predictions = np.argmax(predictions, axis=2)
predictions = predictions[0][1:-1]
assert len(tokens) == len(predictions)
return tokens, predictions
text = "Nhin nhung mua thu di, em nghe sau len trong nang."
tokens, predictions = insert_accents(text, model, tokenizer)
第三步:获取带声调的词汇
3.1 从本仓库下载标签集文件(selected_tags_names.txt
)。假设它被放在当前目录下,我们可以加载它:
def _load_tags_set(fpath):
labels = []
with open(fpath, 'r') as f:
for line in f:
line = line.strip()
if line:
labels.append(line)
return labels
label_list = _load_tags_set("./selected_tags_names.txt")
assert len(label_list) == 528, f"Expect {len(label_list)} tags"
3.2 打印出上面获得的tokens
和predictions
,看看我们得到了什么
print(tokens)
print(list(f"{pred} ({label_list[pred]})" for pred in predictions))
得到:
['▁Nhi', 'n', '▁nhu', 'ng', '▁mua', '▁thu', '▁di', ',', '▁em', '▁nghe', '▁sau', '▁len', '▁trong', '▁nang', '.']
['217 (i-ì)', '217 (i-ì)', '388 (u-ữ)', '388 (u-ữ)', '407 (ua-ùa)', '378 (u-u)', '120 (di-đi)', '0 (-)', '185 (e-e)', '185 (e-e)', '41 (au-âu)', '188 (e-ê)', '302 (o-o)', '14 (a-ắ)', '0 (-)']
可以看到,原始词汇已被模型进一步拆分为更小的词元。但我们知道每个词的第一个词元以特殊字符"▁"开头。
这里,我们需要将这些词元(以及相应的标签)合并回原始的越南语词汇。然后,对于每个词,我们将应用第一个改变该词的标签(如果它有多个标签)。
这可以通过以下方式完成:
TOKENIZER_WORD_PREFIX = "▁"
def merge_tokens_and_preds(tokens, predictions):
merged_tokens_preds = []
i = 0
while i < len(tokens):
tok = tokens[i]
label_indexes = set([predictions[i]])
if tok.startswith(TOKENIZER_WORD_PREFIX):
tok_no_prefix = tok[len(TOKENIZER_WORD_PREFIX):]
cur_word_toks = [tok_no_prefix]
j = i + 1
while j < len(tokens):
if not tokens[j].startswith(TOKENIZER_WORD_PREFIX):
cur_word_toks.append(tokens[j])
label_indexes.add(predictions[j])
j += 1
else:
break
cur_word = ''.join(cur_word_toks)
merged_tokens_preds.append((cur_word, label_indexes))
i = j
else:
merged_tokens_preds.append((tok, label_indexes))
i += 1
return merged_tokens_preds
merged_tokens_preds = merge_tokens_and_preds(tokens, predictions)
print(merged_tokens_preds)
得到:
[('Nhin', {217}), ('nhung', {388}), ('mua', {407}), ('thu', {378}), ('di,', {120, 0}), ('em', {185}), ('nghe', {185}), ('sau', {41}), ('len', {188}), ('trong', {302}), ('nang.', {0, 14})]
对于每个词,我们现在有一组标签索引来应用。例如,对于第一个词"Nhin",我们将应用标签集中索引为217
的标签。
以下是最后一步:
def get_accented_words(merged_tokens_preds, label_list):
accented_words = []
for word_raw, label_indexes in merged_tokens_preds:
for label_index in label_indexes:
tag_name = label_list[int(label_index)]
raw, vowel = tag_name.split("-")
if raw and raw in word_raw:
word_accented = word_raw.replace(raw, vowel)
break
else:
word_accented = word_raw
accented_words.append(word_accented)
return accented_words
accented_words = get_accented_words(merged_tokens_preds, label_list)
print(accented_words)
得到:
['Nhìn', 'những', 'mùa', 'thu', 'đi,', 'em', 'nghe', 'sâu', 'lên', 'trong', 'nắng.']
在这个例子中,模型在词汇"sầu"上犯了一个错误(预测为"sâu")。
局限性
- 该模型最多接受512个词元,这是基础预训练XLM-Roberta模型的限制。
- 与HMM版本(准确率91%)相比,它具有更高的准确率(97%),但代价可能是更长的运行时间。更多信息可以在此找到。
在线演示
- 您可以使用本页面右侧的推理API(由HF自动提供)查看分配给每个词的标签(索引)。