۲۹ شهریور ۱۴۰۳

Techboy

اخبار و اطلاعات روز تکنولوژی

پردازش زبان طبیعی با آپاچی OpenNLP

با استفاده از ابزار رایگان و منبع باز Apache OpenNLP و مدل های از پیش ساخته شده برای تشخیص زبان، تشخیص جملات، برچسب گذاری قسمت های گفتار و موارد دیگر، مقدمه ای سریع و آسان برای پردازش زبان طبیعی دریافت کنید.

با استفاده از ابزار رایگان و منبع باز Apache OpenNLP و مدل های از پیش ساخته شده برای تشخیص زبان، تشخیص جملات، برچسب گذاری قسمت های گفتار و موارد دیگر، مقدمه ای سریع و آسان برای پردازش زبان طبیعی دریافت کنید.

پردازش زبان طبیعی (NLP) یکی از مهمترین مرزهای نرم افزار است. ایده اصلی – چگونگی مصرف و تولید زبان انسانی به طور مؤثر – از آغاز محاسبات دیجیتالی یک تلاش مداوم بوده است. تلاش امروز با یادگیری ماشینی و پایگاه های اطلاعاتی نمودار در خط مقدم تلاش برای تسلط بر زبان طبیعی ادامه دارد.

این مقاله یک معرفی عملی برای Apache OpenNLP است، یک پروژه یادگیری ماشینی مبتنی بر جاوا که ارائه می‌کند موارد اولیه مانند chunking و lemmatization، هر دو برای ساختن سیستم‌های دارای NLP مورد نیاز است.

Apache OpenNLP چیست؟

یک سیستم پردازش زبان طبیعی یادگیری ماشینی مانند Apache OpenNLP معمولاً دارای سه بخش است:

  1. یادگیری از یک پیشه، که مجموعه ای از داده های متنی است (جمع: corpora)
  2. مدلی که از پیکره تولید می شود
  3. استفاده از مدل برای انجام وظایف روی متن مقصد

برای ساده‌تر کردن کارها، OpenNLP مدل‌های از پیش آموزش‌دیده‌ای را برای بسیاری از موارد استفاده رایج در دسترس دارد. برای نیازهای پیچیده تر، ممکن است لازم باشد مدل های خود را آموزش دهید. برای یک سناریوی ساده‌تر، می‌توانید یک مدل موجود را دانلود کرده و آن را برای کار در دست اعمال کنید.

تشخیص زبان با OpenNLP

بیایید یک برنامه اساسی ایجاد کنیم که بتوانیم از آن برای مشاهده نحوه عملکرد OpenNLP استفاده کنیم. همانطور که در فهرست ۱ نشان داده شده است، می‌توانیم طرح‌بندی را با کهن الگوی Maven شروع کنیم.


~/apache-maven-3.8.6/bin/mvn archetype:generate -DgroupId=com.infoworld.com -DartifactId=opennlp -DarchetypeArtifactId=maven-arhectype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false

این کهن الگو یک پروژه جاوا جدید را داربست می کند. سپس، همانطور که در فهرست ۲ نشان داده شده است، وابستگی Apache OpenNLP را به pom.xml در فهرست اصلی پروژه اضافه کنید. (می توانید از هر نسخه ای از وابستگی OpenNLP که جدیدترین.)


<dependency>
  <groupId>org.apache.opennlp</groupId>
  <artifactId>opennlp-tools</artifactId>
  <version>2.0.0</version>
</dependency>

برای سهولت در اجرای برنامه، ورودی زیر را نیز به بخش فایل pom.xml اضافه کنید:


<plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>3.0.0</version>
            <configuration>
                <mainClass>com.infoworld.App</mainClass>
            </configuration>
        </plugin>

اکنون، برنامه را با maven compile exec:java اجرا کنید. (برای اجرای این دستور به Maven و یک JDK نصب شده نیاز دارید.) با اجرای آن اکنون فقط «Hello World!» آشنا را به شما می دهد. خروجی.

یک مدل تشخیص زبان را دانلود و تنظیم کنید

اکنون ما آماده استفاده از OpenNLP برای شناسایی زبان در برنامه مثال خود هستیم. اولین قدم دانلود یک مدل تشخیص زبان است. جدیدترین مؤلفه ردیاب زبان را از صفحه دانلود مدل‌های OpenNLP دانلود کنید. از زمان نوشتن این مقاله، نسخه فعلی langdetect-183.bin.

برای سهولت دسترسی به مدل، اجازه دهید وارد پروژه Maven و mkdir یک دایرکتوری جدید در /opennlp/src/main/resource شده، سپس کد را کپی کنید. فایل langdetect-*.bin در آنجا وجود دارد.

اکنون، اجازه دهید یک فایل موجود را به آنچه در فهرست ۴ می‌بینید تغییر دهیم. برای این مثال از /opennlp/src/main/java/com/infoworld/App.java استفاده می‌کنیم.< /p>


package com.infoworld;

import java.util.Arrays;
import java.io.IOException;
import java.io.InputStream;
import java.io.FileInputStream;
import opennlp.tools.langdetect.LanguageDetectorModel;
import opennlp.tools.langdetect.LanguageDetector;
import opennlp.tools.langdetect.LanguageDetectorME;
import opennlp.tools.langdetect.Language;

public class App {
  public static void main( String[] args ) {
    System.out.println( "Hello World!" );
    App app = new App();
    try {
      app.nlp();
    } catch (IOException ioe){
      System.err.println("Problem: " + ioe);
    }
  }
  public void nlp() throws IOException {
    InputStream is = this.getClass().getClassLoader().getResourceAsStream("langdetect-183.bin"); // 1
    LanguageDetectorModel langModel = new LanguageDetectorModel(is); // 2
    String input = "This is a test.  This is only a test.  Do not pass go.  Do not collect $200.  When in the course of human history."; // 3
    LanguageDetector langDetect = new LanguageDetectorME(langModel); // 4
    Language langGuess = langDetect.predictLanguage(input); // 5

    System.out.println("Language best guess: " + langGuess.getLang());

    Language[] languages = langDetect.predictLanguages(input);
    System.out.println("Languages: " + Arrays.toString(languages));
  }
}

اکنون می توانید این برنامه را با دستور maven compile exec:java اجرا کنید. وقتی این کار را انجام دادید، خروجی مشابه آنچه در فهرست ۵ نشان داده شده است، دریافت خواهید کرد.


Language best guess: eng
Languages: [eng (0.09568318011427969), tgl (0.027236092538322446), cym (0.02607472496029117), war (0.023722424236917564)...

“ME” در این نمونه مخفف حداکثر آنتروپی است. حداکثر آنتروپی مفهومی از آمار است که در پردازش زبان طبیعی برای بهینه‌سازی برای بهترین نتایج استفاده می‌شود.< /p>

نتایج را ارزیابی کنید

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

قبل از اینکه ادامه دهیم، به فهرست ۴ نگاه کنید. جریان بسیار ساده است. هر خط نظر داده شده به این صورت عمل می کند:

  1. فایل langdetect-183.bin را به عنوان جریان ورودی باز کنید.
  2. از جریان ورودی برای پارامترسازی نمونه LanguageDetectorModel استفاده کنید.
  3. یک رشته برای استفاده به عنوان ورودی ایجاد کنید.
  4. با استفاده از LanguageDetectorModel از خط ۲، یک شی آشکارساز زبان بسازید.
  5. روش langDetect.predictLanguage() را روی ورودی خط ۳ اجرا کنید.

آزمایش احتمال

اگر متن انگلیسی بیشتری به رشته اضافه کنیم و دوباره آن را اجرا کنیم، احتمال تخصیص داده شده به eng باید بالا برود. بیایید با چسباندن محتوای اعلامیه استقلال ایالات متحده آن را امتحان کنیم. فایل جدید در فهرست پروژه ما: /src/main/resources/declaration.txt. ما آن را بارگیری می کنیم و همانطور که در لیست ۶ نشان داده شده است پردازش می کنیم و رشته درون خطی را جایگزین می کنیم:


String input = new String(this.getClass().getClassLoader().getResourceAsStream("declaration.txt").readAllBytes());

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

تشخیص جملات با OpenNLP

شما مدل تشخیص زبان را در محل کار مشاهده کرده اید. حالا بیایید مدلی را برای تشخیص جملات امتحان کنیم. برای شروع، به صفحه دانلود مدل OpenNLP برگردید و آخرین مولفه مدل Sentence English را به خود اضافه کنید دایرکتوری /resource پروژه. توجه داشته باشید که دانستن زبان متن یک پیش نیاز برای تشخیص جملات است.

ما از الگوی مشابهی پیروی می‌کنیم که با مدل تشخیص زبان انجام دادیم: فایل را بارگیری کنید (در مورد من opennlp-en-ud-ewt-sentence-1.0-1.9.3.bin) و از آن برای نمونه سازی یک ردیاب جمله استفاده کنید. سپس، از آشکارساز در فایل ورودی استفاده می کنیم. کد جدید را می توانید در لیست ۷ (به همراه واردات آن) مشاهده کنید. بقیه کد ثابت می ماند.


import opennlp.tools.sentdetect.SentenceModel;
import opennlp.tools.sentdetect.SentenceDetectorME;
//...
InputStream modelFile = this.getClass().getClassLoader().getResourceAsStream("opennlp-en-ud-ewt-sentence-1.0-1.9.3.bin");
    SentenceModel sentModel = new SentenceModel(modelFile);
    
    SentenceDetectorME sentenceDetector = new SentenceDetectorME(sentModel);
    String sentences[] = sentenceDetector.sentDetect(input);
    System.out.println("Sentences: " + sentences.length + " first line: "+ sentences[2])

با اجرای فایل اکنون چیزی شبیه آنچه در فهرست ۸ نشان داده شده است.


Sentences: 41 first line: In Congress, July 4, 1776

The unanimous Declaration of the thirteen united States of America, When in the Course of human events, ...

توجه کنید که ردیاب جملات ۴۱ جمله را پیدا کرد که تقریباً درست به نظر می‌رسد. همچنین توجه داشته باشید که این مدل آشکارساز نسبتاً ساده است: فقط به دنبال نقطه ها و فاصله ها می گردد تا وقفه ها را پیدا کند. منطقی برای گرامر ندارد. به همین دلیل است که ما از شاخص ۲ در آرایه جملات برای بدست آوردن مقدمه واقعی استفاده کردیم – خطوط سرصفحه به صورت دو جمله در کنار هم قرار گرفتند. (اسناد مؤسس به طور مشهور با علائم نگارشی ناسازگار است و ردیاب جمله هیچ تلاشی برای در نظر گرفتن “وقتی در دوره …” به عنوان یک جمله جدید انجام نمی دهد.)

توکن سازی با OpenNLP

بعد از شکستن اسناد به جملات، توکن کردن سطح بعدی از جزئیات است. Tokenizing فرآیند تجزیه سند به ترتیب به کلمات و علائم نگارشی است. ما می توانیم از کد نشان داده شده در لیست ۹ استفاده کنیم:


import opennlp.tools.tokenize.SimpleTokenizer;
//...
SimpleTokenizer tokenizer = SimpleTokenizer.INSTANCE;
    String[] tokens = tokenizer.tokenize(input);
    System.out.println("tokens: " + tokens.length + " : " + tokens[73] + " " + tokens[74] + " " + tokens[75]);

این خروجی مانند آنچه در فهرست ۱۰ نشان داده شده است را ارائه می دهد.


tokens: 1704 : human events ,

بنابراین، مدل سند را به ۱۷۰۴ توکن تقسیم کرد. ما می‌توانیم به آرایه نشانه‌ها، کلمات “رویدادهای انسانی” و کامای زیر دسترسی داشته باشیم و هر کدام یک عنصر را اشغال می‌کنند.

یافتن نام با OpenNLP

اکنون، مدل «نام شخص یاب» را برای انگلیسی به نام en-ner-person.bin. نه اینکه این مدل در صفحه دانلودهای مدل Sourceforge قرار دارد. هنگامی که مدل را دارید، آن را در فهرست منابع پروژه خود قرار دهید و از آن برای یافتن نام در سند استفاده کنید، همانطور که در فهرست ۱۱ نشان داده شده است.


import opennlp.tools.namefind.TokenNameFinderModel;
import opennlp.tools.namefind.NameFinderME;
import opennlp.tools.namefind.TokenNameFinder;
import opennlp.tools.util.Span
//...
InputStream nameFinderFile = this.getClass().getClassLoader().getResourceAsStream("en-ner-person.bin");
    TokenNameFinderModel nameFinderModel = new TokenNameFinderModel(nameFinderFile);
    NameFinderME nameFinder = new NameFinderME(nameFinderModel);
    Span[] names = nameFinder.find(tokens);
    System.out.println("names: " + names.length);
    for (Span nameSpan : names){
      System.out.println("name: " + nameSpan + " : " + tokens[nameSpan.getStart()-1] + " " + tokens[nameSpan.getEnd()-1]);
}

در فهرست ۱۱، مدل را بارگذاری می‌کنیم و از آن برای نمونه‌سازی یک شی NameFinderME استفاده می‌کنیم، که سپس از آن برای دریافت آرایه‌ای از نام‌ها استفاده می‌کنیم که به عنوان اشیاء span مدل‌سازی شده‌اند. یک دهانه دارای یک شروع و پایان است که به ما می گوید که آشکارساز فکر می کند نام از کجا شروع می شود و در مجموعه نشانه ها به پایان می رسد. توجه داشته باشید که نام یاب آرایه‌ای از رشته‌های نشانه‌گذاری شده را انتظار دارد.

مدل های آموزشی

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

نشان‌گذاری بخش‌های گفتار با OpenNLP

OpenNLP به ما امکان می‌دهد تا قسمت‌هایی از گفتار (POS) را در برابر رشته‌های نشانه‌گذاری شده برچسب‌گذاری کنیم. فهرست ۱۲ نمونه ای از برچسب گذاری قسمت های گفتار است.


import opennlp.tools.postag.POSModel;
import opennlp.tools.postag.POSTaggerME;
//…
InputStream posIS = this.getClass().getClassLoader().getResourceAsStream("opennlp-en-ud-ewt-pos-1.0-1.9.3.bin");
POSModel posModel = new POSModel(posIS);
POSTaggerME posTagger = new POSTaggerME(posModel);
String tags[] = posTagger.tag(tokens);
System.out.println("tags: " + tags.length);

for (int i = 0; i < 15; i++){
  System.out.println(tokens[i] + " = " + tags[i]);
}

این فرآیند مشابه فایل مدل است که در یک کلاس مدل بارگذاری شده و سپس در آرایه نشانه‌ها استفاده می‌شود. چیزی شبیه لیست ۱۳ را خروجی می دهد.


tags: 1704
Declaration = NOUN
of = ADP
Independence = NOUN
: = PUNCT
A = DET
Transcription = NOUN
Print = VERB
This = DET
Page = NOUN
Note = NOUN
: = PUNCT
The = DET
following = VERB
text = NOUN
is = AUX

بر خلاف مدل یاب نام، تگر POS کار خوبی انجام داده است. چندین بخش مختلف گفتار را به درستی شناسایی کرد. مثال‌هایی در فهرست ۱۳ شامل NOUN، ADP (که مخفف adposition است) و PUNCT (برای نشانه‌گذاری) است.

نتیجه گیری

در این مقاله، نحوه اضافه کردن Apache OpenNLP به پروژه جاوا و استفاده از مدل های از پیش ساخته شده برای پردازش زبان طبیعی را مشاهده کرده اید. در برخی موارد، ممکن است لازم باشد مدل خود را توسعه دهید، اما مدل‌های از قبل موجود اغلب این کار را انجام می‌دهند. علاوه بر مدل‌هایی که در اینجا نشان داده شده‌اند، OpenNLP شامل ویژگی‌هایی مانند دسته‌بندی سند، لماتیزه‌کننده (که کلمات را تا ریشه‌های آنها تجزیه می‌کند)، chunker و تجزیه‌کننده نیز دارد. همه اینها عناصر اساسی یک سیستم پردازش زبان طبیعی هستند و به صورت رایگان با OpenNLP در دسترس هستند.