مفاهیم اصلی پردازش زبان طبیعی را با راهنمای جامع ما برای پیاده سازی مدل های زبانی N-gram از ابتدا کاوش کنید. تئوری، کد و کاربردهای عملی را بیاموزید.
ایجاد پایه های NLP: بررسی عمیق پیاده سازی مدل زبانی N-gram
در عصری که هوش مصنوعی بر آن مسلط است، از دستیارهای هوشمند در جیب های ما گرفته تا الگوریتم های پیچیده ای که موتورهای جستجو را تغذیه می کنند، مدل های زبانی موتورهای نامرئی هستند که بسیاری از این نوآوری ها را هدایت می کنند. آنها دلیلی هستند که تلفن شما می تواند کلمه بعدی را که می خواهید تایپ کنید پیش بینی کند و چگونه خدمات ترجمه می توانند به روانی یک زبان را به زبان دیگر تبدیل کنند. اما این مدل ها چگونه کار می کنند؟ قبل از ظهور شبکه های عصبی پیچیده مانند GPT، پایه و اساس زبان شناسی محاسباتی بر پایه یک رویکرد آماری زیبا، ساده و در عین حال قدرتمند بنا شد: مدل N-gram.
این راهنمای جامع برای مخاطبان جهانی از دانشمندان داده مشتاق، مهندسان نرم افزار و علاقه مندان کنجکاو فناوری طراحی شده است. ما به اصول اولیه باز می گردیم، تئوری پشت مدل های زبانی N-gram را رمزگشایی می کنیم و یک راهنمای عملی گام به گام در مورد چگونگی ساخت یکی از پایه را ارائه می دهیم. درک N-gram ها فقط یک درس تاریخی نیست. این یک گام حیاتی در ایجاد یک پایه محکم در پردازش زبان طبیعی (NLP) است.
مدل زبانی چیست؟
در هسته خود، یک مدل زبانی (LM) یک توزیع احتمال بر روی یک توالی از کلمات است. به عبارت ساده تر، وظیفه اصلی آن پاسخ دادن به یک سوال اساسی است: با توجه به یک توالی از کلمات، محتمل ترین کلمه بعدی چیست؟
جمله زیر را در نظر بگیرید: "دانش آموزان ___ خود را باز کردند."
یک مدل زبانی به خوبی آموزش دیده به کلماتی مانند "کتاب ها"، "لپ تاپ ها" یا "ذهن ها" احتمال بالایی و به کلماتی مانند "فتوسنتز"، "فیل ها" یا "بزرگراه" احتمال بسیار کم، تقریباً صفر، اختصاص می دهد. مدل های زبانی با کمی کردن احتمال توالی کلمات، ماشین ها را قادر می سازند تا زبان انسان را به روشی منسجم درک، تولید و پردازش کنند.
کاربردهای آنها گسترده و در زندگی دیجیتال روزمره ما ادغام شده است، از جمله:
- ترجمه ماشینی: اطمینان از اینکه جمله خروجی روان و از نظر دستوری در زبان مقصد صحیح است.
- تشخیص گفتار: تمایز بین عبارات مشابه آوایی (به عنوان مثال، "recognize speech" در مقابل "wreck a nice beach").
- متن پیش بینی کننده و تکمیل خودکار: پیشنهاد کلمه یا عبارت بعدی هنگام تایپ.
- تصحیح املا و گرامر: شناسایی و نشانه گذاری توالی کلماتی که از نظر آماری غیرمحتمل هستند.
معرفی N-gram ها: مفهوم اصلی
N-gram به سادگی یک توالی پیوسته از 'n' آیتم از یک نمونه متن یا گفتار معین است. 'آیتم ها' معمولاً کلمات هستند، اما می توانند کاراکترها، هجاها یا حتی واج ها نیز باشند. 'n' در N-gram نشان دهنده یک عدد است که منجر به نام های خاص می شود:
- Unigram (n=1): یک کلمه واحد. (به عنوان مثال، "The", "quick", "brown", "fox")
- Bigram (n=2): یک توالی از دو کلمه. (به عنوان مثال، "The quick", "quick brown", "brown fox")
- Trigram (n=3): یک توالی از سه کلمه. (به عنوان مثال، "The quick brown", "quick brown fox")
ایده اساسی پشت یک مدل زبانی N-gram این است که می توانیم کلمه بعدی را در یک توالی با نگاه کردن به 'n-1' کلمه ای که قبل از آن آمده اند پیش بینی کنیم. به جای تلاش برای درک پیچیدگی کامل گرامری و معنایی یک جمله، یک فرض ساده سازی می کنیم که به طور چشمگیری از دشواری مسئله می کاهد.
ریاضیات پشت N-gram ها: احتمال و ساده سازی
برای محاسبه رسمی احتمال یک جمله (یک توالی از کلمات W = w₁, w₂, ..., wₖ)، می توانیم از قانون زنجیره ای احتمال استفاده کنیم:
P(W) = P(w₁) * P(w₂|w₁) * P(w₃|w₁, w₂) * ... * P(wₖ|w₁, ..., wₖ₋₁)
این فرمول بیان می کند که احتمال کل توالی حاصل ضرب احتمالات شرطی هر کلمه است، با توجه به تمام کلماتی که قبل از آن آمده اند. در حالی که از نظر ریاضی درست است، این رویکرد غیر عملی است. محاسبه احتمال یک کلمه با توجه به تاریخچه طولانی از کلمات قبلی (به عنوان مثال، P(word | "The quick brown fox jumps over the lazy dog and then...")) به مقدار غیرممکنی زیاد از داده های متنی نیاز دارد تا مثال های کافی برای تخمین قابل اعتماد پیدا کند.
فرض مارکوف: یک ساده سازی عملی
اینجاست که مدل های N-gram مهمترین مفهوم خود را معرفی می کنند: فرض مارکوف. این فرض بیان می کند که احتمال یک کلمه فقط به تعداد ثابتی از کلمات قبلی بستگی دارد. ما فرض می کنیم که زمینه فوری کافی است و می توانیم تاریخچه دورتر را کنار بگذاریم.
- برای یک مدل بیگراﻡ(n=2)، فرض می کنیم احتمال یک کلمه فقط به یک کلمه قبلی بستگی دارد:
P(wᵢ | w₁, ..., wᵢ₋₁) ≈ P(wᵢ | wᵢ₋₁) - برای یک مدل تریگرام (n=3)، فرض می کنیم به دو کلمه قبلی بستگی دارد:
P(wᵢ | w₁, ..., wᵢ₋₁) ≈ P(wᵢ | wᵢ₋₁, wᵢ₋₂)
این فرض مسئله را از نظر محاسباتی قابل حل می کند. دیگر نیازی نیست که تاریخچه کامل یک کلمه را ببینیم تا احتمال آن را محاسبه کنیم، فقط n-1 کلمه آخر.
محاسبه احتمالات N-gram
با فرض مارکوف در جای خود، چگونه این احتمالات ساده شده را محاسبه می کنیم؟ ما از روشی به نام تخمین حداکثر درست نمایی (MLE) استفاده می کنیم، که راهی شیک برای گفتن این است که احتمالات را مستقیماً از شمارش در متن آموزشی خود (corpus) به دست می آوریم.
برای یک مدل بیگراﻡ، احتمال یک کلمه wᵢ که به دنبال کلمه wᵢ₋₁ می آید به صورت زیر محاسبه می شود:
P(wᵢ | wᵢ₋₁) = Count(wᵢ₋₁, wᵢ) / Count(wᵢ₋₁)
به این صورت: احتمال دیدن کلمه B بعد از کلمه A تعداد دفعاتی است که جفت "A B" را دیدیم تقسیم بر تعداد دفعاتی که کلمه "A" را در مجموع دیدیم.
بیایید از یک corpus کوچک به عنوان مثال استفاده کنیم: "The cat sat. The dog sat."
- Count("The") = 2
- Count("cat") = 1
- Count("dog") = 1
- Count("sat") = 2
- Count("The cat") = 1
- Count("The dog") = 1
- Count("cat sat") = 1
- Count("dog sat") = 1
احتمال "cat" بعد از "The" چقدر است؟
P("cat" | "The") = Count("The cat") / Count("The") = 1 / 2 = 0.5
احتمال "sat" بعد از "cat" چقدر است؟
P("sat" | "cat") = Count("cat sat") / Count("cat") = 1 / 1 = 1.0
پیاده سازی گام به گام از ابتدا
اکنون بیایید این تئوری را به یک پیاده سازی عملی تبدیل کنیم. مراحل را به روشی مستقل از زبان مشخص می کنیم، اگرچه منطق مستقیماً به زبان هایی مانند پایتون نگاشت می شود.
مرحله 1: پیش پردازش داده ها و Tokenization
قبل از اینکه بتوانیم چیزی را بشماریم، باید corpus متنی خود را آماده کنیم. این یک مرحله حیاتی است که کیفیت مدل ما را شکل می دهد.
- Tokenization: فرآیند تقسیم یک بدنه متن به واحدهای کوچکتر، به نام توکن ها (در مورد ما، کلمات). به عنوان مثال، "The cat sat." به ["The", "cat", "sat", "."] تبدیل می شود.
- کوچک کردن حروف: این یک عمل استاندارد است که تمام متن را به حروف کوچک تبدیل کنید. این کار از اینکه مدل "The" و "the" را به عنوان دو کلمه متفاوت در نظر بگیرد جلوگیری می کند، که به ادغام شمارش های ما و قوی تر کردن مدل کمک می کند.
- افزودن نشانه های شروع و توقف: این یک تکنیک حیاتی است. ما نشانه های ویژه ای مانند <s> (شروع) و </s> (توقف) را به ابتدا و انتهای هر جمله اضافه می کنیم. چرا؟ این به مدل اجازه می دهد تا احتمال یک کلمه را در ابتدای یک جمله محاسبه کند (به عنوان مثال، P("The" | <s>)) و به تعریف احتمال یک جمله کامل کمک می کند. جمله مثال ما "the cat sat." به ["<s>", "the", "cat", "sat", ".", "</s>"] تبدیل می شود.
مرحله 2: شمارش N-gram ها
هنگامی که یک لیست تمیز از نشانه ها برای هر جمله داریم، از طریق corpus خود تکرار می کنیم تا شمارش ها را بدست آوریم. بهترین ساختار داده برای این کار یک دیکشنری یا یک نقشه هش است، جایی که کلیدها N-gram ها (که به صورت تاپل نشان داده می شوند) و مقادیر فرکانس های آنها هستند.
برای یک مدل بیگراﻡ، به دو دیکشنری نیاز داریم:
unigram_counts: فرکانس هر کلمه جداگانه را ذخیره می کند.bigram_counts: فرکانس هر توالی دو کلمه ای را ذخیره می کند.
شما از طریق جملات نشانه گذاری شده خود حلقه می زنید. برای جمله ای مانند ["<s>", "the", "cat", "sat", "</s>"]، شما:
- شمارش unigrams را افزایش می دهید: "<s>", "the", "cat", "sat", "</s>".
- شمارش bigrams را افزایش می دهید: ("<s>", "the"), ("the", "cat"), ("cat", "sat"), ("sat", "</s>").
مرحله 3: محاسبه احتمالات
با پر شدن دیکشنری های شمارش ما، اکنون می توانیم مدل احتمال را بسازیم. می توانیم این احتمالات را در یک دیکشنری دیگر ذخیره کنیم یا آنها را در لحظه محاسبه کنیم.
برای محاسبه P(word₂ | word₁)، bigram_counts[(word₁, word₂)] و unigram_counts[word₁] را بازیابی می کنید و تقسیم را انجام می دهید. یک تمرین خوب این است که تمام احتمالات ممکن را از قبل محاسبه کنید و آنها را برای جستجوهای سریع ذخیره کنید.
مرحله 4: تولید متن (یک کاربرد سرگرم کننده)
یک راه عالی برای آزمایش مدل خود این است که آن را وادار کنید متن جدیدی تولید کند. این فرآیند به شرح زیر عمل می کند:
- با یک زمینه اولیه شروع کنید، به عنوان مثال، نشانه شروع <s>.
- تمام bigramsهایی را که با <s> شروع می شوند و احتمالات مرتبط با آنها را جستجو کنید.
- به طور تصادفی کلمه بعدی را بر اساس این توزیع احتمال انتخاب کنید (کلماتی که احتمالات بالاتری دارند به احتمال زیاد انتخاب می شوند).
- زمینه خود را به روز کنید. کلمه تازه انتخاب شده به اولین بخش از bigram بعدی تبدیل می شود.
- این فرآیند را تکرار کنید تا زمانی که یک نشانه توقف </s> تولید کنید یا به طول دلخواه برسید.
متن تولید شده توسط یک مدل N-gram ساده ممکن است کاملاً منسجم نباشد، اما اغلب جملات کوتاه از نظر دستوری قابل قبول تولید می کند، که نشان می دهد روابط اساسی کلمه به کلمه را یاد گرفته است.
چالش پراکندگی و راه حل: هموارسازی
اگر مدل ما در طول آزمایش با یک bigram مواجه شود که هرگز در طول آموزش ندیده باشد، چه اتفاقی می افتد؟ به عنوان مثال، اگر corpus آموزشی ما هرگز عبارت "the purple dog" را شامل نشده باشد،:
Count("the", "purple") = 0
این بدان معناست که P("purple" | "the") 0 خواهد بود. اگر این bigram بخشی از یک جمله طولانی تر باشد که ما در تلاش برای ارزیابی آن هستیم، احتمال کل جمله صفر می شود، زیرا ما همه احتمالات را با هم ضرب می کنیم. این مشکل احتمال صفر است، تظاهری از پراکندگی داده ها. غیرواقعی است که فرض کنیم corpus آموزشی ما شامل هر ترکیب کلمه معتبر ممکن است.
راه حل این هموارسازی است. ایده اصلی هموارسازی این است که مقدار کمی از جرم احتمال را از N-gramهایی که دیده ایم برداریم و آن را به N-gramهایی که هرگز ندیده ایم توزیع کنیم. این تضمین می کند که هیچ توالی کلمه ای احتمال دقیقاً صفر ندارد.
هموارسازی لاپلاس (اضافه کردن یک)
ساده ترین تکنیک هموارسازی، هموارسازی لاپلاس است که به عنوان هموارسازی اضافه کردن یک نیز شناخته می شود. ایده فوق العاده شهودی است: وانمود کنید که هر N-gram ممکن را یک بار بیشتر از آنچه که واقعاً انجام داده ایم دیده ایم.
فرمول احتمال کمی تغییر می کند. ما 1 را به شمارنده صورت اضافه می کنیم. برای اطمینان از اینکه احتمالات همچنان به 1 می رسند، اندازه کل واژگان (V) را به مخرج اضافه می کنیم.
P_laplace(wᵢ | wᵢ₋₁) = (Count(wᵢ₋₁, wᵢ) + 1) / (Count(wᵢ₋₁) + V)
- مزایا: پیاده سازی بسیار ساده و تضمین عدم وجود احتمالات صفر.
- معایب: اغلب احتمال زیادی را به رویدادهای دیده نشده می دهد، به ویژه با واژگان بزرگ. به همین دلیل، اغلب در مقایسه با روش های پیشرفته تر در عمل ضعیف عمل می کند.
هموارسازی اضافه کردن k
یک بهبود جزئی هموارسازی اضافه کردن k است، جایی که به جای اضافه کردن 1، یک مقدار کسری کوچک 'k' (به عنوان مثال، 0.01) اضافه می کنیم. این اثر تخصیص مجدد بیش از حد جرم احتمال را تعدیل می کند.
P_add_k(wᵢ | wᵢ₋₁) = (Count(wᵢ₋₁, wᵢ) + k) / (Count(wᵢ₋₁) + k*V)
در حالی که بهتر از اضافه کردن یک است، یافتن 'k' بهینه می تواند یک چالش باشد. تکنیک های پیشرفته تری مانند هموارسازی Good-Turing و هموارسازی Kneser-Ney وجود دارند و در بسیاری از مجموعه ابزارهای NLP استاندارد هستند و راه های بسیار پیچیده تری را برای تخمین احتمال رویدادهای دیده نشده ارائه می دهند.
ارزیابی یک مدل زبانی: سردرگمی
چگونه می دانیم که مدل N-gram ما خوب است؟ یا اگر یک مدل تریگرام برای کار خاص ما بهتر از یک مدل بیگراﻡ است؟ ما به یک معیار کمی برای ارزیابی نیاز داریم. رایج ترین معیار برای مدل های زبانی سردرگمی است.
سردرگمی معیاری است برای اینکه چگونه یک مدل احتمال یک نمونه را پیش بینی می کند. به طور شهودی، می توان آن را به عنوان ضریب انشعاب میانگین وزنی مدل در نظر گرفت. اگر مدلی دارای سردرگمی 50 باشد، به این معنی است که در هر کلمه، مدل به همان اندازه گیج است که اگر مجبور باشد به طور یکنواخت و مستقل از 50 کلمه مختلف انتخاب کند.
نمره سردرگمی کمتر بهتر است، زیرا نشان می دهد که مدل کمتر از داده های آزمون "غافلگیر" می شود و احتمالات بالاتری را به توالی هایی که در واقع می بیند اختصاص می دهد.
سردرگمی به عنوان احتمال معکوس مجموعه آزمون، نرمال شده توسط تعداد کلمات محاسبه می شود. اغلب برای سهولت محاسبات در شکل لگاریتمی آن نشان داده می شود. مدلی با قدرت پیش بینی خوب، احتمالات بالایی را به جملات آزمون اختصاص می دهد و در نتیجه سردرگمی کم می شود.
محدودیت های مدل های N-gram
با وجود اهمیت اساسی، مدل های N-gram محدودیت های قابل توجهی دارند که زمینه NLP را به سمت معماری های پیچیده تر سوق داده اند:
- پراکندگی داده ها: حتی با هموارسازی، برای N های بزرگتر (تریگرام ها، 4-گرام ها و غیره)، تعداد ترکیبات کلمه ای ممکن منفجر می شود. جمع آوری داده های کافی برای تخمین مطمئن احتمالات برای اکثر آنها غیرممکن می شود.
- ذخیره سازی: مدل از تمام شمارش های N-gram تشکیل شده است. با رشد واژگان و N، حافظه مورد نیاز برای ذخیره این شمارش ها می تواند بسیار زیاد شود.
- ناتوانی در گرفتن وابستگی های دوربرد: این مهمترین نقص آنهاست. یک مدل N-gram حافظه بسیار محدودی دارد. به عنوان مثال، یک مدل تریگرام نمی تواند یک کلمه را به کلمه دیگری که بیش از دو موقعیت قبل از آن ظاهر شده است متصل کند. این جمله را در نظر بگیرید: "نویسنده، که چندین رمان پرفروش نوشت و دهه ها در یک شهر کوچک در یک کشور دور افتاده زندگی کرد، به زبان ___ مسلط است." یک مدل تریگرام که سعی می کند کلمه آخر را پیش بینی کند، فقط زمینه "به زبان مسلط است" را می بیند. او هیچ اطلاعی از کلمه "نویسنده" یا مکان ندارد که سرنخ های مهمی هستند. نمی تواند رابطه معنایی بین کلمات دور را بگیرد.
فراتر از N-gram ها: طلوع مدل های زبانی عصبی
این محدودیت ها، به ویژه ناتوانی در رسیدگی به وابستگی های دوربرد، راه را برای توسعه مدل های زبانی عصبی هموار کرد. معماری هایی مانند شبکه های عصبی بازگشتی (RNNs)، شبکه های حافظه بلندمدت (LSTMs) و به ویژه ترانسفورماتورهای غالب کنونی (که مدل هایی مانند BERT و GPT را نیرو می بخشند) برای غلبه بر این مشکلات خاص طراحی شده اند.
مدل های عصبی به جای تکیه بر شمارش های پراکنده، نمایش های برداری متراکم از کلمات (embedding ها) را یاد می گیرند که روابط معنایی را می گیرند. آنها از مکانیسم های حافظه داخلی برای ردیابی زمینه در توالی های بسیار طولانی تر استفاده می کنند، و به آنها اجازه می دهند وابستگی های پیچیده و طولانی مدت ذاتی در زبان انسان را درک کنند.
نتیجه گیری: یک ستون اساسی NLP
در حالی که NLP مدرن تحت سلطه شبکه های عصبی در مقیاس بزرگ است، مدل N-gram همچنان یک ابزار آموزشی ضروری و یک پایه شگفت آور موثر برای بسیاری از وظایف است. این یک معرفی واضح، قابل تفسیر و از نظر محاسباتی کارآمد برای چالش اصلی مدل سازی زبانی ارائه می دهد: استفاده از الگوهای آماری از گذشته برای پیش بینی آینده.
با ساختن یک مدل N-gram از ابتدا، درک عمیق و اصول اولیه از احتمال، پراکندگی داده ها، هموارسازی و ارزیابی در زمینه NLP به دست می آورید. این دانش فقط تاریخی نیست. این بستر مفهومی است که آسمان خراش های سر به فلک کشیده هوش مصنوعی مدرن بر روی آن ساخته شده اند. این به شما می آموزد که به زبان به عنوان یک توالی از احتمالات فکر کنید - دیدگاهی که برای تسلط بر هر مدل زبانی، صرف نظر از میزان پیچیدگی آن، ضروری است.