编者注:咱们发现了有趣的一系列文章《30天学习30种新技术》,正在翻译中,一天一篇更新,年终礼包。下面是第 14 天的内容。html
我并非一个机器学习(Machine Learning)、天然语言处理(Natural Text Processing,NLP)等的狂热者,但我总会想到一些须要用到它们的主意。咱们今天在这篇博文中要实现的目标是:利用 Twitter 数据创建一个实时的职位搜索。每一个单独的搜索结果要包括提供职位的公司名称、工做的地点、去公司应聘时联系的人。这须要咱们从 我的(Person)、地点(Location)、组织(Organisation)三方面去分析每一条推(tweet)。这类问题被归为命名实体识别(Named Entity Recognition,NER)问题。java
根据维基百科的资料,命名实体识别是信息提取(Information Extraction)的一个子任务,它把文字的原子元素(Atomic Element)定位和分类好,而后输出为固定格式的目录,例如: 人名、组织、位置、时间的表示、数量、货币值、百分比等。git
为了说的更明白,咱们来举个例子。假设咱们有下面这条推:
一个普通人能够轻易地分辨出一个名为 PSI Pax 的组织在 Baltimore 有个空缺的职位。可是咱们怎么用编程的方式来完成这个识别呢? 最简单的办法是维护一个包含全部组织名称、地点的列表,而后对这个列表进行搜索。然而,这种作法的可扩展性太差了。web
今天,在这篇博文中,我会描述如何用斯坦福 NER(Stanford NER) 软件包去设置咱们本身的 NER 服务器。编程
斯坦福 NER 命名实体识别(Named Entity Recognizer,NER)的 Java 实现。 NER 标识一段文字中的一系列名词,例如人名、公司名,又或者基因名、蛋白质名。segmentfault
一些基本的 Java 知识是须要的。在你的操做系统上安装最新版本的 JDK,你能够安装 OpenJDK 或者 Oracle JDK 7。OpenShift 支持 OpenJDK 6 和 7.api
从官网中下载斯坦福 NER 软件包。安全
注册一个 OpenShift 帐户。这是彻底免费的,并且红帽(Red Hat)会给每一个用户三个免费的 Gears,在 Gears 上你能够运行你的程序。在这篇文章写的时候,OpenShift 会为每一个用户分配 1.5GB 的内存和 3GB 的硬盘空间。ruby
在本机上,安装 rhc 客户端工具。rhc 是一个 ruby gem,因此你须要机子上安装好 ruby 1.8.7 及以上的 ruby。要安装 rhc,输入:服务器
sudo gem install rhc
更新 rhc 到最新版本,执行:
sudo gem updatge rhc
若是须要阅读额外的安装 rhc 命令行工具时的帮助文件,能够浏览:https://openshift.redhat.com/community/developers/rhc-client-tools-install
5.使用 rhc setup 命令设置好 OpenShift 帐户,这个命令会为你建立一个命名空间,而后上传你的 ssh keys 到 OpenShift 服务器上。
咱们如今开始建立这个演示应用。这个应用的名称是 nerdemo
rhc create-app nerdemo jbosseap
若是你能够访问媒介齿轮(Medium Gears),你可使用下面的命令:
$ rhc create-app nerdemo jbosseap -g medium
它会为咱们建立一个应用容器,叫作 Gear,会自动设置好须要的 SELinux/cgroup 配置。OpenShift 也会为咱们创建一个私密的 git 仓库,而后可克隆这个仓库到本地系统上。最后,OpenShift 还会部署一个链接外面的 DNS。部署的应用能够经过连接: http://linkbin-domain-name.rhcloud.com/ 来访问。把领域换成本身的 OpenShit 领域(有时候叫 命令空间)
在 pom.xml 文件中,增长一下依赖:
<dependency> <groupId>edu.stanford.nlp</groupId> <artifactId>stanford-corenlp</artifactId> <version>3.2.0</version> </dependency>
而后,经过更新 pom.xml 文件中的一些属性把 Maven 项目更新到 Java 7
<maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target>
如今,经过 右击 > Maven > 更新项目
更新 Maven
咱们会使用 CDI 来进行依赖项注入(Dependency Injection)。CDI(Context and Dependency Injection)是 Java EE 6 的一个特性,它容许在 Java EE 6 项目中的依赖项注入。CDI 为 Java EE 定义一个类型安全(type-safe) 的 依赖项注入机制。几乎任何 POJO 能够做为 CDI 豆(bean)那样被注入。
在 src/main/webapp/WEB-INF 目录下,建立一个名为 beans.xml 的 xml 文件。用下面的内容代替 beans.xml 的内容:
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd"> </beans>
如今,咱们建立一个应用程序做用域的豆(bean),这个豆会建立 CRFClassifier 类的实例。这个分类器用于检测文字中的名字、地点和组织
package com.nerdemo; import javax.annotation.PostConstruct; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.inject.Produces; import javax.inject.Named; import edu.stanford.nlp.ie.crf.CRFClassifier; import edu.stanford.nlp.ling.CoreLabel; @ApplicationScoped public class ClassifierConfig { private String serializedClassifier = "classifiers/english.all.3class.distsim.crf.ser.gz"; private CRFClassifier<CoreLabel> classifier; @PostConstruct public void postConstruct() { CRFClassifier<CoreLabel> classifier = CRFClassifier.getClassifierNoExceptions(serializedClassifier); this.classifier = classifier; } @Produces @Named public CRFClassifier<CoreLabel> classifier() { return classifier; } }
从下载的斯坦福 NER 软件包中复制 english.all.3class.distsim.crf.ser.gz 分类器到 src/main/resources/classifiers 目录下。
为了开启 AX-RS,建立一个扩展 javax.ws.rs.core.Application 的类,而后用下面 javax.ws.rs.ApplicationPath 的标记法标记应用程序的路径:
package com.nerdemo; import javax.ws.rs.ApplicationPath; import javax.ws.rs.core.Application; @ApplicationPath("/api/v1") public class JaxrsInitializer extends Application{ }
如今咱们要建立 ClassifyRestResource 类,它返回一个 NER 结果。建立一个新的 ClassifyRestResource 类,而后用下面代码代替它:
package com.nerdemo; import java.util.ArrayList; import java.util.List; import javax.inject.Inject; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import edu.stanford.nlp.ie.crf.CRFClassifier; import edu.stanford.nlp.ling.CoreAnnotations; import edu.stanford.nlp.ling.CoreLabel; @Path("/classify") public class ClassifierRestResource { @Inject private CRFClassifier<CoreLabel> classifier; @GET @Path(value = "/{text}") @Produces(value = MediaType.APPLICATION_JSON) public List<Result> findNer(@PathParam("text") String text) { List<List<CoreLabel>> classify = classifier.classify(text); List<Result> results = new ArrayList<>(); for (List<CoreLabel> coreLabels : classify) { for (CoreLabel coreLabel : coreLabels) { String word = coreLabel.word(); String answer = coreLabel.get(CoreAnnotations.AnswerAnnotation.class); if(!"O".equals(answer)){ results.add(new Result(word, answer)); } } } return results; } }
最后,部署所作的改变到 OpenShift:
$ git add . $ git commit -am "NER demo app" $ git push
当代码成功部署以后,咱们能够经过访问 http://nerdemo-{domain-name}.rhcloud.com 看到应用运行。个人示例应用运行在: http://nerdemo-t20.rhcloud.com
而后,你就会获得一个 JSON 格式的结果:
[ {"word":"Microsoft","answer":"ORGANIZATION"}, {"word":"PSI","answer":"ORGANIZATION"}, {"word":"Pax","answer":"ORGANIZATION"}, {"word":"Baltimore","answer":"LOCATION"} ]
这就是今天的内容了,保持反馈!
原文:Day 14: Stanford NER--How To Setup Your Own Name, Entity, and Recognition Server in the Cloud
翻译 SegmentFault