کتابخانه هضم (Hazm) | آموزش صفر تا صد پردازش متون فارسی

آموزش کامل کتابخانه هضم در پایتون

فهرست مطالب

در مقاله متن کاوی با پایتون با کتابخانه پارسی ور کامل آشنا شدیم. در این مقاله آموزشی برای اولین‌بار جامع‌ترین آموزش کتابخانه هضم به زبان فارسی را تقدیم شما خواهیم کرد. در این آموزش هیچ نکته‌ای از قلم نیفتاده و پس از مطالعه مثال‌های متعددی که برای شما آماده کردیم، تسلط صددرصدی به این کتابخانه پیدا می‌کنید. همچنین از زحمات آقای مهندس محمودزاده کمال تشکر داریم که در تهیه محتوای آموزشی این جلسه نهایت همکاری را داشتند.

اگر تمامی فرایند مربوط به ساخت، آموزش و استفاده از یک مدل یادگیری ماشین را یک «مسافرت» تصور کنیم، «پیش‌پردازش» معادل جمع‌آوری تمامی ملزومات سفر خواهد بود؛ یک کار روتین و احتمالاً کسل‌کننده اما حیاتی! و هر چه این کار بادقت و حوصله بیشتری انجام شود، احتمال اشتباه در گام‌های بعدی کمتر خواهد بود. در حوزه متن نیز به ‌مانند هر حوزه دیگری، ابزارهایی برای پیش‌‌پردازش متون، طراحی و توسعه داده شده‌اند. در زبان فارسی، به علت وجود پیچیدگی‌های متنوع، اهمیت پیش‌پردازش بسیار زیاد است. برخی از این پیچیدگی‌ها عبارت‌اند از:
  • تشخیص درست فاصله‌ها و نیم‌فاصله‌ها
  • تقسیم جملات به کلمات
  • عدم وجود اِعراب
  • ضمایر متصل، پیشوندها و پسوندهای چسبیده به فعل
برای انجام پیش‌پردازش متون کتابخانه‌های پردازش زبان طبیعی زیادی مثل Spacy و Nltk ارائه شده است که فقط تعداد معدودی از متون فارسی پشتیبانی می‌کنند و دقت بالایی ندارند. تعداد کتابخانه‌هایی که مخصوص پیش پردازش زبان فارسی باشند زیاد نیستند و از معروف‌ترین آن‌ها Hazm و Parsivar است.

آموزش کتابخانه هضم در پایتون

کتابخانه هضم (Hazm) یکی از کتابخانه های پیش‌پردازش متن فارسی است که بر اساس ابزار NLTK طراحی و توسعه داده شده است. در این ابزار امکانات زیر برای پیش‌پردازش متون قرار داده شده است:
  • نرمال‌سازی (Normalization)
    • متون رسمی
    • متون غیررسمی و محاوره‌ای
  • تقسیم‌کننده متن به جملات و کلمات (Tokenization)
  • تجزیه‌گر به کلمات (Split)
  • ریشه‌یابی
    • ریشه‌یابی معنایی یا بُن‌یابی (Lemmatizing)
    • ریشه‌یابی (Stemming)
  • تشخیص نقش کلمات (Part-Of-Speech (POS) tagging)
  • قطعه‌بندی (Chunk)
  • تجزیه‌گر وابستگی (Dependency Parser)
  • بارگذاری دادگان فارسی (Data Reader)
ابتدا برای نصب ابزار هضم از دستور زیر استفاده می‌کنیم: نصب کتابخانه هضم برای استفاده از کتابخانه Hazm ابتدا آن را وارد برنامه می‌کنیم: فراخوانی کتابخانه hazm

یکسان سازی یا نرمال سازی متون رسمی فارسی

هدف اصلی در بخش نرمال‌سازی، یکپارچه‌سازی و متحدالشکل کردن کاراکترها به‌منظور کنترل بیشتر بر نتایج پردازش‌های پیشرفته‌تر بر متن است. این یکپارچه‌سازی‌ها به طور دقیق‌تر شامل موارد زیر می‌شوند:
  • پالایش کاراکترها (character refinement)
    • فاصله‌های اضافی
      • حذف spaceهای اضافی
      • حذف newlineهای اضافی
      • حذف نیم‌فاصله‌های اضافی
      • حذف کشیدگی‌های حروف و carriage returnها
    • قالب فارسی
      • جایگزینی علامت نقل‌قول (”) یا گیومه («»)
      • جایگزینی نقطه با ممیز
      • جایگزینی سه‌نقطه خارجی زبان با …
    • حذف اعراب‌گذاری‌ها (diacritic)
      • حذف تشدید، سکون، تنوین‌ها
  • فاصله‌گذاری «وند»ها (affix spacing)
    • قراردادن نیم‌فاصله بعد از «می» و «نمی»
    • تصحیح فاصله «ه» متصل و «ی» بعد از آن: مثلاً خانه‌ی
    • قراردادن نیم‌فاصله قبل از «تر»، «تری»، «ترین»، «گر»، «گری»، «ها» و «های»
    • تصحیح فاصله ضمایر متصل و شناسه‌های فعل
  • فاصله‌گذاری توکن‌ها (token spacing)
    • حذف فاصله میان توکن‌ها بر اساس وجود یا عدم وجود پسوند، وجود یا عدم وجود پیشوند فعل
  • فاصله‌گذاری علايم نگارشی (punctuation spacing)
    • فاصله میان اعداد با حروف، تنظیم فاصله پیش و پس از علایم نقل‌قول، فاصله پس از . و
فرایند نرمال‌سازی متن در ابزار Hazm به کمک متد normalize کلاس Normalizer انجام می‌شود؛ متدی که در داخل خود، متدهای زیر را فراخوانی کرده و فرایند نرمال‌سازی متن را انجام می‌دهد. پس کافی است از Normalizer یک شی جدید به نام normalizer ساخته و تابع normalize آن را فراخوانده و متن دلخواه را در قالب یک متغیر برای آن ارسال کنید. همان‌طور که از نتیجه مشخص است عبارت “گوشی های” به ” گوشی‌های” تبدیل شده است: نرمال سازی متن رسمی با استفاده از کتابخانه hazm

 دوست دارید پروژه‌هایی برای پردازش متن یاد بگیرید که در کارهای دنیایی واقعی استفاده می‌شوند؟ صفحه آموزش متن کاوی فارسی با شبکه‌های عصبی را ببینید.

یکسان سازی یا نرمال سازی متون غیررسمی و محاوره‌ای فارسی

متن غیررسمی و محاوره‌ای در زبان فارسی تفاوت‌های عمده‌ای با فارسی رسمی و معیار دارد. ازاین‌رو نرمال‌سازی برای متون غیررسمی نیز در نظر گرفته شده است.

  • سازنده(__init__)
    • تبدیل فرم غیررسمی به رسمی (informal_to_formal_conjucation)
  • تجزیه کلمات توکن (split_token_words)
    • این متد به‌منظور به‌دست‌آوردن اجزای مختلف کلمه داده شده، در نظر گرفته شده است. تابع shekan فرایند شکستن کلمه به واحدهای کوچک‌تر و تابع perm به‌منظور یافتن تمامی حالات ممکن در نظر گرفته شده‌اند. در حال حاضر این متد در هیچ یک از متدهای دیگر فراخوانی نشده و مورد استفاده قرار نگرفته است.
  • نرمال‌سازی کلمه (normalized_word)
    • در ابتدا متد straightForwardResult فراخوانی می‌شود تا در صورت وجود، معادل رسمی کلمه موردنظر را برگرداند. در صورت عدم وجود، بررسی حالات و تنوعات پیشوندی و پسوندی فعل و سپس اسم کلمه موردنظر انجام می‌شود تا در نهایت تمامی خروجی‌های ممکن را برگرداند.
    • تحلیل کلمات (analyzeWord)
      • این متد به دنبال تمامی حالات مختلف پیشوندی و پسوندی کلمه موردنظر می‌گردد.
    • تحلیل افعال (analyzeVerbWord)
      • این متد به دنبال تمامی حالات مختلف پیشوندی و پسوندی فعل موردنظر می‌گردد.
    • افزودن پسوند به کلمه (appendSuffixToWord)
      • این متد با درنظرگرفتن حروف چسبیده امکان چسباندن پسوندها به کلمه اصلی را بررسی و اعمال می‌کند.
    • نگاشت مستقیم (straightForwardResult)
      • این متد شامل دیکشنری است که عبارات غیررسمی را به عبارات رسمی‌شان نگاشت می‌کند.
  • نرمال‌سازی جملات (normalize)
    • این متد متن ورودی را به لیستی از جملات که هر یک لیستی از کلمات هستند تبدیل کرده و به‌ازای هر کلمه متد normalized_word را فراخوانی می‌کند.
  • صرف فعل غیررسمی (informal_conjugations)

ابتدا باید یک شی دلخواه از کلاس informalNormalizer از کتابخانه هضم ایجاد کرده و سپس متن دلخواه را در قالب یک متغیر برای تابع normalize ارسال کنید. نتیجه به صورت زیر خواهد شد. همانطور که ملاحظه می کنید، به خوبی کلمه “یه” به “یک” تبدیل شد:

نرمال سازی متن غیر رسمی با کتابخانه هضم

تبدیل متن به جملات (Sentence Tokenization) با هضم

برای بسیاری از پردازش‌ها نیاز به این وجود دارد که متن بر اساس کلمات یا جملات شکسته شود. دو کلاس  WordTokenizer و SentenceTokenizer این نیازمندی را برطرف می‌کنند. تقسیم‌کننده به کلمه (WordTokenizer) شامل موارد زیر است:

  • تقسیم‌کننده به کلمه (WordTokenizer)
    • ایموجی‌ها
      • به طور پیش‌فرض، به همان صورت خام تقسیم می‌شود.
      • با separate_emoji=True هر یک از ایموجی‌ها یک توکن در نظر گرفته می‌شود.
    • لینک‌ها
      • به طور پیش‌فرض، به همان صورت خام تقسیم می‌شود.
      • اگر replace_links=True، آدرس url را با رشته LINK جایگزین می‌کند.
    • ایمیل‌ها
      • به طور پیش‌فرض، به همان صورت خام تقسیم می‌شود.
      • اگر replace_emails=True، آدرس را با رشته EMAIL جایگزین می‌کند.
    • شناسه‌ها
      • به طور پیش‌فرض، به همان صورت خام تقسیم می‌شود.
      • اگر replace_IDs=True، آدرس را با رشته ID جایگزین می‌کند.
    • اعداد
      • به طور پیش‌فرض، به همان صورت خام تقسیم می‌شود.
      • اگر replace_numbers=True، آدرس را با رشته NUMF (برای اعداد اعشاری) یا NUMX (برای اعداد صحیح) که X تعداد ارقام عدد است، جایگزین می‌کند.
    • هشتگ‌ها
      • به طور پیش‌فرض، به همان صورت خام تقسیم می‌شود.
      • اگر replace_hashtags=True، آدرس را با رشته TAG جایگزین می‌کند.
    • متصل کردن اجزای مختلف فعل (join_verb_parts)
      • به طور پیش‌فرض انجام می‌شود.
      • مثلاً «رفته است» به‌عنوان یک توکن («رفته_است») در نظر گرفته می‌شود. این اتصال بر اساس اجزای متصل به بن فعل صورت می‌گیرد و برای تمامی افعال صادق نیست‌.
    • تقسیم‌کننده به جمله (SentenceTokenizer)
      • یافتن جملات بر اساس نقطه، علامت سؤال، علامت تعجب و سپس حذف کاراکترهای newline

پس برای تبدیل یک متن دلخواه به جمله از کلاس SentenceTokenizer و تبدیل متن به یکسری کلمه از کلاس WordTokenizer و تابع tokenize آن استفاده می‌کنیم:

تقسیم متن به کلمه در کتابخانه هضم

تبدیل متن به کلمات (Word Tokenization)

در کتابخانه Hazm این امکان فراهم شده است که به کمک کلاس TokenSplitter، ساده یا مرکب بودن کلمات را بررسی نمود و در صورت مرکب بودن آن را به کلمات ساده تشکیل‌دهنده آن شکست.
متد split_token_words ابتدا کلمات را بر اساس نیم‌فاصله (در صورت وجود) می‌شکند و لیستی از کاندیدها را (برای استخراج کلمات ساده از کلمه اصلی) به وجود می‌آورد. سپس تمامی زیررشته‌های ناهمپوشان (با حداقل طول 1 و حداکثر طول length(word) – 1) را بن‌یابی کرده و با حذف حالت‌های تکراری، حالاتی را که در دادگان کلمات ابزار Hazm وجود دارند به‌عنوان کاندیدها خروجی می‌دهد.

مثلاً در «شهر موشها» لیست splitها به‌صورت زیر است و در نهایت split سوم، تنها کاندید برای مرکب بودن کلمه اصلی است:

  1. (‘ش’, ‘هرموشها’)
  2. (‘شه’, ‘رموشها’)
  3. (‘شهر’, ‘موشها’)
  4. (‘شهرم’, ‘وشها’)
  5. (‘شهرمو’, ‘شها’)
  6. (‘شهرموش’, ‘ها’)
  7. (‘شهرموشه’, ‘ا’)
  8. (‘شهرموشها’,)

تجزیه به کلمات با کتابخانه هضم

ریشه‌یابی (بُن‌واژه‌یاب) متن فارسی

ریشه‌یابی معنایی، فرایند گروه‌بندی شکل‌های عطف یک کلمه است تا بتوان آن‌ها را به‌عنوان یک مورد تجزیه‌وتحلیل کرد که با ریشه معنایی یا فرم فرهنگ لغت کلمه شناسایی می‌شود. به عبارت ساده‌تر، فرایند پیداکردن ریشه یک کلمه، ریشه‌یابی است، مثلاً ریشه کلمه “درخت‌ها” کلمه “درخت” یا ریشه فعل “می‌خورد”، “خورد – خور” است.
کلاس Lemmatizer در ابزار Hazm وظیفه ریشه‌یاب معنایی کلمات را بر عهده دارد. در زمان نمونه‌سازی این کلاس ابتدا دادگان مربوط به اسم‌ها و افعال (که در ابزار Hazm موجودند) بارگذاری شده و فرایند صرف افعال (که در متد conjugations انجام می‌شود) صورت می‌گیرد.
در متد lemmatize بر اساس کلمه و نقش (Part of Speech) داده شده (که یک پارامتر اختیاری است) کلمه، ریشه‌یابی معنایی می‌شود:

ریشه یابی یا بن یابی با کتابخانه hazm

نقش ریشه یاب (Stemmer) در تحلیل متن و پردازش زبان طبیعی

ریشه‌یابی عمدتاً با هدف حذف وندهای متصل به اسم مورداستفاده قرار می‌گیرد.
اگر پایان یک توکن به یکی از «ات»، «ان»، «ترین»، «تر»، «م»، «ت»، «ش»، «یی»، «ی»، «ها»، «’ٔ»(همزه)، «ا» و «”» ختم شود، ریشه‌یاب آن‌ها را حذف می‌کند. پس از ریشه‌یابی اگر «ۀ» در پایان کلمه وجود داشته باشد، با «ه» جایگزین می‌شود. پس پیاده‌سازی ریشه‌یاب خیلی دشوار نیست و صرفاً یکسری قوانین به‌صورت الگوریتم‌وار باید روی عبارات اعمال شود.

لازم به یادآوری است که معمولاً سرعت Stemmer بالاتر ولی کیفیت ریشه‌یابی آن از Lemmatizer پایین‌تر است. همچنین ابزار هضم مثل ابزار پارسی‌ور معمولاً توانایی مناسبی در ریشه‌یابی کلمات ندارد، خصوصاً وقتی متن غیررسمی داشته باشیم:

ریشه یابی کلمه با کتابخانه هضم

نقش برچسب گذار (POS tagger) در پردازش متن

برچسب‌گذاری نقش کلمات، فرایند برچسب‌گذاری یک واژه در یک متن است که آن برچسب، متناظر با نقش یا پاره‌گفتار (Part of speech) خاص آن واژه است. برای مثال شناسایی واژه‌ها به‌عنوان «اسم»، «فعل»، «صفت»، «قید» و … نوعی برچسب‌گذاری پاره‌های گفتار است. بااین‌حال برچسب‌گذاری واژه‌ها در یک متن می‌تواند مبنایی به جز پاره‌های گفتار داشته باشد.
نوع دیگری از برچسب‌گذاری واژه‌ها باهدف «شناسایی موجودیت‌های نامدار (Named Entity Recognition)» انجام می‌شود که به برچسب‌گذاری IOB معروف است. در این نوع برچسب‌گذاری واژه اول موجودیت با B(Begin)، واژه‌های بعدی (در صورت وجود) با I(Inside)، و دیگر واژه‌ها با O(Outside) برچسب زده می‌شوند.
در ابزار Hazm، کلاس‌های POSTagger و IOBTagger به ترتیب برای برچسب‌گذاری نقش و موجودیت‌های نامدار استفاده می‌شوند. هر دو کلاس، از کلاس SequenceTagger که خود رابط TaggerI ابزار NLTK را پیاده‌سازی می‌نماید، ارث‌بری می‌کنند.
از متدهای tag و tag_sents می‌توان به ترتیب برای برچسب‌گذاری واژه‌های یک یا چند جمله استفاده کرد. به‌طورکلی برچسب‌گذارها نیاز به مدل‌های از پیش آماده شده دارند تا بر اساس آن بتوانند فرایند برچسب‌گذاری را انجام دهند؛ بنابراین در هنگام نمونه‌سازی از کلاس‌ها باید این مدل‌ها را به‌عنوان پارامتر در اختیار سازنده قرارداد.

برای استفاده از برچسب‌گذار نقش کلمات ابتدا باید با استفاده از دستور زیر، پیش‌نیازهای لازم را به کمک دستور wget دانلود کرد (این پیش‌نیازها شامل مدل برچسب‌گذاری نقش کلمات، مدل زبانی و مدل قطعه بند است):

دانلود پیش نیازها با wget

در ادامه به کمک دستور mkdir دایرکتوری معینی را ساخته، محتوای استخراج‌شده به کمک دستور unzip را در این دایرکتوری قرار می‌دهیم:

ساخت دایرکتوری با mkdir  

همان‌طور که مشاهده می‌کنید عملکرد هضم در زمینه pos و تشخیص نقش دستوری کلمات متون رسمی مناسب و قابل‌قبول است:

برچسب‌گذاری نقش کلمات در کتابخانه هضم

همچنین در ابزار Hazm امکان استفاده از برچسب‌گذار آزمایشگاه NLP دانشگاه استنفورد فراهم گردیده که با در اختیار قراردادن مدل‌های از پیش آماده می‌توان از این برچسب‌گذاری استفاده کرد. کلاس StanforfPOSTagger از کلاس StanfordTagger که در ماژول Stanford ابزار NLTK تعبیه شده ارث‌بری می‌کند.

اگر می‌خواهید کار بر روی پروژه‌های واقعی NLP را یاد بگیرید، دوره آموزش پردازش زبان طبیعی مقدماتی را از دست ندهید.

قطعه‌بندی (Chunker)

قطعه‌بندی فرایندی است که برای شناسایی نقش و عبارت‌های کوتاه موجود در یک جمله استفاده می‌شود. به‌عبارت‌دیگر می‌توان شناسایی گروه‌های زبانی ناهمپوشان (مانند عبارت‌های اسمی پایه) را هدف این فرایند قلمداد نمود. به عبارت ساده‌تر، تشخیص کلماتی که پشت‌سرهم آمده و با هم ارتباط معنایی دارند مثل “اولین متخصص هوش مصنوعی ایران” که شاهد یک عبارت اسمی هستیم.
در کتابخانه Hazm کلاس Chunker برای این هدف استفاده می‌شود. این کلاس رابط ChunkParserI را پیاده‌سازی می‌نماید و از کلاس IOBTagger  ارث‌بری می‌کند. از متدهای parse و parse_sents می‌توان به ترتیب برای بخش‌سازی یک یا چند جمله استفاده کرد.
مشابه برچسب‌گذارها، قطعه‌بندها نیز نیاز به مدل‌های از پیش آماده شده دارند تا براساس آن بتوانند فرایند قطعه‌بندی را انجام دهند. همچنین قطعه‌بندها برای انجام ‌وظیفه‌شان نیاز به برچسب نقش کلمات دارند.

همچنین در ابزار Hazm امکان استفاده از قطعه‌بندی مبتنی بر قاعده (Rule-based) نیز فراهم گردیده است. کلاس RuleBasedChunker از کلاس RegexpParser که در ماژول chunk ابزار NLTK تعبیه شده ارث‌بری می‌کند:

قطعه‌بندی و شناسایی عبارات در کتابخانه hazm

تجزیه‌گر وابستگی (Dependency Parser)

تجزیه وابستگی، فرایند تحلیل ساختار نحوی در یک جمله و یافتن کلمات مرتبط و نوع رابطه بین آن‌هاست.
در ابزار Hazm کلاس DependencyParser وظیفه تجزیه ‌و تحلیل نحوی و رسم گراف وابستگی را بر عهده دارد. کلاس DependencyParser از کلاس MaltParser ارث‌بری می‌نماید. این کلاس خود از کلاس MaltParser ماژول NLTK (که رابط ParserI را پیاده‌سازی می‌کند) ارث‌بری می‌نماید.
به کمک متد parse می‌توان فرایند تجزیه نحوی را بر روی یک جمله اجرا نمود. همچنین این فرایند برای انجام، نیاز به برچسب نقش کلمات بن‌یابی دارد. ازاین‌رو کلاس‌های POSTagger و Lemmatizer نیز در سازنده آن استفاده می‌شوند:

تجزیه وابستگی و تحلیل ساختار متن با کتابخانه هضم

خروجی به‌صورت زیر خواهد بود:

خروجی و نتیجه تجزیه وابستگی و تحلیل ساختار متن با کتابخانه hazm

نکته: برای گرفتن خروجی به‌صورت فوق، نیاز به نصب ماژول graphviz دارید. این ماژول در سیستم‌های مبتنی بر یونیکس با دستور زیر قابل نصب است:

نصب ماژول graphviz

دانلود و نصب graphviz روی ویندوز بسیار ساده است.

همچنین در کتابخانه Hazm امکان استفاده از TurboParser که یک تجزیه‌گر مبتنی بر برنامه‌ریزی خطی (Linear Programming) چندزبانه است نیز فراهم گردیده است. کلاس TurboParser رابط ParserI موجود در ابزار NLTK را پیاده‌سازی می‌کند.

بارگذاری دادگان

به ‌منظور سهولت در استفاده از دادگان شناخته‌شده و پرکاربرد در زبان فارسی، کلاس‌هایی برای خواندن و بارگذاری آن‌ها در نظر گرفته شده است:

مطالب بیشتر

2 دیدگاه

به گفتگوی ما بپیوندید و دیدگاه خود را با ما در میان بگذارید.

دیدگاهتان را بنویسید