coreNLP-java使用(中文)

1. IntelliJ IDEA中建立maven工程

推荐参考 maven工程建立具体过程

2. pom.xml 新增内容


    3.9.1


    edu.stanford.nlp
    stanford-corenlp
    ${corenlp.version}



    edu.stanford.nlp
    stanford-corenlp
    ${corenlp.version}
    models



    edu.stanford.nlp
    stanford-corenlp
    ${corenlp.version}
    models-chinese

这时maven工程会自动从maven repository 中下载指定版本的jar包,并把该资源存储到指定仓库中。
如果下载速度很慢,可能会出现中断现象,这时可以尝试使用国内镜像,修改maven根目录下的conf文件夹中的setting.xml文件,内容如下:


   
     alimaven
     aliyun maven
     http://maven.aliyun.com/nexus/content/groups/public/
     central        
   
 

注:如果使用的是idea内置的maven,打开该文件的方法,如下:

cd .m2/
open settings.xml

3. CoreNLP-chinese.properties文件内容

# Pipeline options - lemma is no-op for Chinese but currently needed because coref demands it (bad old requirements system)

#设定了管道中包括哪些Annotators(一个Annotator就是你需要的文本分析分析工具, 他的结果就是一个或多个Annotation)
#segment:分词, ssplit:分隔, pos: 词性标注, lemma: has->have, ner:命名实体识别, parse:语法分析 
annotators = segment, ssplit, pos, lemma, ner, parse, sentiment, mention, coref
#annotators = segment, ssplit, pos, parse, sentiment 


# segment 分词
customAnnotatorClass.segment = edu.stanford.nlp.pipeline.ChineseSegmenterAnnotator
segment.model = edu/stanford/nlp/models/segmenter/chinese/pku.gz
segment.sighanCorporaDict = edu/stanford/nlp/models/segmenter/chinese
segment.serDictionary = edu/stanford/nlp/models/segmenter/chinese/dict-chris6.ser.gz
segment.sighanPostProcessing = true

# sentence split
ssplit.boundaryTokenRegex = [.]|[!?]+|[\u3002]|[\uFF01\uFF1F]+

# pos
pos.model = edu/stanford/nlp/models/pos-tagger/chinese-distsim/chinese-distsim.tagger

#ner 此处设定了ner使用的语言、模型(crf),目前SUTime只支持英文,不支持中文,所以设置为false。
ner.language = chinese
ner.model = edu/stanford/nlp/models/ner/chinese.misc.distsim.crf.ser.gz
ner.applyNumericClassifiers = true
ner.useSUTime = false

#parse
parse.model = edu/stanford/nlp/models/lexparser/chineseFactored.ser.gz

# coref
coref.sieves = ChineseHeadMatch, ExactStringMatch, PreciseConstructs, StrictHeadMatch1, StrictHeadMatch2, StrictHeadMatch3, StrictHeadMatch4, PronounMatch
coref.input.type = raw
coref.postprocessing = true
coref.calculateFeatureImportance = false
coref.useConstituencyTree = true
coref.useSemantics = false
coref.md.type = RULE
coref.mode = hybrid
coref.path.word2vec =
coref.language = zh
coref.print.md.log = false
coref.defaultPronounAgreement = true
coref.zh.dict = edu/stanford/nlp/models/dcoref/zh-attributes.txt.gz

4. 主要功能

1)名词解释

nameEg nameCh
Summary 功能总结
Annotator dependencies 注释器依赖项
Tokenization 符号化<=>tokenize
Sentence Splitting 句子切分<=>ssplit
Lemmatization 词干提取<=>lemma (例: has=>have
Parts of Speech 词性<=>pos
Named Entity Recognition 命名实体识别<=>ner
RegexNER(Named Entity Recognition) RegexNER(命名实体识别)<=>regexner(常常作为ner的补充
Constituency Parsing 选区解析<=>parse(把句子组织成短语形式
Dependency Parsing 依存句法分析<=>depparse
Coreference Resolution 共指消解<=>coref (例:美国总统<=>特朗普
Natural Logic 自然的逻辑<=>natlog
Open information Extraction 开放的信息提取<=>openIE
Sentiment 情感分析<=>sentiment
Relation Extraction 关系抽取<=>relation
Quote Annotator 引用注释<=>quote(获取引用的内容
CleanXML Annotator cleanxml注释<=>clean(解析xml文件

2) 各个功能模块的依赖项

功能模块 ANNOTATOR 类 依赖项
tokenize TokenizerAnnotator None
cleanxml CleanXmlAnnotator tokenize/segment
ssplit WordsToSentenceAnnotator tokenize/segment
pos POSTaggerAnnotator tokenize/segment, ssplit
lemma MorphaAnnotator tokenize/segment, ssplit, pos
ner NERClassifierCombiner tokenize/segment, ssplit, pos, lemma
regexner RegexNERAnnotator tokenize/segment,ssplit,pos,lemma,ner
sentiment SentimentAnnotator tokenize/segment, ssplit, parse
parse ParserAnnotator tokenize/segment, ssplit,pos,lemma
depparse DependencyParseAnnotator tokenize, ssplit, pos
coref CorefAnnotator tokenize/segment,ssplit,pos,lemma,ner,parse
relation RelationExtractorAnnotator tokenize, ssplit, pos, lemma, ner,depparse
natlog NaturalLogicAnnotator tokenize, ssplit, pos, lemma, depparse/parse
quote QuoteAnnotator None

5. 案例

1)加载所用的模型

  • 创建加载模型的类(各个模块通用的类
import edu.stanford.nlp.pipeline.StanfordCoreNLP;
public class CoreNLPHel {
    private static CoreNLPHel instance = new CoreNLPHel();
    private StanfordCoreNLP pipeline;
    private CoreNLPHel(){
        String props="CoreNLP-chinese.properties";  //第三步骤的配置文件,放在main/resources目录下
        pipeline = new StanfordCoreNLP(props);
    };
    public static CoreNLPHel getInstance(){
        return instance;
    }
    public StanfordCoreNLP getPipeline(){
        return pipeline;
    }
}

2) 中文分词

  • 修改配置文件
    只需分句和分词模块,其他模块注释掉
annotators = segment, ssplit, pos, lemma, ner, parse, sentiment, mention, coref

修改成

annotators = segment, ssplit
  • 创建中文分词所用的类
import edu.stanford.nlp.ling.CoreAnnotations;
import edu.stanford.nlp.ling.CoreLabel;
import edu.stanford.nlp.pipeline.Annotation;
import edu.stanford.nlp.pipeline.StanfordCoreNLP;
import edu.stanford.nlp.util.CoreMap;
import java.util.List;

public class Segmentation {
   private String segtext="";

   public String getSegtext() {
       return segtext;
   }
   public Segmentation(String text){
       CoreNLPHel coreNLPHel = CoreNLPHel.getInstance();
       StanfordCoreNLP pipeline = coreNLPHel.getPipeline();
       Annotation annotation = new Annotation(text);
       pipeline.annotate(annotation);
       List sentences = annotation.get(CoreAnnotations.SentencesAnnotation.class);
       //ArrayList array = new ArrayList();
       StringBuffer sb = new StringBuffer();
       for (CoreMap sentence:sentences){
           for (CoreLabel token : sentence.get(CoreAnnotations.TokensAnnotation.class)){
               String word = token.get(CoreAnnotations.TextAnnotation.class);
               sb.append(word);
               sb.append(" ");
           }
       }
      segtext = sb.toString().trim();
       //segtext = array.toString();
   }

}
  • 中文分词案例
public class Test {
    public static void main(String []args){
        System.out.println(new Segmentation("这家酒店很好,我很喜欢。").getSegtext());
        System.out.println(new Segmentation("他和我在学校里常打桌球。").getSegtext());
        System.out.println(new Segmentation("貌似实际用的不是这几篇。").getSegtext());
        System.out.println(new Segmentation("硕士研究生产。").getSegtext());
        System.out.println(new Segmentation("我是中国人。").getSegtext());
    }
}
out:
这 家 酒店 很 好 , 我 很 喜欢 。
他 和 我 在 学校 里 常 打 桌球 ; 毕业 了
貌似 实际 用 的 不 是 这 几 篇
硕士 研究生 产 ? 批判 官员 的 尺度
我 是 中国人 。
  • 自定义字典
    修改配置文件CoreNLP-chinese.properties
segment.serDictionary = edu/stanford/nlp/models/segmenter/chinese/dict-chris6.ser.gz

修改成

segment.serDictionary = edu/stanford/nlp/models/segmenter/chinese/dict-chris6.ser.gz,自己的路径/cedict.txt

亲测没用,待补充(唯一能查到的方法)

3) 中文分句

  • 修改配置文件
    保留分句部分,注释其他部分
annotators = segment, ssplit, pos, lemma, ner, parse, sentiment, mention, coref

修改成

annotators = tokenize, ssplit

并且可以修改下述句子分割符

ssplit.boundaryTokenRegex = [.。;;]|[!?!?]+
  • 创建分句所需的类
import edu.stanford.nlp.ling.CoreAnnotations;
import edu.stanford.nlp.pipeline.Annotation;
import edu.stanford.nlp.pipeline.StanfordCoreNLP;
import edu.stanford.nlp.util.CoreMap;

import java.util.ArrayList;
import java.util.List;

public class SenSplit {

    private ArrayListsensRes = new ArrayList();

    public ArrayList getSensRes() {
        return sensRes;   //返回存储句子的数组(ArrayList类型)
    }
    public SenSplit(String text){
        CoreNLPHel coreNLPHel = CoreNLPHel.getInstance();
        StanfordCoreNLP pipeline = coreNLPHel.getPipeline();
        Annotation annotation = new Annotation(text);
        pipeline.annotate(annotation);
        Listsentences = annotation.get(CoreAnnotations.SentencesAnnotation.class);
        for (CoreMap setence:sentences){
            sensRes.add(setence.get(CoreAnnotations.TextAnnotation.class));
        }
    }
}
  • 中文分句案例
import java.util.ArrayList;
public class Test {
    public static void main(String []args){
        String text = "巴拉克·奥巴马是美国总统。他在2008年当选?今年的美国总统是特朗普?普京的粉丝";
        ArrayListsensRes = new SenSplit(text).getSensRes();
        for(String str:sensRes){
            System.out.println(str);
        }
    }
}
out:
巴拉克·奥巴马是美国总统。
他在2008年当选?
今年的美国总统是特朗普?
普京的粉丝

4) 词性标注

  • 修改配置文件
    保留分词、分句、词性标注模块,注释其他
annotators = segment, ssplit, pos, lemma, ner, parse, sentiment, mention, coref

修改成

annotators = segment, ssplit, pos
  • 创建词性标注所需的类
import edu.stanford.nlp.ling.CoreAnnotations;
import edu.stanford.nlp.ling.CoreLabel;
import edu.stanford.nlp.pipeline.Annotation;
import edu.stanford.nlp.pipeline.StanfordCoreNLP;
import edu.stanford.nlp.util.CoreMap;

import java.util.List;

public class PosTag {

    private String postext = "";

    public String getPostext() {
        return postext;
    }
    public PosTag(String text){

        CoreNLPHel coreNLPHel = CoreNLPHel.getInstance();
        StanfordCoreNLP pipeline = coreNLPHel.getPipeline();
        Annotation annotation = new Annotation(text);
        pipeline.annotate(annotation);
        List sentences = annotation.get(CoreAnnotations.SentencesAnnotation.class);
        StringBuffer sb = new StringBuffer();
        for (CoreMap sentence:sentences){
            for (CoreLabel token : sentence.get(CoreAnnotations.TokensAnnotation.class)){
                String word = token.get(CoreAnnotations.TextAnnotation.class);
                String pos = token.get(CoreAnnotations.PartOfSpeechAnnotation.class);
                sb.append(word);
                sb.append("/");
                sb.append(pos);
                sb.append(" ");
            }
        }
        postext = sb.toString().trim();
    }
}
  • 词性标注案例
public class Test {
    public static void main(String []args){
        String text = "巴拉克·奥巴马是美国总统。他在2008年当选?今年的美国总统是特朗普?普京的粉丝";
        System.out.println(new PosTag(text).getPostext());
    }
}
out:
巴拉克·奥巴马/NR 是/VC 美国/NR 总统/NN 。/PU 他/PN 在/P 2008年/NT 当选/VV ?/PU 今年/NT 的/DEG 美国/NR 总统/NN 是/VC 特朗普/NN ?/PU 普京/NR 的/DEG 粉丝/NN
  • 词性标注符号含义
符号 含义 例子
VA 谓词性形容词 没有宾语且能被“很”修饰的谓语。
VC 系动词 连接两个名词短语或者主语:他 是/VC 学生
VE “有”作为主要动词 有当“有,没{有}”和“无”作为主要动词
VV 其他动词 情态动词、提升谓词、控制动词、行为动词、心理动词等
NR 专有名词 人名、政治或地理上定义的地方、组织
NT 时间名词 一月、汉朝、当今、何时、今后
NN 其他名词 种族、国籍、职称、疾病
LC 方位词 表示方向、位置。前,后,里,外,之间,以北
PN 代词 我、你、这、那、如其
DT 限定词 限定词包括指示词(如这、那、该)和诸如“每、各、前、后”等词
CD 基数词 好些、若干、半、许多、很多
OD 序列词 我们把第+CD看做一个词,并标注它为OD。第一百
M 度量词 个、群、公里、升
AD 副词 仍然、很、最、大大、又、约
P 介词 从、对
CC 并列连接词 与、和、或、或者、还是(or)
CS 从属连词 如果/CS,……就/AD……
DEC “的”作为补语标记/名词化标记 拿来吃的/DEC
DEG “的”作为关联标记或所有格标记 普京/NR 的/DEG 粉丝/NN
DER 补语短语 在V-得-R和V-得结构中,“得”标记为DER
DEV 方式“地” 当“地”出现在“地VP”,很大程度地完成
AS 动态助词 动态助词仅包括“着,了,过,的”
SP 句末助词 他好吧[SP]?
ETC ETC用于标注等 None
MSP 其他助词 “所,以,来,而”,当它们出现在VP前时,标注为MSP
IJ 感叹词 出现在句首位置的感叹词,如:啊
ON 拟声词 雨哗哗,砰[ON]的/DEG一声!,砰砰[ON]!
LB 长“被”结构 仅包括“被,叫,给,为(口语中)”,他叫/VV你去
SB 短“被”结构 NP0+SB+VP,他被/SB 训了/AS一顿/M
BA 把字结构 他把/BA你骗了/AS
JJ 其他名词修饰语 共同/JJ的/DEG目标/NN
FW 外来词 词性标注标记在上下文中不是很清楚的词
PU 标点 。?!

5) 命名实体识别

  • 修改配置文件
    保留分词、分句、词性标注、命名实体识别模块,注释其他
annotators = segment, ssplit, pos, lemma, ner, parse, sentiment, mention, coref

修改成

annotators = segment, ssplit, pos,ner 
  • 创建命名实体识别所需的类
import edu.stanford.nlp.ling.CoreAnnotations;
import edu.stanford.nlp.ling.CoreLabel;
import edu.stanford.nlp.pipeline.Annotation;
import edu.stanford.nlp.pipeline.StanfordCoreNLP;
import edu.stanford.nlp.util.CoreMap;

import java.util.List;

public class NamedEntity {

    private String nertext = "";

    public String getNertext() {
        return nertext;
    }

    public NamedEntity(String text){
        CoreNLPHel coreNLPHel = CoreNLPHel.getInstance();
        StanfordCoreNLP pipeline = coreNLPHel.getPipeline();
        Annotation annotation = new Annotation(text);
        pipeline.annotate(annotation);
        List sentences = annotation.get(CoreAnnotations.SentencesAnnotation.class);
        StringBuffer sb = new StringBuffer();
        for (CoreMap sentence:sentences){
            // 获取句子的token(可以是作为分词后的词语)
            for (CoreLabel token : sentence.get(CoreAnnotations.TokensAnnotation.class)){
                String word = token.get(CoreAnnotations.TextAnnotation.class);
                //String pos = token.get(CoreAnnotations.PartOfSpeechAnnotation.class);
                //String ne = token.get(CoreAnnotations.NormalizedNamedEntityTagAnnotation.class);
                String ner = token.get(CoreAnnotations.NamedEntityTagAnnotation.class);
                //System.out.println(word + "\t" + pos + " | analysis : {  original : " + ner + "," + " normalized : " + ne + "}");
                sb.append(word);
                sb.append("/");
                sb.append(ner);
                sb.append(" ");
            }
        }
        nertext = sb.toString().trim();
    }
}
  • 命名实体识别案例
public class Test {
    public static void main(String []args){
        String text = "巴拉克·奥巴马是美国总统。他在2008年当选?今年的美国总统是特朗普?普京的粉丝";
       System.out.println(new NamedEntity(text).getNertext());
    }
}
out:
巴拉克·奥巴马/PERSON 是/O 美国/GPE 总统/O 。/O 他/O 在/O 2008年/DATE 当选/O ?/O 今年/DATE 的/O 美国/GPE 总统/O 是/O 特朗普/O ?/O 普京/PERSON 的/O 粉丝/O

6) 句子的解析树 && 句子依存分析

修改配置文件
保留分词、分句、词性标注、lemma、prase模块,注释其他

annotators = segment, ssplit, pos, lemma, ner, parse, sentiment, mention, coref

修改成

annotators = segment, ssplit, pos, lemma, parse
  • 创建句子解析和依存分析所需的类
import edu.stanford.nlp.ling.CoreAnnotations;
import edu.stanford.nlp.pipeline.Annotation;
import edu.stanford.nlp.pipeline.StanfordCoreNLP;
import edu.stanford.nlp.semgraph.SemanticGraph;
import edu.stanford.nlp.semgraph.SemanticGraphCoreAnnotations;
import edu.stanford.nlp.trees.Tree;
import edu.stanford.nlp.trees.TreeCoreAnnotations;
import edu.stanford.nlp.util.CoreMap;
import java.util.List;

public class SPTree {
    Listsentences;

    public SPTree(String text){
        CoreNLPHel coreNLPHel = CoreNLPHel.getInstance();
        StanfordCoreNLP pipeline = coreNLPHel.getPipeline();
        Annotation annotation = new Annotation(text);
        pipeline.annotate(annotation);
        sentences = annotation.get(CoreAnnotations.SentencesAnnotation.class);
    }

    //句子的依赖图(依存分析)
    public String getDepprasetext() {
        StringBuffer sb2 = new StringBuffer();
        for (CoreMap sentence:sentences){
            String sentext = sentence.get(CoreAnnotations.TextAnnotation.class);
            SemanticGraph graph = sentence.get(SemanticGraphCoreAnnotations.BasicDependenciesAnnotation.class);
            //System.out.println("句子的依赖图");
            sb2.append(sentext);
            sb2.append("\n");
            sb2.append(graph.toString(SemanticGraph.OutputFormat.LIST));
            sb2.append("\n");
        }
        return sb2.toString().trim();
    }
    // 句子的解析树
    public String getPrasetext() {
        StringBuffer sb1 = new StringBuffer();
        for (CoreMap sentence:sentences){
            Tree tree = sentence.get(TreeCoreAnnotations.TreeAnnotation.class);
            String sentext = sentence.get(CoreAnnotations.TextAnnotation.class);
            sb1.append(sentext);
            sb1.append("/");
            sb1.append(tree.toString());
            sb1.append("\n");
        }
        return sb1.toString().trim();
    }
}
  • 句子解析案例
public class Test {
    public static void main(String []args){
        String text = "巴拉克·奥巴马是美国总统。他在2008年当选?今年的美国总统是特朗普?普京的粉丝";
        SPTree spTree = new SPTree(text);
        System.out.println(spTree.getPrasetext());
    }
}
out:
巴拉克·奥巴马是美国总统。/(ROOT (IP (NP (NR 巴拉克·奥巴马)) (VP (VC 是) (NP (NP (NR 美国)) (NP (NN 总统)))) (PU 。)))
他在2008年当选?/(ROOT (IP (NP (PN 他)) (VP (PP (P 在) (NP (NT 2008年))) (VP (VV 当选))) (PU ?)))
今年的美国总统是特朗普?/(ROOT (IP (NP (DNP (NP (NT 今年)) (DEG 的)) (NP (NR 美国)) (NP (NN 总统))) (VP (VC 是) (NP (NN 特朗普))) (PU ?)))
普京的粉丝/(ROOT (NP (DNP (NP (NR 普京)) (DEG 的)) (NP (NN 粉丝))))
  • 句子依存分析案例
public class Test {
    public static void main(String []args){
        String text = "巴拉克·奥巴马是美国总统。他在2008年当选?今年的美国总统是特朗普?普京的粉丝";
        SPTree spTree = new SPTree(text);
        System.out.println(spTree.getDepprasetext());
    }
}
out:
巴拉克·奥巴马是美国总统。:
root(ROOT-0, 总统-4)
nsubj(总统-4, 巴拉克·奥巴马-1)
cop(总统-4, 是-2)
nmod:assmod(总统-4, 美国-3)
punct(总统-4, 。-5)

他在2008年当选?:
root(ROOT-0, 当选-4)
nsubj(当选-4, 他-1)
case(2008年-3, 在-2)
nmod:prep(当选-4, 2008年-3)
punct(当选-4, ?-5)

今年的美国总统是特朗普?:
root(ROOT-0, 特朗普-6)
nmod(总统-4, 今年-1)
case(今年-1, 的-2)
nmod:assmod(总统-4, 美国-3)
nsubj(特朗普-6, 总统-4)
cop(特朗普-6, 是-5)
punct(特朗普-6, ?-7)

普京的粉丝:
root(ROOT-0, 粉丝-3)
nmod:assmod(粉丝-3, 普京-1)
case(普京-1, 的-2)
  • Stanford-parser依存句法关系解释

你可能感兴趣的:(coreNLP-java使用(中文))