編者注:咱們發現了有趣的一系列文章《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