شناسایی موجودیت نام دار با NLTK و SpaCy — راهنمای کاربردی

۵۶۳ بازدید
آخرین به‌روزرسانی: ۲۴ اردیبهشت ۱۴۰۲
زمان مطالعه: ۵ دقیقه
شناسایی موجودیت نام دار  با NLTK و SpaCy — راهنمای کاربردی

«شناسایی موجودیت نام‌ دار» (Named entity recognition | NER) یکی از اولین گام‌ها در فرآیند استخراج اطلاعات است که منجر به شناسایی و دسته‌بندی موجودیت‌های دارای نام در متن، به دسته‌های از پیش تعریف شده مانند اسامی افراد، سازمان‌ها، مکان‌ها، بیان زمان‌ها، مقادیر، ارزش‌های پولی، درصدها و دیگر موارد می‌شود. NER در زمینه‌های گوناگون «پردازش زبان طبیعی» (Natural Language Processing | NLP) کاربرد دارد و می‌تواند در پاسخگویی به بسیاری از پرسش‌های جهان واقعی مانند مواردی که در زیر بیان شده کمک کند.

  • کدام سازمان‌ها در مقالات خبری مورد اشاره قرار گرفته‌اند؟
  • از چه محصولاتی در نقد و بررسی‌ها نام برده شده است؟
  • آیا اسامی افراد در توییت‌ها آورده شده؟ آیا توییت در برگیرنده موقعیت جغرافیایی فرد است؟

در این مقاله چگونگی ساخت شناساگر موجودیت‌های نام‌دار با «NLTK» (سرنامی برای عبارت Natural Language Toolkit) و «SpaCy» به منظور شناسایی اسامی نهادهایی که دارای نام هستند، مانند افراد، سازمان‌ها یا موقعیت‌ها در متن خام شرح داده شده است. اما پیش از آغاز کار دو ابزار بیان شده معرفی می‌شوند.

NLTK

«NLTK» سرنامی برای عبارت Natural Language Toolkit است. این عنوان برای اشاره به مجموعه‌ای از کتابخانه‌ها و برنامه‌های نوشته شده برای پردازش زبان طبیعی سمبلیک و آماری برای زبان انگلیسی به کار برده می‌شود که به «زبان برنامه‌نویسی پایتون» (Python Programming Language) نوشته شده‌اند.

این ابزار توسط «استیون بِرد» (Steven Bird) و «ادوارد لوپر» (Edward Loper) در دپارتمان علوم کامپیوتر و اطلاعات «دانشگاه پنسیلوانیا» (University of Pennsylvania) ساخته و توسعه داده شده است. NLTK شامل ارائه‌های گرافیکی و داده‌های نمونه (sample data) می‌شود. این جعبه ابزار با کتابی که مفاهیم نهفته در پس وظایف پردازش زبان طبیعی پشتیبانی شده توسط این ابزار را تشریح می‌کند و یک کتاب راهنما همراه است.

SpaCy

«SpaCy» یک کتابخانه نرم‌افزاری «متن‌باز» (open source) برای پردازش زبان طبیعی پیشرفته محسوب می‌شود که به زبان‌های برنامه‌نویسی «پایتون» (Python) و «سایتون» (Cython) نوشته شده است. این کتابخانه تحت گواهینامه MIT منتشر شده و در حال حاضر دارای مدل‌های شبکه عصبی آماری برای زبان‌های انگلیسی، آلمانی، اسپانیایی، پرتغالی، فرانسوی، ایتالیایی، هلندی و شناسایی موجودیت‌های نام‌دار چند زبان و توکن‌سازی بسیاری از زبان‌های دیگر است.

برخلاف NLTK که به طور گسترده برای آموزش و پژوهش مورد استفاده قرار می‌گیرد، spaCy بر فراهم کردن نرم‌افزارهایی برای استفاده‌های تولیدی تاکید دارد. نسخه ۱.۰ spaCy از جریان‌های کاری «یادگیری عمیق» نیز پشتیبانی می‌کند که امکان اتصال مدل‌های آموزش دیده شده با کتابخانه‌های یادگیری ماشینی مانند «تنسورفلو» (TensorFlow)، «کِراس» (Keras)، «سایکیت لِرن» (Scikit-learn) یا «پای تُرچ» (PyTorch) را فراهم می‌کند. کتابخانه یادگیری ماشین spaCy با نام «Thinc» به عنوان یک کتابخانه پایتون مجزا نیز موجود است.

ایمپورت کردن کتابخانه‌ها

برای ایمپورت کردن کتابخانه NLTK از قطعه کد زیر استفاده می‌شود:

1import nltk
2from nltk.tokenize import word_tokenize
3from nltk.tag import pos_tag

استخراج اطلاعات

در ادامه، از جمله زیر که از نیویورک تایمز برداشته شده برای شرح مبحث استفاده می‌شود.

European authorities fined Google a record $5.1 billion on Wednesday for abusing its power in the mobile phone market .and ordered the company to alter its practices.

1ex = 'European authorities fined Google a record $5.1 billion on Wednesday for abusing its power in the mobile phone market and ordered the company to alter its practices'

اکنون، «توکن‌سازی کلمات» (word tokenization) و تگ کردن «اقسام کلمه» «part of speech» صورت می‌پذیرد.

1def preprocess(sent):
2    sent = nltk.word_tokenize(sent)
3    sent = nltk.pos_tag(sent)
4    return sent

سپس، خروجی قطعه کد بالا مورد بررسی قرار می‌گیرد.

1sent = preprocess(ex)
2sent

Word Tokenization

یک لیست از تاپل‌های حاوی کلمات مجزا در جملات و قسم کلمه آن‌ها دریافت می‌شود. اکنون، بخش‌بندی «گروه اسمی» (noun phrase) به منظور شناسایی موجودیت‌های نام‌دار با استفاده از عبارت باقاعده حاوی قواعدی که نشان می‌دهد جمله چگونه باید بخش‌بندی شود پیاده‌سازی می‌شود.

1pattern = 'NP: {<DT>?<JJ>*<NN>}'

بخش‌بندی برای شناسایی موجودیت نام‌دار

با استفاده از این الگو، یک تجزیه‌کننده بخش ساخته و روی جمله تست می‌شود.

1cp = nltk.RegexpParser(pattern)
2cs = cp.parse(sent)
3print(cs)

Chunk Parser

خروجی به صورت یک درخت یا سلسله مراتب با S در سطح اول و ادامه جمله قابل خواندن است.

chunk parser

تگ‌های IOB راه استاندارد برای ارائه ساختار بخش‌ها داخل فایل‌ها هستند و به فرمت زیر نیز قابل استفاده محسوب می‌شوند.

1from nltk.chunk import conlltags2tree, tree2conlltags
2from pprint import pprint
3iob_tagged = tree2conlltags(cs)
4pprint(iob_tagged)

در این ارائه، یک توکن در هر خط با تگ قسم کلمه و تگ موجودیت نام‌دار خود وجود دارد. برپایه این واحد آموزش، می‌توان یک تگ‌کننده ساخت که برای برچسب‌گذاری جملات جدید مورد استفاده قرار بگیرد و از تابع ()nltk.chunk.conlltags2tree برای تبدیل توالی تگ‌ها در یک درخت بخش استفاده شود. تابع ()nltk.ne_chunk می‌تواند موجودیت‌های نام‌دار را با استفاده از یک دسته‌بند شناسایی و دسته‌بندی برچسب‌های دسته‌ها مانند ORGANIZATION ،PERSON و GPE را اضافه کند.

1ne_tree = ne_chunk(pos_tag(word_tokenize(ex)))
2print(ne_tree)

named entities recognition

«گوگل» (google) به عنوان یک شخص شناسایی شده و این واقعا ناامید کننده است.

استفاده از SpaCy

شناساگر موجودیت نام‌دار SpaCy بر فراز  «OntoNotes (+) آموزش داده شده و نوع موجودیت‌های ارائه شده در زیر را پشتیبانی می‌کند.

SpaCy’s named entity recognition

موجودیت

1import spacy
2from spacy import displacy
3from collections import Counter
4import en_core_web_sm
5nlp = en_core_web_sm.load()

در اینجا نیز از همان جمله «European authorities fined Google a record $5.1 billion on Wednesday for abusing its power in the mobile phone market and ordered the company to alter its practices» استفاده می‌شود. به عنوان یکی از نقاط قوت Spacy می‌توان به این نکته اشاره کرد که یک بار اعمال NLP کافی است.

1doc = nlp('European authorities fined Google a record $5.1 billion on Wednesday for abusing its power in the mobile phone market and ordered the company to alter its practices')
2pprint([(X.text, X.label_) for X in doc.ents])

SpaCy’s named entity recognition

«European» یک NORP (ملت یا مذهب یا گروه سیاسی)، «Google» یک «سازمان»، «$5.1 billion» یک «مقدار پول» و «Wednesday» یک شی «تاریخ» است.

توکن

در طول مثال بالا، کار در سطح موجودیت انجام شده است.

در مثال پیش رو، تفسیر در سطح توکن برای موجودیت‌ها با استفاده از شمای تگ‌گذاری BILUO به منظور توصیف مرزهای موجودیت انجام می‌شود.

 BILUO tagging scheme

1pprint([(X, X.ent_iob_, X.ent_type_) for X in doc])

 BILUO tagging scheme

«B» بدین معنا است که توکن یک موجودیت را شروع کرده، «I» یعنی توکن درون یک موجودیت است، «O» یعنی توکن خارج از موجودیت محسوب می‌شود و "" یعنی هیچ تگ موجودیتی تنظیم نشده است.

استخراج موجودیت نام‌دار از یک مقاله

اکنون در مساله‌ای جدی‌تر و شبیه‌تر به مسائل جهان واقعی، موجودیت‌های نام‌دار یکی از مقالات جدید نیویورک تایمز با عنوان «F.B.I. Agent Peter Strzok, Who Criticized Trump in Texts, Is Fired» (+) استخراج می‌شوند.

1from bs4 import BeautifulSoup
2import requests
3import re
4def url_to_string(url):
5    res = requests.get(url)
6    html = res.text
7    soup = BeautifulSoup(html, 'html5lib')
8    for script in soup(["script", "style", 'aside']):
9        script.extract()
10    return " ".join(re.split(r'[\n\t]+', soup.get_text()))
11ny_bb = url_to_string('https://www.nytimes.com/2018/08/13/us/politics/peter-strzok-fired-fbi.html?hp&action=click&pgtype=Homepage&clickSource=story-heading&module=first-column-region®ion=top-news&WT.nav=top-news')
12article = nlp(ny_bb)
13len(article.ents)

188 موجودیت در مقاله وجود دارد و این موجودیت‌ها با ۱۰ برچسب یکتا نمایش داده شده‌اند.

1labels = [x.label_ for x in article.ents]
2Counter(labels)

Named Entity Recognition

در ادامه سه تا از مکررترین موجودیت‌ها مشخص شده‌اند.

1items = [x.text for x in article.ents]
2Counter(items).most_common(3)

Named-Entity-Recognition11

اکنون یک جمله به صورت تصادفی انتخاب می‌شود تا مساله شفاف‌تر باشد.

1sentences = [x for x in article.sents]
2print(sentences[20])

named entity recognition

در این وهله به منظور تولید نشانه‌گذاری خام، «displacy.render» باید اجرا شود.

1displacy.render(nlp(str(sentences[20])), jupyter=True, style='ent')

named entity recognition

یکی از مواردی که به اشتباه دسته‌بندی شده FBI است. با استفاده از «displaCy visualizer» (+) توکار spaCy، جمله بالا و وابستگی‌های آن نمایش داده می‌شوند.

1displacy.render(nlp(str(sentences[20])), style='dep', jupyter = True, options = {'distance': 120})

Named Entity Recognition

اکنون، به صورت کلمه به کلمه (verbatim)، قسم کلمه استخراج و این جمله مرتب‌سازی می‌شود.

1[(x.orth_,x.pos_, x.lemma_) for x in [y 
2                                      for y
3                                      in nlp(str(sentences[20])) 
4                                      if not y.is_stop and y.pos_ != 'PUNCT']]

1dict([(str(x), x.label_) for x in nlp(str(sentences[20])).ents])

Named Entity Recognition

استخراج موجودیت‌های نام‌دار به جز «F.B.I»، برای کلیه موارد صحیح است.

1print([(x, x.ent_iob_, x.ent_type_) for x in sentences[20]])

Named Entity Recognition

در نهایت، موجودیت کل مقاله تعیین می‌شود.

Named Entity Recognition

کد کامل این مطلب در گیت‌هاب (+) موجود است.

اگر مطلب بالا برای شما مفید بوده، آموزش‌های زیر نیز به شما پیشنهاد می‌شود:

^^

بر اساس رای ۰ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
towardsdatascience
۲ دیدگاه برای «شناسایی موجودیت نام دار با NLTK و SpaCy — راهنمای کاربردی»

سلام
اگر بخواهیم به جای ex از یک دیتاست که در گوگل درایو داریم استفاده کنیم، چطوری باید این دیتاست را به sent بدهیم؟؟؟

با سلام؛

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

نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *