Naturlig språkbehandlingsteknologi har blitt ganske sofistikert de siste årene. Fra tekniske giganter til hobbyister, skynder mange seg å bygge rike grensesnitt som kan analysere, forstå og svare på naturlig språk. Amazons Alexa, Microsofts Cortana, Googles Google Home og Apples Siri tar sikte på å endre måten vi kommuniserer med datamaskiner på.
Sentimentanalyse, et underfelt av naturlig språkbehandling, består av teknikker som bestemmer tonen i en tekst eller tale. I dag, med maskinlæring og den enorme mengden data samlet inn fra sosiale medier og gjennomgangssider, kan vi trene modeller for å identifisere følelsen av en naturlig språkpassasje med rimelig presisjon.
I denne opplæringen lærer du hvordan du kan lage en bot som kan analysere følelsen av e-postene du mottar og varsle deg om e-post som kan kreve oppmerksomhet umiddelbart.
Boten bygges ved hjelp av en blanding av Java og Python. De to prosessene vil kommunisere med hverandre ved hjelp av Thrift. Hvis du ikke er kjent med ett eller begge språkene, kan du lese videre, da de grunnleggende begrepene i denne artikkelen også gjelder andre språk.
For å avgjøre om en e-post trenger din oppmerksomhet, vil boten analysere den og avgjøre om det er en sterk negativ tone. Det vil da sende et tekstvarsel om nødvendig.
Vi bruker Sendgrid for å koble til postkassen vår, og Twilio vil sende tekstvarsler. ## Sentimentanalyse: et villedende enkelt problem
Det er ord vi forbinder med positive følelser, som kjærlighet, glede og glede. Og det er ord vi forbinder med negative følelser, som hat, tristhet og smerte. Hvorfor ikke trene modellen til å gjenkjenne disse ordene og telle den relative frekvensen og styrken til hvert positive og negative ord?
Vel, det er et par problemer med det.
For det første er det et fornektelsesproblem. For eksempel innebærer en setning som 'Fersken ikke dårlig' en positiv følelse ved å bruke et ord som vi ofte forbinder med å være negativt. En enkel pose med ordmodell vil ikke kunne gjenkjenne negasjonen i denne setningen.
Også blandede følelser viser seg å være et annet problem med naiv sentimentanalyse. For eksempel inneholder en setning som 'Ferskenen ikke dårlig, men eplet er virkelig forferdelig' blandede følelser av blandede intensiteter som samhandler med hverandre. En enkel tilnærming vil ikke være i stand til å løse blandede følelser, forskjellig intensitet eller interaksjoner mellom følelser.
Bibliotek Stanford Natural Language Processing for sentimentanalyse løser disse problemene ved hjelp av et Recursive Neural Tensor Network (RNTN).
RNTN-algoritmen deler først en setning i individuelle ord. Bygg deretter et nevralt nettverk der nodene er de enkelte ordene. Til slutt tilsettes et tensorlag slik at modellen kan justere samspillet mellom ord og uttrykk riktig.
Du kan finne en visuell demonstrasjon av algoritmen i din offesiell nettside .
Stanford NLP-gruppen trente Recursive Neural Tensor Network ved hjelp av evalueringer av manuelt merkede IMDB-filmer og fant at modellen deres er i stand til å forutsi følelse med veldig god presisjon.
Den første tingen å gjøre er å konfigurere e-postintegrasjonen slik at dataene kan overføres til boten din.
Det er mange måter å oppnå dette på, men la oss for enkelhets skyld sette opp en enkel webserver og bruke Sendgrids inngangsparseringskrok til å sende e-post til serveren. Vi kan videresende e-post til Sendgrids innkommende analyseadresse. Sendgrid vil sende en POST-forespørsel til webserveren vår, og så kan vi behandle dataene via serveren vår.
For å bygge serveren vil vi bruke Flask, et enkelt nettrammeverk for Python .
I tillegg til å bygge webserveren, vil vi koble webtjenesten til et domene. Kort fortalt hopper vi over å skrive om dette i artikkelen. Du kan imidlertid lese mer om dette her .
Opprett en webserver i Kolbe det er utrolig enkelt.
Bare lag en app.py
og legg den til i filen:
from flask import Flask, request import datetime app = Flask(__name__) @app.route('/analyze', methods=['POST']) def analyze(): with open('logfile.txt', 'a') as fp_log: fp_log.write('endpoint hit %s
' % datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')) return 'Got it' app.run(host='0.0.0.0')
Hvis vi distribuerer dette programmet bak et domenenavn og klikker på sluttpunktet '/ analyse', bør du se noe slikt:
> >> requests.post ('http://sentiments.shanglunwang.com:5000/analyze') .text 'Lo tengo'
Deretter vil vi sende e-post til dette sluttpunktet.
Du finner mer dokumentasjon her men i utgangspunktet vil du konfigurere Sendgrid til å være din e-postprosessor og Sendgrid videresende e-postene til webserveren vår.
Her er konfigurasjonen min i Sendgrid. Dette vil videresende e-post til @sentibot.shanglunwang.com
som POST ber om til “http://sentiments.shanglunwang.com/analyze”:
Du kan bruke hvilken som helst annen tjeneste som støtter sending av innkommende e-post via webhooks.
Når du har konfigurert alt, kan du prøve å sende en e-post til SendGrid-adressen. Du bør se noe slikt i loggene:
endpoint hit 2017-05-25 14:35:46
Det er flott! Nå har du en bot som kan motta e-post. Det er halvparten av det vi prøver å gjøre.
Nå vil du gi denne bot muligheten til å analysere følelser i e-post.
Siden Stanford NLP-biblioteket er skrevet på Java, vil vi bygge analyseringsmotoren i Java.
La oss komme i gang ved å laste ned Stanford NLP-bibliotek og modeller på Maven. Lag et nytt prosjekt Java , legg til følgende i dine Maven-avhengigheter og importer:
edu.stanford.nlp stanford-corenlp 3.6.0
Stanford NLP-sentimentanalysemotoren kan nås ved å spesifisere sentimentkommentatoren i initialiseringskoden for rørledningen. Kommentaren kan hentes som en trestruktur.
I forbindelse med denne opplæringen ønsker vi bare å vite den generelle følelsen av en setning, så det vil ikke være nødvendig å analysere treet. Vi må bare se på basenoden.
Dette gjør hovedkoden relativt enkel:
package seanwang; import edu.stanford.nlp.pipeline.*; import edu.stanford.nlp.util.CoreMap; import edu.stanford.nlp.ling.CoreAnnotations; import edu.stanford.nlp.sentiment.SentimentCoreAnnotations; import java.util.*; public class App { public static void main( String[] args ) { Properties pipelineProps = new Properties(); Properties tokenizerProps = new Properties(); pipelineProps.setProperty('annotators', 'parse, sentiment'); pipelineProps.setProperty('parse.binaryTrees', 'true'); pipelineProps.setProperty('enforceRequirements', 'false'); tokenizerProps.setProperty('annotators', 'tokenize ssplit'); StanfordCoreNLP tokenizer = new StanfordCoreNLP(tokenizerProps); StanfordCoreNLP pipeline = new StanfordCoreNLP(pipelineProps); String line = 'Los amigos hermosos increíblemente agradecidos están cumpliendo un logro increíblemente alegre. ¡Qué idea verdaderamente terrible!'; Annotation annotation = tokenizer.process(line); pipeline.annotate(annotation); // normal output for (CoreMap sentence : annotation.get(CoreAnnotations.SentencesAnnotation.class)) { String output = sentence.get(SentimentCoreAnnotations.SentimentClass.class); System.out.println(output); } } }
Prøv noen setninger, og du bør se de riktige kommentarene. Kjører resultatene av eksempelkoden:
Muy positivo Negativo
Så vi har et sentimentanalysatorprogram skrevet i Java og en e-post bot skrevet i Python. Hvordan får vi dem til å snakke med hverandre?
Det er mange mulige løsninger på dette problemet, men her vil vi bruke Sparsommelighet . Vi vil aktivere Sentiment Analyzer som en Thrift-server og e-postboten som en Thrift-klient.
Thrift er en kodegenerator og protokoll som brukes til å gjøre det mulig for to applikasjoner, ofte skrevet på forskjellige språk, å kunne kommunisere med hverandre ved hjelp av en definert protokoll. Polyglot-team bruker Thrift til å bygge nettverk av mikrotjenester for å dra nytte av det beste fra hvert språk de bruker.
For å bruke Thrift trenger vi to ting: en fil .thrift
for å definere sluttpunktene til tjenesten og en kode generert for å gjøre bruk av protokollen definert i filen .proto
. For parsertjenesten, sentiment.thrift
det ser slik ut:
namespace java sentiment namespace py sentiment service SentimentAnalysisService { string sentimentAnalyze(1:string sentence), }
Vi kan generere klient- og serverkode ved hjelp av denne .thrift-filen. Løpe:
thrift-0.10.0.exe --gen py sentiment.thrift thrift-0.10.0.exe --gen java sentiment.thrift
Merk: Bygg koden på en Windows-maskin. Du må bruke riktig vei til Thrift-kjørbarheten i ditt miljø.
La oss nå gjøre de nødvendige endringene i skannemotoren for å opprette en server. Java-programmet ditt skal se slik ut:
SentimentHandler.java
package seanwang; public class SentimentHandler implements SentimentAnalysisService.Iface { SentimentAnalyzer analyzer; SentimentHandler() { analyzer = new SentimentAnalyzer(); } public String sentimentAnalyze(String sentence) { System.out.println('got: ' + sentence); return analyzer.analyze(sentence); } }
Denne behandleren er der vi mottar forespørselen om analyse av Thrift-protokollen.
SentimentAnalyzer.java
package seanwang; // ... public class SentimentAnalyzer { StanfordCoreNLP tokenizer; StanfordCoreNLP pipeline; public SentimentAnalyzer() { Properties pipelineProps = new Properties(); Properties tokenizerProps = new Properties(); pipelineProps.setProperty('annotators', 'parse, sentiment'); pipelineProps.setProperty('parse.binaryTrees', 'true'); pipelineProps.setProperty('enforceRequirements', 'false'); tokenizerProps.setProperty('annotators', 'tokenize ssplit'); tokenizer = new StanfordCoreNLP(tokenizerProps); pipeline = new StanfordCoreNLP(pipelineProps); } public String analyze(String line) { Annotation annotation = tokenizer.process(line); pipeline.annotate(annotation); String output = ''; for (CoreMap sentence : annotation.get(CoreAnnotations.SentencesAnnotation.class)) { output += sentence.get(SentimentCoreAnnotations.SentimentClass.class); output += '
'; } return output; } }
Parseren bruker Stanford NLP-biblioteket for å bestemme følelsen av teksten og produserer en streng som inneholder sentimentkommentarene for hver setning i teksten.
SentimentServer.java
package seanwang; // ... public class SentimentServer { public static SentimentHandler handler; public static SentimentAnalysisService.Processor processor; public static void main(String [] args) { try { handler = new SentimentHandler(); processor = new SentimentAnalysisService.Processor(handler); Runnable simple = new Runnable() { public void run() { simple(processor); } }; new Thread(simple).start(); } catch (Exception x) { x.printStackTrace(); } } public static void simple(SentimentAnalysisService.Processor processor) { try { TServerTransport serverTransport = new TServerSocket(9090); TServer server = new TSimpleServer(new Args(serverTransport).processor(processor)); System.out.println('Starting the simple server...'); server.serve(); } catch (Exception e) { e.printStackTrace(); } } }
Merk at jeg ikke inkluderte filen SentimentAnalysisService.java
her fordi det er en generert fil. Du bør plassere den genererte koden på et sted der resten av koden din har tilgang til den.
Nå som vi har serveren oppe, la oss skrive en Python-klient for å bruke serveren.
client.py
from sentiment import SentimentAnalysisService from thrift.transport import TSocket from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol class SentimentClient: def __init__(self, server='localhost', socket=9090): transport = TSocket.TSocket(server, socket) transport = TTransport.TBufferedTransport(transport) protocol = TBinaryProtocol.TBinaryProtocol(transport) self.transport = transport self.client = SentimentAnalysisService.Client(protocol) self.transport.open() def __del__(self): self.transport.close() def analyze(self, sentence): return self.client.sentimentAnalyze(sentence) if __name__ == '__main__': client = SentimentClient() print(client.analyze('An amazingly wonderful sentence'))
Kjør dette, og du bør se:
Muy positivo
Flott! Nå som vi har serveren som kjører og snakker med klienten, la oss integrere den med e-postroboten ved å starte en klient og koble den til e-posten.
import client # ... @app.route('/analyze', methods=['POST']) def analyze(): sentiment_client = client.SentimentClient() with open('logfile.txt', 'a') as fp_log: fp_log.write(str(request.form.get('text'))) fp_log.write(request.form.get('text')) fp_log.write(sentiment_client.analyze(request.form.get('text'))) return 'Got it'
Nå distribuerer du Java-tjenesten på samme maskin som du kjører webserveren, starter tjenesten og starter applikasjonen på nytt. Send boten med en testsetning via e-post, og du bør se noe slikt i loggfilen:
Increíblemente maravillosamente positiva y hermosa frase. Muy positivo
Helt fint! Nå har vi en e-post bot som kan utføre sentimentanalyse! Vi kan sende en e-post og motta en meningsmerke for hver setning vi sender. La oss nå utforske hvordan vi kan gjøre intelligens handlingsbar.
For å holde ting enkelt, la oss fokusere på e-post der det er høy konsentrasjon av negative og svært negative setninger. La oss bruke et enkelt poengsystem og si at hvis en e-post inneholder mer enn 75% negative setningssetninger, vil vi markere den som en potensiell alarm-e-post som kan kreve et øyeblikkelig svar. La oss implementere poenglogikken i analysebanen:
@app.route('/analyze', methods=['POST']) def analyze(): text = str(request.form.get('text')) sentiment_client = client.SentimentClient() text.replace('
', '') # remove all new lines sentences = text.rstrip('.').split('.') # remove the last period before splitting negative_sentences = [ sentence for sentence in sentences if sentiment_client.analyze(sentence).rstrip() in ['Negative', 'Very negative'] # remove newline char ] urgent = len(negative_sentences) / len(sentences) > 0.75 with open('logfile.txt', 'a') as fp_log: fp_log.write('Received: %s' % (request.form.get('text'))) fp_log.write('urgent = %s' % (str(urgent))) return 'Got it'
Ovennevnte kode gir noen antakelser, men den vil fungere for demonstrasjonsformål. Send et par e-poster til boten din, og du bør se e-postanalysen i loggene:
Recibido: Aquí hay una prueba para el sistema. Se supone que es una solicitud no urgente. ¡Es muy bueno! En su mayor parte esto es positivo o neutral. Grandes cosas están sucediendo! urgente = Falso Recibido: esta es una solicitud urgente. Todo es realmente horrible Esto es un desastre. La gente odia este correo insípido. urgente = True
Vi er nesten ferdige!
Vi har opprettet en e-post bot som kan motta e-post, utføre sentimentanalyse og avgjøre om en e-post krever øyeblikkelig oppmerksomhet. Nå trenger vi bare sende et tekstvarsel når en e-post er spesielt negativ.
Vi bruker Twilio til å sende et tekstvarsel. Din Python API, som er dokumentert her , det er ganske enkelt. La oss endre analysebanen for å sende inn en forespørsel når du mottar en presserende forespørsel.
def send_message(body): twilio_client.messages.create( to=on_call, from_=os.getenv('TWILIO_PHONE_NUMBER'), body=body ) app = Flask(__name__) @app.route('/analyze', methods=['POST']) def analyze(): text = str(request.form.get('text')) sentiment_client = client.SentimentClient() text.replace('
', '') # remove all new lines sentences = text.rstrip('.').split('.') # remove the last period before splitting negative_sentences = [ sentence for sentence in sentences if sentiment_client.analyze(sentence).rstrip() in ['Negative', 'Very negative'] # remove newline char ] urgent = len(negative_sentences) / len(sentences) > 0.75 if urgent: send_message('Highly negative email received. Please take action') with open('logfile.txt', 'a') as fp_log: fp_log.write('Received: ' % request.form.get('text')) fp_log.write('urgent = %s' % (str(urgent))) fp_log.write('
') return 'Got it'
Du må angi miljøvariablene i påloggingsinformasjonen til Twilio-kontoen din og angi telefonnummeret til en telefon som det kan bekrefte. Når du har gjort det, send en e-post til endepunktet for skanningen, så ser du en tekstmelding sendt til det aktuelle telefonnummeret.
Og vi er ferdige!
I denne artikkelen lærte du hvordan du lager en analyse-sentimentanalysebot ved hjelp av Stanford NLP-bibliotek. Biblioteket hjelper til med å trekke ut alle viktige detaljer i prosessering av naturlig språk og lar deg bruke det som en byggestein for NLP-applikasjonene dine.
Jeg håper dette innlegget har vist en av de mange fantastiske potensielle applikasjonene for sentimentanalyse, og at dette inspirerer deg til å lage din egen NLP-applikasjon.