2

我想构建一个多类分类模型,我将对话数据作为 BERT 模型的输入(使用 bert-base-uncased)。

问:我想问一个问题。
回答:当然,请走开。
问:今天天气怎么样?
回答:天气晴朗,阳光明媚。
问:好的,很高兴知道。
回答:你还想知道什么吗?

除此之外,我还有两个输入。

我想知道是否应该在对话中加入特殊标记,以使其对 BERT 模型更有意义,例如:

[CLS]QUERY:我想问一个问题。[EOT]
回答:当然,请走开。[EOT]
QUERY:今天天气怎么样?[EOT]
回答:天气晴朗,阳光明媚。[EOT]
QUERY:好的,很高兴知道。[EOT]
回答:你还想知道什么吗?[九月]

但我无法添加新的 [EOT] 特殊令牌。
或者我应该为此使用 [SEP] 令牌吗?

编辑:重现的步骤

from transformers import AutoTokenizer, AutoModelForSequenceClassification
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
model = AutoModelForSequenceClassification.from_pretrained("bert-base-uncased")

print(tokenizer.all_special_tokens) # --> ['[UNK]', '[SEP]', '[PAD]', '[CLS]', '[MASK]']
print(tokenizer.all_special_ids)    # --> [100, 102, 0, 101, 103]

num_added_toks = tokenizer.add_tokens(['[EOT]'])
model.resize_token_embeddings(len(tokenizer))  # --> Embedding(30523, 768)

tokenizer.convert_tokens_to_ids('[EOT]')  # --> 30522

text_to_encode = '''QUERY: I want to ask a question. [EOT]
ANSWER: Sure, ask away. [EOT]
QUERY: How is the weather today? [EOT]
ANSWER: It is nice and sunny. [EOT]
QUERY: Okay, nice to know. [EOT]
ANSWER: Would you like to know anything else?'''

enc = tokenizer.encode_plus(
  text_to_encode,
  max_length=128,
  add_special_tokens=True,
  return_token_type_ids=False,
  return_attention_mask=False,
)['input_ids']

print(tokenizer.convert_ids_to_tokens(enc))

结果:

['[CLS]', 'query', ':', 'i', 'want', 'to', 'ask', 'a', 'question', '.', '[', 'e' , '##ot', ']', 'answer', ':', 'sure', ',', 'ask', 'away', '.', '[', 'e', '## ot', ']', 'query', ':', 'how', 'is', 'the', 'weather', 'today', '?', '[', 'e', '## ot', ']', 'answer', ':', 'it', 'is', 'nice', 'and', 'sunny', '.', '[', 'e', '## ot', ']', 'query', ':', 'okay', ',', 'nice', 'to', 'know', '.', '[', 'e'、'##ot'、']'、'answer'、':'、'would'、'you'、'like'、'to'、'know'、'anything'、'else'、' ?', '[九月]']

4

1 回答 1

1

由于[SEP]标记的目的是充当两个句子之间的分隔符,因此它符合您使用[SEP]标记来分隔 QUERY 和 ANSWER 序列的目标。

您还尝试添加不同的标记来标记 QUERY 或 ANSWER的开头和结尾,<BOQ><EOQ>标记 QUERY 的开头和结尾。同样,<BOA><EOA>标记 ANSWER 的开始和结束。

有时,使用现有的标记比在词汇表中添加新的标记要好得多,因为它需要大量的训练迭代以及学习新标记嵌入的数据。

但是,如果您想在应用程序需要时添加新令牌,则可以按如下方式添加:

num_added_toks = tokenizer.add_tokens(['[EOT]'], special_tokens=True) ##This line is updated
model.resize_token_embeddings(len(tokenizer))

###The tokenizer has to be saved if it has to be reused
tokenizer.save_pretrained(<output_dir>)
于 2021-09-15T14:07:14.737 回答