肯定的ですか? 否定的ですか? 中立的ですか? Stanford CoreNLP コンポーネントと数行のコードを使用して文章を分析します。 [[442118]] この記事では、自然言語処理用のオープンソース ライブラリである Stanford CoreNLP に統合された感情ツールを使用して、このようなタスクを Java で実装する方法について説明します。 スタンフォード CoreNLP 感情分類器感情分析を実行するには、トレーニング データセットから学習した予測に基づいて感情情報を識別できるツールである感情分類器が必要です。 Stanford CoreNLP では、感情分類器は、Stanford Sentiment Treebank (SST) でトレーニングされたリカレント ニューラル ネットワーク (RNN) ディープラーニング モデルに基づいて構築されています。 SST データセットは、感情ラベル付けされたコーパスであり、構文的に可能なすべてのフレーズが何千もの使用済み文から派生しており、テキスト内の感情の構成効果を捉えることができます。簡単に言えば、これによりモデルは単語を単独で評価するのではなく、単語がフレーズの意味をどのように形成するかに基づいて感情を識別できるようになります。 SST データセットの構造をより深く理解するには、Stanford CoreNLP 感情分析ページからデータセット ファイルをダウンロードしてください。 Java コードでは、Stanford CoreNLP 感情分類器は次のように使用されます。 まず、トークン化、分割、解析、感情などの感情分析を実行するために必要なアノテーターを追加して、テキスト処理パイプラインを構築します。 Stanford CoreNLP のコンテキストでは、アノテーターは、ドキュメント内のテキストの一部を表す注釈オブジェクトを操作するインターフェースです。 たとえば、トークン シーケンスを文に分割するには、ssplit アノテーターが必要です。 Stanford CoreNLP は文ごとに感情を計算します。 したがって、感情アノテーターを適用した後は必ず、テキストを文に分割するプロセスが続きます。 テキストが文に分割されると、解析アノテーターは構文依存関係の解析を実行し、各文の依存関係表現を生成します。 次に、感情アノテーターはこれらの依存関係の表現を処理し、基礎となるモデルと比較して、各文の感情ラベル (アノテーション) を含むバイナリ ツリーを構築します。 簡単に言えば、ツリーのノードは入力文のトークンによって決定され、文から派生したすべてのフレーズに対して、非常に否定的なものから非常に肯定的なものまで 5 つの感情カテゴリの中から予測されるカテゴリを示す注釈が含まれます。 これらの予測に基づいて、感情アノテーターは文全体の感情を計算します。 Stanford CoreNLP の設定Stanford CoreNLP の使用を開始する前に、次の設定を行う必要があります。 Stanford CoreNLP を実行するには、Java 1.8 以上が必要です。 Stanford CoreNLP パッケージをダウンロードし、パッケージをマシン上のローカル フォルダーに解凍します。 ダウンロードアドレス: https://nlp.stanford.edu/software/stanford-corenlp-latest.zip この記事では、上記のコードを例として、次のディレクトリに解凍します。 c:/softwareInstall/corenlp/stanford-corenlp-4.3.2 上記の手順を完了すると、Stanford CoreNLP パイプラインを実行してテキストを処理する Java プログラムを作成する準備が整います。 まず、新しい Maven プロジェクトを作成し、stanford-corenlp-4.3.2 をライブラリに手動で追加します。 次の例では、Stanford CoreNLP パイプラインを実行して複数の文を含むテキストの感情分析を実行する簡単な Java プログラムを実装します。 まず、パイプラインを初期化するメソッドと、このパイプラインを使用して送信されたテキストを文に分割し、各文の感情を分類するメソッドを提供する NlpPipeline クラスを実装します。 以下は NlpPipeline クラスのコードです。 - パッケージ com.zh.ch.corenlp;
-
- edu.stanford.nlp.ling.CoreAnnotations をインポートします。
- edu.stanford.nlp.neural.rnn.RNNCoreAnnotations をインポートします。
- edu.stanford.nlp.pipeline.Annotation をインポートします。
- edu.stanford.nlp.pipeline.StanfordCoreNLP をインポートします。
- edu.stanford.nlp.sentiment.SentimentCoreAnnotations をインポートします。
- edu.stanford.nlp.trees.Tree をインポートします。
- edu.stanford.nlp.util.CoreMap をインポートします。
-
- java.util.Properties をインポートします。
-
- パブリッククラスNlpPipeline {
- StanfordCoreNLP パイプライン = null ;
- パブリックvoid init()
- {
- プロパティ props = new Properties();
- props.setProperty( "annotators" , "tokenize, ssplit, parse, sentiment" );
- パイプライン = 新しい StanfordCoreNLP(props);
- }
- パブリックvoid estimatingSentiment(文字列テキスト)
- {
- int感情Int;
- 文字列 sentimentName;
- 注釈annotation = pipeline.process(text);
- (CoreMap 文:annotation.get(CoreAnnotations.SentencesAnnotation.class))の場合
- {
- ツリー tree = sentence.get(SentimentCoreAnnotations.SentimentAnnotatedTree.class);
- ツリーの sentimentInt を取得します。
- 感情名 = sentence.get(SentimentCoreAnnotations.SentimentClass.class);
- システム.out .println(sentimentName + "\t" + sentimentInt + "\t" + sentence);
- }
- }
- }
init() メソッドは StanfordCoreNLP パイプラインを初期化します。これにより、感情ツールを使用するために必要なトークナイザー、依存関係パーサー、および文スプリッターも初期化されます。 パイプラインを初期化するには、適切なアノテーターのリストを含む Properties オブジェクトを StanfordCoreNLP() コンストラクターに渡します。 これにより、テキストに対して感情分析を実行する準備が整ったカスタム パイプラインが作成されます。 NlpPipeline クラスの estimatingSentiment() メソッドで、先ほど作成したパイプライン オブジェクトの process() メソッドを呼び出し、処理するテキストを渡します。 process() メソッドは、送信されたテキストの分析を保存する注釈オブジェクトを返します。 次に、注釈オブジェクトを反復処理し、各反復で文レベルの CoreMap オブジェクトを取得します。これらのオブジェクトごとに、基礎となる文の感情を決定するために使用される感情注釈を含む Tree オブジェクトを取得します。 Tree オブジェクトを RNNCoreAnnotations クラスの getPredictedClass() メソッドに渡して、文の予測された感情に対応する数値コードを抽出します。次に、予測された感情の名前を取得し、結果を出力します。 上記の機能をテストするには、init() メソッドを呼び出し、次に nlpPipeline クラスの estimatingSentiment() メソッドを呼び出してサンプル テキストを渡す main() メソッドを持つクラスを実装します。 以下の実装では、簡潔にするためにテキストを直接指定します。例文は、Stanford CoreNLP で利用可能な感情スコアの全範囲 (非常に肯定的、肯定的、中立的、否定的、非常に否定的) をカバーするように設計されています。 - パッケージ com.zh.ch.corenlp;
-
- java.io.FileReader をインポートします。
- java.io.IOException をインポートします。
-
- パブリッククラスMain {
-
- 静的NlpPipeline nlpPipeline = null ;
-
- 公共 静的void processText(文字列テキスト) {
- nlpPipeline.estimatingSentiment(テキスト);
- }
-
- 公共 静的void main(String[] args) {
- String text = "これは素晴らしい本です。楽しく読めました。日曜日でも読めます。今日はまだ火曜日です。次の日曜日が待ちきれません。仕事の週は耐えられないほど長いです。ひどいです。" ;
- nlpPipeline = 新しい NlpPipeline();
- nlpPipeline.init();
- processText(テキスト);
- }
-
- }
実行結果: オンライン顧客レビューを分析する前の例から学んだように、Stanford CoreNLP は文の感情を返すことができます。 ただし、複数の段落のテキストの感情を分析する必要があるユースケースは数多くあり、各段落には複数の文が含まれる場合があります。 たとえば、eコマース サイトのツイートや顧客レビューの感情を分析したい場合があります。 Stanford CoreNLP を使用して複数文のテキスト サンプルの感情を計算するには、いくつかの異なる手法を使用する場合があります。 ツイートを処理するときに、ツイート内の各文の感情を分析し、肯定的または否定的な文がある場合は、中立的な感情の文を無視して、ツイート全体を個別にランク付けすることができます。 ツイート内のすべての(またはほぼすべての)文が中立的である場合、そのツイートは中立的として分類されることがあります。 ただし、テキスト全体の感情を推測するために、すべての文を分析する必要がない場合もあります。 たとえば、顧客レビューを分析する場合、通常は 1 つの文で構成される見出しを頼りにすることができます。 次の例を完了するには、一連の顧客レビューが必要です。 この記事に付属する NlpBookReviews.csv ファイルのレビューを使用できます。 このファイルには、Amazon Review Export を利用して Amazon Web ページからダウンロードされた実際のレビューのセットが含まれています。Amazon Review Export は、製品レビューをタイトルや評価とともにコンマ区切り値 (CSV) ファイルにダウンロードできる Google Chrome ブラウザ拡張機能です。(このツールを使用して、分析用に別のレビュー セットを調べることができます。) NlpPipelineに次のコードを追加します - パブリック文字列 findSentiment(文字列テキスト) {
- 感情の度合いは2 です。
- 文字列 sentimentName = "NULL" ;
- テキストがnullの場合、text.length() > 0 になります。
- 注釈annotation = pipeline.process(text);
- CoreMap 文 = 注釈
- .get(CoreAnnotations.SentencesAnnotation.class).get(0);
- 木 木 = 文
- SentimentCoreAnnotations.SentimentAnnotatedTree.class を取得します。
- ツリーの sentimentInt を取得します。
- 感情名 = sentence.get(SentimentCoreAnnotations.SentimentClass.class);
- }
- sentimentNameを返します。
- }
上記のコードは、前のセクションで定義した estimatingSentiment() メソッドのコードと似ていることに気付くかもしれません。 唯一の大きな違いは、今回は入力テキスト内の文を反復処理しないことです。 ほとんどの場合、レビューのタイトルは 1 つの文で構成されているため、代わりに最初の文のみが表示されます。 次のコードは、CSV ファイルからコメントを読み取り、新しく作成された findSentiment() に渡して処理します。 - 公共 静的void processCsvComment(String csvCommentFilePath) {
- 試してください (CSVReader リーダー = 新しい CSVReaderBuilder(新しい FileReader(csvCommentFilePath)).withSkipLines(1).build())
- {
- 文字列[] 行;
- ((row = reader.readNext()) != null ) の間 {
- System.out.println ( "レビュー:" + row[1] + "\t" + "Amazon評価:" + row[4] + "\t" + "感情:" + nlpPipeline.findSentiment(row[1]));
- }
- }
- キャッチ (IOException | CsvValidationException e) {
- e.printStackTrace();
- }
- }
実行結果: 完全なコード: Nlpパイプライン.java - パッケージ com.zh.ch.corenlp;
-
- edu.stanford.nlp.ling.CoreAnnotations をインポートします。
- edu.stanford.nlp.neural.rnn.RNNCoreAnnotations をインポートします。
- edu.stanford.nlp.pipeline.Annotation をインポートします。
- edu.stanford.nlp.pipeline.StanfordCoreNLP をインポートします。
- edu.stanford.nlp.sentiment.SentimentCoreAnnotations をインポートします。
- edu.stanford.nlp.trees.Tree をインポートします。
- edu.stanford.nlp.util.CoreMap をインポートします。
-
- java.util.Properties をインポートします。
-
- パブリッククラスNlpPipeline {
- StanfordCoreNLP パイプライン = null ;
- パブリックvoid init() {
- プロパティ props = new Properties();
- props.setProperty( "annotators" , "tokenize, ssplit, parse, sentiment" );
- パイプライン = 新しい StanfordCoreNLP(props);
- }
- パブリックvoid estimatingSentiment(文字列テキスト) {
- int感情Int;
- 文字列 sentimentName;
- 注釈annotation = pipeline.process(text);
- (CoreMap 文:annotation.get(CoreAnnotations.SentencesAnnotation.class))の場合
- {
- ツリー tree = sentence.get(SentimentCoreAnnotations.SentimentAnnotatedTree.class);
- ツリーの sentimentInt を取得します。
- 感情名 = sentence.get(SentimentCoreAnnotations.SentimentClass.class);
- システム.out .println(sentimentName + "\t" + sentimentInt + "\t" + sentence);
- }
- }
-
- パブリック文字列 findSentiment(文字列テキスト) {
- 感情の度合いは2 です。
- 文字列 sentimentName = "NULL" ;
- テキストがnullの場合、text.length() > 0 になります。
- 注釈annotation = pipeline.process(text);
- CoreMap 文 = 注釈
- .get(CoreAnnotations.SentencesAnnotation.class).get(0);
- 木 木 = 文
- SentimentCoreAnnotations.SentimentAnnotatedTree.class を取得します。
- ツリーの sentimentInt を取得します。
- 感情名 = sentence.get(SentimentCoreAnnotations.SentimentClass.class);
- }
- sentimentNameを返します。
- }
- }
メイン.java - パッケージ com.zh.ch.corenlp;
-
- com.opencsv.CSVReader をインポートします。
- com.opencsv.CSVReaderBuilder をインポートします。
- com.opencsv.exceptions.CsvValidationException をインポートします。
-
- java.io.FileReader をインポートします。
- java.io.IOException をインポートします。
-
- パブリッククラスMain {
- 静的NlpPipeline nlpPipeline = null ;
-
- 公共 静的void processCsvComment(String csvCommentFilePath) {
- 試してください (CSVReader リーダー = 新しい CSVReaderBuilder(新しい FileReader(csvCommentFilePath)).withSkipLines(1).build())
- {
- 文字列[] 行;
- ((row = reader.readNext()) != null ) の間 {
- System.out.println ( "レビュー:" + row[1] + "\t" + "Amazon評価:" + row[4] + "\t" + "感情:" + nlpPipeline.findSentiment(row[1]));
- }
- }
- キャッチ (IOException | CsvValidationException e) {
- e.printStackTrace();
- }
- }
-
- 公共 静的void processText(文字列テキスト) {
- nlpPipeline.estimatingSentiment(テキスト);
- }
-
- 公共 静的void main(String[] args) {
- String text = "これは素晴らしい本です。楽しく読めました。日曜日でも読めます。今日はまだ火曜日です。次の日曜日が待ちきれません。仕事の週は耐えられないほど長いです。ひどいです。" ;
- nlpPipeline = 新しい NlpPipeline();
- nlpPipeline.init();
- // テキストを処理します。
- processCsvComment( "src/main/resources/NlpBookReviews.csv" );
- }
- }
|