服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - 使用深度学习模型在 Java 中执行文本情感分析

使用深度学习模型在 Java 中执行文本情感分析

2021-12-27 23:13从大数据到人工智能 Java教程

本文介绍如何使用集成到斯坦福 CoreNLP(一个用于自然语言处理的开源库)中的情感工具在 Java 中实现此类任务。

积极的? 消极的? 中性的? 使用斯坦福 CoreNLP 组件以及几行代码便可对句子进行分析。

使用深度学习模型在 Java 中执行文本情感分析

本文介绍如何使用集成到斯坦福 CoreNLP(一个用于自然语言处理的开源库)中的情感工具在 Java 中实现此类任务。

斯坦福 CoreNLP 情感分类器

要执行情感分析,您需要一个情感分类器,这是一种可以根据从训练数据集中学习的预测来识别情感信息的工具。

在斯坦福 CoreNLP 中,情感分类器建立在递归神经网络 (RNN) 深度学习模型之上,该模型在斯坦福情感树库 (SST) 上进行训练。

SST 数据集是一个带有情感标签的语料库,从数千个使用的句子中推导出每个句法上可能的短语,从而允许捕获文本中情感的构成效果。简单来说,这允许模型根据单词如何构成短语的含义来识别情绪,而不仅仅是通过孤立地评估单词。

为了更好地了解 SST 数据集的结构,您可从斯坦福 CoreNLP 情感分析页面下载数据集文件。

在 Java 代码中,Stanford CoreNLP 情感分类器使用如下。

首先,您通过添加执行情感分析所需的注释器(例如标记化、拆分、解析和情感)来构建文本处理管道。 就斯坦福 CoreNLP 而言,注释器是一个对注释对象进行操作的接口,其中后者表示文档中的一段文本。 例如,需要使用 ssplit 注释器将标记序列拆分为句子。

斯坦福 CoreNLP 以每个句子为基础计算情绪。 因此,将文本分割成句子的过程始终遵循应用情感注释器。

一旦文本被分成句子,解析注释器就会执行句法依赖解析,为每个句子生成一个依赖表示。 然后,情感注释器处理这些依赖表示,将它们与底层模型进行比较,以构建带有每个句子的情感标签(注释)的二值化树。

简单来说,树的节点由输入句子的标记确定,并包含注释,指示从句子导出的所有短语的从非常消极到非常积极的五个情感类别中的预测类别。 基于这些预测,情感注释器计算整个句子的情感。

设置斯坦福 CoreNLP

在开始使用斯坦福 CoreNLP 之前,您需要进行以下设置:

要运行斯坦福 CoreNLP,您需要 Java 1.8 或更高版本。

下载 Stanford CoreNLP 包并将该包解压缩到您机器上的本地文件夹中。

下载地址:

https://nlp.stanford.edu/software/stanford-corenlp-latest.zip

本文以将上述代码解压到如下目录为例:

c:/softwareInstall/corenlp/stanford-corenlp-4.3.2

完成上述步骤后,您就可以创建运行斯坦福 CoreNLP 管道来处理文本的 Java 程序了。

首先新建一个maven项目,并手动将stanford-corenlp-4.3.2添加到Libraries中:

使用深度学习模型在 Java 中执行文本情感分析

在以下示例中,您将实现一个简单的 Java 程序,该程序运行斯坦福 CoreNLP 管道,以对包含多个句子的文本进行情感分析。

首先,实现一个NlpPipeline类,该类提供初始化管道的方法和使用此管道将提交的文本拆分为句子然后对每个句子的情感进行分类的方法。 下面是NlpPipeline类代码:

  1. package com.zh.ch.corenlp;
  2. import edu.stanford.nlp.ling.CoreAnnotations;
  3. import edu.stanford.nlp.neural.rnn.RNNCoreAnnotations;
  4. import edu.stanford.nlp.pipeline.Annotation;
  5. import edu.stanford.nlp.pipeline.StanfordCoreNLP;
  6. import edu.stanford.nlp.sentiment.SentimentCoreAnnotations;
  7. import edu.stanford.nlp.trees.Tree;
  8. import edu.stanford.nlp.util.CoreMap;
  9. import java.util.Properties;
  10. public class NlpPipeline {
  11. StanfordCoreNLP pipeline = null;
  12. public void init()
  13. {
  14. Properties props = new Properties();
  15. props.setProperty("annotators", "tokenize, ssplit, parse, sentiment");
  16. pipeline = new StanfordCoreNLP(props);
  17. }
  18. public void estimatingSentiment(String text)
  19. {
  20. int sentimentInt;
  21. String sentimentName;
  22. Annotation annotation = pipeline.process(text);
  23. for(CoreMap sentence : annotation.get(CoreAnnotations.SentencesAnnotation.class))
  24. {
  25. Tree tree = sentence.get(SentimentCoreAnnotations.SentimentAnnotatedTree.class);
  26. sentimentInt = RNNCoreAnnotations.getPredictedClass(tree);
  27. sentimentName = sentence.get(SentimentCoreAnnotations.SentimentClass.class);
  28. System.out.println(sentimentName + "\t" + sentimentInt + "\t" + sentence);
  29. }
  30. }
  31. }

init() 方法初始化StanfordCoreNLP 管道,它还初始化使用该情感工具所需的分词器、依赖解析器和句子拆分器。 要初始化管道,请将带有相应注释器列表的 Properties 对象传递给 StanfordCoreNLP() 构造函数。 这将创建一个定制的管道,准备好对文本执行情感分析。

在NlpPipeline类的estimatingSentiment()方法中,调用之前创建的管道对象的process()方法,传入文本进行处理。 process() 方法返回一个注释对象,该对象存储对提交的文本的分析。

接下来,迭代注释对象,在每次迭代中获得一个句子级 CoreMap 对象。对于这些对象中的每一个,获取一个包含用于确定底层句子情绪的情绪注释的 Tree 对象。

将 Tree 对象传递给 RNNCoreAnnotations 类的 getPredictedClass() 方法,以提取对应句子的预测情绪的编号代码。然后,获取预测情绪的名称并打印结果。

要测试上述功能,请使用调用 init() 方法的 main() 方法实现一个类,然后调用 nlpPipeline 类的 estimatingSentiment() 方法,将示例文本传递给后者。

在以下实现中,为了简单起见,直接指定text文本。示例句子旨在涵盖斯坦福 CoreNLP 可用的整个情绪评分范围:非常积极、积极、中立、消极和非常消极。

  1. package com.zh.ch.corenlp;
  2. import java.io.FileReader;
  3. import java.io.IOException;
  4. public class Main {
  5. static NlpPipeline nlpPipeline = null;
  6. public static void processText(String text) {
  7. nlpPipeline.estimatingSentiment(text);
  8. }
  9. public static void main(String[] args) {
  10. String text = "This is an excellent book. I enjoy reading it. I can read on Sundays. Today is only Tuesday. Can't wait for next Sunday. The working week is unbearably long. It's awful.";
  11. nlpPipeline = new NlpPipeline();
  12. nlpPipeline.init();
  13. processText(text);
  14. }
  15. }

执行结果:

使用深度学习模型在 Java 中执行文本情感分析

分析在线客户评论

正如您从前面的示例中了解到的,Stanford CoreNLP 可以返回句子的情绪。 然而,有许多用例需要分析多段文本的情绪,每段文本可能包含不止一个句子。 例如,您可能想要分析来自电子商务网站的推文或客户评论的情绪。

要使用斯坦福 CoreNLP 计算多句文本样本的情绪,您可能会使用几种不同的技术。

在处理推文时,您可能会分析推文中每个句子的情绪,如果有一些正面或负面的句子,您可以分别对整个推文进行排名,忽略带有中性情绪的句子。 如果推文中的所有(或几乎所有)句子都是中性的,则该推文可以被列为中性。

然而,有时您甚至不必分析每个句子来估计整个文本的情绪。 例如,在分析客户评论时,您可以依赖他们的标题,标题通常由一个句子组成。

要完成以下示例,您需要一组客户评论。 您可以使用本文随附的 NlpBookReviews.csv 文件中的评论。 该文件包含在 Amazon Review Export 的帮助下从 Amazon 网页下载的一组实际评论,这是一个 Google Chrome 浏览器扩展程序,允许您将产品评论及其标题和评级下载到逗号分隔值 (CSV) 文件中 . (您可以使用该工具探索一组不同的评论以进行分析。)

将下述代码添加到NlpPipeline中

  1. public String findSentiment(String text) {
  2. int sentimentInt = 2;
  3. String sentimentName = "NULL";
  4. if (text != null && text.length() > 0) {
  5. Annotation annotation = pipeline.process(text);
  6. CoreMap sentence = annotation
  7. .get(CoreAnnotations.SentencesAnnotation.class).get(0);
  8. Tree tree = sentence
  9. .get(SentimentCoreAnnotations.SentimentAnnotatedTree.class);
  10. sentimentInt = RNNCoreAnnotations.getPredictedClass(tree);
  11. sentimentName = sentence.get(SentimentCoreAnnotations.SentimentClass.class);
  12. }
  13. return sentimentName;
  14. }

您可能会注意到,上面的代码类似于上一节中定义的 estimatingSentiment() 方法中的代码。 唯一的显着区别是这次您没有迭代输入文本中的句子。 相反,您只会得到第一句话,因为在大多数情况下,评论的标题由一个句子组成。

下述代码将从 CSV 文件中读取评论并将它们传递给新创建的 findSentiment() 进行处理,如下所示:

  1. public static void processCsvComment(String csvCommentFilePath) {
  2. try (CSVReader reader = new CSVReaderBuilder(new FileReader(csvCommentFilePath)).withSkipLines(1).build())
  3. {
  4. String[] row;
  5. while ((row = reader.readNext()) != null) {
  6. System.out.println("Review: " + row[1] + "\t" + " Amazon rating: " + row[4] + "\t" + " Sentiment: " + nlpPipeline.findSentiment(row[1]));
  7. }
  8. }
  9. catch (IOException | CsvValidationException e) {
  10. e.printStackTrace();
  11. }
  12. }

执行结果:

使用深度学习模型在 Java 中执行文本情感分析

完整代码:

NlpPipeline.java

  1. package com.zh.ch.corenlp;
  2. import edu.stanford.nlp.ling.CoreAnnotations;
  3. import edu.stanford.nlp.neural.rnn.RNNCoreAnnotations;
  4. import edu.stanford.nlp.pipeline.Annotation;
  5. import edu.stanford.nlp.pipeline.StanfordCoreNLP;
  6. import edu.stanford.nlp.sentiment.SentimentCoreAnnotations;
  7. import edu.stanford.nlp.trees.Tree;
  8. import edu.stanford.nlp.util.CoreMap;
  9. import java.util.Properties;
  10. public class NlpPipeline {
  11. StanfordCoreNLP pipeline = null;
  12. public void init() {
  13. Properties props = new Properties();
  14. props.setProperty("annotators", "tokenize, ssplit, parse, sentiment");
  15. pipeline = new StanfordCoreNLP(props);
  16. }
  17. public void estimatingSentiment(String text) {
  18. int sentimentInt;
  19. String sentimentName;
  20. Annotation annotation = pipeline.process(text);
  21. for(CoreMap sentence : annotation.get(CoreAnnotations.SentencesAnnotation.class))
  22. {
  23. Tree tree = sentence.get(SentimentCoreAnnotations.SentimentAnnotatedTree.class);
  24. sentimentInt = RNNCoreAnnotations.getPredictedClass(tree);
  25. sentimentName = sentence.get(SentimentCoreAnnotations.SentimentClass.class);
  26. System.out.println(sentimentName + "\t" + sentimentInt + "\t" + sentence);
  27. }
  28. }
  29. public String findSentiment(String text) {
  30. int sentimentInt = 2;
  31. String sentimentName = "NULL";
  32. if (text != null && text.length() > 0) {
  33. Annotation annotation = pipeline.process(text);
  34. CoreMap sentence = annotation
  35. .get(CoreAnnotations.SentencesAnnotation.class).get(0);
  36. Tree tree = sentence
  37. .get(SentimentCoreAnnotations.SentimentAnnotatedTree.class);
  38. sentimentInt = RNNCoreAnnotations.getPredictedClass(tree);
  39. sentimentName = sentence.get(SentimentCoreAnnotations.SentimentClass.class);
  40. }
  41. return sentimentName;
  42. }
  43. }

Main.java

  1. package com.zh.ch.corenlp;
  2. import com.opencsv.CSVReader;
  3. import com.opencsv.CSVReaderBuilder;
  4. import com.opencsv.exceptions.CsvValidationException;
  5. import java.io.FileReader;
  6. import java.io.IOException;
  7. public class Main {
  8. static NlpPipeline nlpPipeline = null;
  9. public static void processCsvComment(String csvCommentFilePath) {
  10. try (CSVReader reader = new CSVReaderBuilder(new FileReader(csvCommentFilePath)).withSkipLines(1).build())
  11. {
  12. String[] row;
  13. while ((row = reader.readNext()) != null) {
  14. System.out.println("Review: " + row[1] + "\t" + " Amazon rating: " + row[4] + "\t" + " Sentiment: " + nlpPipeline.findSentiment(row[1]));
  15. }
  16. }
  17. catch (IOException | CsvValidationException e) {
  18. e.printStackTrace();
  19. }
  20. }
  21. public static void processText(String text) {
  22. nlpPipeline.estimatingSentiment(text);
  23. }
  24. public static void main(String[] args) {
  25. String text = "This is an excellent book. I enjoy reading it. I can read on Sundays. Today is only Tuesday. Can't wait for next Sunday. The working week is unbearably long. It's awful.";
  26. nlpPipeline = new NlpPipeline();
  27. nlpPipeline.init();
  28. // processText(text);
  29. processCsvComment("src/main/resources/NlpBookReviews.csv");
  30. }
  31. }

原文链接:https://www.toutiao.com/a7045718473149792775/

延伸 · 阅读

精彩推荐
  • Java教程eclipse配置javap命令的方法

    eclipse配置javap命令的方法

    本篇文章主要介绍了如何为eclipse配置javap命令,在配置过程中会出现的小问题的解决方法,非常实用,需要的朋友可以参考下 ...

    RiccioZhang4202019-12-28
  • Java教程Java字符判断的小例子

    Java字符判断的小例子

    从键盘上输入一个字符串,遍历该字符串中的每个字符,若该字符为小写字母,则输出“此字符是小写字母”;若为大写字母,则输出“此字符为大写字母...

    java之家4952019-10-14
  • Java教程Java泛型枚举Annotation接口详细解读与Eclipse发展

    Java泛型枚举Annotation接口详细解读与Eclipse发展

    这篇文章主要给大家介绍了关于Java中方法使用的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们...

    zsr61353742021-11-30
  • Java教程Ehcache简介_动力节点Java学院整理

    Ehcache简介_动力节点Java学院整理

    这篇文章主要介绍了Ehcache简介,使用Spring的AOP进行整合,可以灵活的对方法的返回结果对象进行缓存...

    chenjumin4352020-12-07
  • Java教程java用split分割字符串的一个有趣现象

    java用split分割字符串的一个有趣现象

    最近在项目中使用了java中的split分割字符串,发现了一个bug,充分了展示了自己对java底层的认知有很多的不足和欠缺。下面将这次的经过总结出来分享给大...

    刺风1902020-07-16
  • Java教程详解Spring中的FactoryBean

    详解Spring中的FactoryBean

    本篇文章主要介绍了Spring中的FactoryBean,如果一个bean的创建过程中涉及到很多其他的bean 和复杂的逻辑,用xml配置比较困难,这时可以考虑用FactoryBean...

    bird_cat5262020-09-06
  • Java教程java——多线程基础

    java——多线程基础

    Java多线程实现方式有两种,第一种是继承Thread类,第二种是实现Runnable接口,两种有很多差异,下面跟着本文一起学习吧,希望能给你带来帮助...

    wbcra11152021-10-06
  • Java教程IntelliJ IDEA中打开拼写检查与忽略提示曲线的方法

    IntelliJ IDEA中打开拼写检查与忽略提示曲线的方法

    今天小编就为大家分享一篇关于IntelliJ IDEA中打开拼写检查与忽略提示曲线的方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的...

    李学凯4742021-06-07