subword系列算法

1. 前言

nlp领域目前已经发展到一个非常高的层次了,这个层次不仅仅是模型和数据方面,还涌现出了很多非常巧妙的trick,这篇文章就记录一下关于tokenization方面的工作。

 所谓的tokenization其实就是将文本切分成words或者subwords,然后转成ids以便模型处理。最初的nlp分词非常简单,对于英语类以空格分割的语言来说,简单的以空格进行分割就行,不过这样简单的处理还存在一些问题,比如说*“Don’t you love 🤗 Transformers? We sure do.”,如果简单分割,那么就会得到[“Don’t”, “you”, “love”, “🤗”, “Transformers?”, “We”, “sure”, “do.”],对于“Transformers?”* 或者 “do.”这样的分词结果,显然是不合适,所以还需要考虑一下符号的影响,这可以通过现在很多开源工具实现,比如spaCy或者Moses等等。不过很明显会有个问题,那就是你切分的越细,得到的vocabulary越大,对于存储空间的要求也越大,虽然大部分情况下我们的词典都不会特别大,但是总是存在意外情况,尤其是Bert这类对于语料越大效果越好的模型的出现,更是加剧了这种情况。如果切分成words会导致内存问题,那么一个想法就是做character级别的tokenization,对于英文来说只有26个,那么算上大小写也只有52个,这可以大大缓解过大的embedding matrix问题,但是,character级别需要模型去从序列顺序中学习word的表示,模型在这方面显然不如直接切分word来的直观,所以这类方法会有性能方面的损失。在这种情况下,混合了wordcharacter的一些新方法应运而出,这类方法被称为subword

2.subword tokenization

2.1 Byte Pair Encoding

 这种算法其实很简单,从其名字基本可以了解到一些东西,最显眼的就是pair这个词。它的做法是每次使用频次最高的一个字节对来替换这两个字节。

 算法流程:

  1. 准备足够大的训练语料
  2. 确定期望的subword词表大小
  3. 将单词拆分为字符序列并在末尾添加后缀“ </ w>”(这里不是必须,可以添加任意可以代表结束的字符),统计单词频率。 本阶段的subword的粒度是字符。 例如,“ low”的频率为5,那么我们将其改写为“ l o w </ w>”:5
  4. 统计每一个连续字节对的出现频率,选择最高频者合并成新的subword
  5. 重复第4步直到达到第2步设定的subword词表大小或下一个最高频的字节对出现频率为1

2.1.1 构建subword字典

 有输入的word和其频次,首先将word分成character,并将subword词典初始化为character

{
   'l o w </w>': 5, 'l o w e r </w>': 2, 'n e w e s t </w>': 6, 'w i d e s t </w>': 3}

Iter 1, 最高频连续字节对"e"和"s"出现了6+3=9次,合并成"es",将"es"加入subword词典。输出:

{
   'l o w </w>': 5, 'l o w e r </w>': 2, 'n e w es t </w>': 6, 'w i d es t </w>': 3}

Iter 2, 最高频连续字节对"es"和"t"出现了6+3=9次, 合并成"est",并将"est"加入subword词典。输出:

{
   'l o w </w>': 5, 'l o w e r </w>': 2, 'n e w est </w>': 6, 'w i d est </w>': 3}

 Iter 3, 以此类推,最高频连续字节对为"est"和"</ w>" 输出,同样加入subword词典:

{
   'l o w </w>': 5, 'l o w e r </w>': 2, 'n e w est</w>': 6, 'w i d est</w>': 3}

 ……

 Iter n, 继续迭代直到达到预设的subword词表大小或下一个最高频的字节对出现频率为1。

2.1.2 编码

 根据2.1.1得到了subword的字典,对单词就可以进行编码了,将字典按照字符长度递减排列,然后依次遍历词典中的subword,如果单词包含了该subword,那么就用该subword加入单词的分解集合中,对剩余的字符进行迭代。这里将词典首先排序,便可以保证最先加入集合的subword是最后生成的。若最后还有一些字符序列无法在字典中找到,则替换为特殊的subword,比如*< unk >*.

 同样举个例子, 已有排好序的词典:

[“errrr</w>”, “tain</w>”, “moun”, “est</w>”, “high”, “the</w>”, “a</w>”]

 对单词"mountain</ w>",遍历词典,首先看到“tain</ w>”出现在了单词中,加入该subword,对剩余的"moun"继续便利,下一个subwordmoun”匹配,加入,那么便得到了单词的分解结果为:[“moun”, “tain</ w>”]

2.1.3 解码

 将tokens拼接在一起即可,注意"< /w>"代表句子结束。

# 编码序列
[“the<
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值