E-posta Duyarlılık Analizi Botu Nasıl Oluşturulur: Bir NLP Eğitimi

Yayınlanan: 2022-03-11

Doğal dil işleme teknolojileri son birkaç yılda oldukça karmaşık hale geldi. Teknoloji devlerinden hobi meraklılarına kadar pek çok kişi, doğal dili analiz edebilen, anlayabilen ve bunlara yanıt verebilen zengin arayüzler oluşturmak için acele ediyor. Amazon'un Alexa'sı, Microsoft'un Cortana'sı, Google'ın Google Home'u ve Apple'ın Siri'si, bilgisayarlarla etkileşim biçimimizi değiştirmeyi amaçlıyor.

Doğal dil işlemenin bir alt alanı olan duygu analizi, bir metnin veya konuşmanın tonunu belirleyen tekniklerden oluşur. Bugün, makine öğrenimi ve sosyal medyadan ve inceleme sitelerinden toplanan büyük miktarda veriyle, doğal bir dil pasajının duyarlılığını adil bir doğrulukla belirlemek için modeller eğitebiliriz.

E-posta duyarlılık analizi bot eğitimi

Bu eğitimde, aldığı e-postaların duyarlılığını analiz edebilen ve hemen ilgilenmenizi gerektirebilecek e-postalar hakkında sizi bilgilendirebilen bir botu nasıl oluşturabileceğinizi öğreneceksiniz.

E-postalardaki Duyguyu Analiz Etme

Bot, Java ve Python geliştirmesinin bir karışımı kullanılarak oluşturulacak. İki süreç, Thrift kullanarak birbirleriyle iletişim kuracaktır. Bu dillerden birine veya her ikisine aşina değilseniz, bu makalenin temel kavramları diğer diller için de geçerli olacağından okumaya devam edebilirsiniz.

Bir e-postanın ilgilenmeniz gerekip gerekmediğini belirlemek için bot, onu ayrıştırır ve güçlü bir olumsuz ton olup olmadığını belirler. Daha sonra gerekirse bir metin uyarısı gönderir.

Posta kutumuza bağlanmak için Sendgrid'i ve metin uyarıları göndermek için Twilio'yu kullanacağız.

Duygu Analizi: Aldatıcı Bir Şekilde Basit Bir Problem

Sevgi, neşe ve zevk gibi olumlu duygularla ilişkilendirdiğimiz kelimeler vardır. Ve nefret, üzüntü ve acı gibi olumsuz duygularla ilişkilendirdiğimiz kelimeler var. Neden modeli bu sözcükleri tanıması ve her olumlu ve olumsuz sözcüğün göreli sıklığını ve gücünü sayması için eğitmiyorsunuz?

Bununla ilgili birkaç sorun var.

İlk olarak, bir olumsuzlama sorunu var. Örneğin, "Şeftali fena değil" gibi bir cümle, çoğunlukla olumsuz olmakla ilişkilendirdiğimiz bir kelimeyi kullanarak olumlu bir duyguyu ifade eder. Basit bir kelime torbası modeli bu cümledeki olumsuzlamayı tanıyamayacaktır.

Ayrıca, karışık duygular, saf duygu analiziyle ilgili başka bir sorun olduğunu kanıtlıyor. Örneğin, "Şeftali fena değil, ama elma gerçekten korkunç" gibi bir cümle, birbiriyle etkileşime giren karışık yoğunluktaki karışık duyguları içerir. Basit bir yaklaşım, birleşik duyguları, farklı yoğunluğu veya duygular arasındaki etkileşimleri çözemez.

Özyinelemeli Sinir Tensör Ağı Kullanılarak Duyarlılık Analizi

Duygu analizi için Stanford Doğal Dil İşleme kitaplığı, bu sorunları Özyinelemeli Sinir Tensör Ağı (RNTN) kullanarak çözer.

bir cümle üzerinde RNTN

RNTN algoritması önce bir cümleyi tek tek kelimelere böler. Daha sonra, düğümlerin tek tek kelimeler olduğu bir sinir ağı oluşturur. Son olarak, modelin kelimeler ve deyimler arasındaki etkileşimleri uygun şekilde ayarlayabilmesi için bir tensör katmanı eklenir.

Algoritmanın görsel bir gösterimini resmi web sitelerinde bulabilirsiniz.

Stanford NLP grubu, manuel olarak etiketlenen IMDB film incelemelerini kullanarak Özyinelemeli Sinir Tensor Ağını eğitti ve modellerinin duyarlılığı çok iyi bir doğrulukla tahmin edebildiğini buldu.

E-posta Alan Bot

Yapmak istediğiniz ilk şey, e-posta entegrasyonunu ayarlamaktır, böylece veriler botunuza iletilebilir.

Bunu başarmanın birçok yolu vardır, ancak basitlik adına, basit bir web sunucusu kuralım ve e-postaları sunucuya iletmek için Sendgrid'in gelen ayrıştırma kancasını kullanalım. E-postaları Sendgrid'in gelen ayrıştırma adresine yönlendirebiliriz. Sendgrid daha sonra web sunucumuza bir POST isteği gönderecek ve ardından verileri sunucumuz aracılığıyla işleyebileceğiz.

Sunucuyu oluşturmak için Python için basit bir web çerçevesi olan Flask'ı kullanacağız.

Web sunucusunu oluşturmaya ek olarak, web hizmetini bir etki alanına bağlamak isteyeceğiz. Kısaca, bu konuda makalede yazmayı atlayacağız. Ancak, bununla ilgili daha fazla bilgiyi buradan okuyabilirsiniz.

Flask'ta bir web sunucusu oluşturmak inanılmaz derecede basittir.

Basitçe bir app.py oluşturun ve bunu dosyaya ekleyin:

 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 \n' % datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')) return "Got it" app.run(host='0.0.0.0')

Bu uygulamayı bir alan adının arkasına yerleştirirsek ve “/analyze” uç noktasına ulaşırsak, şunun gibi bir şey görmelisiniz:

 > >> requests.post('http://sentiments.shanglunwang.com:5000/analyze').text 'Got it'

Ardından, bu uç noktaya e-posta göndermek istiyoruz.

Burada daha fazla belge bulabilirsiniz, ancak esas olarak Sendgrid'i e-posta işlemciniz olarak ayarlamak ve Sendgrid'in e-postaları web sunucumuza yönlendirmesini sağlamak istiyorsunuz.

İşte Sendgrid'deki kurulumum. Bu, e-postaları "http://sentiments.shanglunwang.com/analyze" adresine POST istekleri olarak @sentibot.shanglunwang.com iletecektir:

Sendgrid yapılandırması

Web kancaları üzerinden gelen e-posta göndermeyi destekleyen herhangi bir hizmeti kullanabilirsiniz.

Her şeyi ayarladıktan sonra Sendgrid adresinize bir e-posta göndermeyi deneyin, Günlüklerde şöyle bir şey görmelisiniz:

 endpoint hit 2017-05-25 14:35:46

Bu harika! Artık e-posta alabilen bir botunuz var. Yapmaya çalıştığımız işin yarısı bu.

Şimdi, bu bota e-postalardaki duyguları analiz etme yeteneği vermek istiyorsunuz.

Stanford NLP ile E-posta Duyarlılık Analizi

Stanford NLP kütüphanesi Java ile yazıldığı için analiz motorunu Java ile kurmak isteyeceğiz.

Maven'deki Stanford NLP kitaplığını ve modellerini indirerek başlayalım. Yeni bir Java projesi oluşturun, aşağıdakileri Maven bağımlılıklarınıza ekleyin ve içe aktarın:

 <dependency> <groupId>edu.stanford.nlp</groupId> <artifactId>stanford-corenlp</artifactId> <version>3.6.0</version> </dependency>

Stanford NLP'nin duygu analizi motoruna, işlem hattı başlatma kodunda duygu açıklayıcısı belirtilerek erişilebilir. Açıklama daha sonra bir ağaç yapısı olarak alınabilir.

Bu öğreticinin amaçları doğrultusunda, sadece bir cümlenin genel hissini bilmek istiyoruz, bu yüzden ağaçta ayrıştırma yapmamıza gerek kalmayacak. Sadece temel düğüme bakmamız gerekiyor.

Bu, ana kodu nispeten basit hale getirir:

 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 = "Amazingly grateful beautiful friends are fulfilling an incredibly joyful accomplishment. What an truly terrible idea."; 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); } } }

Birkaç cümle deneyin ve uygun açıklamaları görmelisiniz. Örnek kod çıktılarının çalıştırılması:

 Very Positive Negative

Bot ve Analiz Motorunu Entegre Etme

Yani Java ile yazılmış bir duygu analiz programımız ve Python ile yazılmış bir e-posta botumuz var. Birbirleriyle konuşmalarını nasıl sağlarız?

Bu sorunun birçok olası çözümü var, ancak burada Thrift'i kullanacağız. Sentiment Analyzer'ı bir Thrift sunucusu ve e-posta botunu Thrift istemcisi olarak çalıştıracağız.

Thrift, genellikle farklı dillerde yazılmış iki uygulamanın tanımlı bir protokol kullanarak birbirleriyle iletişim kurabilmesini sağlamak için kullanılan bir kod üreticisi ve protokoldür. Polyglot ekipleri, kullandıkları her dilden en iyi şekilde yararlanmak için mikro hizmet ağları oluşturmak için Thrift'i kullanır.

Thrift'i kullanmak için iki şeye ihtiyacımız olacak: hizmet uç noktalarını tanımlamak için bir .thrift dosyası ve .proto dosyasında tanımlanan protokolü kullanmak için oluşturulan kod. Analizör hizmeti için, sentiment.thrift şöyle görünür:

 namespace java sentiment namespace py sentiment service SentimentAnalysisService { string sentimentAnalyze(1:string sentence), }

Bu .thrift dosyasını kullanarak istemci ve sunucu kodu üretebiliriz. Koşmak:

 thrift-0.10.0.exe --gen py sentiment.thrift thrift-0.10.0.exe --gen java sentiment.thrift

Not: Kodu bir Windows makinesinde oluşturdum. Ortamınızda Thrift yürütülebilir dosyasına uygun yolu kullanmak isteyeceksiniz.

Şimdi bir sunucu oluşturmak için analiz motorunda uygun değişiklikleri yapalım. Java programınız şöyle görünmelidir:

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); } }

Bu işleyici, Thrift protokolü üzerinden analiz talebini aldığımız yerdir.

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 += "\n"; } return output; } }

Çözümleyici, metnin duyarlılığını belirlemek için Stanford NLP kitaplığını kullanır ve metindeki her cümle için duygu açıklamalarını içeren bir dize üretir.

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(); } } }

SentimentAnalysisService.java dosyasını oluşturulmuş bir dosya olduğu için buraya eklemediğimi unutmayın. Oluşturulan kodu, kodunuzun geri kalanının erişebileceği bir yere koymak isteyeceksiniz.

Artık sunucumuz hazır olduğuna göre, sunucuyu kullanmak için bir Python istemcisi yazalım.

müşteri.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'))

Bunu çalıştırın ve görmelisiniz:

 Very Positive

Harika! Artık çalışan ve istemciyle konuşan bir sunucumuz olduğuna göre, bir istemci başlatıp e-postayı ona aktararak onu e-posta botuyla bütünleştirelim.

 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"

Şimdi Java hizmetinizi web sunucusunu çalıştırdığınız makineye dağıtın, hizmeti başlatın ve uygulamayı yeniden başlatın. Bot'a bir test cümlesi içeren bir e-posta gönderin ve günlük dosyasında şöyle bir şey görmelisiniz:

 Amazingly wonderfully positive and beautiful sentence. Very Positive

E-postayı Analiz Etme

Tamam! Artık duygu analizi yapabilen bir e-posta botumuz var! Bir e-posta gönderebilir ve gönderdiğimiz her cümle için bir duygu etiketi alabiliriz. Şimdi, istihbaratı nasıl eyleme geçirilebilir hale getirebileceğimizi keşfedelim.

İşleri basit tutmak için, olumsuz ve çok olumsuz cümlelerin yoğun olarak bulunduğu e-postalara odaklanalım. Basit bir puanlama sistemi kullanalım ve bir e-posta %75'ten fazla olumsuz duygu cümlesi içeriyorsa, bunu anında yanıt gerektirebilecek potansiyel bir alarm e-postası olarak işaretleyeceğimizi söyleyelim. Analiz rotasında puanlama mantığını uygulayalım:

 @app.route('/analyze', methods=['POST']) def analyze(): text = str(request.form.get('text')) sentiment_client = client.SentimentClient() text.replace('\n', '') # 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"

Yukarıdaki kod birkaç varsayımda bulunur, ancak gösterim amacıyla çalışacaktır. Botunuza birkaç e-posta gönderin ve günlüklerde e-posta analizini görmelisiniz:

 Received: Here is a test for the system. This is supposed to be a non-urgent request. It's very good! For the most part this is positive or neutral. Great things are happening! urgent = False Received: This is an urgent request. Everything is truly awful. This is a disaster. People hate this tasteless mail. urgent = True

Bir Uyarı Gönderme

Neredeyse tamamız!

E-postaları alabilen, duyarlılık analizi gerçekleştirebilen ve bir e-postanın hemen ilgilenilmesini gerektirip gerektirmediğini belirleyen bir e-posta botu oluşturduk. Şimdi, bir e-posta özellikle olumsuz olduğunda bir metin uyarısı göndermemiz gerekiyor.

Bir metin uyarısı göndermek için Twilio'yu kullanacağız. Burada belgelenen Python API'leri oldukça basittir. Acil bir istek aldığında bir istek göndermek için analiz yolunu değiştirelim.

 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('\n', '') # 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("\n") return "Got it"

Ortam değişkenlerinizi Twilio hesap kimlik bilgilerinize ayarlamanız ve arama numarasını kontrol edebileceğiniz bir telefona ayarlamanız gerekecektir. Bunu yaptıktan sonra, analiz uç noktasına bir e-posta gönderin; söz konusu telefon numarasına bir metin gönderildiğini görmelisiniz.

Ve işimiz bitti!

Stanford NLP ile Doğal Dil İşleme Kolaylaştı

Bu makalede, Stanford NLP kitaplığını kullanarak bir e-posta duyarlılık analizi botunun nasıl oluşturulacağını öğrendiniz. Kütüphane, doğal dil işlemenin tüm önemli ayrıntılarını soyutlamaya yardımcı olur ve onu NLP uygulamalarınız için bir yapı taşı olarak kullanmanıza olanak tanır.

Umarım bu gönderi, duygu analizinin birçok şaşırtıcı potansiyel uygulamasından birini göstermiştir ve bu, kendi NLP uygulamanızı oluşturmanız için size ilham verir.

E-posta duyarlılık analizi botunun kodunu GitHub'daki bu NLP eğitiminde bulabilirsiniz.

İlgili: Duygu Analizi Doğruluğunun Dört Tuzağı