Natural Language Processing (NLP) in R5 perc olvasás

A cikk témája a Natural Language Provessing (NPL), valamint annak egy implementációja a komment formátumú éttermi értékeléseken keresztül.

Mi is az NLP?

Az NLP (Natural Language Processing)  a data science és a mesterséges intelligencia metszete, leginkább az emberi beszéd és a számítógép közötti interakcióként lehetne jellemezni. Az NLP-nek több szintje van, amelyek bonyolultságukat tekintve változatosak, azonban elmondható, hogy minden alkalmazása deep learningen alapul. Vagyis adott egy nagy, optimálisan legalább ezer elemű minta, amelynek egy részét tanításra, másik részét tesztelésre használjuk fel.

A legegyszerűbben az írott szöveget (pl. valamilyen értékeléseket) lehet feldolgozni, illetve önállóan szöveget íratni. Az emberi beszéd felismerése, megértése és önálló előállítása már sokkal bonyolultabb feladat. A cikkben az írott szöveg feldolgozásának kivitelezését mutatom be R-ben.

NLP programozás R-ben

Az implementációban egy étteremben fogyasztó vendégek angol nyelvű értékeléseit dolgozom fel, vagyis olyan modellt készítek, ami egy adott inputról (kommentek), képes megmondani, hogy pozitív vagy negatív véleményt tartalmaz az étteremről. Elsőre úgy tűnhet, hogy ez egy nagyon bonyolult feladat lesz, de logikusan átgondolva már nem fog gondot okozni.

Az értékeléseket tartalmazó adatbázisom ezer elemű, és két oszlopból áll: maga az értékelés szövege, és egy logikai mező, ami igaz, ha a vendég véleménye pozitív, ellenkező esetben hamis. Vagyis az a feladat, hogy a szöveges vélemény alapján a modell helyesen adja meg a logikai értéket. Ehhez két részre választom az adatbázist: 800 megfigyelés alapján készítem el a modellt, a maradék 200 megfigyelést pedig tesztelésre használom.

A legfontosabb rész nem maga a modell megalkotása, hanem a rendelkezésre álló adatok megfelelő előkészítése. Ezzel a lépéssel eltávolítjuk a felesleges szövegrészleteket, amelyek a mondattá formálást szolgálják, de nincsen jelentős információtartalmuk. Egy értékelésben nem az számít, hogyha leírják az étterem nevét, a fogyasztás időpontját, vagy a fogyasztott fogásokat, hanem az, hogy milyen véleménnyel vannak arról, amit kaptak. Tehát igyekszünk kinyerni azt a néhány szót egy adott mondatból, ami a lényeget tartalmazza, hogy a modell tényleg jól működjön.

Általában kevés teljesen egyforma szavakat tartalmazó értékelés érkezik egy étteremről, főleg ha hosszabbak a leírt vélemények. Ahány ember, annyiféle szóhasználat, preferált szókészlet, így ha egyesével akarnánk kiszűrni a lényegtelen szavakat, akkor nagyon sokáig tartani összeállítani a lehetséges szavak listáját. Szerencsére az R ebben segítségünkre van, több különböző package áll a rendelkezésre, amelyek kategorizálva távolítják el a felesleges szavakat. A két leggyakrabban alkalmazott package a tm és a SnowballC.

Először a szöveges értékeléseket corpus-okká kell alakítani, hogy a tm package alkalmazható legyen. Fontos, hogy minden karaktert kisbetűssé alakítunk, hogy a szöveg kezelhetővé váljon, utána a számokat távolítjuk el, mivel azok jelentéktelenek a vélemény szempontjából. Az idézetek sem lényegesek, mivel bizonyos szituációkat írnak le, nem a kialakult véleményt. Ezután a tm package szerint irreleváns szavakat távolítjuk el, ilyenek például a névelők, ételek és a napok nevei, végül minden megmaradt szónak a ragozatlan alakját vesszük. Természetesen a negatív értelmű jelzők negatívak maradnak ezután is. Az átalakítások során az eltávolított karakterek helyére space-ek kerültek, utolsó lépésben ezeket töröljük ki, hogy a modell ne foglalkozzon feleslegesen karakterekkel.

library(tm)
library(SnowballC)
corpus = VCorpus(VectorSource(dataset_original$Review))
corpus = tm_map(corpus, content_transformer(tolower)) # put all character in lower case
corpus = tm_map(corpus, removeNumbers) # all the numbers are removed
corpus = tm_map(corpus, removePunctuation) # remove punctuation
corpus = tm_map(corpus, removeWords, stopwords()) # Remove all non-relevant words
corpus = tm_map(corpus, stemDocument) # took the roots of all the words
corpus = tm_map(corpus, stripWhitespace) # remove extra spaces)

Ezután az adatokat data frame-be rendezzük, hogy folytatni tudjuk a munkát. Ahhoz, hogy  a modell működni tudjon, a második oszlop logikai értékeit faktorokká kell alakítani:

dataset$Liked = factor(dataset$Liked, levels = c(0, 1)) 

Ezután az adatbázist két részre osztom a modellépítéshez (800 megfigyelés) és a teszteléshez (200 megfigyelés) a caTools package segítségével. Innentől egy tipikus klasszifikációs feladattal van dolgunk, ezekről itt olvashatsz bevezetőt. Én a random forest klasszifikációt választottam, ami több becslést készít, majd azok eredményeit átlagolja. Ehhez a randomForest package-t használtam:

classifier = randomForest(x = training_set[-692],
                          y = training_set$Liked,
                          ntree = 10)

Az elkészült modell működését teszteltem az erre a célra meghagyott 200 adaton, szintén a caTools package segítségével:

y_pred = predict(classifier, newdata = test_set[-692])

Megvan a modell és megvannak a tesztelés eredményei, így azokat össze tudjuk vetni a valósággal. Az  összehasonlításhoz klasszifikációs mátrixot készítettem, ami 25 elsőfajú és 23 másodfajú hibát jelzett. 77 esetben negatív értékelésre negatív becslés érkezett, 75-ben pedig pozitívra pozitív. Vagyis az esetek 76%-ában adott helyes eredményt a modell a teszt adatbázison, ezzel egészen jó NLP modellt építettünk.

Remélem felkeltette a cikkem az érdeklődésed a bonyolultabb NLP algoritmusok iránt!

Leave a Reply

Your email address will not be published. Required fields are marked *