Obdelava naravnega jezika - tehnologija, ki programskim aplikacijam omogoča obdelavo človeškega jezika - je v zadnjih letih postala nekoliko povsod prisotna.
Iskanje Google lahko odgovori na vprašanja, ki se slišijo naravno. Appleova Siri je sposobna razumeti najrazličnejša vprašanja, zato številna podjetja uporabljajo (razumne) pametne klepetalnice in botske telefone za komunikacijo s strankami. Kako pa ta na videz 'pametna' programska oprema dejansko deluje?
V tem članku boste spoznali tehnologijo, ki poganja te aplikacije, in se naučili, kako sami razviti programsko opremo za obdelavo naravnega jezika.
Članek vas bo vodil skozi primer postopka izdelave analizatorja, vrednega novic. Predstavljajte si, da imate portfelj vrednostnih papirjev in bi želeli aplikacijo, ki samodejno preide na priljubljena spletna mesta z novicami in opredeli članke, ki ustrezajo vašemu portfelju. Če na primer vaš delniški portfelj vključuje podjetja, kot so Microsoft, BlackStone in Luxottica, morate biti seznanjeni s članki, ki omenjajo ta tri podjetja.
Aplikacije za obdelavo naravnega jezika, tako kot katera koli druga aplikacija za strojno učenje, temeljijo na sorazmerno majhnih, preprostih in intuitivnih algoritmih, ki delujejo skupaj. Pogosto je bolj smiselno uporabiti zunanjo knjižnico, kjer so vsi ti algoritmi že implementirani in integrirani.
Za naš primer bomo uporabili Knjižnica Stanford NLP , zmogljiva knjižnica za obdelavo naravnih jezikov, ki temelji na Javi, ima podporo za številne jezike.
Poseben algoritem, ki nas zanima v tej knjižnici, je označevanje slovnice. Slovnično označevanje se uporablja za samodejno dodeljevanje delov govora vsaki besedi v delu besedila. To slovnično označevanje razvršča besede v besedilu na podlagi leksikalnih značilnosti, hkrati pa jih analizira glede na druge besede okoli njih.
Natančna mehanika algoritma označevanja slovnice ne presega tega članka, vendar lahko o tem izveste. tukaj .
Za začetek bomo ustvarili nov projekt Java (lahko uporabite svoje interaktivno razvojno okolje TUKAJ ) in na seznam odvisnosti dodajte knjižnico Stanford NLP. Če uporabljate Maven, ga preprosto dodajte med svoje pom.xml
:
edu.stanford.nlp stanford-corenlp 3.6.0 edu.stanford.nlp stanford-corenlp 3.6.0 models
Ker bo morala aplikacija samodejno izvleči vsebino članka s spletne strani, morate določiti še naslednji dve odvisnosti:
de.l3s.boilerpipe boilerpipe 1.1.0
net.sourceforge.nekohtml nekohtml 1.9.22
Z dodajanjem teh odvisnosti ste pripravljeni nadaljevati:
Prvi del našega analizatorja bo namenjen jemanju člankov in pridobivanju njihove vsebine s spletnih strani.
Ko jemljemo članke iz virov novic, so strani običajno napolnjene z nepomembnimi informacijami (vdelani videoposnetki, odhodne povezave, videoposnetki, oglaševanje itd.), Ki za članek kot tak niso pomembni. Tu je Kotlovnica je zabeleženo.
Kotlovnica je izjemno pomemben in učinkovit algoritem za odstranjevanje 'nereda', ki identificira glavno vsebino članka z analizo različnih vsebinskih blokov z uporabo značilnosti, kot so povprečna dolžina stavka, vrste oznak, uporabljene v vsebinskih blokih, in gostota vsebinskih povezav. Algoritem kotlovnica dokazal je, da se lahko kosa z drugimi algoritmi, ki so računsko veliko dražji, na primer tistimi, ki temeljijo na strojnem vidu. Več o tem lahko izveste v spletnem mestu vašega projekta .
Knjižnica kotlovnica prihaja z nameščeno podporo za strganje spletnih strani. HTML lahko pridobi iz spleta, iz njega izvleče besedilo in izvlečeno besedilo očisti. Določite lahko funkcijo, extractFromURL
, ki bo zajela url in jo uporabila Kotlovnica da vrnete najpomembnejše besedilo kot niz znakov z uporabo ArticleExtractor
Za to nalogo:
import java.net.URL; import de.l3s.boilerpipe.document.TextDocument; import de.l3s.boilerpipe.extractors.CommonExtractors; import de.l3s.boilerpipe.sax.BoilerpipeSAXInput; import de.l3s.boilerpipe.sax.HTMLDocument; import de.l3s.boilerpipe.sax.HTMLFetcher; public class BoilerPipeExtractor { public static String extractFromUrl(String userUrl) throws java.io.IOException, org.xml.sax.SAXException, de.l3s.boilerpipe.BoilerpipeProcessingException { final HTMLDocument htmlDoc = HTMLFetcher.fetch(new URL(userUrl)); final TextDocument doc = new BoilerpipeSAXInput(htmlDoc.toInputSource()).getTextDocument(); return CommonExtractors.ARTICLE_EXTRACTOR.getText(doc); } }
Knjižnica kotlovnica ponuja različne ekstraktorje, ki temeljijo na algoritmu kotlovnice, z ArticleExtractor
optimizirana posebej za novice, oblikovane v HTML. ArticleExtractor
osredotoča se na oznake HTML, uporabljene v vsakem bloku vsebine, in gostoto odhodnih povezav. To je za našo nalogo bolj primerno kot hitrejše, a lažje DefaultExtractor
Dodane funkcije poskrbijo za vse za nas:
HTMLFetcher.fetch
zgrabite dokument HTMLgetTextDocument
izvleči besedilni dokumentCommonExtractors.ARTICLE_EXTRACTOR.getText
z algoritmom izvlecite ustrezno besedilo iz članka kotlovnica Zdaj lahko poskusite s primernim člankom v zvezi z združitvami optičnih velikanov Essilor in Luxottica, ki ga najdete tukaj . Ta URL lahko dodate funkciji in si ogledate rezultat.
V glavno funkcijo dodajte naslednjo kodo:
public class App { public static void main( String[] args ) throws java.io.IOException, org.xml.sax.SAXException, de.l3s.boilerpipe.BoilerpipeProcessingException { String urlString = 'http://www.reuters.com/article/us-essilor-m-a-luxottica-group-idUSKBN14Z110'; String text = BoilerPipeExtractor.extractFromUrl(urlString); System.out.println(text); } }
Izhodne informacije bi morali videti v glavnem delu članka, brez oglaševanja, oznak HTML in odhodnih povezav. Tu je majhen del tega, kar sem dobil, ko sem ga začel:
MILAN/PARIS Luxottica de Italia (LUX.MI) y Essilor de Francia (ESSI.PA) han llegado a un acuerdo de una fusión de 46 billones de euros (49 billones de dólares) para crear *global eyewear powerhouse* con ingresos anuales de más de 15 billones de euros. El acuerdo de todo tipo de acciones es uno de los mayores vínculos transfronterizos de Europa y une a Luxottica, el mayor creador de lentes del mundo con marcas como Ray-Ban y Oakley, con el fabricante de lentes líder Essilor. 'Finalmente... dos productos que naturalmente se complementan – es decir monturas y lentes – serán diseñados, manufacturados y distribuidos bajo el mismo techo,' Leonardo Del Vecchio, fundador de Luxottica de 81 años, dijo en un comunicado el lunes. Las acciones en Luxottica subieron un 8.6 por ciento a 53.80 euros a las 1405 GMT (9:05 a.m. ET), con Essilor arriba un 12.2 por ciento a 114.60 euros. La fusión entre estos jugadores tan importantes en el mercado de lentes de 95 billones, se enfoca en ayudar a los negocios a aprovechar la demanda tan fuerte que se espera para lentes de prescripción y lentes de sol, debido a una población global que envejece y una toma de conciencia mayor con respecto al cuidado de los ojos. Los analistas Jefferies estiman que el mercado está creciendo entre…
In to je poglavje glavnega članka. Težko si je predstavljati, da bi bilo to lažje izvesti.
Zdaj, ko ste uspešno izvlekli telo članka, se lahko osredotočite na določitev, ali članek omenja podjetja, ki zanimajo uporabnika.
Morda vas bo zamikalo, da bi naredili niz ali iskali regularni izraz, vendar ima ta pristop več slabosti.
Najprej je iskanje nizov lahko izpostavljeno lažno pozitivnim rezultatom. Članek, ki omenja Microsoft Excel, je lahko označen, kot da na primer omenja Microsoft.
Drugič, odvisno od konstrukcije regularnega izraza lahko iskanje regularnega izraza privede do lažnih negativov. Na primer, članek, ki vsebuje besedno zvezo »četrtletni zaslužek Luxottice presegel pričakovanja«, bi se lahko izgubil pri iskanju z regularnimi izrazi, pri katerem je beseda »Luxottica« obdana z belimi presledki.
Če vas zanima veliko število podjetij in obdelujete veliko člankov, lahko iskanje vsakega podjetja v uporabnikovem portfelju v celotnem besedilu povzroči slabo delovanje in hkrati dolgotrajno čas.
Knjižnica Stanford CoreNLP ima veliko močnih lastnosti in ponuja način za rešitev teh treh problemov.
Za naš razčlenjevalnik bomo uporabili slovnično označevanje. Z njim lahko še posebej poiščemo vsa ustrezna imena v članku in jih primerjamo v našem portfelju zanimivih zalog.
Z vključitvijo tehnologije NLP ne samo izboljšujemo natančnost označevalca in zmanjšujemo zgoraj omenjene lažne pozitivne in negativne strani, temveč tudi drastično zmanjšujemo količino besedila, ki ga moramo primerjati z našim portfeljem delnic, saj pravilna imena ogrožajo le majhno podskupino celotno besedilo članka.
S predhodno obdelavo našega članka v podatkovni strukturi, ki je nizki stroški posvetovanja o članstvu , lahko bistveno zmanjšamo čas, ki je potreben za analizo predmeta.
Stanfordov CoreNLP ponuja zelo priročen tagger, imenovan MaxentTagger ki lahko v nekaj vrsticah kode zagotovi oznake slovnice.
Tu je preprosta izvedba:
public class PortfolioNewsAnalyzer { private HashSet portfolio; private static final String modelPath = 'edu\stanford\nlp\models\pos-tagger\english-left3words\english-left3words-distsim.tagger'; private MaxentTagger tagger; public PortfolioNewsAnalyzer() { tagger = new MaxentTagger(modelPath); } public String tagPos(String input) { return tagger.tagString(input); }
Funkcija označevalnika, tagPos
, za vhod vzame niz znakov in izpiše niz znakov, ki vsebuje besede v izvirnem nizu skupaj z ustreznim delom govora. V svoji glavni funkciji ustvarite primer | PortfolioNewsAnalyzer
in zagotavlja rezultat strgalo do funkcije označevalca in morali bi videti nekaj takega:
MILAN/PARIS_NN Italy_NNP 's_POS Luxottica_NNP -LRB-_-LRB- LUX.MI_NNP -RRB-_-RRB- and_CC France_NNP 's_POS Essilor_NNP -LRB-_-LRB- ESSI.PA_NNP -RRB-_-RRB- have_VBP agreed_VBN a_DT 46_CD billion_CD euro_NN -LRB-_-LRB- $_$ 49_CD billion_CD -RRB-_-RRB- merger_NN to_TO create_VB a_DT global_JJ eyewear_NN powerhouse_NN with_IN annual_JJ revenue_NN of_IN more_JJR than_IN 15_CD billion_CD euros_NNS ._. The_DT all-share_JJ deal_NN is_VBZ one_CD of_IN Europe_NNP 's_POS largest_JJS cross-border_JJ tie-ups_NNS and_CC brings_VBZ together_RB Luxottica_NNP ,_, the_DT world_NN 's_POS top_JJ spectacles_NNS maker_NN with_IN brands_NNS such_JJ as_IN Ray-Ban_NNP and_CC Oakley_NNP ,_, with_IN leading_VBG lens_NN manufacturer_NN Essilor_NNP ._. ``_`` Finally_RB ..._: two_CD products_NNS which_WDT are_VBP naturally_RB complementary_JJ --_: namely_RB frames_NNS and_CC lenses_NNS --_: will_MD be_VB designed_VBN ,_, manufactured_VBN and_CC distributed_VBN under_IN the_DT same_JJ roof_NN ,_, ''_'' Luxottica_NNP 's_POS 81-year-old_JJ founder_NN Leonardo_NNP Del_NNP Vecchio_NNP said_VBD in_IN a_DT statement_NN on_IN Monday_NNP ._. Shares_NNS in_IN Luxottica_NNP were_VBD up_RB by_IN 8.6_CD percent_NN at_IN 53.80_CD euros_NNS by_IN 1405_CD GMT_NNP -LRB-_-LRB- 9:05_CD a.m._NN ET_NNP -RRB-_-RRB- ,_, with_IN Essilor_NNP up_IN 12.2_CD percent_NN at_IN 114.60_CD euros_NNS ._. The_DT merger_NN between_IN the_DT top_JJ players_NNS in_IN the_DT 95_CD billion_CD eyewear_NN market_NN is_VBZ aimed_VBN at_IN helping_VBG the_DT businesses_NNS to_TO take_VB full_JJ advantage_NN of_IN expected_VBN strong_JJ demand_NN for_IN prescription_NN spectacles_NNS and_CC sunglasses_NNS due_JJ to_TO an_DT aging_NN global_JJ population_NN and_CC increasing_VBG awareness_NN about_IN...
Do zdaj smo vgradili funkcije za prenos, čiščenje in označevanje novic. A kljub temu moramo ugotoviti, ali članek omenja podjetja, ki zanimajo uporabnika.
Če želite to narediti, moramo zbrati vsa lastna imena in preveriti, ali so v teh lastnih imenih vključene nekatere zaloge v našem portfelju.
Da bi našli vsa lastna imena, moramo najprej ločiti označeni izhodni niz na identifikatorje (z uporabo presledkov kot ločila), nato ločiti vsakega od identifikatorjev v podčrtaju (_
) in preveriti, ali je del govora pravilen ime.
Ko imamo vsa lastna imena, jih shranimo v podatkovno strukturo, ki je bolje optimizirana za naš namen. Za naš primer bomo uporabili HashSet
. Kot kompromis za prepoved podvojenih vnosov in neupoštevanje vrstnega reda vnosov, HashSet
omogoča zelo hitro povpraševanje po članstvu. Ker nas zanima samo prošnja za članstvo, HashSet
je kot nalašč za naše namene.
Spodaj je funkcija, ki izvaja ločevanje in shranjevanje lastnih imen. Uvrstite to funkcijo v svoj razred PortfolioNewsAnalyzer
:
public static HashSet extractProperNouns(String taggedOutput) { HashSet propNounSet = new HashSet(); String[] split = taggedOutput.split(' '); for (String token: split ){ String[] splitTokens = token.split('_'); if(splitTokesn[1].equals('NNP')){ propNounSet.add(splitTokens[0]); } } return propNounSet; }
Vendar pa pri tej izvedbi obstaja težava. Če je ime podjetja sestavljeno iz več besed (npr. Carl Zeiss v primeru Luxottica), ga ta izvedba ne bo mogla ujeti. V primeru Carl Zeiss bosta 'Carl' in 'Zeiss' vstavljena v komplet posebej, zato nikoli ne bo vsebovala edinstvenega niza 'Carl Zeiss'.
Za rešitev te težave lahko zberemo vsa pravilna imena zaporedoma in se jim pridružite s presledki. Tu je posodobljena izvedba, ki to doseže:
public static HashSet extractProperNouns(String taggedOutput) { HashSet propNounSet = new HashSet(); String[] split = taggedOutput.split(' '); List propNounList = new ArrayList(); for (String token: split ){ String[] splitTokens = token.split('_'); if(splitTokens[1].equals('NNP')){ propNounList.add(splitTokens[0]); } else { if (!propNounList.isEmpty()) { propNounSet.add(StringUtils.join(propNounList, ' ')); propNounList.clear(); } } } if (!propNounList.isEmpty()) { propNounSet.add(StringUtils.join(propNounList, ' ')); propNounList.clear(); } return propNounSet; }
Zdaj mora funkcija vrniti niz s posameznimi lastnimi imeni Y. zaporedna lastna imena (npr. združena s presledki). Če natisnete propNounSet
, boste videli nekaj takega:
[... Monday, Gianluca Semeraro, David Goodman, Delfin, North America, Luxottica, Latin America, Rossi/File Photo, Rome, Safilo Group, SFLG.MI, Friday, Valentina Za, Del Vecchio, CEO Hubert Sagnieres, Oakley, Sagnieres, Jefferies, Ray Ban, ...]
Skoraj smo končali!
V prejšnjih odsekih smo zgradili a strgalo ki lahko prenese in izvleče telo članka, označevalnik, ki lahko razčleni telo članka in prepozna lastna imena, kot tudi upodabljalnik, ki sprejme označeni izhod in zbere lastna imena v HashSet
Zdaj je treba še uporabiti HashSet
in ga primerjajte s seznamom podjetij, ki nas zanimajo.
Izvedba je zelo preprosta. V svoj razred dodajte naslednjo kodo PortfolioNewsAnalyzer
:
private HashSet portfolio; public PortfolioNewsAnalyzer() { portfolio = new HashSet(); } public void addPortfolioCompany(String company) { portfolio.add(company); } public boolean arePortfolioCompaniesMentioned(HashSet articleProperNouns){ return !Collections.disjoint(articleProperNouns, portfolio); }
Zdaj lahko zaženemo celotno aplikacijo - strganje, čiščenje, označevanje, zbiranje in primerjanje. Tu je funkcija, ki se izvaja v celotni aplikaciji. Dodajte to funkcijo v svoj razred PortfolioNewsAnalyzer
:
public boolean analyzeArticle(String urlString) throws IOException, SAXException, BoilerpipeProcessingException { String articleText = extractFromUrl(urlString); String tagged = tagPos(articleText); HashSet properNounsSet = extractProperNouns(tagged); return arePortfolioCompaniesMentioned(properNounsSet); }
Končno lahko uporabimo aplikacijo!
Tu je primer uporabe istega izdelka kot zgoraj in Luxottice kot portfeljskega podjetja:
public static void main( String[] args ) throws IOException, SAXException, BoilerpipeProcessingException { PortfolioNewsAnalyzer analyzer = new PortfolioNewsAnalyzer(); analyzer.addPortfolioCompany('Luxottica'); boolean mentioned = analyzer.analyzeArticle('http://www.reuters.com/article/us-essilor-m-a-luxottica-group-idUSKBN14Z110'); if (mentioned) { System.out.println('Article mentions portfolio companies'); } else { System.out.println('Article does not mention portfolio companies'); } }
Zaženite to in aplikacija mora natisniti 'Članek omenja portfeljska podjetja.'
Portfeljsko podjetje Luxottica spremenite v podjetje, ki ni omenjeno v članku (na primer »Microsoft«), aplikacija pa naj natisne »Članek ne omenja portfeljskih podjetij«.
V tem članku gremo skozi postopek izdelave aplikacije, ki članek prenese iz URL-ja in ga očisti z uporabo Kotlovnica , obdela z uporabo Stanfordovega NLP in preveri, ali članek vsebuje posebne reference (v našem primeru podjetja iz našega portfelja). Kot je bilo že prikazano, upravljanje te matrice tehnologij naredi tisto, kar bi sicer bilo zastrašujoča naloga, ki je razmeroma enostavna.
Upam, da vas je ta članek naučil koristnih konceptov in tehnik pri obdelavi naravnega jezika ter vas navdihnil, da sami pišete aplikacije v naravnem jeziku.
[Opomba: V tem članku najdete kopijo kode, na katero se sklicuje tukaj .