您的位置:首页 > 编程语言 > PHP开发

HIT LTP的使用及利用句法关系简单抽取示例

2012-12-05 19:35 363 查看
中文的分词工具相对来说多点,比较有名的是计算所的ICTCLAS,哈工大的LTP,斯坦福的Parser等。但是命名实体识别、句法分析等的工具却不多,我所知的有哈工大的LTP、Stanford Parser。由于Stanford Parser最先是针对英文的处理工具,在中文上效果相对来说比LTP差些。下面我介绍一些个人对LTP的简单认识及初步使用。
不同于Stanford Parser的java版本,LTP的原始程序是用C++开发的(也提供了python版)。提供的接口使得能输入字符串文本或文件名,文本可以是单句,也可以是段落或文章(但需要先调用分句模块)。然后是分词、词性标注、句法分析,还包括其他功能如命名实体识别、词义消歧、语义角色标注。LTP底层以XML表示文本,以DOM处理文本。看其说明的好处是首先可以保留处理结果而不需要以后重新运行(牺牲空间换取时间),另外xml文件存储的处理结果可以用LTP提供的工具通过浏览器以图形化界面查看,具有直观效果。写的这些其实算是多此一举,详细内容可以参考下载的LTP中的"LTP使用文档v*.0.pdf"。
注意点:
如何扩展分词模块的词表?
在ltp_data/irlas_data/extend_dict.dat中的相应词性下添加新词即可。(它需要我们添加的新词给出词性,所以词性的正确与否将影响结果。)
LTP路径配置
test_vs2008文件夹下的ltp_all_modules.conf中设置。(我用的一个版本的初始设置有错,需要修正)
LTP依存关系
据我个人观察,句子中一般只有一个中心词,父亲节点编号-1,依存关系HED,一般词性为v。但是句子中可能存在多个主谓宾关系,一个主谓宾关系的小句子中的中心词为大句子的宾或主。Stanford Parser中则似乎最多只有一个主谓宾,其他动词则成为修饰。
抽取句子主谓宾(最外围)
void extract_action(vector<const char *> vecWord, vector<int> vecDep,vector<string> vecRel)
{
int i,j,hed = -1;
for(i = 0;i < vecDep.size();i ++)
if(vecDep[i] == -1)
{
hed = i;
break;
}
if(hed == -1)return;
for(i = 0;i < vecRel.size();i ++)
{
string rel = vecRel[i];
if(rel.compare("SBV") == 0 && vecDep[i] == hed)
printf("|%s",vecWord[i]);
}
printf("->%s->",vecWord[hed]);
for(j = vecRel.size()-1;j >= 0;j --)
{
string rel = vecRel[j];
if(rel.compare("VOB") == 0 && vecDep[j] == hed)
printf("%s|",vecWord[j]);
}
printf("\n");
}
我曾经总结了一些种简单的主谓宾抽取模板,由于很不全,仅介绍如下作为大家参考:



具体参考:Tan Z., Mao W., and Zeng D. Semi-Automatic Construction of Agent-Based Model for Netizen Groups in Food Safety Internet Events, Chinese Conference on Social Computing (CCSC 2011), Zhangjiajie, Hunan.
url: http://wenku.baidu.com/view/a159f20603d8ce2f006623d1.html
split_pair_vector()函数
void split_pair_vector(const vector< pair<int, const char *> > &vecParse, vector<int> &vecDep, vector<string> &vecRel)
{
vecDep.clear();
vecRel.clear();
vector< pair<int, const char *> >::const_iterator iter;
for(iter=vecParse.begin(); iter != vecParse.end(); iter++) {
vecDep.push_back(iter->first);
vecRel.push_back( string(iter->second) );
}
}

附:
? 分句,SplitSentence
? 分词及词性标注 (Word segment and POS),IRLAS
? 分词(Word segment),SegmentWord
? 词性标注 (POS Tagging),PosTag
? 命名实体识别 (Named entity recognition),NER
? 词义消歧 (Word sense disambiguation),WSD
? 依存分析器 (Dependency Parser)
? 基于局部动态算法的依存句法分析,Parser
? 基于图方法的依存句法分析, GParser
? 语义角色标注 (Semantic role labeling),SRL
以句子为单位的处理模块
? int SplitSentence(); // 严格来讲是以段落为单位的处理模块
? int IRLAS(); // Word segment and POS
? int SegmentWord(); // Word segment
? int PosTag(); // POS Tagging
? int NER(); // Named entity recognition
? int WSD(); // Word sense disambiguation
? int Parser(); // Dependency parser
? int GParser(); // Dependency parser
? int SRL(); // Semantic role labeling
每次抽取一个句子中所有词语的信息
// Get words
? int GetWordsFromSentence(vector<const char *> &vecWord, int paragraphIdx, int sentenceIdx);
? int GetWordsFromSentence(vector<const char *> &vecWord, int globalSentIdx);
第一个函数抽取第paragraphIdx个段落中的第sentenceIdx个句子的词语。 第二个函数抽取整个篇章第globalSentIdx个句子的词语。
// Get POSs
? int GetPOSsFromSentence(vector<const char *> &vecPOS, int paragraphIdx, int sentenceIdx);
? int GetPOSsFromSentence(vector<const char *> &vecPOS, int globalSentIdx);
// Get NEs
? int GetNEsFromSentence(vector<const char *> &vecNE, int paragraphIdx, int sentenceIdx);
? int GetNEsFromSentence(vector<const char *> &vecNE, int globalSentIdx);
// Get WSDs // 抽取同义词词林的语义代码
? int GetWSDsFromSentence(vector<const char *> &vecWSD, int paragraphIdx, int sentenceIdx);
? int GetWSDsFromSentence(vector<const char *> &vecWSD, int globalSentIdx);
// 抽取同义词词林的语义解释
? int GetWSDExplainsFromSentence(vector<const char *> &vecWSDExplain, int paragraphIdx,
int sentenceIdx);
? int GetWSDExplainsFromSentence(vector<const char *> &vecWSDExplain, int globalSentIdx);
// Get Parses
? int GetParsesFromSentence(vector< pair<int, const char *> > &vecParse, int paragraphIdx, int sentenceIdx);
? int GetParsesFromSentence(vector< pair<int, const char *> > &vecParse, int globalSentIdx);
pair<int, const char *>中int表示父亲节点在本句子中的编号,从0开始编号;const char*为关系类型。 父亲节点编号为-1表示为句子的核心节点。 父亲节点编号为-2表示为标点符号,没有父亲节点。
处理句子程序实例
ifstream inf("test_200_in.txt");
ofstream outf("test_200_out.txt");
string strText;
while(getline(inf,strText))
{
CreateDOMFromString(strText);
SegmentWord();
GParser();
vector<const char*> vecWord,vecPos;
GetWordsFromSentence(vecWord,0);
GetPOSsFromSentence(vecPos,0);
copy(vecWord.begin(),vecWord.end(),ostream_iterator<const char *>(outf,"\t"));outf<<endl;
copy(vecPos.begin(),vecPos.end(),ostream_iterator<const char *>(outf,"\t"));outf<<endl;
vector<pair<int,const char *>> vecParse;
vector<int> vecDep;
vector<string> vecRel;
GetParsesFromSentence(vecParse,0);
split_pair_vector(vecParse,vecDep,vecRel);
copy(vecDep.begin(),vecDep.end(),ostream_iterator<int>(outf,"\t"));outf<<endl;
copy(vecRel.begin(),vecRel.end(),ostream_iterator<string>(outf,"\t"));outf<<endl;
//extract_action(vecWord,vecDep,vecRel);
}
inf.close();
outf.close();
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: