Tokenization یک مرحله پیش پردازش برای اکثر برنامه های پردازش زبان طبیعی NLP است. توکن سازی شامل تقسیم متن به واحدهای کوچکتر به نام توکنها (به عنوان مثال کلمات) به منظور تبدیل یک رشته ورودی بدون ساختار به دنبالهای از واحدهای جدا از یکدیگر که برای یک مدل یادگیری ماشینی ML مناسب است. در مدل های مبتنی بر یادگیری عمیق (به عنوان مثال BERT)، هر توکن به یک بردار نگاشت می شود تا به عنوان ورودی مدل استفاده شود.
الگوریتمهای توکنسازی زیرکلمه (Subword tokenization) بر این اصل تکیه میکنند که کلمات پرکاربرد نباید به زیرکلمههای کوچکتر تقسیم شوند، بلکه کلمات نادر باید به زیرکلمههای معنادار تجزیه شوند. به عنوان مثال، 'واژه annoyingly
به معنی 'آزاردهنده' ممکن است یک کلمه نادر در نظر گرفته شود و می تواند به 'annoying
' و 'ly
' تجزیه شود. هم annoying
و هم ly
بهعنوان زیرکلمههای مستقل بیشتر در متون ظاهر میشوند، همچنین معنای annoyingly
با ترکیب معنای annoying
و ly
نیز درک میشود. این به ویژه در زبانهای پیوندی مانند ترکی مفید است، جایی که میتوانید کلمات پیچیده (تقریباً) دلخواه خود را با اتصال زیرکلمهها تشکیل دهید.
توکنسازی زیرکلمه Subword به مدل اجازه می دهد تا اندازه مجموعه واژگان معقولی داشته باشد در حالی که قادر به یادگیری بازنمایی های معنادار مستقل از متن زمینه است. بهعلاوه، توکنسازی زیرکلمهای، مدل را قادر میسازد تا کلماتی را که قبلاً ندیده است، با تجزیه آنها به زیرکلمههای شناخته شده پردازش کند. به عنوان مثال توکنسازی جمله "!I have a new GPU" <من یک GPU جدید دارم!> توسط BertTokenizer به شرح زیر است:
>>>from transformers import BertTokenizer >>>tokenizer = BertTokenizer.from_pretrained("bert-base-uncased") >>>tokenizer.tokenize("I have a new GPU!") ["i", "have", "a", "new", "gp", "##u", "!"]
از آنجا که ما مدل BERT base model (uncased) را استفاده می کنیم، ابتدا حروف lowercased می کند. میتوانیم ببینیم که کلمات ['i'، 'have'، 'a'، 'new'] در مجموعه واژگان توکنایزر وجود دارد، اما کلمه 'gpu' وجود ندارد. در نتیجه، توکنایزر 'gpu' را به زیرکلمه های شناخته شده تقسیم می کند: ['gp' و '##u']. '##' به این معنی است که بقیه توکن باید بدون فاصله (برای رمزگشایی یا معکوس کردن توکن) به علامت قبلی متصل شود.
به عنوان مثالی دیگر، XLNetTokenizer متن را به صورت زیر توکن می کند:
>>>from transformers import XLNetTokenizer >>>tokenizer = XLNetTokenizer.from_pretrained("xlnet-base-cased") >>>tokenizer.tokenize("Don't you love ? Transformers? We sure do.") ["▁Don", "'", "t", "▁you", "▁love", "▁", "?", "▁", "Transform", "ers", "?", "▁We", "▁sure", "▁do", "."]
وقتی به بخش SentencePiece در ادامه این مقاله برسیم به معنای '▁
' نیز برمی گردیم. همانطور که مشاهده می شود، کلمه کمیاب 'Transformers' به زیرکلمه های متداول تر 'Transform' و 'ers' تقسیم شده است.
بیایید اکنون به نحوه عملکرد الگوریتمهای مختلف توکنایز زیرکلمه نگاه کنیم. توجه داشته باشید که همه الگوریتمهای توکنسازی به آموزشی متکی هستند که معمولاً روی مجموعهای انجام میشود که مدل مربوطه روی آن آموزش داده شده است.
رمزگذاری زوج بایت (BPE) در مقاله Neural Machine Translation of Rare Words with Subword Units (Sennrich et al., 2015) معرفی شد. BPE به یک پیش_توکنساز متکی است که دادههای آموزشی را به کلمات تقسیم میکند. پیش_توکنسازی میتواند به سادگی توکنسازی بوسیله اسپیس باشد، به عنوان مثال GPT-2، روبرتا. پیش_توکنسازی پیشرفته تر شامل توکن سازی مبتنی بر قاعده است، به عنوان مثال XLM، FlauBERT که از تولکیت Moses برای اکثر زبان ها استفاده می کند، یا GPT که از Spacy و ftfy برای شمارش فراوانی هر کلمه در مجموعه آموزشی استفاده می کند.
بعد از پیش_توکنسازی، مجموعه ای از کلمات منحصر به فرد ایجاد شده و فراوانی هر کلمه ای که در داده های آموزشی رخ می دهد مشخص شده است. در مرحله بعد، BPE یک مجموعه واژگان پایه متشکل از تمام سیمبلهایی که در مجموعه کلمات منحصر به فرد رخ می دهد ایجاد می کند و قواعد ادغام را می آموزد تا یک سیمبل جدید از دو سیمبل از واژگان پایه تشکیل دهد. این کار را تا زمانی انجام می دهد که واژگان به اندازه واژگان مورد نظر برسد. توجه داشته باشید که اندازه واژگان مورد نظر یک فراپارامتر است که قبل از آموزش توکنایزر باید تعریف شود.
به عنوان مثال، فرض می کنیم که پس از پیش_توکنسازی، مجموعه کلمات زیر شامل فراوانی مشخص شده است:
("hug", 10), ("pug", 5), ("pun", 12), ("bun", 4), ("hugs", 5)
در نتیجه، واژگان پایه ['b'، 'g'، 'h'، 'n'، 'p'، 's'، 'u'] است. با تقسیم تمام کلمات به سیمبل واژگان پایه، به دست می آوریم:
("h" "u" "g", 10), ("p" "u" "g", 5), ("p" "u" "n", 12), ("b" "u" "n", 4), ("h" "u" "g" "s", 5)
سپس BPE فرکانس هر جفت نماد ممکن را می شمارد و جفت نمادی را که بیشتر اتفاق می افتد انتخاب میکند. در مثال بالا، 'h' که به دنبال آن u بیاید 15 = 10 + 5 بار وجود دارد (10 بار در 10 مورد HUG و 5 بار در 5 مورد hugs). با این حال، رایج ترین جفت نماد 'u' و به دنبال آن 'g' است که در مجموع 20 = 10 + 5 + 5 بار رخ می دهد. بنابراین، اولین قانون ادغامی که توکنایزر میآموزد این است که همه نمادهای 'u' و سپس یک نماد 'g' را با هم گروه بندی کند. بعد، 'ug' به واژگان اضافه می شود. سپس مجموعه کلمات تبدیل می شود به:
("h" "ug", 10), ("p" "ug", 5), ("p" "u" "n", 12), ("b" "u" "n", 4), ("h" "ug" "s", 5)
سپس BPE متداول ترین جفت نماد بعدی را شناسایی می کند. 'u' به دنبال آن 'n' است که 16 بار تکرار می شود. 'u'، 'n' با 'un' ادغام شده و به واژگان اضافه می شود. پرتکرارترین جفت نماد بعدی 'h' و به دنبال آن 'ug' است که 15 بار رخ می دهد. دوباره این جفت ادغام می شود و hug را می توان به مجموعه واژگان اضافه کرد.
در این مرحله، واژگان ['b'، 'g'، 'h'، 'n'، 'p'، 's'، 'u'، 'ug'، 'un'، 'hug'] و ما هستند. مجموعه ای از کلمات منحصر به فرد به عنوان نشان داده شده است
("hug", 10), ("p" "ug", 5), ("p" "un", 12), ("b" "un", 4), ("hug" "s", 5)
با فرض اینکه آموزش رمزگذاری زوج بایت در این نقطه متوقف شود، قوانین ادغام آموخته شده سپس بر روی کلمات جدید اعمال می شود (تا زمانی که کلمات جدید شامل نمادهایی نباشند که در واژگان پایه نیستند). به عنوان مثال، کلمه bug
به["b", "ug"]
نشانه می شود، اما mug
به عنوان ["unk>", "ug>"]
نشان داده می شود زیرا نماد 'm' در واژگان پایه نیست. . به طور کلی، حروف منفرد مانند 'm' با نماد "<unk>"
جایگزین نمیشوند، زیرا دادههای آموزشی معمولاً حداقل یک مورد از هر حرف را شامل میشود، اما احتمالاً برای کاراکترهای بسیار خاص مانند ایموجیها اتفاق میافتد.
همانطور که قبلا ذکر شد، اندازه واژگان، یعنی اندازه واژگان پایه + تعداد ادغام ها، یک فراپارامتر است. به عنوان مثال GPT دارای اندازه واژگان 40478 است زیرا آنها 478 کاراکتر پایه دارند و تصمیم گرفتند پس از 40000 ادغام آموزش را متوقف کنند.
یک مجموعه واژگان پایه که شامل تمام کاراکترهای پایه ممکن است می تواند بسیار بزرگ باشد. اگر به عنوان مثال همه کاراکترهای یونیکد به عنوان کاراکترهای پایه در نظر گرفته می شوند. برای داشتن واژگان پایه بهتر، GPT-2 از بایت ها به عنوان واژگان پایه استفاده می کند، که یک ترفند هوشمندانه برای وادار کردن واژگان پایه به اندازه 256 است و در عین حال اطمینان می دهد که هر کاراکتر پایه در واژگان گنجانده شده است. با برخی قواعد اضافی برای مقابله با علائم نقطه گذاری، توکنایزر GPT2 می تواند هر متنی را بدون نیاز به نماد <unk> توکنیزه کند. GPT-2 دارای اندازه واژگان 50257 است که با توکن های پایه 256 بایتی، یک توکن ویژه برای پایان متن و نمادهایی که از 50000 ادغام یاد گرفته شدهاند به دست آمده است.
WordPiece الگوریتم توکن سازی زیرکلمه ای است که برای BERT، DistilBERT و Electra استفاده می شود. این الگوریتم در Japanese and Korean Voice Search (Schuster et al., 2012) تشریح شد و بسیار شبیه BPE است. WordPiece ابتدا واژگان را برای گنجاندن هر کاراکتر موجود در دادههای آموزشی مقداردهی اولیه میکند و به تدریج تعداد معینی از قواعد ادغام را یاد می گیرد. برخلاف BPE، روش WordPiece متداولترین جفت نماد را انتخاب نمیکند، بلکه یکی را انتخاب میکند که احتمال دادههای آموزشی را پس از افزودن به واژگان را به حداکثر میرساند.
این دقیقا به چه معناست؟ با اشاره به مثال قبلی، به حداکثر رساندن احتمال داده های آموزشی معادل یافتن جفت نماد است که احتمال تقسیم آن بر احتمالات نماد اول و سپس نماد دوم آن، در بین تمام جفت نمادها بیشترین است. به عنوان مثال 'u' و سپس 'g' تنها در صورتی با هم ادغام میشوند که احتمال "ug"
تقسیم بر "u"
, "g"
بیشتر از هر جفت نماد دیگری باشد. به طور شهودی، WordPiece کمی با BPE متفاوت است زیرا آنچه را که با ادغام دو نماد از دست می دهد ارزیابی می کند تا مطمئن شود ارزشش را دارد.
Unigram یک الگوریتم نشانهسازی Subword است که در Subword Regularization: Improving Neural Network Translation Models with Multiple Subword Candidates (Kudo, 2018) معرفی شده است. برخلاف BPE یا WordPiece، یونیگرام واژگان پایه خود را به تعداد زیادی نماد مقداردهی می کند و به تدریج هر نماد را کاهش می دهد تا واژگان کوچکتری به دست آورد. برای مثال، واژگان پایه می تواند با تمام کلمات از پیش توکنسازی شده و رایج ترین substringها مطابقت داشته باشد. Unigram به طور مستقیم برای هیچ یک از مدل های ترانسفورمر استفاده نمی شود، اما همراه با SentencePiece استفاده می شود.
در هر مرحله آموزشی، الگوریتم Unigram با توجه به واژگان فعلی و یک مدل زبانی unigram، تابع هزینه (loss) (اغلب به عنوان log-likelihood تعریف میشود) را بر روی دادههای آموزشی تعریف میکند. سپس، برای هر نماد در واژگان، الگوریتم محاسبه می کند که اگر نماد از واژگان حذف شود، هزینه کلی چقدر افزایش می یابد. سپس Unigram نماد p را حذف می کند (که p معمولاً 10٪ یا 20٪) درصد نمادهایی است که افزایش هزینه آنها کمترین است، یعنی آن نمادهایی که کمترین تأثیر را بر هزینه کلی در داده های آموزشی دارند. این روند تا زمانی که واژگان به اندازه دلخواه برسد تکرار می شود. الگوریتم Unigram همیشه کاراکترهای پایه را نگه می دارد تا هر کلمه ای را بتوان توکنگذاری کرد.
از آنجایی که Unigram بر اساس قوانین ادغام نیست (برخلاف BPE و WordPiece)، الگوریتم چندین روش برای توکن کردن متن جدید پس از آموزش دارد. به عنوان مثال، اگر یک توکنایزر Unigram آموزش دیده این واژگان را به نمایش بگذارد:
["b", "g", "h", "n", "p", "s", "u", "ug", "un", "hug"],
hugs
' را می توان به صورت ["hug", "s"]
، ["h", "ug", "s"]
یا ["h", "u", "g", "s"]
توکن گذاری کرد. پس کدام را انتخاب کنیم؟ Unigram علاوه بر ذخیره واژگان، احتمال هر نشانه را در مجموعه آموزشی ذخیره می کند تا احتمال هر توکن سازی ممکن پس از آموزش محاسبه شود. این الگوریتم به سادگی محتملترین توکنسازی را در عمل انتخاب میکند، اما همچنین امکان نمونهبرداری از توکنسازی ممکن را با توجه به احتمالات آنها ارائه میدهد.همه الگوریتمهای توکنسازی که تاکنون توضیح داده شد، مشکل یکسانی دارند: فرض بر این است که متن ورودی از اسپیس برای جدا کردن کلمات استفاده میکند. با این حال، همه زبان ها از اسپیس برای جدا کردن کلمات استفاده نمی کنند. یکی از راه حل های ممکن استفاده از پیش_توکنایزر خاص زبان است، به عنوان مثال XLM از یک پیش توکنایزر خاص چینی، ژاپنی و تایلندی استفاده می کند. برای حل این مشکل SentencePiece: A simple and language independent subword tokenizer and detokenizer for Neural Text Processing (Kudo et al., 2018) ورودی را به عنوان یک جریان ورودی خام در نظر میگیرد، بنابراین اسپیس در مجموعه کاراکترها برای استفاده در نظر گرفته میشود. سپس از الگوریتم BPE یا unigram برای ساخت واژگان مناسب استفاده می کند.
برای مثال XLNetTokenizer از SentencePiece استفاده می کند، به همین دلیل است که در مثال قبلی کاراکتر "▁"
در واژگان گنجانده شده است. رمزگشایی با SentencePiece بسیار آسان است زیرا همه توکنها را می توان به هم متصل کرد و "▁"
با یک فاصله جایگزین می شوند.