1. ProgrammeringBig DataData Science Bruker AI for sentimentanalyse

Av John Paul Mueller, Luca Mueller

Sentimentanalyse stammer beregningsmessig fra en skrevet tekst ved å bruke forfatterens holdning (enten positiv, negativ eller nøytral) til tekstemnet. Denne typen analyser viser seg å være nyttige for folk som jobber med markedsføring og kommunikasjon fordi den hjelper dem å forstå hva kunder og forbrukere synes om et produkt eller en tjeneste, og dermed handle riktig (for eksempel å prøve å gjenopprette utilfredse kunder eller bestemme seg for å bruke en annen salgsstrategi ). Alle utfører sentimentanalyse. Når du for eksempel leser tekst, prøver folk naturlig nok å bestemme følelsen som beveget personen som skrev den. Når antallet tekster å lese og forstå er for stort og teksten stadig akkumuleres, som i sosiale medier og kunde e-post, er automatisering av følelsesanalyse viktig.

AI sentiment analyse

Det kommende eksemplet er en testkjøring av RNNer som bruker Keras og TensorFlow som bygger en følelsesanalysealgoritme som er i stand til å klassifisere holdningene uttrykt i en filmanmeldelse. Dataene er et utvalg av IMDb-datasettet som inneholder 50 000 anmeldelser (delt i to mellom tog- og testsett) av filmer akkompagnert av en etikett som uttrykker følelsen av anmeldelsen (0 = negativ, 1 = positiv). IMDb er en stor online database som inneholder informasjon om filmer, TV-serier og videospill. Opprinnelig vedlikeholdt av en fanbase, og drives nå av et Amazon-datterselskap. På IMDb finner folk informasjonen de trenger om favorittprogrammet sitt, så kan de legge inn kommentarer eller skrive en anmeldelse som andre besøkende kan lese.

Keras tilbyr en nedlastbar innpakning for IMDb-data. Du forbereder, stokker og ordner disse dataene i et tog og et testsett. Spesielt blir IMDb-tekstdataene som tilbys av Keras renset for tegnsetting, normalisert til små bokstaver og omgjort til numeriske verdier. Hvert ord er kodet til et tall som representerer rangeringen i frekvens. De hyppigste ordene har lave tall; sjeldnere ord har høyere tall.

Som startpunkt importerer koden imdb-funksjonen fra Keras og bruker den til å hente dataene fra Internett (omtrent 17,5 MB nedlasting). Parametrene som eksemplet bruker omfatter bare de 10.000 ordene, og Keras bør blande dataene ved å bruke et bestemt tilfeldig frø. (Å kjenne frøet gjør det mulig å reprodusere blandingen etter behov.) Funksjonen returnerer to tog- og testsett, begge laget av tekstsekvenser og følelsesutfallet.

fra keras.datasets import imdb
top_words = 10000
((x_train, y_train),
(x_test, y_test)) = imdb.load_data (num_words = top_words,
seed = 21)

Etter at forrige kode er fullført, kan du sjekke antall eksempler ved å bruke følgende kode:

print ("Treningseksempler:% i"% len (x_train))
print ("Testeksempler:% i"% len (x_test))

Etter å ha spurt om antall tilfeller som er tilgjengelige for bruk i trenings- og testfasen i det nevrale nettverket, gir koden et svar på 25 000 eksempler for hver fase. (Dette datasettet er relativt lite for et språkproblem; tydeligvis er datasettet hovedsakelig for demonstrasjonsformål.) I tillegg bestemmer koden om datasettet er balansert, noe som betyr at det har et nesten like antall positive og negative følelseseksempler.

importer numpy som np
print (np.unique (y_train, return_counts = True))

Resultatet, matrise ([12500, 12500]), bekrefter at datasettet er delt jevnt mellom positive og negative utfall. En slik balanse mellom responsklasser skyldes utelukkende datasettets demonstrative karakter. I den virkelige verden finner du sjelden balanserte datasett. Neste trinn lager noen Python-ordbøker som kan konvertere mellom koden som brukes i datasettet og de virkelige ordene. Faktisk er datasettet som brukes i dette eksemplet forbehandlet og gir sekvenser med tall som representerer ordene, ikke ordene i seg selv. (LSTM- og GRU-algoritmer som du finner i Keras forventer sekvenser av tall som tall.)

word_to_id = {w: i ​​+ 3 for w, i i imdb.get_word_index (). items ()}
id_to_word = {0: '', 1: '', 2: ''}
id_to_word.update ({i + 3: w for w, i i imdb.get_word_index (). elementer ()})
def convert_to_text (sekvens):
return '' .join ([id_to_word [s] for s i sekvens hvis s> = 3])
ut (convert_to_text (x_train [8]))

Den forrige kodebiten definerer to konverteringsordbøker (fra ord til numeriske koder og omvendt) og en funksjon som oversetter datasetteksemplene til lesbar tekst. Som et eksempel skriver koden det niende eksemplet: "denne filmen var som et dårlig togvrak like fryktelig som det var ...". Fra dette utdraget kan du lett forutse at stemningen for denne filmen ikke er positiv. Ord som dårlig, vrak og fryktelig formidler en sterk negativ følelse, og det gjør det å gjette riktig stemning enkelt.

I dette eksemplet mottar du de numeriske sekvensene og gjør dem om til ord, men det motsatte er vanlig. Vanligvis får du uttrykk som består av ord og gjør dem om til sekvenser med heltall for å mates til et lag med RNN-er. Keras tilbyr en spesialisert funksjon, Tokenizer som kan gjøre det for deg. Den bruker metodene fit_on_text, for å lære å kartlegge ord til heltall fra treningsdata, og tekster_til_matrise, for å transformere tekst til en sekvens.

Imidlertid, i andre setninger, kan det hende du ikke finner slike avslørende ord for følelsesanalysen. Følelsen kommer til uttrykk på en mer subtil eller indirekte måte, og det er ikke mulig å forstå følelsen tidlig i teksten fordi avslørende fraser og ord kan vises mye senere i diskursen. Av denne grunn må du også bestemme hvor mye av setningen du vil analysere.

Konvensjonelt tar du en innledende del av teksten og bruker den som representativ for hele anmeldelsen. Noen ganger trenger du bare noen få innledende ord - for eksempel de første 50 ordene - for å få mening; noen ganger trenger du mer. Spesielt lange tekster avslører ikke deres orientering tidlig. Det er derfor opp til deg å forstå hvilken type tekst du jobber med og bestemme hvor mange ord du skal analysere ved hjelp av dyp læring. Dette eksemplet vurderer bare de første 200 ordene, noe som burde være tilstrekkelig.

Du har lagt merke til at koden begynner å gi kode til ord som begynner med nummeret 3, og dermed overlater koder fra 0 til 2. Lavere tall brukes til spesielle koder, for eksempel å signalisere starten på frasen, fylle tomme mellomrom for å få sekvensen fikset på en viss lengde, og merke ordene som er ekskludert fordi de ikke er hyppige nok. Dette eksemplet henter bare de hyppigste 10.000 ordene. Å bruke tagger for å påpeke start, slutt og bemerkelsesverdige situasjoner er et triks som fungerer med RNN, spesielt for maskinoversettelse.

fra keras.preprocessing.sequence import pad_sequences
max_pad = 200
x_train = pad_sequences (x_train,
maxlen = max_pad)
x_test = pad_sequences (x_test,
maxlen = max_pad)
print (x_train [0])

Ved å bruke pad_sequences-funksjonen fra Keras med max_pad satt til 200, tar koden de første to hundre ordene for hver anmeldelse. I tilfelle gjennomgangen inneholder færre enn to hundre ord, går så mange nullverdier som nødvendig foran sekvensen for å nå det nødvendige antall sekvenselementer. Å kutte sekvensene til en viss lengde og fylle tomrommene med null verdier kalles input padding, en viktig prosesseringsaktivitet når du bruker RNN-er som dype læringsalgoritmer. Nå designer koden arkitekturen:

fra keras.models import Sequential
fra keras.layers importerer Bidirectional, Dense, Dropout
fra keras.layers importerer GlobalMaxPool1D, LSTM
fra keras.layers.embeddings import Embedding
embedding_vector_length = 32
modell = Sekvensiell ()
model.add (-innebygging (top_words,
embedding_vector_length,
input_length = max_pad))
model.add (toveis (LSTM (64, return_sequences = True)))
model.add (GlobalMaxPool1D ())
model.add (Tett (16, aktivering = "relu"))
model.add (Tett (1, aktivering = "sigmoid"))
model.compile (tap = 'binary_crossentropy',
optimerings = 'Adam',
beregninger = [ 'nøyaktighet'])
print (model.summary ())

Den forrige kodebiten definerer formen til den dype læringsmodellen, der den bruker noen få spesialiserte lag for naturlig språkbehandling fra Keras. Eksemplet har også krevd en oppsummering av kommandoen (model.summary ()) for å bestemme hva som skjer med arkitektur ved å bruke forskjellige nevrale lag.

Du har Embedding-laget, som forvandler de numeriske sekvensene til et tett innebygging av ord. Den typen ord innebygging er mer egnet for å bli lært av et lag med RNN-er. Keras gir et Embedding-lag, som bortsett fra at det nødvendigvis må være det første laget i nettverket, kan utføre to oppgaver:

  • Bruke forhåndsbestemt ord innebygging (for eksempel Word2vec eller GloVe) på sekvensinndata. Du trenger bare å sende matrisen som inneholder innebygningen til dens parametervekter. Opprette et innebygging av ord fra bunnen av, basert på inngangene det mottar.

I dette andre tilfellet trenger Embedding bare å vite:

  • input_dim: Størrelsen på ordforrådet som forventes fra data output_dim: Størrelsen på innebygningsrommet som skal produseres (de såkalte dimensjonene) input_length: Sekvensstørrelsen du kan forvente

Etter at du har bestemt parametrene, vil Embedding finne de bedre vektene for å transformere sekvensene til en tett matrise under trening. Den tette matrisestørrelsen er gitt av lengden på sekvenser og dimensjonaliteten til innebygningen.

Hvis du bruker Embedding-laget levert av Keras, må du huske at funksjonen bare gir en vektmatrise av størrelsen på vokabularet etter dimensjonen til ønsket innebygging. Den kartlegger ordene til kolonnene i matrisen og innstiller deretter matriksvektene til de medfølgende eksempler. Selv om denne løsningen er praktisk for ikke-standardiserte språkproblemer, er det ikke analogt med ordembeddlingene som er omtalt tidligere, som er trent på en annen måte og på flere millioner eksempler.

Eksemplet bruker toveisinnpakning - et LSTM-lag på 64 celler. Toveis transformerer et normalt LSTM-lag ved å doble det: På første side bruker det den normale sekvensen med innganger du gir; på den andre passerer det motsatt rekkefølge. Du bruker denne tilnærmingen fordi noen ganger bruker du ord i en forskjellig overordnet rekkefølge, og å bygge et toveis lag vil fange ethvert ordmønster, uansett rekkefølge. Implementeringen av Keras er faktisk grei: Du bruker den bare som en funksjon på det laget du vil gjengi toveis.

Den toveis LSTM er satt til å returnere sekvenser (return_sequences = True); det vil si at for hver celle returnerer det resultatet som gis etter å ha sett hvert element i sekvensen. Resultatene for hver sekvens er en utgangsmatrise på 200 x 128, hvor 200 er antall sekvenselementer og 128 er antall LSTM-celler som brukes i laget. Denne teknikken forhindrer RNN i å ta det siste resultatet av hver LSTM-celle. Tips om tekstens følelse kan faktisk vises hvor som helst i den innebygde ordssekvensen.

Kort sagt er det viktig å ikke ta det siste resultatet av hver celle, men heller det beste resultatet av den. Koden er derfor avhengig av følgende lag, GlobalMaxPool1D, for å sjekke hver sekvens av resultater levert av hver LSTM-celle og bare beholde det maksimale resultatet. Det skal sikre at eksemplet plukker det sterkeste signalet fra hver LSTM-celle, som forhåpentligvis er spesialisert ved sin trening for å velge noen meningsfylte signaler.

Etter at nevrale signaler er filtrert, har eksemplet et lag på 128 utganger, en for hver LSTM-celle. Koden reduserer og blander signalene ved å bruke et suksessivt tett lag på 16 nevroner med ReLU-aktivering (og får dermed bare positive signaler til å passere). Arkitekturen avsluttes med en endelig node ved bruk av sigmoid aktivering, som vil presse resultatene inn i 0–1 området og få dem til å se ut som sannsynligheter.

Etter å ha definert arkitekturen, kan du nå trene nettverket til å utføre sentimentanalyse. Tre epoker (ved å sende dataene tre ganger gjennom nettverket for å få dem til å lære mønstrene) vil være tilstrekkelig. Koden bruker grupper på 256 anmeldelser hver gang, noe som gjør at nettverket kan se nok utvalg av ord og følelser hver gang før oppdatering av vekten ved hjelp av tilbakestillering. Til slutt fokuserer koden på resultatene som gis av valideringsdataene (som ikke er en del av treningsdataene). Å få et godt resultat fra valideringsdataene betyr at nevrale nettet behandler inndata riktig. Koden rapporterer om valideringsdata like etter hver epoke er fullført.

history = model.fit (x_train, y_train,
validation_data = (x_test, y_test),
epoker = 3, batchstørrelse = 256)

Det tar litt tid å få resultatene, men hvis du bruker en GPU, vil den fullføre i løpet av tiden du tar å drikke en kopp kaffe. På dette tidspunktet kan du evaluere resultatene ved å bruke valideringsdataene igjen. (Resultatene skal ikke ha noen overraskelser eller forskjeller fra koden rapportert under trening.)

tap, metrisk = modell.evaluere (x_test, y_test, verbose = 0)
print ("Testnøyaktighet:% 0.3f"% metrisk)

Den endelige nøyaktigheten, som er prosentandelen av riktige svar fra det dype nevrale nettverket, vil være en verdi på rundt 85–86 prosent. Resultatet vil endres litt hver gang du kjører eksperimentet på grunn av randomisering når du bygger ditt nevrale nettverk. Det er helt normalt gitt den lille størrelsen på dataene du jobber med. Hvis du starter med de riktige heldige vektene, vil læringen bli lettere på en så kort treningsøkt.

Til slutt er nettverket ditt en sentimentanalysator som kan gjette sentimentet uttrykt i en filmanmeldelse riktig rundt 85 prosent av tiden. Gitt enda mer treningsdata og mer sofistikerte nevrale arkitekturer, kan du få resultater som er enda mer imponerende. I markedsføring brukes et lignende verktøy for å automatisere mange prosesser som krever lesing av tekst og iverksetting. Igjen, kan du koble et nettverk som dette med et nevralt nettverk som lytter til en stemme og gjør det til tekst. (Dette er en annen applikasjon av RNN-er, som nå driver Alexa, Siri, Google Voice og mange andre personlige assistenter.) Overgangen gjør at applikasjonen kan forstå stemningen selv i vokale uttrykk, for eksempel en telefonsamtale fra en kunde.