import{S as wr,i as vr,s as gr,e as a,k as p,w as u,t as n,M as br,c as o,d as s,m as c,a as i,x as m,h as r,b as f,N as mr,G as t,g as h,y as k,q as w,o as v,B as g,v as zr}from"../../chunks/vendor-hf-doc-builder.js";import{T as _r}from"../../chunks/Tip-hf-doc-builder.js";import{Y as kr}from"../../chunks/Youtube-hf-doc-builder.js";import{I as Jt}from"../../chunks/IconCopyLink-hf-doc-builder.js";import{C as R}from"../../chunks/CodeBlock-hf-doc-builder.js";import{C as $r}from"../../chunks/CourseFloatingBanner-hf-doc-builder.js";function Er(Yt){let d,K,b,E,M,_,ue,U;return{c(){d=a("p"),K=n("\u270F\uFE0F "),b=a("strong"),E=n("Try it out!"),M=n(" Load a tokenizer from the "),_=a("code"),ue=n("bert-base-cased"),U=n(" checkpoint and pass the same example to it. What are the main differences you can see between the cased and uncased versions of the tokenizer?")},l(F){d=o(F,"P",{});var $=i(d);K=r($,"\u270F\uFE0F "),b=o($,"STRONG",{});var q=i(b);E=r(q,"Try it out!"),q.forEach(s),M=r($," Load a tokenizer from the "),_=o($,"CODE",{});var me=i(_);ue=r(me,"bert-base-cased"),me.forEach(s),U=r($," checkpoint and pass the same example to it. What are the main differences you can see between the cased and uncased versions of the tokenizer?"),$.forEach(s)},m(F,$){h(F,d,$),t(d,K),t(d,b),t(b,E),t(d,M),t(d,_),t(_,ue),t(d,U)},d(F){F&&s(d)}}}function yr(Yt){let d,K,b,E,M,_,ue,U,F,$,q,me,Oe,Fs,Kt,G,ke,Qo,Gs,we,Zo,Vt,H,Ls,wt,Ws,Js,vt,Ys,Ks,Xt,L,V,gt,ve,Vs,bt,Xs,Qt,ge,Zt,X,Qs,be,Zs,ea,es,N,ta,zt,sa,aa,_t,oa,na,ts,ze,ss,_e,as,y,ra,$t,ia,la,Et,ha,pa,yt,ca,fa,os,$e,ns,Ee,rs,Q,da,xt,ua,ma,is,Z,ls,W,ee,Tt,ye,ka,jt,wa,hs,xe,ps,te,va,Ie,ga,ba,cs,x,za,Pt,_a,$a,At,Ea,ya,Dt,xa,Ta,fs,Te,ds,je,us,B,ja,St,Pa,Aa,Ct,Da,Sa,ms,Re,Ca,ks,Pe,ws,se,qa,qt,Ha,Na,vs,Ae,gs,Me,Ba,bs,Ue,Oa,zs,De,_s,Se,$s,z,Ia,Ht,Ra,Ma,Nt,Ua,Fa,Bt,Ga,La,Ot,Wa,Ja,Es,Fe,Ya,ys,J,ae,It,Ce,Ka,Rt,Va,xs,T,qe,Xa,Qa,Mt,Za,eo,Ge,to,so,Ts,O,ao,Ut,oo,no,Ft,ro,io,js,Y,oe,Gt,He,lo,Lt,ho,Ps,Le,po,As,ne,Wt,j,We,co,fo,Je,uo,mo,Ye,ko,wo,Ke,vo,go,P,A,Ve,bo,zo,Xe,_o,$o,Qe,Eo,yo,Ze,xo,To,D,et,jo,Po,tt,Ao,Do,st,So,Co,at,qo,Ho,S,ot,No,Bo,nt,Oo,Io,rt,Ro,Mo,it,Uo,Fo,C,lt,Go,Lo,ht,Wo,Jo,pt,Yo,Ko,ct,Vo,Ds,ft,Xo,Ss;return _=new Jt({}),q=new $r({props:{chapter:6,classNames:"absolute z-10 right-0 top-0",notebooks:[{label:"Google Colab",value:"https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/en/chapter6/section4.ipynb"},{label:"Aws Studio",value:"https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/en/chapter6/section4.ipynb"}]}}),ve=new Jt({}),ge=new kr({props:{id:"4IIC2jI9CaU"}}),ze=new R({props:{code:`from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
print(type(tokenizer.backend_tokenizer))`,highlighted:`<span class="hljs-keyword">from</span> transformers <span class="hljs-keyword">import</span> AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained(<span class="hljs-string">&quot;bert-base-uncased&quot;</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-built_in">type</span>(tokenizer.backend_tokenizer))`}}),_e=new R({props:{code:"<class 'tokenizers.Tokenizer'>",highlighted:'&lt;<span class="hljs-keyword">class</span> <span class="hljs-string">&#x27;tokenizers.Tokenizer&#x27;</span>&gt;'}}),$e=new R({props:{code:'print(tokenizer.backend_tokenizer.normalizer.normalize_str("H\xE9ll\xF2 h\xF4w are \xFC?"))',highlighted:'<span class="hljs-built_in">print</span>(tokenizer.backend_tokenizer.normalizer.normalize_str(<span class="hljs-string">&quot;H\xE9ll\xF2 h\xF4w are \xFC?&quot;</span>))'}}),Ee=new R({props:{code:"'hello how are u?'",highlighted:'<span class="hljs-string">&#x27;hello how are u?&#x27;</span>'}}),Z=new _r({props:{$$slots:{default:[Er]},$$scope:{ctx:Yt}}}),ye=new Jt({}),xe=new kr({props:{id:"grlLV8AIXug"}}),Te=new R({props:{code:'tokenizer.backend_tokenizer.pre_tokenizer.pre_tokenize_str("Hello, how are  you?")',highlighted:'tokenizer.backend_tokenizer.pre_tokenizer.pre_tokenize_str(<span class="hljs-string">&quot;Hello, how are  you?&quot;</span>)'}}),je=new R({props:{code:"[('Hello', (0, 5)), (',', (5, 6)), ('how', (7, 10)), ('are', (11, 14)), ('you', (16, 19)), ('?', (19, 20))]",highlighted:'[(<span class="hljs-string">&#x27;Hello&#x27;</span>, (<span class="hljs-number">0</span>, <span class="hljs-number">5</span>)), (<span class="hljs-string">&#x27;,&#x27;</span>, (<span class="hljs-number">5</span>, <span class="hljs-number">6</span>)), (<span class="hljs-string">&#x27;how&#x27;</span>, (<span class="hljs-number">7</span>, <span class="hljs-number">10</span>)), (<span class="hljs-string">&#x27;are&#x27;</span>, (<span class="hljs-number">11</span>, <span class="hljs-number">14</span>)), (<span class="hljs-string">&#x27;you&#x27;</span>, (<span class="hljs-number">16</span>, <span class="hljs-number">19</span>)), (<span class="hljs-string">&#x27;?&#x27;</span>, (<span class="hljs-number">19</span>, <span class="hljs-number">20</span>))]'}}),Pe=new R({props:{code:`tokenizer = AutoTokenizer.from_pretrained("gpt2")
tokenizer.backend_tokenizer.pre_tokenizer.pre_tokenize_str("Hello, how are  you?")`,highlighted:`tokenizer = AutoTokenizer.from_pretrained(<span class="hljs-string">&quot;gpt2&quot;</span>)
tokenizer.backend_tokenizer.pre_tokenizer.pre_tokenize_str(<span class="hljs-string">&quot;Hello, how are  you?&quot;</span>)`}}),Ae=new R({props:{code:`[('Hello', (0, 5)), (',', (5, 6)), ('\u0120how', (6, 10)), ('\u0120are', (10, 14)), ('\u0120', (14, 15)), ('\u0120you', (15, 19)),
 ('?', (19, 20))]`,highlighted:`[(<span class="hljs-string">&#x27;Hello&#x27;</span>, (<span class="hljs-number">0</span>, <span class="hljs-number">5</span>)), (<span class="hljs-string">&#x27;,&#x27;</span>, (<span class="hljs-number">5</span>, <span class="hljs-number">6</span>)), (<span class="hljs-string">&#x27;\u0120how&#x27;</span>, (<span class="hljs-number">6</span>, <span class="hljs-number">10</span>)), (<span class="hljs-string">&#x27;\u0120are&#x27;</span>, (<span class="hljs-number">10</span>, <span class="hljs-number">14</span>)), (<span class="hljs-string">&#x27;\u0120&#x27;</span>, (<span class="hljs-number">14</span>, <span class="hljs-number">15</span>)), (<span class="hljs-string">&#x27;\u0120you&#x27;</span>, (<span class="hljs-number">15</span>, <span class="hljs-number">19</span>)),
 (<span class="hljs-string">&#x27;?&#x27;</span>, (<span class="hljs-number">19</span>, <span class="hljs-number">20</span>))]`}}),De=new R({props:{code:`tokenizer = AutoTokenizer.from_pretrained("t5-small")
tokenizer.backend_tokenizer.pre_tokenizer.pre_tokenize_str("Hello, how are  you?")`,highlighted:`tokenizer = AutoTokenizer.from_pretrained(<span class="hljs-string">&quot;t5-small&quot;</span>)
tokenizer.backend_tokenizer.pre_tokenizer.pre_tokenize_str(<span class="hljs-string">&quot;Hello, how are  you?&quot;</span>)`}}),Se=new R({props:{code:"[('\u2581Hello,', (0, 6)), ('\u2581how', (7, 10)), ('\u2581are', (11, 14)), ('\u2581you?', (16, 20))]",highlighted:'[(<span class="hljs-string">&#x27;\u2581Hello,&#x27;</span>, (<span class="hljs-number">0</span>, <span class="hljs-number">6</span>)), (<span class="hljs-string">&#x27;\u2581how&#x27;</span>, (<span class="hljs-number">7</span>, <span class="hljs-number">10</span>)), (<span class="hljs-string">&#x27;\u2581are&#x27;</span>, (<span class="hljs-number">11</span>, <span class="hljs-number">14</span>)), (<span class="hljs-string">&#x27;\u2581you?&#x27;</span>, (<span class="hljs-number">16</span>, <span class="hljs-number">20</span>))]'}}),Ce=new Jt({}),He=new Jt({}),{c(){d=a("meta"),K=p(),b=a("h1"),E=a("a"),M=a("span"),u(_.$$.fragment),ue=p(),U=a("span"),F=n("Normalization and pre-tokenization"),$=p(),u(q.$$.fragment),me=p(),Oe=a("p"),Fs=n("Before we dive more deeply into the three most common subword tokenization algorithms used with Transformer models (Byte-Pair Encoding [BPE], WordPiece, and Unigram), we\u2019ll first take a look at the preprocessing that each tokenizer applies to text. Here\u2019s a high-level overview of the steps in the tokenization pipeline:"),Kt=p(),G=a("div"),ke=a("img"),Gs=p(),we=a("img"),Vt=p(),H=a("p"),Ls=n("Before splitting a text into subtokens (according to its model), the tokenizer performs two steps: "),wt=a("em"),Ws=n("normalization"),Js=n(" and "),vt=a("em"),Ys=n("pre-tokenization"),Ks=n("."),Xt=p(),L=a("h2"),V=a("a"),gt=a("span"),u(ve.$$.fragment),Vs=p(),bt=a("span"),Xs=n("Normalization"),Qt=p(),u(ge.$$.fragment),Zt=p(),X=a("p"),Qs=n("The normalization step involves some general cleanup, such as removing needless whitespace, lowercasing, and/or removing accents. If you\u2019re familiar with "),be=a("a"),Zs=n("Unicode normalization"),ea=n(" (such as NFC or NFKC), this is also something the tokenizer may apply."),es=p(),N=a("p"),ta=n("The \u{1F917} Transformers "),zt=a("code"),sa=n("tokenizer"),aa=n(" has an attribute called "),_t=a("code"),oa=n("backend_tokenizer"),na=n(" that provides access to the underlying tokenizer from the \u{1F917} Tokenizers library:"),ts=p(),u(ze.$$.fragment),ss=p(),u(_e.$$.fragment),as=p(),y=a("p"),ra=n("The "),$t=a("code"),ia=n("normalizer"),la=n(" attribute of the "),Et=a("code"),ha=n("tokenizer"),pa=n(" object has a "),yt=a("code"),ca=n("normalize_str()"),fa=n(" method that we can use to see how the normalization is performed:"),os=p(),u($e.$$.fragment),ns=p(),u(Ee.$$.fragment),rs=p(),Q=a("p"),da=n("In this example, since we picked the "),xt=a("code"),ua=n("bert-base-uncased"),ma=n(" checkpoint, the normalization applied lowercasing and removed the accents."),is=p(),u(Z.$$.fragment),ls=p(),W=a("h2"),ee=a("a"),Tt=a("span"),u(ye.$$.fragment),ka=p(),jt=a("span"),wa=n("Pre-tokenization"),hs=p(),u(xe.$$.fragment),ps=p(),te=a("p"),va=n("As we will see in the next sections, a tokenizer cannot be trained on raw text alone. Instead, we first need to split the texts into small entities, like words. That\u2019s where the pre-tokenization step comes in. As we saw in "),Ie=a("a"),ga=n("Chapter 2"),ba=n(", a word-based tokenizer can simply split a raw text into words on whitespace and punctuation. Those words will be the boundaries of the subtokens the tokenizer can learn during its training."),cs=p(),x=a("p"),za=n("To see how a fast tokenizer performs pre-tokenization, we can use the "),Pt=a("code"),_a=n("pre_tokenize_str()"),$a=n(" method of the "),At=a("code"),Ea=n("pre_tokenizer"),ya=n(" attribute of the "),Dt=a("code"),xa=n("tokenizer"),Ta=n(" object:"),fs=p(),u(Te.$$.fragment),ds=p(),u(je.$$.fragment),us=p(),B=a("p"),ja=n("Notice how the tokenizer is already keeping track of the offsets, which is how it can give us the offset mapping we used in the previous section. Here the tokenizer ignores the two spaces and replaces them with just one, but the offset jumps between "),St=a("code"),Pa=n("are"),Aa=n(" and "),Ct=a("code"),Da=n("you"),Sa=n(" to account for that."),ms=p(),Re=a("p"),Ca=n("Since we\u2019re using a BERT tokenizer, the pre-tokenization involves splitting on whitespace and punctuation. Other tokenizers can have different rules for this step. For example, if we use the GPT-2 tokenizer:"),ks=p(),u(Pe.$$.fragment),ws=p(),se=a("p"),qa=n("it will split on whitespace and punctuation as well, but it will keep the spaces and replace them with a "),qt=a("code"),Ha=n("\u0120"),Na=n(" symbol, enabling it to recover the original spaces if we decode the tokens:"),vs=p(),u(Ae.$$.fragment),gs=p(),Me=a("p"),Ba=n("Also note that unlike the BERT tokenizer, this tokenizer does not ignore the double space."),bs=p(),Ue=a("p"),Oa=n("For a last example, let\u2019s have a look at the T5 tokenizer, which is based on the SentencePiece algorithm:"),zs=p(),u(De.$$.fragment),_s=p(),u(Se.$$.fragment),$s=p(),z=a("p"),Ia=n("Like the GPT-2 tokenizer, this one keeps spaces and replaces them with a specific token ("),Ht=a("code"),Ra=n("_"),Ma=n("), but the T5 tokenizer only splits on whitespace, not punctuation. Also note that it added a space by default at the beginning of the sentence (before "),Nt=a("code"),Ua=n("Hello"),Fa=n(") and ignored the double space between "),Bt=a("code"),Ga=n("are"),La=n(" and "),Ot=a("code"),Wa=n("you"),Ja=n("."),Es=p(),Fe=a("p"),Ya=n("Now that we\u2019ve seen a little of how some different tokenizers process text, we can start to explore the underlying algorithms themselves. We\u2019ll begin with a quick look at the broadly widely applicable SentencePiece; then, over the next three sections, we\u2019ll examine how the three main algorithms used for subword tokenization work."),ys=p(),J=a("h2"),ae=a("a"),It=a("span"),u(Ce.$$.fragment),Ka=p(),Rt=a("span"),Va=n("SentencePiece"),xs=p(),T=a("p"),qe=a("a"),Xa=n("SentencePiece"),Qa=n(" is a tokenization algorithm for the preprocessing of text that you can use with any of the models we will see in the next three sections. It considers the text as a sequence of Unicode characters, and replaces spaces with a special character, "),Mt=a("code"),Za=n("\u2581"),eo=n(". Used in conjunction with the Unigram algorithm (see "),Ge=a("a"),to=n("section 7"),so=n("), it doesn\u2019t even require a pre-tokenization step, which is very useful for languages where the space character is not used (like Chinese or Japanese)."),Ts=p(),O=a("p"),ao=n("The other main feature of SentencePiece is "),Ut=a("em"),oo=n("reversible tokenization"),no=n(": since there is no special treatment of spaces, decoding the tokens is done simply by concatenating them and replacing the "),Ft=a("code"),ro=n("_"),io=n("s with spaces \u2014 this results in the normalized text. As we saw earlier, the BERT tokenizer removes repeating spaces, so its tokenization is not reversible."),js=p(),Y=a("h2"),oe=a("a"),Gt=a("span"),u(He.$$.fragment),lo=p(),Lt=a("span"),ho=n("Algorithm overview"),Ps=p(),Le=a("p"),po=n("In the following sections, we\u2019ll dive into the three main subword tokenization algorithms: BPE (used by GPT-2 and others), WordPiece (used for example by BERT), and Unigram (used by T5 and others). Before we get started, here\u2019s a quick overview of how they each work. Don\u2019t hesitate to come back to this table after reading each of the next sections if it doesn\u2019t make sense to you yet."),As=p(),ne=a("table"),Wt=a("thead"),j=a("tr"),We=a("th"),co=n("Model"),fo=p(),Je=a("th"),uo=n("BPE"),mo=p(),Ye=a("th"),ko=n("WordPiece"),wo=p(),Ke=a("th"),vo=n("Unigram"),go=p(),P=a("tbody"),A=a("tr"),Ve=a("td"),bo=n("Training"),zo=p(),Xe=a("td"),_o=n("Starts from a small vocabulary and learns rules to merge tokens"),$o=p(),Qe=a("td"),Eo=n("Starts from a small vocabulary and learns rules to merge tokens"),yo=p(),Ze=a("td"),xo=n("Starts from a large vocabulary and learns rules to remove tokens"),To=p(),D=a("tr"),et=a("td"),jo=n("Training step"),Po=p(),tt=a("td"),Ao=n("Merges the tokens corresponding to the most common pair"),Do=p(),st=a("td"),So=n("Merges the tokens corresponding to the pair with the best score based on the frequency of the pair, privileging pairs where each individual token is less frequent"),Co=p(),at=a("td"),qo=n("Removes all the tokens in the vocabulary that will minimize the loss computed on the whole corpus"),Ho=p(),S=a("tr"),ot=a("td"),No=n("Learns"),Bo=p(),nt=a("td"),Oo=n("Merge rules and a vocabulary"),Io=p(),rt=a("td"),Ro=n("Just a vocabulary"),Mo=p(),it=a("td"),Uo=n("A vocabulary with a score for each token"),Fo=p(),C=a("tr"),lt=a("td"),Go=n("Encoding"),Lo=p(),ht=a("td"),Wo=n("Splits a word into characters and applies the merges learned during training"),Jo=p(),pt=a("td"),Yo=n("Finds the longest subword starting from the beginning that is in the vocabulary, then does the same for the rest of the word"),Ko=p(),ct=a("td"),Vo=n("Finds the most likely split into tokens, using the scores learned during training"),Ds=p(),ft=a("p"),Xo=n("Now let\u2019s dive into BPE!"),this.h()},l(e){const l=br('[data-svelte="svelte-1phssyn"]',document.head);d=o(l,"META",{name:!0,content:!0}),l.forEach(s),K=c(e),b=o(e,"H1",{class:!0});var Ne=i(b);E=o(Ne,"A",{id:!0,class:!0,href:!0});var en=i(E);M=o(en,"SPAN",{});var tn=i(M);m(_.$$.fragment,tn),tn.forEach(s),en.forEach(s),ue=c(Ne),U=o(Ne,"SPAN",{});var sn=i(U);F=r(sn,"Normalization and pre-tokenization"),sn.forEach(s),Ne.forEach(s),$=c(e),m(q.$$.fragment,e),me=c(e),Oe=o(e,"P",{});var an=i(Oe);Fs=r(an,"Before we dive more deeply into the three most common subword tokenization algorithms used with Transformer models (Byte-Pair Encoding [BPE], WordPiece, and Unigram), we\u2019ll first take a look at the preprocessing that each tokenizer applies to text. Here\u2019s a high-level overview of the steps in the tokenization pipeline:"),an.forEach(s),Kt=c(e),G=o(e,"DIV",{class:!0});var Cs=i(G);ke=o(Cs,"IMG",{class:!0,src:!0,alt:!0}),Gs=c(Cs),we=o(Cs,"IMG",{class:!0,src:!0,alt:!0}),Cs.forEach(s),Vt=c(e),H=o(e,"P",{});var dt=i(H);Ls=r(dt,"Before splitting a text into subtokens (according to its model), the tokenizer performs two steps: "),wt=o(dt,"EM",{});var on=i(wt);Ws=r(on,"normalization"),on.forEach(s),Js=r(dt," and "),vt=o(dt,"EM",{});var nn=i(vt);Ys=r(nn,"pre-tokenization"),nn.forEach(s),Ks=r(dt,"."),dt.forEach(s),Xt=c(e),L=o(e,"H2",{class:!0});var qs=i(L);V=o(qs,"A",{id:!0,class:!0,href:!0});var rn=i(V);gt=o(rn,"SPAN",{});var ln=i(gt);m(ve.$$.fragment,ln),ln.forEach(s),rn.forEach(s),Vs=c(qs),bt=o(qs,"SPAN",{});var hn=i(bt);Xs=r(hn,"Normalization"),hn.forEach(s),qs.forEach(s),Qt=c(e),m(ge.$$.fragment,e),Zt=c(e),X=o(e,"P",{});var Hs=i(X);Qs=r(Hs,"The normalization step involves some general cleanup, such as removing needless whitespace, lowercasing, and/or removing accents. If you\u2019re familiar with "),be=o(Hs,"A",{href:!0,rel:!0});var pn=i(be);Zs=r(pn,"Unicode normalization"),pn.forEach(s),ea=r(Hs," (such as NFC or NFKC), this is also something the tokenizer may apply."),Hs.forEach(s),es=c(e),N=o(e,"P",{});var ut=i(N);ta=r(ut,"The \u{1F917} Transformers "),zt=o(ut,"CODE",{});var cn=i(zt);sa=r(cn,"tokenizer"),cn.forEach(s),aa=r(ut," has an attribute called "),_t=o(ut,"CODE",{});var fn=i(_t);oa=r(fn,"backend_tokenizer"),fn.forEach(s),na=r(ut," that provides access to the underlying tokenizer from the \u{1F917} Tokenizers library:"),ut.forEach(s),ts=c(e),m(ze.$$.fragment,e),ss=c(e),m(_e.$$.fragment,e),as=c(e),y=o(e,"P",{});var re=i(y);ra=r(re,"The "),$t=o(re,"CODE",{});var dn=i($t);ia=r(dn,"normalizer"),dn.forEach(s),la=r(re," attribute of the "),Et=o(re,"CODE",{});var un=i(Et);ha=r(un,"tokenizer"),un.forEach(s),pa=r(re," object has a "),yt=o(re,"CODE",{});var mn=i(yt);ca=r(mn,"normalize_str()"),mn.forEach(s),fa=r(re," method that we can use to see how the normalization is performed:"),re.forEach(s),os=c(e),m($e.$$.fragment,e),ns=c(e),m(Ee.$$.fragment,e),rs=c(e),Q=o(e,"P",{});var Ns=i(Q);da=r(Ns,"In this example, since we picked the "),xt=o(Ns,"CODE",{});var kn=i(xt);ua=r(kn,"bert-base-uncased"),kn.forEach(s),ma=r(Ns," checkpoint, the normalization applied lowercasing and removed the accents."),Ns.forEach(s),is=c(e),m(Z.$$.fragment,e),ls=c(e),W=o(e,"H2",{class:!0});var Bs=i(W);ee=o(Bs,"A",{id:!0,class:!0,href:!0});var wn=i(ee);Tt=o(wn,"SPAN",{});var vn=i(Tt);m(ye.$$.fragment,vn),vn.forEach(s),wn.forEach(s),ka=c(Bs),jt=o(Bs,"SPAN",{});var gn=i(jt);wa=r(gn,"Pre-tokenization"),gn.forEach(s),Bs.forEach(s),hs=c(e),m(xe.$$.fragment,e),ps=c(e),te=o(e,"P",{});var Os=i(te);va=r(Os,"As we will see in the next sections, a tokenizer cannot be trained on raw text alone. Instead, we first need to split the texts into small entities, like words. That\u2019s where the pre-tokenization step comes in. As we saw in "),Ie=o(Os,"A",{href:!0});var bn=i(Ie);ga=r(bn,"Chapter 2"),bn.forEach(s),ba=r(Os,", a word-based tokenizer can simply split a raw text into words on whitespace and punctuation. Those words will be the boundaries of the subtokens the tokenizer can learn during its training."),Os.forEach(s),cs=c(e),x=o(e,"P",{});var ie=i(x);za=r(ie,"To see how a fast tokenizer performs pre-tokenization, we can use the "),Pt=o(ie,"CODE",{});var zn=i(Pt);_a=r(zn,"pre_tokenize_str()"),zn.forEach(s),$a=r(ie," method of the "),At=o(ie,"CODE",{});var _n=i(At);Ea=r(_n,"pre_tokenizer"),_n.forEach(s),ya=r(ie," attribute of the "),Dt=o(ie,"CODE",{});var $n=i(Dt);xa=r($n,"tokenizer"),$n.forEach(s),Ta=r(ie," object:"),ie.forEach(s),fs=c(e),m(Te.$$.fragment,e),ds=c(e),m(je.$$.fragment,e),us=c(e),B=o(e,"P",{});var mt=i(B);ja=r(mt,"Notice how the tokenizer is already keeping track of the offsets, which is how it can give us the offset mapping we used in the previous section. Here the tokenizer ignores the two spaces and replaces them with just one, but the offset jumps between "),St=o(mt,"CODE",{});var En=i(St);Pa=r(En,"are"),En.forEach(s),Aa=r(mt," and "),Ct=o(mt,"CODE",{});var yn=i(Ct);Da=r(yn,"you"),yn.forEach(s),Sa=r(mt," to account for that."),mt.forEach(s),ms=c(e),Re=o(e,"P",{});var xn=i(Re);Ca=r(xn,"Since we\u2019re using a BERT tokenizer, the pre-tokenization involves splitting on whitespace and punctuation. Other tokenizers can have different rules for this step. For example, if we use the GPT-2 tokenizer:"),xn.forEach(s),ks=c(e),m(Pe.$$.fragment,e),ws=c(e),se=o(e,"P",{});var Is=i(se);qa=r(Is,"it will split on whitespace and punctuation as well, but it will keep the spaces and replace them with a "),qt=o(Is,"CODE",{});var Tn=i(qt);Ha=r(Tn,"\u0120"),Tn.forEach(s),Na=r(Is," symbol, enabling it to recover the original spaces if we decode the tokens:"),Is.forEach(s),vs=c(e),m(Ae.$$.fragment,e),gs=c(e),Me=o(e,"P",{});var jn=i(Me);Ba=r(jn,"Also note that unlike the BERT tokenizer, this tokenizer does not ignore the double space."),jn.forEach(s),bs=c(e),Ue=o(e,"P",{});var Pn=i(Ue);Oa=r(Pn,"For a last example, let\u2019s have a look at the T5 tokenizer, which is based on the SentencePiece algorithm:"),Pn.forEach(s),zs=c(e),m(De.$$.fragment,e),_s=c(e),m(Se.$$.fragment,e),$s=c(e),z=o(e,"P",{});var I=i(z);Ia=r(I,"Like the GPT-2 tokenizer, this one keeps spaces and replaces them with a specific token ("),Ht=o(I,"CODE",{});var An=i(Ht);Ra=r(An,"_"),An.forEach(s),Ma=r(I,"), but the T5 tokenizer only splits on whitespace, not punctuation. Also note that it added a space by default at the beginning of the sentence (before "),Nt=o(I,"CODE",{});var Dn=i(Nt);Ua=r(Dn,"Hello"),Dn.forEach(s),Fa=r(I,") and ignored the double space between "),Bt=o(I,"CODE",{});var Sn=i(Bt);Ga=r(Sn,"are"),Sn.forEach(s),La=r(I," and "),Ot=o(I,"CODE",{});var Cn=i(Ot);Wa=r(Cn,"you"),Cn.forEach(s),Ja=r(I,"."),I.forEach(s),Es=c(e),Fe=o(e,"P",{});var qn=i(Fe);Ya=r(qn,"Now that we\u2019ve seen a little of how some different tokenizers process text, we can start to explore the underlying algorithms themselves. We\u2019ll begin with a quick look at the broadly widely applicable SentencePiece; then, over the next three sections, we\u2019ll examine how the three main algorithms used for subword tokenization work."),qn.forEach(s),ys=c(e),J=o(e,"H2",{class:!0});var Rs=i(J);ae=o(Rs,"A",{id:!0,class:!0,href:!0});var Hn=i(ae);It=o(Hn,"SPAN",{});var Nn=i(It);m(Ce.$$.fragment,Nn),Nn.forEach(s),Hn.forEach(s),Ka=c(Rs),Rt=o(Rs,"SPAN",{});var Bn=i(Rt);Va=r(Bn,"SentencePiece"),Bn.forEach(s),Rs.forEach(s),xs=c(e),T=o(e,"P",{});var Be=i(T);qe=o(Be,"A",{href:!0,rel:!0});var On=i(qe);Xa=r(On,"SentencePiece"),On.forEach(s),Qa=r(Be," is a tokenization algorithm for the preprocessing of text that you can use with any of the models we will see in the next three sections. It considers the text as a sequence of Unicode characters, and replaces spaces with a special character, "),Mt=o(Be,"CODE",{});var In=i(Mt);Za=r(In,"\u2581"),In.forEach(s),eo=r(Be,". Used in conjunction with the Unigram algorithm (see "),Ge=o(Be,"A",{href:!0});var Rn=i(Ge);to=r(Rn,"section 7"),Rn.forEach(s),so=r(Be,"), it doesn\u2019t even require a pre-tokenization step, which is very useful for languages where the space character is not used (like Chinese or Japanese)."),Be.forEach(s),Ts=c(e),O=o(e,"P",{});var kt=i(O);ao=r(kt,"The other main feature of SentencePiece is "),Ut=o(kt,"EM",{});var Mn=i(Ut);oo=r(Mn,"reversible tokenization"),Mn.forEach(s),no=r(kt,": since there is no special treatment of spaces, decoding the tokens is done simply by concatenating them and replacing the "),Ft=o(kt,"CODE",{});var Un=i(Ft);ro=r(Un,"_"),Un.forEach(s),io=r(kt,"s with spaces \u2014 this results in the normalized text. As we saw earlier, the BERT tokenizer removes repeating spaces, so its tokenization is not reversible."),kt.forEach(s),js=c(e),Y=o(e,"H2",{class:!0});var Ms=i(Y);oe=o(Ms,"A",{id:!0,class:!0,href:!0});var Fn=i(oe);Gt=o(Fn,"SPAN",{});var Gn=i(Gt);m(He.$$.fragment,Gn),Gn.forEach(s),Fn.forEach(s),lo=c(Ms),Lt=o(Ms,"SPAN",{});var Ln=i(Lt);ho=r(Ln,"Algorithm overview"),Ln.forEach(s),Ms.forEach(s),Ps=c(e),Le=o(e,"P",{});var Wn=i(Le);po=r(Wn,"In the following sections, we\u2019ll dive into the three main subword tokenization algorithms: BPE (used by GPT-2 and others), WordPiece (used for example by BERT), and Unigram (used by T5 and others). Before we get started, here\u2019s a quick overview of how they each work. Don\u2019t hesitate to come back to this table after reading each of the next sections if it doesn\u2019t make sense to you yet."),Wn.forEach(s),As=c(e),ne=o(e,"TABLE",{});var Us=i(ne);Wt=o(Us,"THEAD",{});var Jn=i(Wt);j=o(Jn,"TR",{});var le=i(j);We=o(le,"TH",{align:!0});var Yn=i(We);co=r(Yn,"Model"),Yn.forEach(s),fo=c(le),Je=o(le,"TH",{align:!0});var Kn=i(Je);uo=r(Kn,"BPE"),Kn.forEach(s),mo=c(le),Ye=o(le,"TH",{align:!0});var Vn=i(Ye);ko=r(Vn,"WordPiece"),Vn.forEach(s),wo=c(le),Ke=o(le,"TH",{align:!0});var Xn=i(Ke);vo=r(Xn,"Unigram"),Xn.forEach(s),le.forEach(s),Jn.forEach(s),go=c(Us),P=o(Us,"TBODY",{});var he=i(P);A=o(he,"TR",{});var pe=i(A);Ve=o(pe,"TD",{align:!0});var Qn=i(Ve);bo=r(Qn,"Training"),Qn.forEach(s),zo=c(pe),Xe=o(pe,"TD",{align:!0});var Zn=i(Xe);_o=r(Zn,"Starts from a small vocabulary and learns rules to merge tokens"),Zn.forEach(s),$o=c(pe),Qe=o(pe,"TD",{align:!0});var er=i(Qe);Eo=r(er,"Starts from a small vocabulary and learns rules to merge tokens"),er.forEach(s),yo=c(pe),Ze=o(pe,"TD",{align:!0});var tr=i(Ze);xo=r(tr,"Starts from a large vocabulary and learns rules to remove tokens"),tr.forEach(s),pe.forEach(s),To=c(he),D=o(he,"TR",{});var ce=i(D);et=o(ce,"TD",{align:!0});var sr=i(et);jo=r(sr,"Training step"),sr.forEach(s),Po=c(ce),tt=o(ce,"TD",{align:!0});var ar=i(tt);Ao=r(ar,"Merges the tokens corresponding to the most common pair"),ar.forEach(s),Do=c(ce),st=o(ce,"TD",{align:!0});var or=i(st);So=r(or,"Merges the tokens corresponding to the pair with the best score based on the frequency of the pair, privileging pairs where each individual token is less frequent"),or.forEach(s),Co=c(ce),at=o(ce,"TD",{align:!0});var nr=i(at);qo=r(nr,"Removes all the tokens in the vocabulary that will minimize the loss computed on the whole corpus"),nr.forEach(s),ce.forEach(s),Ho=c(he),S=o(he,"TR",{});var fe=i(S);ot=o(fe,"TD",{align:!0});var rr=i(ot);No=r(rr,"Learns"),rr.forEach(s),Bo=c(fe),nt=o(fe,"TD",{align:!0});var ir=i(nt);Oo=r(ir,"Merge rules and a vocabulary"),ir.forEach(s),Io=c(fe),rt=o(fe,"TD",{align:!0});var lr=i(rt);Ro=r(lr,"Just a vocabulary"),lr.forEach(s),Mo=c(fe),it=o(fe,"TD",{align:!0});var hr=i(it);Uo=r(hr,"A vocabulary with a score for each token"),hr.forEach(s),fe.forEach(s),Fo=c(he),C=o(he,"TR",{});var de=i(C);lt=o(de,"TD",{align:!0});var pr=i(lt);Go=r(pr,"Encoding"),pr.forEach(s),Lo=c(de),ht=o(de,"TD",{align:!0});var cr=i(ht);Wo=r(cr,"Splits a word into characters and applies the merges learned during training"),cr.forEach(s),Jo=c(de),pt=o(de,"TD",{align:!0});var fr=i(pt);Yo=r(fr,"Finds the longest subword starting from the beginning that is in the vocabulary, then does the same for the rest of the word"),fr.forEach(s),Ko=c(de),ct=o(de,"TD",{align:!0});var dr=i(ct);Vo=r(dr,"Finds the most likely split into tokens, using the scores learned during training"),dr.forEach(s),de.forEach(s),he.forEach(s),Us.forEach(s),Ds=c(e),ft=o(e,"P",{});var ur=i(ft);Xo=r(ur,"Now let\u2019s dive into BPE!"),ur.forEach(s),this.h()},h(){f(d,"name","hf:doc:metadata"),f(d,"content",JSON.stringify(xr)),f(E,"id","normalization-and-pre-tokenization"),f(E,"class","header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full"),f(E,"href","#normalization-and-pre-tokenization"),f(b,"class","relative group"),f(ke,"class","block dark:hidden"),mr(ke.src,Qo="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter6/tokenization_pipeline.svg")||f(ke,"src",Qo),f(ke,"alt","The tokenization pipeline."),f(we,"class","hidden dark:block"),mr(we.src,Zo="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter6/tokenization_pipeline-dark.svg")||f(we,"src",Zo),f(we,"alt","The tokenization pipeline."),f(G,"class","flex justify-center"),f(V,"id","normalization"),f(V,"class","header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full"),f(V,"href","#normalization"),f(L,"class","relative group"),f(be,"href","http://www.unicode.org/reports/tr15/"),f(be,"rel","nofollow"),f(ee,"id","pre-tokenization"),f(ee,"class","header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full"),f(ee,"href","#pre-tokenization"),f(W,"class","relative group"),f(Ie,"href","/course/chapter2"),f(ae,"id","sentencepiece"),f(ae,"class","header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full"),f(ae,"href","#sentencepiece"),f(J,"class","relative group"),f(qe,"href","https://github.com/google/sentencepiece"),f(qe,"rel","nofollow"),f(Ge,"href","/course/chapter7/7"),f(oe,"id","algorithm-overview"),f(oe,"class","header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full"),f(oe,"href","#algorithm-overview"),f(Y,"class","relative group"),f(We,"align","center"),f(Je,"align","center"),f(Ye,"align","center"),f(Ke,"align","center"),f(Ve,"align","center"),f(Xe,"align","center"),f(Qe,"align","center"),f(Ze,"align","center"),f(et,"align","center"),f(tt,"align","center"),f(st,"align","center"),f(at,"align","center"),f(ot,"align","center"),f(nt,"align","center"),f(rt,"align","center"),f(it,"align","center"),f(lt,"align","center"),f(ht,"align","center"),f(pt,"align","center"),f(ct,"align","center")},m(e,l){t(document.head,d),h(e,K,l),h(e,b,l),t(b,E),t(E,M),k(_,M,null),t(b,ue),t(b,U),t(U,F),h(e,$,l),k(q,e,l),h(e,me,l),h(e,Oe,l),t(Oe,Fs),h(e,Kt,l),h(e,G,l),t(G,ke),t(G,Gs),t(G,we),h(e,Vt,l),h(e,H,l),t(H,Ls),t(H,wt),t(wt,Ws),t(H,Js),t(H,vt),t(vt,Ys),t(H,Ks),h(e,Xt,l),h(e,L,l),t(L,V),t(V,gt),k(ve,gt,null),t(L,Vs),t(L,bt),t(bt,Xs),h(e,Qt,l),k(ge,e,l),h(e,Zt,l),h(e,X,l),t(X,Qs),t(X,be),t(be,Zs),t(X,ea),h(e,es,l),h(e,N,l),t(N,ta),t(N,zt),t(zt,sa),t(N,aa),t(N,_t),t(_t,oa),t(N,na),h(e,ts,l),k(ze,e,l),h(e,ss,l),k(_e,e,l),h(e,as,l),h(e,y,l),t(y,ra),t(y,$t),t($t,ia),t(y,la),t(y,Et),t(Et,ha),t(y,pa),t(y,yt),t(yt,ca),t(y,fa),h(e,os,l),k($e,e,l),h(e,ns,l),k(Ee,e,l),h(e,rs,l),h(e,Q,l),t(Q,da),t(Q,xt),t(xt,ua),t(Q,ma),h(e,is,l),k(Z,e,l),h(e,ls,l),h(e,W,l),t(W,ee),t(ee,Tt),k(ye,Tt,null),t(W,ka),t(W,jt),t(jt,wa),h(e,hs,l),k(xe,e,l),h(e,ps,l),h(e,te,l),t(te,va),t(te,Ie),t(Ie,ga),t(te,ba),h(e,cs,l),h(e,x,l),t(x,za),t(x,Pt),t(Pt,_a),t(x,$a),t(x,At),t(At,Ea),t(x,ya),t(x,Dt),t(Dt,xa),t(x,Ta),h(e,fs,l),k(Te,e,l),h(e,ds,l),k(je,e,l),h(e,us,l),h(e,B,l),t(B,ja),t(B,St),t(St,Pa),t(B,Aa),t(B,Ct),t(Ct,Da),t(B,Sa),h(e,ms,l),h(e,Re,l),t(Re,Ca),h(e,ks,l),k(Pe,e,l),h(e,ws,l),h(e,se,l),t(se,qa),t(se,qt),t(qt,Ha),t(se,Na),h(e,vs,l),k(Ae,e,l),h(e,gs,l),h(e,Me,l),t(Me,Ba),h(e,bs,l),h(e,Ue,l),t(Ue,Oa),h(e,zs,l),k(De,e,l),h(e,_s,l),k(Se,e,l),h(e,$s,l),h(e,z,l),t(z,Ia),t(z,Ht),t(Ht,Ra),t(z,Ma),t(z,Nt),t(Nt,Ua),t(z,Fa),t(z,Bt),t(Bt,Ga),t(z,La),t(z,Ot),t(Ot,Wa),t(z,Ja),h(e,Es,l),h(e,Fe,l),t(Fe,Ya),h(e,ys,l),h(e,J,l),t(J,ae),t(ae,It),k(Ce,It,null),t(J,Ka),t(J,Rt),t(Rt,Va),h(e,xs,l),h(e,T,l),t(T,qe),t(qe,Xa),t(T,Qa),t(T,Mt),t(Mt,Za),t(T,eo),t(T,Ge),t(Ge,to),t(T,so),h(e,Ts,l),h(e,O,l),t(O,ao),t(O,Ut),t(Ut,oo),t(O,no),t(O,Ft),t(Ft,ro),t(O,io),h(e,js,l),h(e,Y,l),t(Y,oe),t(oe,Gt),k(He,Gt,null),t(Y,lo),t(Y,Lt),t(Lt,ho),h(e,Ps,l),h(e,Le,l),t(Le,po),h(e,As,l),h(e,ne,l),t(ne,Wt),t(Wt,j),t(j,We),t(We,co),t(j,fo),t(j,Je),t(Je,uo),t(j,mo),t(j,Ye),t(Ye,ko),t(j,wo),t(j,Ke),t(Ke,vo),t(ne,go),t(ne,P),t(P,A),t(A,Ve),t(Ve,bo),t(A,zo),t(A,Xe),t(Xe,_o),t(A,$o),t(A,Qe),t(Qe,Eo),t(A,yo),t(A,Ze),t(Ze,xo),t(P,To),t(P,D),t(D,et),t(et,jo),t(D,Po),t(D,tt),t(tt,Ao),t(D,Do),t(D,st),t(st,So),t(D,Co),t(D,at),t(at,qo),t(P,Ho),t(P,S),t(S,ot),t(ot,No),t(S,Bo),t(S,nt),t(nt,Oo),t(S,Io),t(S,rt),t(rt,Ro),t(S,Mo),t(S,it),t(it,Uo),t(P,Fo),t(P,C),t(C,lt),t(lt,Go),t(C,Lo),t(C,ht),t(ht,Wo),t(C,Jo),t(C,pt),t(pt,Yo),t(C,Ko),t(C,ct),t(ct,Vo),h(e,Ds,l),h(e,ft,l),t(ft,Xo),Ss=!0},p(e,[l]){const Ne={};l&2&&(Ne.$$scope={dirty:l,ctx:e}),Z.$set(Ne)},i(e){Ss||(w(_.$$.fragment,e),w(q.$$.fragment,e),w(ve.$$.fragment,e),w(ge.$$.fragment,e),w(ze.$$.fragment,e),w(_e.$$.fragment,e),w($e.$$.fragment,e),w(Ee.$$.fragment,e),w(Z.$$.fragment,e),w(ye.$$.fragment,e),w(xe.$$.fragment,e),w(Te.$$.fragment,e),w(je.$$.fragment,e),w(Pe.$$.fragment,e),w(Ae.$$.fragment,e),w(De.$$.fragment,e),w(Se.$$.fragment,e),w(Ce.$$.fragment,e),w(He.$$.fragment,e),Ss=!0)},o(e){v(_.$$.fragment,e),v(q.$$.fragment,e),v(ve.$$.fragment,e),v(ge.$$.fragment,e),v(ze.$$.fragment,e),v(_e.$$.fragment,e),v($e.$$.fragment,e),v(Ee.$$.fragment,e),v(Z.$$.fragment,e),v(ye.$$.fragment,e),v(xe.$$.fragment,e),v(Te.$$.fragment,e),v(je.$$.fragment,e),v(Pe.$$.fragment,e),v(Ae.$$.fragment,e),v(De.$$.fragment,e),v(Se.$$.fragment,e),v(Ce.$$.fragment,e),v(He.$$.fragment,e),Ss=!1},d(e){s(d),e&&s(K),e&&s(b),g(_),e&&s($),g(q,e),e&&s(me),e&&s(Oe),e&&s(Kt),e&&s(G),e&&s(Vt),e&&s(H),e&&s(Xt),e&&s(L),g(ve),e&&s(Qt),g(ge,e),e&&s(Zt),e&&s(X),e&&s(es),e&&s(N),e&&s(ts),g(ze,e),e&&s(ss),g(_e,e),e&&s(as),e&&s(y),e&&s(os),g($e,e),e&&s(ns),g(Ee,e),e&&s(rs),e&&s(Q),e&&s(is),g(Z,e),e&&s(ls),e&&s(W),g(ye),e&&s(hs),g(xe,e),e&&s(ps),e&&s(te),e&&s(cs),e&&s(x),e&&s(fs),g(Te,e),e&&s(ds),g(je,e),e&&s(us),e&&s(B),e&&s(ms),e&&s(Re),e&&s(ks),g(Pe,e),e&&s(ws),e&&s(se),e&&s(vs),g(Ae,e),e&&s(gs),e&&s(Me),e&&s(bs),e&&s(Ue),e&&s(zs),g(De,e),e&&s(_s),g(Se,e),e&&s($s),e&&s(z),e&&s(Es),e&&s(Fe),e&&s(ys),e&&s(J),g(Ce),e&&s(xs),e&&s(T),e&&s(Ts),e&&s(O),e&&s(js),e&&s(Y),g(He),e&&s(Ps),e&&s(Le),e&&s(As),e&&s(ne),e&&s(Ds),e&&s(ft)}}}const xr={local:"normalization-and-pre-tokenization",sections:[{local:"normalization",title:"Normalization"},{local:"pre-tokenization",title:"Pre-tokenization"},{local:"sentencepiece",title:"SentencePiece"},{local:"algorithm-overview",title:"Algorithm overview"}],title:"Normalization and pre-tokenization"};function Tr(Yt){return zr(()=>{new URLSearchParams(window.location.search).get("fw")}),[]}class qr extends wr{constructor(d){super();vr(this,d,Tr,yr,gr,{})}}export{qr as default,xr as metadata};
