<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title>Tokenizer - Tag - Naifan Li's Blog</title><link>https://blog.omagiclee.com/tags/tokenizer/</link><description>Tokenizer - Tag - Naifan Li's Blog</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Thu, 14 Feb 2019 11:04:08 +0800</lastBuildDate><atom:link href="https://blog.omagiclee.com/tags/tokenizer/" rel="self" type="application/rss+xml"/><item><title>BBPE: Byte-level Byte Pair Encoding</title><link>https://blog.omagiclee.com/posts/llms/bbpe/</link><pubDate>Thu, 14 Feb 2019 11:04:08 +0800</pubDate><author>Naifan Li</author><guid>https://blog.omagiclee.com/posts/llms/bbpe/</guid><description><![CDATA[<h2 id="引言">引言</h2>
<p>字节级字节对编码（Byte-level Byte Pair Encoding, BBPE）是 GPT-2 引入的一种分词算法，它将传统的 BPE（Byte Pair Encoding）算法扩展为在字节级别操作。这种方法通过确保任何文本都能被分词而不产生未知标记，从根本上解决了词表外（Out-of-Vocabulary, OOV）问题，因为所有字符都可以表示为 UTF-8 字节。</p>
<h2 id="传统-bpe-的问题">传统 BPE 的问题</h2>
<p>传统 BPE 算法直接在 Unicode 字符上操作。当遇到词表中不存在的字符时，这些算法会产生 <code>&lt;UNK&gt;</code>（未知）标记，导致信息丢失和模型性能下降。在处理以下情况时，这一限制变得尤为严重：</p>
<ul>
<li><strong>多语言文本</strong>：不同语言具有完全不同的字符集</li>
<li><strong>罕见字符</strong>：特殊符号、表情符号或领域特定字符</li>
<li><strong>混合脚本</strong>：包含多种书写系统的文本</li>
</ul>
<h2 id="bbpe-解决方案">BBPE 解决方案</h2>
<p>BBPE 通过引入字节级预处理步骤来解决这些限制。BBPE 不是直接在字符上操作，而是：</p>
<ol>
<li>将所有文本转换为 UTF-8 字节序列</li>
<li>将字节映射到可打印的 Unicode 字符（避免控制字符）</li>
<li>对这些字节表示应用 BPE 合并操作</li>
</ol>
<p>这确保了任何文本，无论语言或字符集如何，都能被分词而不产生未知标记。</p>
<h2 id="技术架构">技术架构</h2>
<p>BBPE 分词过程包含四个顺序步骤：</p>
<h3 id="步骤-1预分词pre-tokenization">步骤 1：预分词（Pre-tokenization）</h3>
<p>预分词使用正则表达式在应用 BPE 之前将文本分割成更小的片段。这防止了不同类型字符的错误合并。GPT-2 分词器使用以下正则模式：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">regex</span> <span class="k">as</span> <span class="nn">re</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">PATTERN</span> <span class="o">=</span> <span class="sa">r</span><span class="s2">&#34;&#34;&#34;&#39;s|&#39;t|&#39;re|&#39;ve|&#39;m|&#39;ll|&#39;d| ?\p</span><span class="si">{L}</span><span class="s2">+| ?\p</span><span class="si">{N}</span><span class="s2">+| ?[^\s\p</span><span class="si">{L}</span><span class="s2">\p</span><span class="si">{N}</span><span class="s2">]+|\s+(?!\S)|\s+&#34;&#34;&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><strong>模式组件：</strong></p>
<ol>
<li><strong>缩略词</strong>：<code>'s|'t|'re|'ve|'m|'ll|'d</code> - 处理英文缩略形式</li>
<li><strong>字母</strong>：<code> ?\p{L}+</code> - 可选空格后跟一个或多个 Unicode 字母（包括中文字符）</li>
<li><strong>数字</strong>：<code> ?\p{N}+</code> - 可选空格后跟一个或多个 Unicode 数字</li>
<li><strong>标点符号</strong>：<code> ?[^\s\p{L}\p{N}]+</code> - 可选空格后跟非空白、非字母、非数字字符</li>
<li><strong>尾部空白</strong>：<code>\s+(?!\S)</code> - 文本末尾的空白字符（负向前瞻）</li>
<li><strong>通用空白</strong>：<code>\s+</code> - 任何空白字符序列（兜底规则）</li>
</ol>
<p><strong>示例：</strong></p>]]></description></item></channel></rss>