BertTokenizer详解

Tokenizing:将任意长的文本转化成数字序列,定义为TokenIds.每一个TokenId是word,subword或者character在词汇表里的索引。

Tokenizing的前提必须要有一张词汇表。

词汇表的学习过程:

1.Standardize:滤出标点符号,将所有大写统一为小写。这个步骤属于可选步骤,可以执行,也可以不执行。

2.split:分词

3.最后便是统计所有出现过的字符,并组成一个词汇表。

英语文本的预处理通常是Tokenizing,而Tokenizing的最小维度分为三种——word(单词),wordpiece(单词块),character(字母)。word的Tokenizing很好处理,因为英文文本单词之间有着天然的空格符,完全可以根据空格符进行Tokenizing。character的Tokenizing也同样好处理,只需将文本里所有字母切分开就行了。但是wordpiece的Tokenizing却显得更复杂,却又更实用。这种方式可以将" unintended "分解成 " un "," intend ", "ed",将" actor "分解成" act "和" or "。显然这种Tonkenizing更符合英语文本的语法分析。以wordpiece建立的词汇表,称之为Bert wordpiece vocabulary。


利用tensorflow_text包可以在英文文本集上学习到一张Bert wordpiece vocabulary。

 导包,
from tensorflow_text.tools.wordpiece_vocab import bert_vocab_from_dataset as bert_vocab

  利用如下方法即可实现,

bert_vocab.bert_vocab_from_dataset(
    dataset,
    **bert_vocab_args
)

 该方法的关键源码部分为

tokenizer = bert_tokenizer.BasicTokenizer(**bert_tokenizer_params)
  words_dataset = dataset.map(tokenizer.tokenize)
  word_counts = learner.count_words(words_dataset)

  vocab = learner.learn(word_counts, vocab_size, reserved_tokens,
                        **learn_params)

  return vocab

 

注意

从数据集里产生wordpiece vocabulary之前,该方法会先通过类对象BasicTokenizer进行分词。我们可以通过使用它,分析一下该对象的分词原理是什么。

 导入包,

from tensorflow_text.python.ops import bert_tokenizer

  使用该对象对英文文本分词,

text_inputs1 = [b'taste the rustisc indiefrost']
text_inputs2 = [b'tastethe rustiscindiefrost']
a = bert_tokenizer.BasicTokenizer(lower_case=False, normalization_form='NFC')
print(a.tokenize(text_inputs1))
print(a.tokenize(text_inputs2))



<tf.RaggedTensor [[b'taste', b'the', b'rustisc', b'indiefrost']]>
<tf.RaggedTensor [[b'tastethe', b'rustiscindiefrost']]>

  观察输出结果可知,对英文文本是以空格符作为分词依据的


   使用该对象对中文文本分词,

text_inputs1 = '明天你有时间吗'
text_inputs2 = '明 天 你 有 时 间 吗'
a = bert_tokenizer.BasicTokenizer(lower_case=False, normalization_form='NFC')
print(a.tokenize(text_inputs1))
for i in a.tokenize(text_inputs1).numpy():
    for j in i:
        print(j.decode('utf-8'))

print(a.tokenize(text_inputs2).numpy())
for i in a.tokenize(text_inputs2).numpy():
    for j in i:
        print(j.decode('utf-8'))
<tf.RaggedTensor [[b'\xe6\x98\x8e', b'\xe5\xa4\xa9', b'\xe4\xbd\xa0', b'\xe6\x9c\x89',
  b'\xe6\x97\xb6', b'\xe9\x97\xb4', b'\xe5\x90\x97']]>
明
天
你
有
时
间
吗
[[b'\xe6\x98\x8e' b'\xe5\xa4\xa9' b'\xe4\xbd\xa0' b'\xe6\x9c\x89'
  b'\xe6\x97\xb6' b'\xe9\x97\xb4' b'\xe5\x90\x97']]
明
天
你
有
时
间
吗

发现对于中文来说,不管字与字之间是否有空格,都会将一句话分解成一个个字。

 

A basic tokenizer that tokenizes using some deterministic rules:
- For most languages, this tokenizer will split on whitespace.
- For Chinese, Japanese, and Korean characters, this tokenizer will split on
    Unicode characters.

学习词汇表,

dataset = tf.data.Dataset.from_tensor_slices(tf.constant(['明天你有时间吗']))
en_vocab = bert_vocab.bert_vocab_from_dataset(
    dataset,
    vocab_size=2,
    # Reserved tokens that must be included in the vocabulary
    reserved_tokens=[],
    # Arguments for `text.BertTokenizer`
    bert_tokenizer_params=dict(lower_case=True),
    # Arguments for `wordpiece_vocab.wordpiece_tokenizer_learner_lib.learn`
    learn_params={}
)
print(en_vocab)  
['你', '吗', '天', '时', '明', '有', '间', '##你', '##吗', '##天', '##时', '##明', '##有', '##间']

 将词汇表写入文件,每一行含一个字。然后以形参的方式传给BertTokenizer对象,

tokenizers = text.BertTokenizer(vocab_lookup_table='vocab.txt')
print(tokenizers.tokenize(['明天你']))
<tf.RaggedTensor [[[5],
  [2],
  [0]]]>

4e25792ae72548858bb984e44d721084.png 

 输出的维度是三维的,(batch_size, text_length, subword_num),因为中文没有subword的概念,所以subword_num都是为1。

注意:BertTokenizer里的tokenize方法在Tokenizing之前同样调用了BasicTokenizer进行分词处理。上文已经强调了,BasicTokenizer对于中文的分词原则是根据Unicode字符(一个汉字对应一个Unicode字符单位)来进行处理的,也就是说,无需将中文文本的每个字用空格隔开。但在tf.keras.layers.TextVectorization层里需要用空格隔开,因为该层一律是根据空格来进行分词的。

总结:

  1. tensorflow_text对于中文,日文,韩文的分词是根据Unicode,而英文,葡萄牙文之类的是依据空格的。
  2. 在tokenizing之前或者学习wordpiece词汇表之前,首先进行的是分词处理。

加深影响,以英文为例,

tokenizers = text.BertTokenizer(vocab_lookup_table='vocab.txt', lower_case=True)
print(tokenizers.tokenize(['I am unintended']))
print(tokenizers.detokenize(tokenizers.tokenize(['I am unintended'])))
<tf.RaggedTensor [[[3], [4, 5], [0, 1, 2]]]>
<tf.RaggedTensor [[[b'i'],
  [b'am'],
  [b'unintended']]]>

01d9e2399e0b4c87b69ee45b5261a0bf.png

##代表充当后缀的subword,无##的subword是位于word首部的。

由上面可知,am被分解为a和##m,unintended分解为un,##intend和##ed。

detokenize就是将索引对应的subword在三维数组中沿着-1轴进行拼接。以无##的subword为首,然后向后拼接有##的subword。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
berttokenizer分词原理是基于Bert模型的分词器。在BertTokenizer中,分词过程分为两个步骤:tokenization和detokenization。在tokenization过程中,原始文本会被分解成一个个标记,每个标记对应于词汇表中的一个字或一个子词。这个过程使用了Bert模型的词汇表进行标记化。每个标记都由一个整数表示,例如`'I am unintended'`会被分解成`[, [4, 5], [0, 1, 2]]`。其中,``对应的是字`'I'`,`[4, 5]`对应的是子词`'am'`,`[0, 1, 2]`对应的是子词`'unintended'`。 在detokenization过程中,标记会被还原成原始文本。使用`tokenizers.detokenize()`方法,可以将标记序列还原为原始文本。例如,`tokenizers.detokenize(tokenizers.tokenize(['I am unintended']))`会得到`[[b'i'], [b'am'], [b'unintended']]`,即`'I am unintended'`的还原结果。 具体实现中,BertTokenizer使用了Bert模型的词汇表进行标记化和还原化操作。词汇表是由字或子词构成的,每个标记对应一个字或子词。通过将词汇表写入文件,每一行含一个字的方式,可以生成BertTokenizer对象,并在初始化时将词汇表文件作为参数传入。然后,使用BertTokenizer对象的`tokenize()`方法可以将文本分解为标记序列。例如,`tokenizers.tokenize(['明天你'])`会得到`[, , ]`,即`'明天你'`被分解成了``、``和``三个标记。 综上所述,BertTokenizer分词原理可概括为:使用Bert模型的词汇表将原始文本分解为标记序列,并通过标记序列还原出原始文本。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [BertTokenizer详解](https://blog.csdn.net/qq_57390446/article/details/131056984)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值