- 浏览: 562466 次
- 性别:
- 来自: 杭州
文章分类
- 全部博客 (478)
- lucene (45)
- oracle (19)
- nutch (2)
- blog (2)
- 垂直搜索 (19)
- java综合 (89)
- spring (15)
- Hibernate (9)
- Struts (9)
- Hadoop (16)
- Mysql (12)
- nosql (10)
- Linux (3)
- MyEclipse (4)
- Ant (1)
- 设计模式 (19)
- JBPM (1)
- JSP (1)
- HtmlParser (5)
- SVN (2)
- 插件 (2)
- 收藏 (7)
- Others (1)
- Heritrix (18)
- Solr (4)
- 主题爬虫 (31)
- 内存数据库 (24)
- 分布式与海量数据 (32)
- httpclient (14)
- Tomcat (1)
- 面试宝典 (6)
- Python (14)
- 数据挖掘 (1)
- 算法 (6)
- 其他 (4)
- JVM (12)
- Redis (18)
最新评论
-
hanjiyun:
本人水平还有待提高,进步空间很大,看这些文章给我有很大的指导作 ...
JVM的内存管理 Ⅲ -
liuxinglanyue:
四年后的自己:这种方法 不靠谱。 使用javaagent的方式 ...
计算Java对象占用内存空间的大小(对于32位虚拟机而言) -
jaysoncn:
附件在哪里啊test.NoCertificationHttps ...
使用HttpClient过程中常见的一些问题 -
231fuchenxi:
你好,有redis,memlink,mysql的测试代码吗?可 ...
MemLink 性能测试 -
guyue1015:
[color=orange][/color][size=lar ...
JAVA同步机制
ICTCLAS 中科院分词系统 代码 注释 中文分词 词性标注 http://hi.baidu.com/hupoo/blog/item/a8898044b434514c500ffee3.html2006-11-09 11:01
ICTCLAS 中科院分词系统 代码 注释 中文分词 词性标注 这几天看完了中科院分词程序的代码,现在来做一个概述,并对一些关键的数据结构作出解释 考虑输入的一句话,sSentence="张华平欢迎您" 总体流程: 一、分词 "张/华/平/欢迎/您" 二、posTagging "张/q 华/j 平/j 欢迎/v 您/r" 三、NE识别:人名识别,音译名识别,地名识别 "张/q 华/j 平/j 欢迎/v 您/r" "张华平/nr" 四、重新分词:"张华平/欢迎/您" 五、重新posTagging: "张华平/nr 欢迎/v 您/r" 一、分词 分词程序首先在其头末添加开始符和结束符 然后是分词,基本思想就是分词的得到的词的联合概率最大 假设 "张华平欢迎您" 分为 "w_1/w_2/.../w_k" 则 细节: 首先给原句按字划分,所有汉字一个一段,连续的字母,数字一段,比如"始##始张华平2006欢迎您asdf末##末"被划为"始##始/张/华/平/2006/欢/迎/您/asdf/末##末" 接着找出这个句子中所有可能出现的词,比如"始##始张华平欢迎您末##末",出现的词有"始##始","张","华","平","欢","迎","您","末##末","欢迎" 将这些词保存在一个结构中,具体实现如下: m_segGraph中有一个(PARRAY_CHAIN)m_pHead,是一个链 (PARRAY_CHAIN)p->row//记录该词的头位置 举个例子: 对于"张"来说, 保存的顺序是按col升序row升序的次序排列 m_segGraph.m_pHead "始##始" 细节: 初始化, sp.ShortPath()函数中, 得到m_pParent之后,按照m_pWeight[m_segGraph.m_nCol-1]的升序,生成path 取出所有nResult[i]作为分词结果,结果保存在m_graphOptimum中,m_graphOptimum和m_segGraph结构一样,只不过只存nResult[i]中的结果: 如果m_nValueKind=1则 m_graphOptimum.m_pHead "始##始" CResult.m_Seg.m_pWordSeg[nIndex][k].sWord//词 至此,分词部分结束 二、posTagging 将句子分成若干段,每段以有唯一pos的w结尾,也就是分词中CResult.m_Seg.m_pWordSeg[0][k].nHandle>0的那些词 比如,举个例子 则该句被划分为 细节: 首先P(w,c)的输出概率存储在dict中,比如dictCore,dictUnknow,通过dict.GetFrequency(char *sWord, int nHandle)函数获取 sWord pos为nHandle的函数 重要的数据结构 m_nTags[i][k]表示第i个w的第k个pos 则 图中的路径的权为W([j,0]->[j+1,2])=m_dFrequency[j][0]-log(m_context.GetContextPossibility(0,m_nTags[j][0],m_nTags[j+1][2])) 在m_POSTagger.POSTagging中,以上面的例子为例 其基本思路和PosTagging一样,只不过词性c换成了role r,以人名识别为例,首先识别出人名的tag(即pos),见 四、重新分词 对上一步的graphOptimum,用第一步中对m_segGraph分词的方法,找出一个联合概率最大的分词结果: 五、重新标注 对于四中分好的结果,用标准词典对其进行posTagging:
风暴红QxRed @ 2006-04-20 20:38
中科院分词系统概述
〇、总体流程
技术细节
sSentence="始##始张华平欢迎您末##末"
w_1/w_2/.../w_k=argmax_{w_1'/w_2'/.../w_k'}P(w_1',w_2',...,w_k')=argmax_{w_1'/w_2'/.../w_k'}P(w_1')P(w_2')...P(w_k')
并查找这些词所有可能的词性和这些词出现的频率。
(PARRAY_CHAIN)p->col//记录该词的末位置
(PARRAY_CHAIN)p->value//记录该词的-log(出现的概率),出现的频率指所有该词的所有词性下出现的概率的总和。
(PARRAY_CHAIN)p->nPos//记录该词的词性,比如人名标记为'nr',则对应的nPos='n'*256+'r',如果该词有很多词性,则nPos=0
(PARRAY_CHAIN)p->sWord//记录该词
(PARRAY_CHAIN)p->nWordLen//记录该词的长度
"0 始##始 1 张 2 华 3 平 4 欢 5 迎 6 您 7 末##末 8"
row=1
col=2
value=-log[("张"出现的频率+1)/(MAX_FREQUENCE)]
nPos=0//"张"有5种词性
sWord="张"
nWordLen=2
"张"
"华"
"平"
"欢"
"欢迎"
"迎"
"您"
"末##末"
m_segGraph.m_nRow=7
m_segGraph.m_nCol=8
然后是生成一幅给予各种组合情况的图,并按照出现的概率大小保存概率最大的前m_nValueKind个结果。
(CNShortPath)sp.m_apCost=m_segGraph;
(CNShortPath)sp.m_nVertex=m_segGraph.m_nCol+1
(CNShortPath)sp.m_pParent=CQueue[m_segGraph.m_nCol][m_nValueKind]
(CNShortPath)sp.m_pWeight=ELEMENT_TYPE[m_segGraph.m_nCol][m_nValueKind]//m_pWeight[0][0]表示1处的weight
for(nCurNode=1;nCurNode<sp.m_nVertex;nCurNode++)
{
CQueue queWork;//零时的CQueue
eWeight=m_apCost->GetElement(-1,nCurNode,0,&pEdgeList);//取出col=nCurNode的第一个PARRAY_CHAIN的value,比如nCurNode=6,则pEdgeList指向"欢迎",eWeight="pEdgeList->value
while(pEdgeList&&pEdgeList->col==nCurNode)//对每一个col=nCurNode的pEdgeList
{
for(i=0;i<m_nValueKind;i++)
{
queWork.Push(pEdgeList->row,0,eWeight+m_pWeight[pEdgeList->row-1][i]);
//将所有col=nCurNode的pEdgeList按照其weight升序放到queWork中
}
}//比如
/*
"欢迎" m_pWeight[3][0]=0.2 eWight=0.2 =>queWork.Push(4,0,0.4);
"0 始##始 1 张 2 华 3 平 4 欢 5 迎 6 您 7 末##末 8"
"欢" m_pWeight[4][0]=0.5 eWight=0.1 =>queWork.Push(5,0,0.6);
m_pWeight[4][1]=0.6 eWight=0.1 =>queWork.Push(5,0,0.7);
queWork "欢迎" 0.4
"迎" 0.6
"迎" 0.7
*/
for(i=0;i<m_nValueKind;i++)m_pWeight[nCurNode-1][i]=INFINITE_VALUE;//初始化当前的m_pWeight[nCurNode-1]
while(i<m_nValueKind&&queWork.Pop(&nPreNode,&nIndex,&eWeight)!=-1)//从queWork中顺序取出每个pEdgeList的row,nIndex的取值从0到m_nValueKind-1,eWeight=pEdgeList->value
{
m_pWeight[nCurNode-1][i]=eWeight;//取前m_nValueKind个结果
m_pParent[nCurNode-1][i].Push(nPreNode,nIndex);//按照pEdgeList->value的升序,也就是P的降序放入m_pParent
}
}
CNShortPath::GetPaths(unsigned int nNode,unsigned int nIndex,int **nResult,bool bBest)
//nNode=m_segGraph.m_nCol,nIndex从0取到m_nValueKind-1,nResult输出结果,bBest=true只输出最佳结果
比如"始##始张华平欢迎您末##末"的结果为
nResult[0]={0,1,2,3,4,6,7,8,-1} "始##始/张/华/平/欢迎/您/末##末"
nResult[1]={0,1,2,3,4,5,6,7,8,-1} "始##始/张/华/平/欢/迎/您/末##末"
没有第三种结果
m_graphOptimum.m_pHead "始##始"
"张"
"华"
"平"
"欢迎"
"您"
"末##末"
m_graphOptimum.m_nRow=7
m_graphOptimum.m_nCol=8
如果m_nValueKind=2则
"张"
"华"
"平"
"欢"
"欢迎"
"迎"
"您"
"末##末"
m_graphOptimum.m_nRow=7
m_graphOptimum.m_nCol=8
见 bool CSegment::GenerateWord(int **nSegRoute, int nIndex)这里的nSegRoute=上面的nResult,是输入参数;nIndex表示第nIndex个分词结果
同时,CResult.m_Seg.m_pWordSeg[nIndex][k]中保存了第nIndex个结果的第k个词的信息:
CResult.m_Seg.m_pWordSeg[nIndex][k].nHandle//词性
CResult.m_Seg.m_pWordSeg[nIndex][k].dValue//-logP
m_POSTagger.POSTagging(m_Seg.m_pWordSeg[nIndex],m_dictCore,m_dictCore);//对第nIndex个分词结果用标准的字典标注
方便起见,下面假设m_nValueKind=1
m_POSTagger用HMM对分词进行标注,这里输出概率为P(w_i|c_i),c_i为词性,w_i为词;转移概率为P(c_i|c_{i-1}),初始状态为P(c_0)即P("始##始"的词性)
用维特比算法求出一个c_1/c_2/.../c_k=argmax_{c_1'/c_2'/.../c_k'}P(w_1',w_2',...,w_k')
"0 始##始 1 张 2 华 3 平 4 欢迎 5 您 6 末##末 7"
pos1 pos1 pos1 pos1 pos1 pos1 pos1
pos2 pos2 pos2 pos2
pos3 pos3 pos3
pos4
pos5
"0 始##始"
"1 张 2 华 3 平 4 欢迎 5 您"
"6 末##末"
对每一段用维特比算法确定一个唯一的postag
概率P(c)存储在context中,比如m_context,通过context.GetFrequency(int nKey, int nSymbol)函数获取 pos为nSymbol的函数,nKey=0
转移概率P(c|c')存储在context中,比如m_context,通过context.GetContextPossibility(int nKey, int nPrev, int nCur)函数获取 c'=nPrev,c=nCur的转移概率,nKey=0
在GetFrom函数中表示 -log(第i个w的第k个pos的输出概率)
在CSpan::Disamb()函数中
m_dFrequency[i][k]表示 -log(从第0个w到第i个w的第k个pos的联合最大输出概率),比如
w_j w_{j+1}
m_dFrequency[j][0]-- m_dFrequency[j+1][0]
m_dFrequency[j][1] -- m_dFrequency[j+1][1]
--m_dFrequency[j+1][2]
这样,选择
m_dFrequency[j+1][2]=min{W([j,0]->[j+1,2]),W([j,1]->[j+1,2])}
m_nCurLength表示当前段的w个数+1
while(i>-1&&pWordItems[i].sWord[0]!=0)//将执行段的个数次,比如上例中将执行3次
{
i=GetFrom(pWordItems,nStartPos,dictCore,dictUnknown);//i=GetFrom(pWordItems,0,dictCore,dictUnknown)=1
//i=GetFrom(pWordItems,1,dictCore,dictUnknown)=6
//i=GetFrom(pWordItems,6,dictCore,dictUnknown)=7
//从nStartPos向前取w,一直取到一个有唯一pos的w为止,该过程中记录每个w的pos,保存在m_nTags中,记录log(w|c)输出概率保存在m_dFrequency中
GetBestPOS();//调用Disamb()函数,用维特比算法找出该段的最佳(联合输出概率最大)的标注,最佳路径保存在m_nBestTag中
通过读取m_nBestTag对pWordItems.nHandle进行赋值
}
三、NE识别:人名识别,音译名识别,地名识别
"Chinese Named Entity Recognition Using Role Model"
在函数CUnknowWord::Recognition(PWORD_RESULT pWordSegResult, CDynamicArray &graphOptimum,CSegGraph &graphSeg,CDictionary &dictCore)中
每个被切开的段被识别完之后,用m_roleTag.POSTagging(pWordSegResult,dictCore,m_dict);对第一步分词的结果进行一次标记。
首先用dictUnknown.GetHandle(m_sWords[i],&nCount,aPOS,aFreq);获得m_sWords[i]在NE词典中的role,
接着用dictCore.GetHandle(m_sWords[i],&nCount,aPOS,aFreq);获得m_sWords[i]在标准词典中的tag,这里只要m_sWords[i]在标准词典中有tag,那么tag一律标记为0,该tag下的输出概率为P(w|c)=P(sum_{aFreq}|c=0)
接下来用SplitPersonPOS(dictUnknown)函数将其中tag为LH和TR的w拆成两个
比如"张/SS 华/GH 平欢/TR 迎/RC 您/RC"中"平欢"被拆成"平/GT" "欢/12"
接着在PersonRecognize(dictUnknown);函数中,用一些模板进行匹配,"SS/GH/TR"将匹配到"张华平"。匹配得到的片断保存在m_nUnknownWords中,其nHandle被设置为人名,地名,音译名中的一个
对第一步中的graphOptimum,加入m_nUnknownWords的边:
graphOptimum.GetElement(nAtomStart,nAtomEnd,&dValue,&nPOSOriginal);
if(dValue>m_roleTag.m_dWordsPossibility[i])//Set the element with less frequency
graphOptimum.SetElement(nAtomStart,nAtomEnd,m_roleTag.m_dWordsPossibility[i],m_nPOS);
m_Seg.OptimumSegmet(nCount);
for(nIndex=0;nIndex<m_Seg.m_nSegmentCount;nIndex++)//m_Seg.m_nSegmentCount是第四步中的分词结果个数
{
m_POSTagger.POSTagging(m_Seg.m_pWordSeg[nIndex],m_dictCore,m_dictCore);
}
最后,用Sort();对标注结果按照联合输出概率的大小降序排序,并按照用户的需求输出前几个
发表评论
-
关于Lucene的讨论
2011-01-01 10:20 1060分类为[lucene]的文章 ... -
有关Lucene的问题(收藏)推荐
2010-12-30 21:02 1107有关Lucene的问题(1):为 ... -
Lucene 学习总结(收藏)推荐
2010-12-30 20:54 1555Lucene学习总结之一:全文检索的基本原理 ... -
基于Lucene的Compass 资源(收藏)
2010-12-29 18:29 11421.2、Compass相关网上资源 1、官方网站1: http ... -
Lucene 3.0.2索引文件官方文档(二)
2010-12-28 22:36 1004Deletable File A writer dy ... -
Lucene 3.0.2索引文件官方文档(一)
2010-12-28 22:34 1457Apache Lucene - Index File ... -
Lucene 3.0 索引文件学习总结(收藏)
2010-12-28 22:28 936lucene学习1——词域信息 ... -
Lucene 字符编码问题
2010-12-27 20:29 992现在如果一个txt文件中包含了ANSI编码的文本文件和Uni ... -
Lucene 字符编码问题
2010-12-27 20:20 1029现在如果一个txt文件中包含了ANSI编码的文本文件和Unic ... -
Annotated Lucene(源码剖析中文版)
2010-12-25 22:52 1260Apache Lucene是一个高性能(high-pe ... -
Lucene 学习推荐博客
2010-12-25 22:42 1031深未来deepfuturelx http://deepfut ... -
Lucene3.0 初窥 总结(收藏)
2010-12-25 22:16 1807【Lucene3.0 初窥】全文检索的基本原理 ... -
转:基于lucene实现自己的推荐引擎
2010-12-17 17:05 1053采用基于数据挖掘的 ... -
加速 lucene 的搜索速度 ImproveSearchingSpeed(二)
2010-12-17 17:01 1031本文 为简单翻译,原文在:http://wiki.apac ... -
加速 lucene 索引建立速度 ImproveIndexingSpeed
2010-12-17 16:58 1070本文 只是简单的翻译,原文 在 http://wiki.a ... -
lucene 3.0 中的demo项目部署
2010-12-15 22:02 970转自:bjqincy 1 在myEclipise 建立 ... -
Lucene 3.0.2 源码 - final class Document
2010-12-14 22:33 888package org.apache.lucene.do ... -
Lucene 3.0.2 源码 - final class Field
2010-12-14 22:29 951package org.apache.lucene.do ... -
Lucene 3.0.2 源码 - abstract class AbstractField
2010-12-14 22:28 1039package org.apache.lucene.do ... -
Lucene 3.0.2 源码 - interface Fieldable
2010-12-14 22:28 1176package org.apache.lucene.do ...
相关推荐
中科院ICTCLAS2014分词系统下载包
ICTCLAS中文分词系统C++代码,内容很强大,很好。ICTCLAS中文分词系统是目前世界最好的分词系统
ICTCLAS 中科院分词 在java上的实现demo 包含了ICTCLAS接口开发文档
ICTCLAS中文分词系统是基于信息技术(ICT)和自然语言处理(NLP)的工具,主要用于处理中文文本。这个系统由中关村的科研团队开发,代表着国内在中文分词技术领域的先进水平。分词是中文信息处理的重要步骤,因为...
在张华平博士的空间上直接下载的,用VS2010打开发现有几处BUG,主要是VC6.0转VC10.0的兼容问题,我上传的源码中,BUG已经恢复,代码现在能完美运行(包括分词词库)。
这是中科院的ICTCLAS的中文分词算法的源代码,可以实现中文分词,词性标注等功能。绝对好用!
ICTCLAS 中文分词 中科院 ICTCLAS 中文分词 中科院
中科院的中文分词系统ICTCLAS是从事文本挖掘研究工作的学者们所广泛使用的软件,在此就不多作介绍了。这是该软件的2015版本,欢迎各位学者下载使用。
ICTCLAS 中科院分词 里面有demo和相关使用文档,最好的中文分词工具
最好的中文分词算法,新鲜出炉,不过里面的文件是2014的
带分词词性分类,VS2008项目,可以直接运行Demo程序,效果棒棒哒!
中科院ICTCLAS分词系统是值得学习和研究,是目前中文分词系统中公认的最为完善的一个,但其缺乏文档使很多爱好者带来极大的困难,参考他人意见,结合代码对其内部进行简要分析。
中科院ICTCLAS2014分词系统下载包,文本分析工具,方便使用。
在IT领域,中文分词和词性标注是自然语言处理(NLP)的重要组成部分,尤其在文本分析、信息检索、机器翻译等领域具有广泛的应用。在C#编程环境下,开发这样的功能可以帮助开发者处理和理解中文文本数据。下面我们将...
中科院分词,最流行的中文分词,我的总结。
ICTCLAS(Chinese Word Segmentation for Information Content Extraction and Linguistic Analysis System)是由北京师范大学的陈天教授基于ICTCLAS(信息内容提取与语言分析系统)进一步开发的一个Java分词系统。...
总的来说,NLPIR/ICTCLAS2014分词系统是一个强大且成熟的工具,对于从事中文自然语言处理的开发者来说,它是一个不可或缺的资源。其提供的高效分词能力以及易于扩展的特性,使得它广泛应用于信息检索、文本挖掘、...
jieba的词性标注采用了与ictclas(NLPIR)兼容的标记法,这是一种标准化的词性标记系统,方便了不同工具之间的数据交换和分析。 在jieba的词性标注体系中,每个词都被赋予了一个特定的标签,这些标签按照词性的英文...
ictclas去掉词性仅分词
中科院分词系统+ICTCLAS2011+JNI版(Java语言)源代码学习