
示例工程【免费下载链接】52-technologies-in-2016Lets learn a new technology every week. A new technology blog every Sunday in 2016.项目地址https://gitcode.com/gh_mirrors/52/52-technologies-in-2016点击查看免费下载导读本文基于本仓库03-stanford-corenlp目录下的完整示例项目系统讲解如何使用 Scala 调用 Stanford CoreNLP 开源库完成非结构化文本的情感分析Sentiment Analysis / Opinion Mining。你将掌握 CoreNLP 管线的 annotator 配置、Sentiment枚举与整数情感分值的映射规则、以句子长度加权选取主情感的算法以及基于 ScalaTest 的正/负/中性三类测试写法最终可以独立搭建一个可运行、可测试的 Scala 情感分析器。为什么选择 Stanford CoreNLP 做情感分析情感分析Sentiment Analysis也称观点挖掘Opinion Mining是自然语言处理中用于分析一段给定文本所蕴含情感倾向的技术其应用场景覆盖从市场营销到客户服务的众多领域。原文作者在多年前曾用 Naive Bayes 分类器写过 Java 程序通过分析某部电影相关的推文来判断观众是否喜欢该电影——这正是情感分析的典型用例。与之相比Stanford CoreNLP 提供了一整套自然语言分析工具按官方说明其能力包括给出单词的词形base forms、词性标注parts of speech、识别文本中的公司名/人名等命名实体、规范化日期时间与数值、标记句子的短语结构与词语依赖关系、判断哪些名词短语指向同一实体、指示情感倾向、抽取提及之间的开放类关系等。本示例只取其情感分析能力但整个管线能力是共用的。本文讲解的完整代码位于仓库的 sentiment-analyzer 目录核心实现见 SentimentAnalyzer.scala测试见 SentimentAnalyzerSpec.scala。第一步搭建 sbt 项目骨架创建目录结构先在文件系统的合适位置创建项目目录sentiment-analyzer$ mkdir sentiment-analyzer随后创建 Scala 源码与测试的标准布局与仓库中src/main/scala/com/shekhargulati/sentiment_analyzer/、src/test/scala/com/shekhargulati/sentiment_analyzer/的包结构保持一致$ mkdir -p src/main/{scala,resources} $ mkdir -p src/test/scala如果你对 sbt 构建工具还不熟悉可以先阅读本仓库 02-sbt 系列文章那里有 sbt 构建脚本的入门讲解。编写 build.sbt在sentiment-analyzer目录下新建build.sbtsbt 构建脚本填入以下内容name : sentiment-analyzer description : A demo application to showcase sentiment analysis using Stanford CoreNLP and Scala version : 0.1.0 scalaVersion : 2.11.7 libraryDependencies edu.stanford.nlp % stanford-corenlp % 3.5.2 artifacts (Artifact(stanford-corenlp, models), Artifact(stanford-corenlp)) libraryDependencies org.scalatest %% scalatest % 2.2.6 % test理解artifacts关键配置上面构建脚本中最值得关注的是artifacts的用法。当某个依赖在仓库中发布了多个 artifact时就需要用artifacts显式声明需要拉取哪些构件。这里我们通过artifacts告诉 sbtclasspath 中需要同时包含stanford-corenlp和stanford-models两个依赖stanford-corenlp定义了我们将在代码中使用的核心 API如StanfordCoreNLP、Annotation、CoreAnnotations等类stanford-models包含stanford-corenlp在底层运行时所需的所有数据模型文件语法解析模型、情感模型等。需要特别提醒的是stanford-models库体积约为378.1 MB因此 sbt 首次下载依赖时会耗时较长属正常现象。另外仓库中的 plugins.sbt 还引入了sbt-dependency-graph插件net.virtual-void % sbt-dependency-graph % 0.8.1运行sbt dependencyTree即可直观查看stanford-corenlp与stanford-models等依赖的传递关系。第二步定义 Sentiment 枚举与分值映射分析器输出的情感结果是一个枚举值。原文档在应用内定义了一个 Scala 枚举Sentiment仓库源码 SentimentAnalyzer.scala 中它的完整实现如下object Sentiment extends Enumeration { type Sentiment Value val POSITIVE, NEGATIVE, NEUTRAL Value def toSentiment(sentiment: Int): Sentiment sentiment match { case x if x 0 || x 1 Sentiment.NEGATIVE case 2 Sentiment.NEUTRAL case x if x 3 || x 4 Sentiment.POSITIVE } }这里的toSentiment方法用于把stanford-corenlpAPI 返回的整数情感分值转换为枚举常量映射规则是CoreNLP 整数分值情感含义映射后的枚举0 或 1负面情感Sentiment.NEGATIVE2中性Sentiment.NEUTRAL3 或 4正面情感Sentiment.POSITIVE从源码结构看该映射是使用模式匹配实现的case x if x 0 || x 1与case x if x 3 || x 4两个守卫条件分别捕获负向与正向分值区间case 2精确匹配中性分值这种写法比逐一列举 0~4 五个 case 更紧凑。第三步编写 SentimentAnalyzer 核心类完整源码SentimentAnalyzer是整个应用的主体。仓库中 SentimentAnalyzer.scala 的完整实现如下import java.util.Properties import com.shekhargulati.sentiment_analyzer.Sentiment.Sentiment import edu.stanford.nlp.ling.CoreAnnotations import edu.stanford.nlp.neural.rnn.RNNCoreAnnotations import edu.stanford.nlp.pipeline.{Annotation, StanfordCoreNLP} import edu.stanford.nlp.sentiment.SentimentCoreAnnotations import scala.collection.convert.wrapAll._ object SentimentAnalyzer { val props new Properties() props.setProperty(annotators, tokenize, ssplit, parse, sentiment) val pipeline: StanfordCoreNLP new StanfordCoreNLP(props) /** * Extracts the main sentiment for a given input */ def mainSentiment(input: String): Sentiment Option(input) match { case Some(text) if text.nonEmpty extractSentiment(text) case _ throw new IllegalArgumentException(input cant be null or empty) } /** * Extracts a list of sentiments for a given input */ def sentiment(input: String): List[(String, Sentiment)] Option(input) match { case Some(text) if text.nonEmpty extractSentiments(text) case _ throw new IllegalArgumentException(input cant be null or empty) } private def extractSentiment(text: String): Sentiment { val (_, sentiment) extractSentiments(text) .maxBy { case (sentence, _) sentence.length } sentiment } private def extractSentiments(text: String): List[(String, Sentiment)] { val annotation: Annotation pipeline.process(text) val sentences annotation.get(classOf[CoreAnnotations.SentencesAnnotation]) sentences .map(sentence (sentence, sentence.get(classOf[SentimentCoreAnnotations.SentimentAnnotatedTree]))) .map { case (sentence, tree) (sentence.toString, Sentiment.toSentiment(RNNCoreAnnotations.getPredictedClass(tree))) } .toList } }逐步拆解实现原理原文档对上述代码给出了四条核心说明结合仓库源码可以进一步细化如下1. 构建 StanfordCoreNLP 管线props.setProperty(annotators, tokenize, ssplit, parse, sentiment)指定了本次使用的 4 个 annotator。StanfordCoreNLP内部会依据该属性构造一条管线输入文本依次经过tokenize分词、ssplit句子切分、parse句法解析、sentiment情感分析最终产出各种被分析过的语言学形态。注意情感 annotator 依赖前面的解析结果因此parse必须先于sentiment执行annotator 顺序不可随意调换。2.mainSentiment的输入校验mainSentiment通过Option(input)配合守卫条件text.nonEmpty做空值防御只有当输入非 null 且非空时才调用extractSentiment否则抛出IllegalArgumentException(input cant be null or empty)。3.extractSentiment的主情感策略extractSentiment对extractSentiments返回的「(句子文本, 情感)」二元组列表执行maxBy操作比较键是sentence.length即以句子长度为权重把最长的句子视为整段文本的主情感。因此对输入Scala is a great general purpose language. I dont use it often.较长的句子Scala is a great general purpose language带有正面情绪mainSentiment就会返回Sentiment.POSITIVE尽管第二句含否定词。4.extractSentiments的管线调用细节pipeline.process(text)对输入文本运行整条管线得到Annotation对象通过annotation.get(classOf[CoreAnnotations.SentencesAnnotation])取出全部句子注解SentencesAnnotation由于已导入scala.collection.convert.wrapAll._可以在 Java 集合sentences上直接使用 Scala 集合方法map、toList等对每个句子注解取出SentimentCoreAnnotations.SentimentAnnotatedTree情感注解树再通过RNNCoreAnnotations.getPredictedClass(tree)读取递归神经网络RNN预测出的整数情感类别最后交给Sentiment.toSentiment转换为枚举。提供逐句情感列表的公开方法除了主情感应用还暴露了sentiment方法返回所有句子及其各自情感的列表def sentiment(input: String): List[(String, Sentiment)] Option(input) match { case Some(text) if !text.isEmpty extractSentiments(text) case _ throw new IllegalArgumentException(input cant be null or empty) }该方法与mainSentiment共用相同的空值校验逻辑区别在于直接返回完整列表而非只取最长句子的情感适合需要细粒度逐句分析的场景。第四步用 ScalaTest 编写三类情感测试项目使用 ScalaTest 编写测试测试文件位于仓库的 SentimentAnalyzerSpec.scala采用FunSpecMatchers风格完整内容如下package com.shekhargulati.sentiment_analyzer import org.scalatest.{FunSpec, Matchers} class SentimentAnalyzerSpec extends FunSpec with Matchers { describe(sentiment analyzer) { it(should return POSITIVE when input has positive emotion) { val input Scala is a great general purpose language. val sentiment SentimentAnalyzer.mainSentiment(input) sentiment should be(Sentiment.POSITIVE) } it(should return NEGATIVE when input has negative emotion) { val input Dhoni laments bowling, fielding errors in series loss val sentiment SentimentAnalyzer.mainSentiment(input) sentiment should be(Sentiment.NEGATIVE) } it(should return NEUTRAL when input has no emotion) { val input I am reading a book val sentiment SentimentAnalyzer.mainSentiment(input) sentiment should be(Sentiment.NEUTRAL) } } }三条用例覆盖了三种情感类别正面用例Scala is a great general purpose language.期望返回Sentiment.POSITIVE负面用例Dhoni laments bowling, fielding errors in series loss板球新闻标题含抱怨/失误等负面语义期望返回Sentiment.NEGATIVE中性用例I am reading a book陈述事实、无情绪倾向期望返回Sentiment.NEUTRAL。用例均调用SentimentAnalyzer.mainSentiment并与Sentiment枚举常量做断言比较。在项目根目录运行sbt test即可执行全部测试由于首跑需要下载约 378 MB 的模型文件请预留足够时间与磁盘空间。小结与扩展方向通过这个示例我们完成了一个麻雀虽小五脏俱全的 Scala 情感分析器用 sbt 的artifacts正确引入了 CoreNLP 核心库与模型库用 4 个 annotator 配置了最小可用的情感分析管线用枚举 模式匹配封装了 CoreNLP 整数分值的语义映射并以「最长句子作为整段文本主情感」的策略对外提供mainSentiment与逐句sentiment两个 API最后用 ScalaTest 验证了正、负、中三类场景。如果你想继续深入可以沿着以下方向在本仓库之外自行扩展实验仓库本身为只读参考在build.sbt的 annotator 列表中加入ner、lemma、parse之外的能力体验 CoreNLP 更完整的语言学分析将extractSentiment的主情感策略从「按句长加权」替换为「按情感分值聚合投票」等更精细的算法用 sbt-dependency-graph 插件sbt dependencyTree核对stanford-corenlp与stanford-models的传递依赖加深对 sbt artifact 机制的理解。本示例同时属于 2016 年「每周一门新技术」系列的一部分该系列还包含 01-finatra 与 02-sbt 等 Scala 生态主题可对照阅读以构建更完整的 Scala 技术栈认知。赞分享示例工程【免费下载链接】52-technologies-in-2016Lets learn a new technology every week. A new technology blog every Sunday in 2016.项目地址https://gitcode.com/gh_mirrors/52/52-technologies-in-2016点击查看免费下载相关推荐从0到1掌握Java语音识别CMU Sphinx与Kaldi全攻略从0到1掌握Java语音识别CMU Sphinx与Kaldi全攻略 引言探索Java语音识别的技术痛点 你是否曾在开发语音交互应用时遇到以下困境开源库配置文档知识库Flair 情感分析实战指南使用预训练 sentiment 模型进行文本情感分类Flair 情感分析实战指南使用预训练 sentiment 模型进行文本情感分类 导读 本文介绍如何在 Flair 框架中使用官方预训练的情感分析sentiNLP深度学习机器学习Feedback Sentiment AnalyzerFSA实战指南基于 AWS 多语言 SDK 构建跨服务评论情感分析应用Feedback Sentiment AnalyzerFSA实战指南基于 AWS 多语言 SDK 构建跨服务评论情感分析应用 Feedback Senti示例工程教程后端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考