当前位置:   article > 正文

NLP-transformer学习:(3)transformer的 tokenizer_slow fast tokenizer的区别

slow fast tokenizer的区别

NLP-transformer学习:(3)transformer的 tokenizer

在这里插入图片描述

基于 NLP-transformer学习:(1),这里对transformer 更近一步,学习尝试使用tokenizer,这些也是 NLP任务的基础之一



提示:以下是本篇文章正文内容,下面案例可供参考

1 tokenizer 概念

在之前的NLP任务,做数据处理非常的麻烦,需要讲文字类数据进行分词。然后根据分词结果构建一个词典,然后统计不同词的频度,还要过滤下,把没用的滤掉。
由于伸进网络无法直接识词语,因此需要根据词典将输入的文本映射成次的向量,所以就需要一个tokenizer

数据预处理:
第一步:分词:将语句分成token,比如 I eat hamburger. j即为[I] [eat] [hamburger]

第二步:映射:根据分词结果,和词典,构建句子和词典的映射

第三步:转换:将文本序列转为数字序列,,因此[I] [eat] [hamburger] 映射为 [2018] [101] [19471]

第四步:填充截断:一个batch中,对过短的数据填充,对过长的数据截断,保证输入数据范围是模型可接受的范围,同时batch 内部的数据维度大小一致。

上述这些,transformer 统统都做好了,我们就是使用。


2 tokenizer 实战

2.1 下载模型,并从本地读取

代码:

from transformers import AutoTokenizer

if __name__ == "__main__":
    sentense = "我爱吃羊肉泡馍和肉夹馍!"
    
    # load the tokenizer
    tokenizer = AutoTokenizer.from_pretrained("uer/roberta-base-finetuned-dianping-chinese")
    print(tokenizer)

    # save the tokenizer to local path
    tokenizer.save_pretrained("./roberta_tokenizer")

    # load tokenizer from local path
    tokenizer = AutoTokenizer.from_pretrained("./roberta_tokenizer/")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

运行结果:
在这里插入图片描述
同理,第一次要下载,再运行一次就好了:

2.2 分词

代码:

    # luanch the tokenizer
    tokens = tokenizer.tokenize(sentense)
    print(tokens)
    print(tokenizer.vocab_size)
  • 1
  • 2
  • 3
  • 4

运行结果:在这里插入图片描述
当前的 这个模型是将句子在分词时分成一个字一个字的,还有其他模型可以按照词组分。

2.3 词典

代码:

   # show the vecab
    print(tokenizer.vocab)
  • 1
  • 2

运行结果:
在这里插入图片描述
其中有些字是一个次,有些字是带个井号是因为为了减少词典,会将一个词拆成字词。

2.4 转换

代码:

    # convert the tokens into ids 
    ids = tokenizer.convert_tokens_to_ids(tokens)
    print(ids)

    # convert ids into tokens
    tokens = tokenizer.convert_ids_to_tokens(ids)
    print(tokens)

    # convert the token into sentense
    str_sentense = tokenizer.convert_tokens_to_string(tokens)
    print(str_sentense)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

运行结果:
在这里插入图片描述

注意:
第1行是将sentense 直接转化为tokens的结果
第2行是将tokens转为ids的结果
第3行是将ids的结果再转为tokens
第4行是讲token再变为句子

2.5 coder 编码

按照上述过就是之前的NLP方法,比较麻烦
huggingface 提供了更简洁的方法:

    # encoder
    ids = tokenizer.encode(sentense, add_special_tokens=True)
    print(ids)
    # decoder 
    str_sentense = tokenizer.decode(ids, skip_special_tokens=False)
    print(str_sentense)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

运行结果:
在这里插入图片描述
注意这里我的编码是 2760而感叹号是106,这里多了开头和结尾。

2.6 填充和截断

代码:

    # fill
    ids = tokenizer.encode(sentense, padding="max_length", max_length=20)
    print("fill:" + str(ids))
    # clip
    ids = tokenizer.encode(sentense, max_length=5, truncation=True)
    print("clip:" + str(ids))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

运行结果:
在这里插入图片描述
注意这里fill 用0进行了填充
截断则是直接截断

2.7 mask

在transformer 的论文中,mask 使用与在训练是不会提前知道结果进而训练错误,因此需要mask,

    # clip
    ids = tokenizer.encode(sentense, max_length=5, truncation=True)
    print("clip:" + str(ids))
    # fill
    ids = tokenizer.encode(sentense, padding="max_length", max_length=20)
    print("fill:" + str(ids))

    #mask
    attention_mask = [1 if idx != 0 else 0 for idx in ids]
    token_type_ids = [0] * len(ids)
    print(ids)
    print(attention_mask)
    print(token_type_ids)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

运行结果:
在这里插入图片描述

2.7 高级的调用方法:

代码:

    # advanced tokenizer
    inputs = tokenizer.encode_plus(sentense, padding="max_length", max_length=20)
    print(inputs)
    inputs = tokenizer(sentense, padding="max_length", max_length=20)
    print(inputs)
  • 1
  • 2
  • 3
  • 4
  • 5

运行结果:
在这里插入图片描述

2.7 deal with batch:

数据处理时,使用batch的方式处理是最快的

    # batchh
    import time
    print("batch test:")
    text = ["我爱吃泡馍",
            "吃泡馍前要先洗手然后用手掰馍",
            "泡馍可以有羊肉泡馍和牛肉泡馍",
            "吃泡馍时还要配有糖蒜",
            "糖蒜可以解腻",
            "吃完泡馍可以要一碗高汤"]
    start = time.time()
    tokens = tokenizer(text, padding="max_length", max_length=20)
    end = time.time()
    print("deal with batch:" + str(end - start))
    # loop
    start = time.time()
    for i in range(len(text)):
            tokens = tokenizer(text[i], padding="max_length", max_length=20)
    end = time.time()
    print("deal with loop :" + str(end - start))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

运行结果:
在这里插入图片描述
在处理数据时,用batch的方式会快一些,其实快很多,只是我这里据的例子过于简短。


3 fast & slow tokenizer

fast tokenizer 是用rust 语言实现的,速度快。
slow tokenizer 使用 python 语言实现的,速度慢。

    # fast
    fast_tokenizer = AutoTokenizer.from_pretrained("uer/roberta-base-finetuned-dianping-chinese")
    # slow
    slow_tokenizer = AutoTokenizer.from_pretrained("uer/roberta-base-finetuned-dianping-chinese", use_fast=False)
  • 1
  • 2
  • 3
  • 4

这个没啥就是使用细节,能用快的就用快的。

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号