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

本文涉及的产品
NLP 自学习平台,3个模型定制额度 1个月
NLP自然语言处理_基础版,每接口每天50万次
NLP自然语言处理_高级版,每接口累计50万次
简介: 本文介绍如何使用集成到斯坦福 CoreNLP(一个用于自然语言处理的开源库)中的情感工具在 Java 中实现此类任务。

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

斯坦福 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 程序,该程序运行斯坦福 CoreNLP 管道,以对包含多个句子的文本进行情感分析。

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

package com.zh.ch.corenlp;

import edu.stanford.nlp.ling.CoreAnnotations;
import edu.stanford.nlp.neural.rnn.RNNCoreAnnotations;
import edu.stanford.nlp.pipeline.Annotation;
import edu.stanford.nlp.pipeline.StanfordCoreNLP;
import edu.stanford.nlp.sentiment.SentimentCoreAnnotations;
import edu.stanford.nlp.trees.Tree;
import edu.stanford.nlp.util.CoreMap;

import java.util.Properties;

public class NlpPipeline {
    StanfordCoreNLP pipeline = null;
    public  void init()
    {
        Properties props = new Properties();
        props.setProperty("annotators", "tokenize, ssplit, parse, sentiment");
        pipeline = new StanfordCoreNLP(props);
    }
    public void estimatingSentiment(String text)
    {
        int sentimentInt;
        String sentimentName;
        Annotation annotation = pipeline.process(text);
        for(CoreMap sentence : annotation.get(CoreAnnotations.SentencesAnnotation.class))
        {
            Tree tree = sentence.get(SentimentCoreAnnotations.SentimentAnnotatedTree.class);
            sentimentInt = RNNCoreAnnotations.getPredictedClass(tree);
            sentimentName = sentence.get(SentimentCoreAnnotations.SentimentClass.class);
            System.out.println(sentimentName + "\t" + sentimentInt + "\t" + sentence);
        }
    }
}


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

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

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

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

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

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

package com.zh.ch.corenlp;

import java.io.FileReader;
import java.io.IOException;

public class Main {
    
    static NlpPipeline nlpPipeline = null;

    public static void processText(String text) {
        nlpPipeline.estimatingSentiment(text);
    }

    public static void main(String[] args) {
        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.";
        nlpPipeline  = new NlpPipeline();
        nlpPipeline.init();
        processText(text);
    }

}

执行结果:

分析在线客户评论

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

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

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

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

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

将下述代码添加到NlpPipeline中

    public String findSentiment(String text) {
        int sentimentInt = 2;
        String sentimentName = "NULL";
        if (text != null && text.length() > 0) {
            Annotation annotation = pipeline.process(text);
            CoreMap sentence = annotation
                    .get(CoreAnnotations.SentencesAnnotation.class).get(0);
            Tree tree = sentence
                    .get(SentimentCoreAnnotations.SentimentAnnotatedTree.class);
            sentimentInt = RNNCoreAnnotations.getPredictedClass(tree);
            sentimentName = sentence.get(SentimentCoreAnnotations.SentimentClass.class);
        }
        return sentimentName;
    }

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

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

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

执行结果:

完整代码:

NlpPipeline.java

package com.zh.ch.corenlp;

import edu.stanford.nlp.ling.CoreAnnotations;
import edu.stanford.nlp.neural.rnn.RNNCoreAnnotations;
import edu.stanford.nlp.pipeline.Annotation;
import edu.stanford.nlp.pipeline.StanfordCoreNLP;
import edu.stanford.nlp.sentiment.SentimentCoreAnnotations;
import edu.stanford.nlp.trees.Tree;
import edu.stanford.nlp.util.CoreMap;

import java.util.Properties;

public class NlpPipeline {
    StanfordCoreNLP pipeline = null;
    public  void init() {
        Properties props = new Properties();
        props.setProperty("annotators", "tokenize, ssplit, parse, sentiment");
        pipeline = new StanfordCoreNLP(props);
    }
    public void estimatingSentiment(String text) {
        int sentimentInt;
        String sentimentName;
        Annotation annotation = pipeline.process(text);
        for(CoreMap sentence : annotation.get(CoreAnnotations.SentencesAnnotation.class))
        {
            Tree tree = sentence.get(SentimentCoreAnnotations.SentimentAnnotatedTree.class);
            sentimentInt = RNNCoreAnnotations.getPredictedClass(tree);
            sentimentName = sentence.get(SentimentCoreAnnotations.SentimentClass.class);
            System.out.println(sentimentName + "\t" + sentimentInt + "\t" + sentence);
        }
    }

    public String findSentiment(String text) {
        int sentimentInt = 2;
        String sentimentName = "NULL";
        if (text != null && text.length() > 0) {
            Annotation annotation = pipeline.process(text);
            CoreMap sentence = annotation
                    .get(CoreAnnotations.SentencesAnnotation.class).get(0);
            Tree tree = sentence
                    .get(SentimentCoreAnnotations.SentimentAnnotatedTree.class);
            sentimentInt = RNNCoreAnnotations.getPredictedClass(tree);
            sentimentName = sentence.get(SentimentCoreAnnotations.SentimentClass.class);
        }
        return sentimentName;
    }
}

Main.java

package com.zh.ch.corenlp;

import com.opencsv.CSVReader;
import com.opencsv.CSVReaderBuilder;
import com.opencsv.exceptions.CsvValidationException;

import java.io.FileReader;
import java.io.IOException;

public class Main {
    static NlpPipeline nlpPipeline = null;

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

    public static void processText(String text) {
        nlpPipeline.estimatingSentiment(text);
    }

    public static void main(String[] args) {
        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.";
        nlpPipeline  = new NlpPipeline();
        nlpPipeline.init();
//        processText(text);
        processCsvComment("src/main/resources/NlpBookReviews.csv");
    }
}

代码地址:

https://git.lrting.top/xiaozhch5/corenlp-examples.git

相关文章
|
3天前
|
机器学习/深度学习 人工智能 自然语言处理
【深度学习】探讨最新的深度学习算法、模型创新以及在图像识别、自然语言处理等领域的应用进展
深度学习作为人工智能领域的重要分支,近年来在算法、模型以及应用领域都取得了显著的进展。以下将探讨最新的深度学习算法与模型创新,以及它们在图像识别、自然语言处理(NLP)等领域的应用进展。
14 6
|
1天前
|
机器学习/深度学习 自然语言处理 负载均衡
揭秘混合专家(MoE)模型的神秘面纱:算法、系统和应用三大视角全面解析,带你领略深度学习领域的前沿技术!
【8月更文挑战第19天】在深度学习领域,混合专家(Mixture of Experts, MoE)模型通过整合多个小型专家网络的输出以实现高性能。从算法视角,MoE利用门控网络分配输入至专家网络,并通过组合机制集成输出。系统视角下,MoE需考虑并行化、通信开销及负载均衡等优化策略。在应用层面,MoE已成功应用于Google的BERT模型、Facebook的推荐系统及Microsoft的语音识别系统等多个场景。这是一种强有力的工具,能够解决复杂问题并提升效率。
|
1天前
|
机器学习/深度学习 程序员 数据处理
2.1 横纵式 学习法完整掌握深度学习模型的建模
这篇文章介绍了使用飞桨框架完成手写数字识别任务的流程,强调了飞桨框架在不同模型间的代码一致性优势,并采用了“横纵式”教学法,通过逐步增加深度和复杂性来帮助初学者全面掌握深度学习模型的构建过程。
5 1
|
2天前
|
机器学习/深度学习 人工智能 自然语言处理
【深度学习】AudioLM音频生成模型概述及应用场景,项目实践及案例分析
AudioLM(Audio Language Model)是一种基于深度学习的音频生成模型,它使用自回归或变分自回归的方法来生成连续的音频信号。这类模型通常建立在Transformer架构或者类似的序列到序列(Seq2Seq)框架上,通过学习大量音频数据中的统计规律,能够生成具有高保真度和创造性的音频片段。AudioLM模型不仅能够合成音乐、语音,还能生成自然界的声音、环境噪声等,其应用广泛,涵盖了娱乐、教育、辅助技术、内容创作等多个领域。
9 1
|
1天前
|
机器学习/深度学习 数据采集 数据可视化
使用Python实现深度学习模型:智能医疗影像识别与诊断
【8月更文挑战第19天】 使用Python实现深度学习模型:智能医疗影像识别与诊断
8 0
|
2天前
|
机器学习/深度学习 存储 物联网
深度学习模型的优化与部署
【8月更文第18天】随着深度学习技术的发展,模型规模变得越来越大,这对计算资源的要求也越来越高。为了能够在资源有限的边缘设备(如智能手机、物联网设备)上运行复杂的深度学习模型,我们需要采用一系列优化方法来减少模型大小和计算复杂度。本文将介绍几种常用的模型优化技术,并讨论如何在边缘设备或云端服务器上部署这些优化后的模型。
13 0
|
2天前
|
机器学习/深度学习 数据采集 数据可视化
使用Python实现深度学习模型:智能娱乐与虚拟现实技术
【8月更文挑战第18天】 使用Python实现深度学习模型:智能娱乐与虚拟现实技术
5 0
|
2天前
|
机器学习/深度学习
深度学习之结合物理定律的预测模型
基于深度学习的结合物理定律的预测模型,通过将深度学习的强大非线性映射能力与物理定律的先验知识相结合,提升预测模型的准确性、可解释性和稳定性。
5 0
|
2天前
|
机器学习/深度学习 传感器 监控
深度学习之环境感知模型
基于深度学习的环境感知模型,旨在通过利用深度学习技术,使系统能够感知、理解并响应其所在的物理或虚拟环境。
6 0
|
3天前
|
机器学习/深度学习 数据采集 数据可视化
使用Python实现深度学习模型:智能城市交通管控与优化
【8月更文挑战第17天】 使用Python实现深度学习模型:智能城市交通管控与优化
3 0