我沒有特別熱衷機器學習或者天然文字處理(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"} ]
這是今天的內容,繼續給反饋吧。