Word2Vec:n toteuttaminen Gensim-kirjastolla Pythonissa

Esittely

Ihmisillä on luontainen kyky ymmärtää, mitä muut ihmiset sanovat ja mitä sanoa vastauksena. Tämä kyky kehittyy, kun ollaan johdonmukaisesti vuorovaikutuksessa muiden ihmisten ja yhteiskunnan kanssa useiden vuosien ajan. Kielellä on hyvin tärkeä rooli siinä, miten ihmiset ovat vuorovaikutuksessa. Kieliä, joita ihmiset käyttävät vuorovaikutuksessa, kutsutaan luonnollisiksi kieliksi.

Erilaisten luonnollisten kielten säännöt ovat erilaisia. Luonnollisissa kielissä on kuitenkin yksi yhteinen asia: joustavuus ja evoluutio.

Luonnolliset kielet ovat erittäin hyvin joustavia. Oletetaan, että ajat autoa ja ystäväsi sanoo yhden näistä kolmesta lausahduksesta: ”Pysäytä auto”, ”Pysäytä auto”, ”Seis”. Ymmärrät heti, että hän pyytää sinua pysäyttämään auton. Tämä johtuu siitä, että luonnolliset kielet ovat erittäin joustavia. On olemassa useita tapoja sanoa yksi asia.

Toinen tärkeä näkökohta luonnollisissa kielissä on se, että ne kehittyvät jatkuvasti. Esimerkiksi muutama vuosi sitten ei ollut olemassa sellaista termiä kuin ”Google it”, joka viittaa jonkin asian etsimiseen Googlen hakukoneella. Luonnolliset kielet kehittyvät jatkuvasti.

Tietokonekielet sen sijaan noudattavat tiukkaa syntaksia. Jos haluat käskeä tietokonetta tulostamaan jotain näytölle, sitä varten on olemassa erityinen komento. Luonnollisen kielen prosessoinnin tehtävänä on saada tietokoneet ymmärtämään ja tuottamaan ihmisen kieltä samalla tavalla kuin ihminen.

Tämä on valtava tehtävä, ja siihen liittyy monia esteitä. Tämä Michiganin yliopiston videoluento sisältää erittäin hyvän selityksen siitä, miksi NLP on niin vaikeaa.

Tässä artikkelissa toteutamme sanavektoreiden luomiseen käytettävän Word2Vec-sanan upottamistekniikan Pythonin Gensim-kirjastolla. Ennen kuin hyppäämme suoraan koodausosioon, käymme kuitenkin ensin lyhyesti läpi joitakin yleisimmin käytettyjä sanojen upottamistekniikoita sekä niiden hyviä ja huonoja puolia.

Sanojen upottamislähestymistapoja

Yksi syy siihen, että luonnollisen kielen prosessointi on vaikeasti ratkaistava ongelma, on se, että tietokoneet ymmärtävät ihmisistä poiketen vain numeroita. Meidän on esitettävä sanat numeerisessa muodossa, jonka tietokoneet ymmärtävät. Sanojen upottamisella tarkoitetaan sanojen numeerista esittämistä.

Sanojen upottamiseen on tällä hetkellä olemassa useita lähestymistapoja, ja kaikilla niillä on hyvät ja huonot puolensa. Seuraavassa esitellään vaiheet, joiden avulla luodaan sanojen upotuksia käyttämällä sanapussi-lähestymistapaa.

Katsomme sanapussi-lähestymistavalla luotuja sanojen upotuksia esimerkin avulla. Oletetaan, että sinulla on korpus, jossa on kolme lausetta.

  • S1 = Rakastan sadetta
  • S2 = Sade sade sade mene pois
  • S3 = Olen poissa

Muuntaaksemme edellä mainitut lauseet vastaaviksi sanojen upotusrepresentaatioiksi sanapussilähestymistapaa käyttäen, meidän on suoritettava seuraavat vaiheet:

Huomaa, että S2:n kohdalla lisäsimme sanakirjan ”rain” tilalle 2; tämä johtuu siitä, että S2 sisältää ”rain” kahdesti.

Sanapussimenetelmän hyvät ja huonot puolet

Sanapussimenetelmällä on sekä hyviä että huonoja puolia. Sanapussi-lähestymistavan tärkein etu on se, että hyvien tulosten saamiseksi ei tarvita kovin suurta sanakorpusta. Näet, että rakennamme hyvin yksinkertaisen bag of words -mallin kolmella lauseella. Laskennallisesti bag of words -malli ei ole kovin monimutkainen.

Bag of words -lähestymistavan suurin haittapuoli on se, että meidän on luotava valtavia vektoreita, joissa on tyhjiä välejä, jotta voimme esittää numeron (harva matriisi), mikä kuluttaa muistia ja tilaa. Edellisessä esimerkissä meillä oli vain 3 lausetta. Silti jokaisessa vektorissa näkyy kolme nollaa.

Kuvittele korpus, jossa on tuhansia artikkeleita. Tällaisessa tapauksessa sanakirjan uniikkien sanojen määrä voi olla tuhansia. Jos yksi dokumentti sisältää 10 % ainutkertaisista sanoista, vastaavassa upotusvektorissa on silti 90 % nollia.

Toinen suuri ongelma bag of words -lähestymistavassa on se, että se ei ylläpidä mitään kontekstitietoa. Se ei välitä siitä, missä järjestyksessä sanat esiintyvät lauseessa. Se kohtelee esimerkiksi lauseita ”Pullo on autossa” ja ”Auto on pullossa” yhtä lailla, vaikka ne ovat täysin eri lauseita.

Tyyppinen sanapussi-lähestymistapa, jota kutsutaan n-grammiksi, voi auttaa ylläpitämään sanojen välisiä suhteita. N-grammilla tarkoitetaan n sanan yhtenäistä sarjaa. Esimerkiksi lauseen ”Et ole onnellinen” 2-grammat ovat ”Olet”, ”et ole” ja ”et ole onnellinen”. Vaikka n-grammi-lähestymistapa kykenee kuvaamaan sanojen välisiä suhteita, ominaisuusjoukon koko kasvaa eksponentiaalisesti, kun n-grammeja on liikaa.

TF-IDF-järjestelmä

TF-IDF-järjestelmä on eräänlainen säkkisana-lähestymistapa, jossa nollien ja ykkösten lisäämisen sijasta sulauttavaan vektoriin lisätään liukulukuja, jotka sisältävät hyödyllisempää informaatiota kuin nollat ja ykköset. TF-IDF-järjestelmän ideana on se, että sanat, joilla on suuri esiintymistiheys yhdessä asiakirjassa ja pienempi esiintymistiheys kaikissa muissa asiakirjoissa, ovat tärkeämpiä luokittelun kannalta.

TF-IDF on kahden arvon tulo: Termifrekvenssi (Term Frequency, TF) ja käänteinen asiakirjan frekvenssi (Inverse Document Frequency, IDF).

Termifrekvenssillä tarkoitetaan sitä, kuinka monta kertaa sana esiintyy asiakirjassa, ja se voidaan laskea seuraavasti:

Term frequence = (Number of Occurences of a word)/(Total words in the document)

Jos esimerkiksi tarkastelemme edellisessä kappaleessa olevaa lausetta S1 eli ”Rakastan sadetta”, lauseen jokainen sana esiintyy kerran, joten sen frekvenssi on 1. Päinvastoin, kun S2:n osalta, ts. ”sade sade sade mene pois”, sanan ”sade” frekvenssi on kaksi, kun taas muiden sanojen frekvenssi on 1.

IDF tarkoittaa asiakirjojen kokonaismäärän logaritmia jaettuna niiden asiakirjojen lukumäärällä, joissa sana esiintyy, ja se voidaan laskea seuraavasti:

IDF(word) = Log((Total number of documents)/(Number of documents containing the word))

Esimerkiksi sanan ”sade” IDF-arvo on 0,1760, koska asiakirjojen kokonaislukumäärä on kolme ja sade esiintyy kahdessa asiakirjassa, joten log(3/2) on 0,1760. Toisaalta, jos tarkastellaan sanaa ”rakkaus” ensimmäisessä lauseessa, se esiintyy yhdessä kolmesta dokumentista, joten sen IDF-arvo on log(3) eli 0,4771.

TF-IDF:n hyvät ja huonot puolet

Kaikkakin TF-IDF on parannus yksinkertaiseen sanasäkkilähestymistapaan verrattuna ja tuottaa parempia tuloksia tavallisissa NLP-tehtävissä, yleiset hyvät ja huonot puolet pysyvät samoina. Meidän on edelleen luotava valtava harva matriisi, mikä vie myös paljon enemmän laskentaa kuin yksinkertainen sanapussi-lähestymistapa.

Word2Vec

Tomas Mikolovin kehittämää <a target=”_blank rel=”nofollow”” href=”https://en.wikipedia.org/wiki/Word2vec”>Word2Vec- upotuslähestymistapaa pidetään uusimpana. Word2Vec-lähestymistapa käyttää syväoppimiseen ja neuroverkkoihin perustuvia tekniikoita muuntamaan sanoja vastaaviksi vektoreiksi siten, että semanttisesti samankaltaiset vektorit ovat lähellä toisiaan N-ulotteisessa avaruudessa, jossa N viittaa vektorin ulottuvuuksiin.

Word2Vec-lähestymistapa palauttaa hämmästyttäviä tuloksia. Word2Vecin kykyä ylläpitää semanttista suhdetta kuvastaa klassinen esimerkki, jossa jos sinulla on vektori sanalle ”Kuningas” ja poistat sanan ”Mies” edustaman vektorin sanasta ”Kuningas” ja lisäät siihen sanan ”Naiset”, saat vektorin, joka on lähellä vektoria ”Kuningatar”. Tämä suhde esitetään yleisesti muodossa:

King - Man + Women = Queen

Word2Vec-mallia on kahta erilaista: Skip Gram -malli ja Continuous Bag of Words -malli (CBOW).

Skip Gram -mallissa kontekstisanoja ennustetaan perussanan avulla. Jos esimerkiksi annetaan lause ”Rakastan tanssia sateessa”, skip gram -malli ennustaa sanat ”rakkaus” ja ”tanssi”, kun syötteenä on sana ”to”.

CBOW-malli sitä vastoin ennustaa sanan ”to”, jos mallille syötetään syötteenä kontekstisanat ”rakkaus” ja ”tanssi”. Malli oppii nämä suhteet käyttämällä syviä neuroverkkoja.

Word2Vecin hyvät ja huonot puolet

Word2Vecillä on useita etuja verrattuna bag of words- ja IF-IDF-järjestelmään. Word2Vec säilyttää asiakirjan eri sanojen semanttisen merkityksen. Kontekstitietoa ei menetetä. Word2Vec-menetelmän toinen suuri etu on se, että upotusvektorin koko on hyvin pieni. Jokainen upotusvektorin ulottuvuus sisältää tietoa yhdestä sanan osa-alueesta. Emme tarvitse valtavia harvoja vektoreita, toisin kuin sanasäkki- ja TF-IDF-lähestymistavoissa.

Huomautus: Matemaattiset yksityiskohdat siitä, miten Word2Vec toimii, edellyttävät neuroverkkojen ja softmax-todennäköisyyden selittämistä, mikä ei kuulu tämän artikkelin piiriin. Jos haluat ymmärtää Word2Vecin matemaattiset perusteet, lue tämä artikkeli: https://arxiv.org/abs/1301.3781

Word2Vec Pythonissa Gensim-kirjastolla

Tässä osassa toteutamme Word2Vec-mallin Pythonin Gensim-kirjaston avulla. Seuraa seuraavia vaiheita:

Korpuksen luominen

Keskustelimme aiemmin, että Word2Vec-mallin luomista varten tarvitsemme korpuksen. Todellisissa sovelluksissa Word2Vec-mallit luodaan käyttämällä miljardeja asiakirjoja. Esimerkiksi Googlen Word2Vec-malli koulutetaan käyttämällä 3 miljoonaa sanaa ja lausetta. Yksinkertaisuuden vuoksi luomme kuitenkin Word2Vec-mallin yhden Wikipedia-artikkelin avulla. Mallimme ei tule olemaan yhtä hyvä kuin Googlen malli. Se on kuitenkin tarpeeksi hyvä selittämään, miten Word2Vec-malli voidaan toteuttaa Gensim-kirjastolla.

Ennen kuin voimme tiivistää Wikipedia-artikkeleita, meidän on haettava ne. Tätä varten käytämme paria kirjastoa. Ensimmäinen kirjasto, joka meidän on ladattava, on Beautiful Soup -kirjasto, joka on erittäin hyödyllinen Python-apuohjelma verkkokaapimiseen. Suorita seuraava komento komentorivillä ladataksesi Beautiful Soup -apuohjelman.

$ pip install beautifulsoup4

Toinen tärkeä kirjasto, jota tarvitsemme XML:n ja HTML:n jäsentämiseen, on lxml-kirjasto. Suorita komentorivillä seuraava komento ladataksesi lxml:

$ pip install lxml

Artikkeli, jonka aiomme kaapata, on Wikipedian artikkeli Artificial Intelligence. Kirjoitetaan Python-skripti artikkelin kaapimiseksi Wikipediasta:

Yllä olevassa skriptissä lataamme ensin Wikipedia-artikkelin käyttäen urllib-kirjaston request-luokan urlopen-metodia. Sen jälkeen luemme artikkelin sisällön ja jäsennämme sen käyttämällä BeautifulSoup-luokan oliota. Wikipedia tallentaa artikkelin tekstisisällön p-tagien sisään. Käytämme BeautifulSoup-olion find_all-funktiota noutaaksemme koko sisällön artikkelin kappaletageista.

Viimeiseksi yhdistämme kaikki kappaleet toisiinsa ja tallennamme kaapatun artikkelin article_text-muuttujaan myöhempää käyttöä varten.

Esikäsittely

Tässä vaiheessa olemme nyt tuoneet artikkelin. Seuraava vaihe on sisällön esikäsittely Word2Vec-mallia varten. Seuraava skripti esikäsittelee tekstin:

Yllä olevassa skriptissä muutamme kaiken tekstin pieniksi kirjaimiksi ja poistamme sitten kaikki numerot, erikoismerkit ja ylimääräiset välilyönnit tekstistä. Esikäsittelyn jälkeen jäljelle jäävät vain sanat.

Word2Vec-malli koulutetaan sanakokoelmalla. Ensin meidän on muunnettava artikkelimme lauseiksi. Käytämme nltk.sent_tokenize apuohjelmaa artikkelimme muuntamiseen lauseiksi. Lauseiden muuntamiseen sanoiksi käytämme nltk.word_tokenize-apuohjelmaa. Viimeisenä esikäsittelyvaiheena poistamme tekstistä kaikki stop-sanat.

Skriptin suorituksen jälkeen all_words-olio sisältää luettelon kaikista artikkelin sanoista. Käytämme tätä luetteloa luodaksemme Word2Vec-mallimme Gensim-kirjastolla.

Word2Vec-mallin luominen

Gensimin avulla Word2Vec-mallin luominen on erittäin suoraviivaista. Sanaluettelo välitetään gensim.models-paketin Word2Vec-luokkaan gensim.models. Meidän on määritettävä arvo min_count-parametrille. min_count:n arvo 2 määrittää, että Word2Vec-malliin sisällytetään vain ne sanat, jotka esiintyvät korpuksessa vähintään kaksi kertaa. Seuraava skripti luo Word2Vec-mallin käyttämällä Wikipedia-artikkelia, jonka kaavimme.

from gensim.models import Word2Vecword2vec = Word2Vec(all_words, min_count=2)

Toteuttaaksesi sanakirjan ainutlaatuisista sanoista, jotka esiintyvät vähintään kahdesti korpuksessa, suorita seuraava skripti:

vocabulary = word2vec.wv.vocabprint(vocabulary)

Kun yllä oleva skripti suoritetaan, näet luettelon kaikista ainutlaatuisista sanoista, jotka esiintyvät vähintään kahdesti.

Mallin analyysi

Loimme onnistuneesti Word2Vec-mallimme edellisessä kappaleessa. Nyt on aika tutkia, mitä loimme.

Sanan vektoreiden löytäminen

Tiedämme, että Word2Vec-malli muuntaa sanat niitä vastaaviksi vektoreiksi. Katsotaanpa, miten voimme tarkastella minkä tahansa tietyn sanan vektoriedustusta.

v1 = word2vec.wv

Vektori v1 sisältää vektoriedustuksen sanalle ”artificial”. Gensim Word2Vec luo oletusarvoisesti sadan ulottuvuuden vektorin. Tämä on paljon, paljon pienempi vektori verrattuna siihen, mitä bag of words olisi tuottanut. Jos käytämme bag of words -lähestymistapaa artikkelin upottamiseen, kunkin vektorin pituus on 1206, koska on 1206 ainutlaatuista sanaa, joiden esiintymistiheys on vähintään 2. Jos esiintymistiheyden vähimmäistiheydeksi asetetaan 1, bag of words -vektorin koko kasvaa entisestään. Toisaalta sanaston koko ei vaikuta Word2Vec-menetelmällä luotuihin vektoreihin.

Samankaltaisten sanojen löytäminen

Aiemmin totesimme, että Word2Vec-menetelmää käytettäessä sanojen kontekstitietoa ei menetetä. Voimme todentaa tämän etsimällä kaikki sanan ”älykkyys” kanssa samankaltaiset sanat.

Katsokaa seuraavaa skriptiä:

sim_words = word2vec.wv.most_similar('intelligence')

Jos tulostat sim_words-muuttujan konsoliin, näet sanan ”älykkyys” kanssa samankaltaisimmat sanat alla esitetyllä tavalla:

Tulosteesta näet ”älykkyys” kanssa samankaltaisimmat sanat ja niiden samankaltaisuusindeksin. Sana ”ai” on mallin mukaan samankaltaisin sana kuin ”älykkyys”, mikä on itse asiassa järkevää. Samoin sellaiset sanat kuin ”human” ja ”artificial” esiintyvät usein rinnakkain sanan ”intelligence” kanssa. Mallimme on onnistuneesti vanginnut nämä suhteet käyttämällä vain yhtä Wikipedia-artikkelia.

Johtopäätös

Tässä artikkelissa toteutimme Word2Vec-sanan upotusmallin Pythonin Gensim-kirjastolla. Teimme tämän kaapimalla Wikipedia-artikkelin ja rakensimme Word2Vec-mallimme käyttämällä artikkelia korpuksena. Tarkastelimme myös lyhyesti yleisimmin käytettyjä sanojen upottamisen lähestymistapoja sekä niiden hyviä ja huonoja puolia Word2Veciin verrattuna.

Esittäisin, että voit luoda oman Word2Vec-mallisi minkä tahansa tekstikorpuksen avulla ja katsoa, saatko parempia tuloksia kuin bag of words -lähestymistavassa.

Vastaa

Sähköpostiosoitettasi ei julkaista.