首页新闻招聘找找看知识库
  • 回复:330 浏览:44712 2009-08-14 07:54 来自 eaglet

    盘古分词是一个中英文分词组件。作者eaglet 曾经开发过KTDictSeg 中文分词组件,拥有大量用户。作者基于之前分词组件的开发经验,结合最新的开发技术重新编写了盘古分词组件。

    项目首页:

    http://www.codeplex.com/pangusegment

     

    为了更好的为大家服务,盘古分词的问题解答统一转移到HubbleDotNet 中文社区进行回复,请大家在HubbleDotNet 中文社区提问和交流。

    中文社区网址

    http://hubbledotnet.51aspx.com/

  • 老黑子
    2010-01-13 03:47 老黑子
    eaglet 老大,这词性对照表能不能发布一个出来啊?呵呵

    俺用这个东西弄了个文章关键词提取的小程序,感觉好用啊,呵呵,可惜就是现在不知道词性代号的规则,没有办法按词性过滤关键词

    点击查看大图

    就是图中这POS_DN啊,POS_UNK啊什么的,有没有个表可以查是啥意思啊?
    第51楼 回到顶楼
  • eaglet
    2010-01-13 07:31 eaglet
    @老黑子
    代码中有中文注释,你看一下代码就知道了。
    第52楼 回到顶楼
  • freefly2010
    2010-01-13 17:21 freefly2010
    最近在做分词算法,看见你写的分词很强大,所以想问问你一些东西,希望得到你的指教。
    1、字典文件如何才能批量修改,因为我觉得有很多词我不需要,还有字典文件我能打开看吗?因为你提供的字典管理工具修改起来太麻烦。
    2、能快速过滤英文或标点符号吗?我觉得添加到停用文件里面太麻烦,因为要停用的东西太多。

    希望能得到你的指教
    第53楼 回到顶楼
  • eaglet
    2010-01-14 10:50 eaglet
    @freefly2010
    字典应该可以批量导入,批量删除目前不行,你可以把字典文件读出来自己去修改。
    标点符号放到停用词中过滤问题不大,英文的过滤,新版本中将提供根据英文词长过滤,如果设置为0,则过滤所有英文。
    第54楼 回到顶楼
  • 不必
    2010-01-14 16:15 不必
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.IO;
    using Lucene.Net.Analysis;
    using Lucene.Net.Analysis.Tokenattributes;
    using PanGu;

    namespace Lucene.Net.Analysis.PanGu
    {
    public class PanGuTokenizer : Tokenizer
    {
    private static object _LockObj = new object();
    private static bool _Inited = false;
    //分词器实现
    private WordInfo[] _WordList;
    //词元文本属性
    private TermAttribute termAtt;
    //词元位移属性
    private OffsetAttribute offsetAtt;
    private bool _OriginalResult = false;
    string _InputText;

    #region 载入分词器
    /// <summary>
    /// 载入分词器
    /// </summary>
    static private void InitPanGuSegment()
    {
    //Init PanGu Segment.
    if (!_Inited)
    {
    global::PanGu.Segment.Init();
    _Inited = true;
    }
    }

    /// <summary>
    /// 载入分词器
    /// </summary>
    /// <param name="fileName">配置文件</param>
    static public void InitPanGuSegment(string fileName)
    {
    lock (_LockObj)
    {
    //Init PanGu Segment.
    if (!_Inited)
    {
    global::PanGu.Segment.Init(fileName);
    _Inited = true;
    }
    }
    }
    public PanGuTokenizer()
    {
    lock (_LockObj)
    {
    InitPanGuSegment();
    }
    }
    #endregion

    #region Lucene Tokenizer适配器类构造函数
    /// <summary>
    /// Lucene Tokenizer适配器类构造函数
    /// </summary>
    /// <param name="input"></param>
    /// <param name="originalResult"></param>
    public PanGuTokenizer(System.IO.TextReader input, bool originalResult)
    : this(input)
    {

    _OriginalResult = originalResult;
    }
    /// <summary>
    /// Lucene Tokenizer适配器类构造函数
    /// </summary>
    /// <param name="input"></param>
    public PanGuTokenizer(System.IO.TextReader input)
    : base(input)
    {
    termAtt = (TermAttribute)AddAttribute(typeof(TermAttribute));
    offsetAtt = (OffsetAttribute)AddAttribute(typeof(OffsetAttribute));
    }
    public ICollection<WordInfo> SegmentToWordInfos(String str)
    {
    if (string.IsNullOrEmpty(str))
    {
    return new LinkedList<WordInfo>();
    }

    global::PanGu.Segment segment = new Segment();
    return segment.DoSegment(str);
    }
    #endregion

    private void Seg()
    {
    lock (_LockObj)
    {
    InitPanGuSegment();
    }
    _InputText = input.ReadToEnd();

    if (string.IsNullOrEmpty(_InputText))
    {
    char[] readBuf = new char[1024];

    int relCount = input.Read(readBuf, 0, readBuf.Length);

    StringBuilder inputStr = new StringBuilder(readBuf.Length);


    while (relCount > 0)
    {
    inputStr.Append(readBuf, 0, relCount);

    relCount = input.Read(readBuf, 0, readBuf.Length);
    }

    if (inputStr.Length > 0)
    {
    _InputText = inputStr.ToString();
    }
    }

    if (string.IsNullOrEmpty(_InputText))
    {
    _WordList = new WordInfo[0];
    }
    else
    {
    global::PanGu.Segment segment = new Segment();
    ICollection<WordInfo> wordInfos = segment.DoSegment(_InputText);
    _WordList = new WordInfo[wordInfos.Count];
    wordInfos.CopyTo(_WordList, 0);
    }
    }
    /// <summary>
    /// 当前位置 长度 位移
    /// </summary>
    private int index = 0, len = 0, offset = 0;
    public override bool IncrementToken()
    {
    ClearAttributes();
    if (index == 0)
    {
    Seg();
    index = 0;
    len = _WordList.Length;
    }
    if (_OriginalResult)
    {
    string retStr = _InputText;

    _InputText = null;

    if (retStr == null)
    {
    return false;
    }
    termAtt.SetTermBuffer(retStr);// 设置termAttr
    offsetAtt.SetOffset(offset, offset + retStr.Length);// 设置位移
    return false;
    }

    if (index > len - 1)
    {// 超过分词结果时退出
    index = 0;
    len = 0;

    return false;
    }
    WordInfo wordinfo = _WordList[index];
    string word = wordinfo.Word;// 得到该索引的词

    termAtt.SetTermBuffer(word);// 设置termAttr

    int wordLen = word.Length;// 词的长度
    offset = wordinfo.Position;
    offsetAtt.SetOffset(offset, offset + wordLen);// 设置位移

    // System.out.println(word + ":(" + Integer.toString(offset) + "-"
    // + Integer.toString(offset + wordLen) + ")");

    offset += wordLen;

    index++;

    return true;

    }

    #region End和Reset
    public override void End()
    {
    int finalOffset = offset;
    offsetAtt.SetOffset(finalOffset, finalOffset);
    }

    public override void Reset()
    {
    base.Reset();
    offset = index = 0;
    }

    public override void Reset(System.IO.TextReader reader)
    {
    base.Reset(reader);
    Reset();
    }
    #endregion

    }

    }
    这是我改的lucent.net2.9.1.2版.不知道哪错了..就是搜不出来内容.麻烦eaglet看看..
    2.9版的 svn https://svn.apache.org/repos/asf/lucene/lucene.net/
    第55楼 回到顶楼
  • freefly2010
    2010-01-15 09:11 freefly2010
    那盘古分词新版本什么时候出?期待呀!我现在把字典文件全部加载到数据库了,准备自己去整理字典文件。
    第56楼 回到顶楼
  • freefly2010
    2010-01-15 11:37 freefly2010
    还有一个问题,我能控制只要不是词库里面的词,就不让它在分词的时候出现,这个可以做到吗
    第57楼 回到顶楼
  • freefly2010
    2010-01-15 14:01 freefly2010
    result.SyncRoot”引发了“System.NotImplementedException”类型的异常
    第58楼 回到顶楼
  • 老黑子
    2010-01-15 16:48 老黑子
    有几个比较弱智的分词不准的问题,eaglet老大看看要怎么配置?呵呵

    例1:3300MAH,电池的容量规格,自行加入字典并保存了,但是词频即使设置到5000,也还是被切分为3300和mah,类似的情况还有2WD啊,4WD啊这些习惯用语,都是数字和字母被切开了

    例2:9月,被切分为9和月,数字和文字被切开

    要怎么才能让这些词不被切开呢?
    第59楼 回到顶楼
  • eaglet
    2010-01-15 18:32 eaglet
    @ 老黑子
    你用的什么版本? 新版本多元分词时会分出整词和切分两种形式。
    数字和中文在一起的,你需要自己判断了,其实我觉得分成整词也不一定好,很多应用是要求分词的粒度比较小,可以比较灵活的切分查询。
    第60楼 回到顶楼
  • eaglet
    2010-01-15 18:32 eaglet
    @ 老黑子
    你用的什么版本? 新版本多元分词时会分出整词和切分两种形式。
    数字和中文在一起的,你需要自己判断了,其实我觉得分成整词也不一定好,很多应用是要求分词的粒度比较小,可以比较灵活的切分查询。
    第61楼 回到顶楼
  • eaglet
    2010-01-15 18:36 eaglet
    @ freefly2010
    新版本可以不输出未登录词,我最近会发布新版本。你那个异常是程序中没有实现某个代码,你看一下程序吧。
    第62楼 回到顶楼
  • freefly2010
    2010-01-15 21:06 freefly2010
    我如何才能不让数字和英文输出
    第63楼 回到顶楼
  • 老黑子
    2010-01-15 21:22 老黑子
    @eaglet
    我用的是1.1.0.1版本。看来分词还是分开几种应用情况的,呵呵,对于搜索引擎应用,应该是要求粒度比较小,我是用于整文的关键词提取,所以我要求它更侧重字典内匹配。
    第64楼 回到顶楼
  • 老黑子
    2010-01-15 21:24 老黑子
    我还是建议组件可以再优化,应该优先匹配字典,呵呵。因为想了一下,现代很多词语都是中英混杂,数字和汉字混杂,比如90后,80后,不能要求人家搜索九零后吧,呵呵,这种词可很多啊,什么奥迪A8啊,21CN邮箱啊.....
    第65楼 回到顶楼
  • 老黑子
    2010-01-15 21:36 老黑子
    需要先匹配字典的情况还主要出现在技术词汇里面,数字加单位,单位可能是英文可能是中文,拆开了就不是要搜索的东西了。而先在字典里面匹配,字典内无整词才做拆分,这样命中率我觉得会更高
    第66楼 回到顶楼
  • 老黑子
    2010-01-15 22:08 老黑子
    @freefly2010

    最傻瓜的方法应该是用盘古输出后,自行分析词性和单词类型,写几句简单的代码过滤一下,呵呵
    第67楼 回到顶楼
  • freefly2010
    2010-01-16 14:42 freefly2010
    关于不输出未登录词的我已经搞定
    第68楼 回到顶楼
  • lfzpf
    2010-01-19 09:07 lfzpf
    你好eaglet
    我在分词时遇见两个个问题,请教一下
    1.分词时我把一元分词关闭,打开多元分词,并把冗余度设置到2,然后“一元一次方程”的分词结果是“一元(0,3)/一元一次方程(0,5)/一次(2,2)/一次方程(2,3)/方程(4,2)/”,但我输入“一元二次方程”的结果是“一(0,2)/一元(0,5)/元(1,2)/二次方程(2,2)/二次(2,3)/二次方程(2,5)/方程(4,3)/” ,这个分词结果里怎么没有把“一元二次方程”作为一个词输出来?(我已经把一元二次方程添加到词典里去了)
    2.第二个问题是关于hubble.net的,我插入多条关于“一元二次方程”的信息后,搜索时排名怎么感觉有点问题,sql语句是select between 0 to 19 * from ddt_t_question where f_secpoint match '一^16^0 一元^5000^0 元^16^1 二次方程^16^2 二次^125^2 二次方程^5000^2 方程^125^4' order by score desc ,搜索结果是 完全匹配的“一元二次方程”在第一位,但第二位就是“二次根式”,第三位是“二次函数”,第四位是“解一元二次方程”,第五位是“一元二次方程的定义”,怎么会出现这种搜索结果,给分析分析
    第69楼 回到顶楼
  • freefly2010
    2010-01-19 09:26 freefly2010
    期待eaglet更新盘古分词新版本
    第70楼 回到顶楼
  • eaglet
    2010-01-19 10:34 eaglet
    @ lfzpf
    1. 你确定词库中有 一元二次方程 吗?
    我在我机器上试了一下,字典加入 一元二次方程 可以分出来的
    一元(0,3)/一元二次方程(0,5)/二次(2,2)/二次方程(2,3)/方程(4,2)/
    你检查你加载的字典对不对
    2.一方面是分词造成的,另一方面 match 的得分算法是模仿lucene的,那个算法有缺陷,我后面会改进。
    第71楼 回到顶楼
  • lfzpf
    2010-01-19 15:00 lfzpf
    @eaglet
    嗯,确实是没填进去,谢了,第一个问题解决了
    第72楼 回到顶楼
  • jorbin
    2010-01-31 14:13 jorbin
    请教一下。
    用盘古分词并建立索引后。如果向词典里添加新的词,如(可耕地吊顶龙骨),如果要用这个词搜索,是否需要重建索引?谢谢指教!
    第73楼 回到顶楼
  • eaglet
    2010-02-01 06:32 eaglet
    要重建索引
    第74楼 回到顶楼
  • lfzpf
    2010-02-02 08:38 lfzpf
    eaglet 你好
    现在遇到一个问题,在 输入“What is your name?” 搜索时,对问号这块分词出现这种情况“?^500^23 ^10^23”,我用的是 EnglishAnalyzer,
    第75楼 回到顶楼
  • eaglet
    2010-02-19 06:40 eaglet
    @ lfzpf
    最新版本已经改掉了
    第76楼 回到顶楼
  • billou
    2010-02-26 10:26 billou
    我是用VB.NET的,盘古分词的功能我已经了解,但是我还不知道具体应用到VB.NET,该如何调用相应的函数?
    比如具体的调用函数的格式是怎样,如何获取分词出来的结果(包括:词、权重、词频)
    第77楼 回到顶楼
  • 清面刀
    2010-02-26 11:20 清面刀
    你好,我用PanGu4LuceneV1.2.0.0,但输入“流行感冒",搜出来的“流行性感冒"排在包含“感冒"的后面,我现在想把包含“流行"和“感冒"的记录放在只包含“感冒"或只包含“流行"的前面怎么办?
    第78楼 回到顶楼
  • eaglet
    2010-02-26 11:41 eaglet
    @ 清面刀
    先检查 流行性感冒 是怎么分词的
    我在我本机上测了一下,多元分词时,分成
    流行性/流行性感冒/感冒/
    也就是说这个句子在索引时根本没有将流行这个词分出来。这是一个分词粒度选择的问题,要解决这个问题,目前只有将强制一元分词开关打开,重新索引,并且在搜索时也要强制一元分词。
    第79楼 回到顶楼
  • 清面刀
    2010-02-26 11:56 清面刀
    那怎样在配置文件里面改呢
    第80楼 回到顶楼
  • billou
    2010-02-27 11:33 billou
    我下载的盘古分词,运行出现下面的错误:

    未能找到路径“...\Dictionaries\Dict.Dct”的一部分。


    请问是什么问题的?我下载的版本是PanGu_ReleaseV1.2.0.0
    第81楼 回到顶楼
  • eaglet
    2010-02-27 17:17 eaglet
    @清面刀
    看使用文档

    第82楼 回到顶楼
  • eaglet
    2010-02-27 17:18 eaglet
    ◎ billou
    你的...\Dictionaries\ 目录下没有文件Dict.Dct
    第83楼 回到顶楼
  • zbinxp
    2010-02-28 18:14 zbinxp
    你好,我使用PanGu4LuceneV1.2.0.0时发现:输入中包含"NOT" "AND"等词会报黄页。而使用lucene.net的demo中,"NOT"就能正确的排除关键字。我将他们加入到stopwords.txt中后可以解决报错的问题,但是还是不能排除关键字。
    不知道有什么地方可以配置,以实现上述功能。谢谢!
    第84楼 回到顶楼
  • eaglet
    2010-03-01 11:56 eaglet
    @zbinxp
    lucene.net 的 demo 应该是开源的,你跟踪一下代码,看看它是怎么实现的。
    第85楼 回到顶楼
  • David neissar03
    2010-03-03 14:54 David neissar03
    请问:
    同义词的问题解决了没有啊
    第86楼 回到顶楼
  • eaglet
    2010-03-04 07:19 eaglet
    @David neissar03
    同义词的功能还没有加进去
    第87楼 回到顶楼
  • 赵某某
    2010-03-05 10:20 赵某某
    您好,我刚下载了PanGu_ReleaseV1.2.0.0版本,但是不知道如何将它应该到网页当中,老大能否指点一下。
    第88楼 回到顶楼
  • eaglet
    2010-03-05 10:56 eaglet
    盘古下面有一个 PanGu4Lucene 的例子,你可以下下来看看
    第89楼 回到顶楼
  • 赵某某
    2010-03-05 11:00 赵某某
    刚刚看了PanGu4Lucene 的例子,是用于asp.net中的(不懂.net),能否用于asp中呢,谢老大指教!
    第90楼 回到顶楼
  • eaglet
    2010-03-05 12:37 eaglet
    asp 中应该可以调用 .net 组件的,怎么调用可以找一些资料看看,我也不太清楚,没搞过。
    第91楼 回到顶楼
  • 神无领域
    2010-03-09 01:05 神无领域
    PanGuSettings的GetDictionaryPath()方法在某些WebFrom应用中,如果是虚拟主机会出对Bin目录没有权限。
    第92楼 回到顶楼
  • eaglet
    2010-03-09 06:40 eaglet
    @神无领域
    你可以用这个函数来初始化,fileName 是 pangu.xml 文件路径(包括文件名)
    你可以在pangu.xml 中指定你字典的路径。
    public static void Init(string fileName)
    第93楼 回到顶楼
  • woodynet
    2010-03-12 16:43 woodynet
    点击查看大图

    请看图片,用盘古分词 + lucene.net做的,怎么会出现这样的情况呢?
    我搜索“琚老师英语培训学校",它居然排在第四位,为什么不是第一位呢?

    我个人认为搜索它的同名标题的时候,这个document应该是拍在首位的吧。
    下面代码是我创建索引时的代码:
    LuceneWrite writer = new LuceneWrite(INDEX_DIR, true);
    List<Document> documentList = new List<Document>();
    Document document; Field field ;
    foreach (var item in corpList)
    {
    document = new Document();
    //"ID"
    field = new Field("ID", item.ID.ToString(), Field.Store.YES, Field.Index.TOKENIZED);
    document.Add(field);

    // "CorpName"
    field = new Field("CorpName", item.CorpName, Field.Store.YES, Field.Index.TOKENIZED);
    document.Add(field);

    //"CorpIntro"
    field = new Field("CorpIntro", item.CorpIntro, Field.Store.YES, Field.Index.TOKENIZED);
    document.Add(field);

    // "Phone"
    field = new Field("Phone", "{0}:{1},{2}".StringFormat(item.Linkman, item.LinkmanMobilePhone, item.FixPhone), Field.Store.YES, Field.Index.NO);
    document.Add(field);//在这个函数里已经进行优化了

    documentList.Add(document);

    }
    writer.AddDocument(documentList);

    writer.Close();

    第94楼 回到顶楼
  • eaglet
    2010-03-14 11:48 eaglet
    @ woodynet
    因为lucene 是根据统计来计算得分的,没有对单词位置信息等做相关考虑,才造成这个问题。你如果用 hubble 的最新版本,肯定排第一位,因为hubble 针对位置进行了考虑,搜到的准确度要比 lucene 高。
    第95楼 回到顶楼
  • NetSoft
    2010-03-15 16:41 NetSoft
    你好,我在使用盘古分词的时候发生异常,系统报directoryNotFoundException异常,我将网站部署的UNC路径的存储上,如\\192.168.0.22\website\bin,系统为64位window2003,错误提示directoryNotFoundException c:\windows\syswow64\inetsrv\92.168.0.22\website\bin\ 未找到。请问能解决嘛?
    第96楼 回到顶楼
  • eaglet
    2010-03-16 16:17 eaglet
    映射个驱动器吧
    第97楼 回到顶楼
  • NetSoft
    2010-03-16 17:14 NetSoft
    @eaglet
    这个和环境有关,比较难做到,希望老大能指点一二,小弟看了源代码,Setting.PanGuSettings.Config.GetDictionaryPath中的几行不理解。
    string path = DictionaryPath;
    string currentDir = System.IO.Directory.GetCurrentDirectory();
    System.IO.Directory.SetCurrentDirectory(Framework.Path.GetAssemblyPath());
    path = System.IO.Path.GetFullPath(path);
    System.IO.Directory.SetCurrentDirectory(currentDir);

    return Path.AppendDivision(path, '\\');
    设置当前目录的方法执行后,对其他函数中的代码有什么作用嘛?没有的话,我想修改掉这里。
    第98楼 回到顶楼
  • eaglet
    2010-03-17 07:14 eaglet
    没有作用,你可以修改。修改后请把你修改的部分贴上来,我参考参考,谢谢!
    第99楼 回到顶楼
  • NetSoft
    2010-03-17 15:29 NetSoft
    @eaglet
    后来发现是由于另一个方法引起问题。
    PanGu.Framework.Path.GetAssemblyPath()
    修改为
    {
    string codeBase = System.Reflection.Assembly.GetExecutingAssembly().CodeBase;
    codeBase = codeBase.Replace("file:///", "").Replace(@"file://", "\\\\").Replace('/', '\\');
    return System.IO.Path.GetDirectoryName(codeBase) + @"\";
    }
    主要是因为CodeBase属性,对于本地路径返回字符串开头为"file:///c:/",而对于网络路径"\\172....\"返回字符串为"file://172.../"。
    第100楼 回到顶楼
登录后才能评论,请先登录注册