近年、自然言語処理技術は非常に高度になっています。テクノロジーの巨人から愛好家まで、多くの人が自然言語を分析、理解、応答できる豊富なインターフェースの構築を急いでいます。 AmazonのAlexa、MicrosoftのCortana、GoogleのGoogle Home、AppleのSiriはすべて、コンピューターとのやり取りの方法を変えることを目的としています。
自然言語処理のサブフィールドである感情分析は、テキストまたはスピーチのトーンを決定する手法で構成されています。今日、機械学習とソーシャルメディアやレビューサイトから収集された膨大な量のデータを使用して、モデルをトレーニングし、自然言語のパッセージの感情を妥当な精度で特定できます。
このチュートリアルでは、受信した電子メールの感情を分析し、すぐに注意が必要な可能性のある電子メールを通知できるボットを作成する方法を学習します。
ボットは、JavaとPythonを組み合わせて構築されます。 2つのプロセスは、Thriftを使用して相互に通信します。一方または両方の言語に精通していない場合は、この記事の基本的な概念が他の言語にも適用されるため、読み進めることができます。
電子メールに注意が必要かどうかを判断するために、ボットはそれを分析し、強い否定的なトーンがあるかどうかを判断します。その後、必要に応じてテキストアラートを送信します。
Sendgridを使用してメールボックスに接続し、Twilioがテキストアラートを送信します。 ##感情分析:一見単純な問題
愛、喜び、喜びなどのポジティブな感情に関連する言葉があります。そして、憎しみ、悲しみ、痛みなどの否定的な感情に関連する言葉があります。これらの単語を認識し、正と負の各単語の相対頻度と強さを数えるようにモデルをトレーニングしてみませんか?
さて、それにはいくつかの問題があります。
サーバーサイドレンダリングとは
まず、拒否の問題があります。たとえば、「桃は悪くない」のような文は、私たちがしばしば否定的であると関連付ける単語を使用した肯定的な感情を意味します。単純なバッグオブワードモデルでは、この文の否定を認識できません。
また、混合感情は、素朴な感情分析のもう1つの問題であることがわかります。たとえば、「桃は悪くないが、リンゴは本当にひどい」のような文には、互いに相互作用する混合された強さの混合された感情が含まれています。単純なアプローチでは、混合された感情、異なる強度、または感情間の相互作用を解決することはできません。
図書館 スタンフォード自然言語処理 forセンチメント分析は、再帰型ニューラルテンソルネットワーク(RNTN)を使用してこれらの問題を解決します。
RNTNアルゴリズムは、最初に文を個々の単語に分割します。次に、ノードが個々の単語であるニューラルネットワークを構築します。最後に、テンソルレイヤーが追加され、モデルが単語とフレーズの間の相互作用を適切に調整できるようになります。
あなたはあなたのアルゴリズムの視覚的なデモンストレーションを見つけることができます 公式サイト 。
スタンフォードNLPグループは、手動でタグ付けされたIMDBムービーの評価を使用して、再帰型ニューラルテンソルネットワークをトレーニングし、そのモデルが非常に高い精度で感情を予測できることを発見しました。
最初に行うことは、データをボットに転送できるように電子メール統合を設定することです。
これを実現する方法はたくさんありますが、簡単にするために、簡単なWebサーバーをセットアップし、Sendgridの入力解析フックを使用してメールをサーバーにパイプします。 Sendgridの受信分析アドレスにメールを転送できます。 SendgridはPOSTリクエストをウェブサーバーに送信し、サーバーを介してデータを処理できます。
サーバーを構築するために、Flaskを使用します。Flaskは、 Python 。
Webサーバーを構築することに加えて、Webサービスをドメインに接続する必要があります。要するに、これについての記事への書き込みはスキップします。しかし、あなたはこれについてもっと読むことができます ここに 。
でWebサーバーを作成する フラスコ それは信じられないほど簡単です。
app.py
を作成するだけですそしてそれをファイルに追加します:
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')
このアプリケーションをドメイン名の背後にデプロイし、エンドポイント「/分析」をクリックすると、次のように表示されます。
> >> requests.post ('http://sentiments.shanglunwang.com:5000/analyze') .text 'Lo tengo'
次に、このエンドポイントにメールを送信します。
あなたはより多くのドキュメントを見つけることができます ここに ただし、基本的には、Sendgridをメールプロセッサとして設定し、Sendgridがメールをウェブサーバーに転送する必要があります。
これがSendgridでの私の設定です。これにより、メールが@sentibot.shanglunwang.com
に転送されます。 「http://sentiments.shanglunwang.com/analyze」へのPOSTリクエストとして:
Webhookを介した受信メールの送信をサポートする他のサービスを使用できます。
すべてを設定したら、SendGridアドレスにメールを送信してみてください。ログに次のようなものが表示されるはずです。
endpoint hit 2017-05-25 14:35:46
それは素晴らしいことです!これで、メールを受信できるボットができました。それは私たちがやろうとしていることの半分です。
ここで、このボットに電子メールの感情を分析する機能を提供したいとします。
Stanford NLPライブラリはJavaで記述されているため、Javaで解析エンジンを構築する必要があります。
MavenにStanfordNLPライブラリとモデルをダウンロードすることから始めましょう。新しいプロジェクトを作成する Java 、Mavenの依存関係に以下を追加してインポートします。
edu.stanford.nlp stanford-corenlp 3.6.0
パイプライン初期化コードで感情アノテーターを指定することにより、StanfordNLP感情分析エンジンにアクセスできます。注釈はツリー構造として取得できます。
このチュートリアルでは、文の一般的な感情のみを知りたいので、ツリーを解析する必要はありません。ベースノードを確認するだけです。
これにより、メインコードが比較的単純になります。
知覚組織のゲシュタルト原則
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); } } }
いくつかの文を試してみると、適切な注釈が表示されます。サンプルコードの結果を実行します。
Muy positivo Negativo
つまり、Javaで記述された感情分析プログラムとPythonで記述された電子メールボットがあります。どうすれば彼らに話し合うことができますか?
この問題には多くの可能な解決策がありますが、ここでは使用します リサイクル 。 Sentiment AnalyzerをThriftサーバーとしてアクティブ化し、電子メールボットをThriftクライアントとしてアクティブ化します。
Thriftは、多くの場合異なる言語で記述された2つのアプリケーションが、定義されたプロトコルを使用して相互に通信できるようにするために使用されるコードジェネレーターおよびプロトコルです。 Polyglotチームは、Thriftを使用してマイクロサービスのネットワークを構築し、使用する各言語の長所を活用します。
Thriftを使用するには、次の2つが必要です。ファイル.thrift
サービスのエンドポイントと、ファイル .proto
で定義されたプロトコルを利用するために生成されたコードを定義します。パーサーサービスの場合、sentiment.thrift
次のようになります。
namespace java sentiment namespace py sentiment service SentimentAnalysisService { string sentimentAnalyze(1:string sentence), }
この.thriftファイルを使用してクライアントとサーバーのコードを生成できます。実行:
thrift-0.10.0.exe --gen py sentiment.thrift thrift-0.10.0.exe --gen java sentiment.thrift
注:Windowsマシンでコードをビルドします。環境内のThrift実行可能ファイルへの適切なパスを使用する必要があります。
それでは、スキャンエンジンに適切な変更を加えて、サーバーを作成しましょう。 Javaプログラムは次のようになります。
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); } }
このハンドラーは、Thriftプロトコルの分析要求を受け取る場所です。
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; } }
パーサーは、Stanford NLPライブラリを使用してテキストの感情を判別し、テキスト内の各文の感情注釈を含む文字列を生成します。
今年の緑色
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
これは生成されたファイルであるためです。生成されたコードは、残りのコードがアクセスできる場所に配置する必要があります。
サーバーが起動したので、サーバーを使用するPythonクライアントを作成しましょう。
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'))
これを実行すると、次のように表示されます。
Muy positivo
すごい!サーバーを実行してクライアントと通信しているので、クライアントをインスタンス化して電子メールに接続することにより、サーバーを電子メールロボットと統合しましょう。
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'
次に、Webサーバーを実行しているのと同じマシンにJavaサービスをデプロイし、サービスを開始して、アプリケーションを再起動します。ボットにテスト文を電子メールで送信すると、ログファイルに次のようなものが表示されます。
Increíblemente maravillosamente positiva y hermosa frase. Muy positivo
すべて良いです!これで、感情分析を実行できるメールボットができました。送信するすべての文について、メールを送信し、意見タグを受け取ることができます。それでは、インテリジェンスを実行可能にする方法を探りましょう。
物事を単純にするために、否定的な文と非常に否定的な文が集中している電子メールに焦点を当てましょう。簡単なスコアリングシステムを使用して、電子メールに75%を超える否定的な感情文が含まれている場合、即時の応答が必要になる可能性のある潜在的なアラーム電子メールとしてマークするとします。解析パスにスコアリングロジックを実装しましょう。
@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'
上記のコードはいくつかの仮定をしていますが、デモンストレーションの目的で機能します。ボットにいくつかのメールを送信すると、ログにメール分析が表示されます。
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
ほぼ完了です!
メールを受信し、感情分析を実行し、メールに早急な対応が必要かどうかを判断できるメールボットを作成しました。今では、電子メールが特に否定的な場合にのみ、テキストアラートを送信する必要があります。
Twilioを使用してテキストアラートを送信します。文書化されているPythonAPI ここに 、それは非常に簡単です。緊急のリクエストを受け取ったときにリクエストを送信するように分析パスを変更しましょう。
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'
Twilioアカウントの資格情報に環境変数を設定し、確認できる電話に発信者番号を設定する必要があります。それが完了したら、スキャンのエンドポイントに電子メールを送信すると、問題の電話番号に送信されたテキストメッセージが表示されます。
そして終了しました!
この記事では、StanfordNLPライブラリを使用して電子メール感情分析ボットを構築する方法を学びました。このライブラリは、自然言語処理のすべての重要な詳細を抽象化するのに役立ち、NLPアプリケーションの構成要素として使用できます。
この投稿が、感情分析の多くの驚くべき潜在的なアプリケーションの1つを示し、これが独自のNLPアプリケーションを作成するきっかけになることを願っています。