我没有特别热衷机器学习或者天然文字处理(NLP),不过也总能想到办法用他们。这篇博客我想探讨一下利用twitter数据构建实时搜索引擎。例如提供工做,Tweets会包含公司名字,公司地址,公司联系人,这就须要咱们从Tweet上分析人,位置,公司信息。这类问题就落到了Named Entity Recognition(NER)身上。html
维基解释java
命名实体识别(NER)是一个信息提取子任务,用于探索位置和把文字中的分类原子元素归到预先定义好的如人名,机构,地理位置,时间表述,质量,货币价值,百分比等类别中。git
为了更清晰的表述,来看一个示例,假如咱们有一下一段信息。web
常人能够很容易的指出公司PSI Pax开在Baltmore. 可是咱们怎样让程序来识别呢?最简单的方法是维护一个列表,收集全部的公司和地址,经过这个列表来搜索,可是,这个工做量没法衡量。api
今天,咱们来讨论怎样用Standford NER包来安装咱们本身的NER服务。 安全
Stanford NER是用Java编写的命名识别实体,它给文中的文字针对名字贴上标签,像人名,公司名,基因,蛋白质名等。 ruby
sudo gem install rhc
若是已经安装了,确保是最新的,要更新rhc,输入服务器
sudo gem update rhc
想了解rhc command-line 工具,更多帮助参考https://openshift.redhat.com/community/developers/rhc-client-tools-install。网络
咱们从建一个demo开始,程序叫nerdemo.oracle
$ rhc create-app nerdemo jbosseap
若是你能访问普通gears, 能够用如下命令。
$ rhc create-app nerdemo jbosseap -g medium
这会建立一个程序容器,叫gear,安装所需的SELinux策略和cgroup配置。OpenShift也会为你安装一个私有的git仓库,并克隆到本地。最后,OpenShift会把DNS 扩散到网络中。程序可访问http://linkbin-domain-name.rhcloud.com/. 替换你本身惟一的OpenShift域名(有时也叫命名空间)。
在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 >Update Project.
咱们用CDI添加依赖,CDI或者内容和依赖注入用来在Java EE 6项目中激活依赖注入。CDI给Java EE定义了安全类型的依赖注入机制,基本上全部POJO能够做为CDI bean注入。
在src/main/webapp/WEB-INF文件下新建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>
如今咱们建立一个ApplicationScoped 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; } }
从下载的Stanford NER包中复制english.all.3class.distsim.crf.ser.gz分类器到文件夹src/main/resources/classifiers.
要激活JAX-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
代码和war成功推送和发布后,咱们能够看到程序在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"} ]
这是今天的内容,继续给反馈吧。