Comments (9)
CharTable
是一个很好的正规化工具,但是忽略大小写会导致需要输出正规化之后内容含义不正确,只能在这种场景下自定义数据表,但是 CharTable.CONVERT
是静态属性,切换数据表又会让其他需要忽略大小写的场景麻烦起来
from hanlp.
1.用户是不考虑输入的字母是大写还是小写的问题的
这个是不是在建索引的时候就得定义清楚,索引的词项表也同样处理。如 所有英文字母均归范化为”小写“
2.无论输入的是 爱听4g 还是 爱听4G 都能分出来[爱听4g/nz]
词典中若无该新词,后其召回不了[爱听4g/nz]专名
博主速来:)
from hanlp.
"爱听4G" 是 我加入到自定义扩展词库中的. 有这样的场景:在对数据建立索引的时候,我对"爱听4g"这个词进行分词(但是自定义词库中是"爱听4G"),那么分词之后再进行单词小写化的结果就是:[爱/v, 听/v, 4g/nz].Yuchao Z 所说的大小写是后期搜索引擎中token标准化term时候需要考虑的吧? 这样处理也行,不过需要对词库标准化处理,比如词库中的所有的词都必须是小写化,这样我在token标准化之前,直接将输入文本统一小写化也能解决.但是感觉这样比较冗余. 考虑直接在分词的过程中,不考虑输入词与词库中单词的大小写问题,直接输出小写化之后的结果.这样更简单一些.比如IK的分词机制:实现加入关键词"爱听4G"
keyword = "爱听4G";
analyzer = new IKAnalyzer(true);
sb = new StringBuilder();
try {
TokenStream ts = analyzer.tokenStream("", new StringReader(keyword));
ts.reset();
CharTermAttribute cta = ts.addAttribute(CharTermAttribute.class);
while(ts.incrementToken()){
String term = cta.toString();
sb.append(term+" , ");
}
ts.end();
ts.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("分词前:"+keyword);
System.out.println(" ["+sb.toString()+"]");
long time2 = System.currentTimeMillis();
==========================结果===================================
加载扩展词典:ext.dic
分词前:[爱听4G]
分词后:[爱听4g , ]
from hanlp.
这其实不难,最直接的做法无非是,在加载词典和输入文本的时候都进行一个toLowerCase,但是我希望做得优雅高效。有几个问题欢迎大家讨论:
- toLowerCase效率不高。HanLP中的CRFSegment使用了一个CharTable,可以将任意字符规范化,包括繁体->简体,全角->半角,大写->小写等等。我比较倾向于用CharTable做规范化。
- 规范化了之后,分词的结果也被修改得和原文不一样了,比如词典是 爱听4G, “爱听4G”分词结果变成了[爱听4g/nz]。一部分人认为这是合理的,我觉得应该再转回来,变成[爱听4G/nz],不知道大家意见怎么样?
- 如果要支持这个特性,那么就不会提供一个局部的配置接口enableFuzzyCase之类的,因为词典的加载是全局的。所以只能提供一个全局的配置,影响所有分词器。而且切换配置后还必须删缓存重建。
from hanlp.
第一个问题:String类的toLowerCase 实现方法是挺复杂的,效率不是很高,我感觉放入到CharacterHelper或者是CharTable中应该都行.我参考的是lucene-query 中的小写化处理方式,直接对代码点操作,应该是比较高的效率了.供楼主参考:
/**
- 转换每一个unicode代码点为小写.使用{@link Character#toLowerCase(int)}.
- @param buffer the char buffer to lowercase
- @param offset the offset to start at
- @param limit the max char in the buffer to lower case
*/
public final void toLowerCase(final char[] buffer, final int offset, final int limit) {
assert buffer.length >= limit;
assert offset <=0 && offset <= buffer.length;
for (int i = offset; i < limit;) {
i += Character.toChars(
Character.toLowerCase(
codePointAt(buffer, i, limit)), buffer, i);
}
}
第二个问题:能够做一个开关,在用于索引的时候,需要小写化,那么我就不需要还原原词了,这样在索引的时候,就不需要二次处理,直接开启开关即可.
第三个问题:楼主说的全局配置,是不是在加载词典的时候,就将所有的词小写化存储了. 如果我们不在加载词典的时候将词小写化,而是在对文本分词时,将从词库中取出的词再小写化处理.这种方式相对来说用影响分词速度,就是不知道影响的程度有多大?博主可以做个评测.
这是我的观点哈.
from hanlp.
感谢建议。
- CharTable是直接用数组下标转换字符,比调用任何方法都要快。
- 我又想了想,正规化本来就是用于检索系统的,最后又转为大写的话就没意义了。还是不转了。
- 对。影响程度非常大,由于内部采用了DAT,所以不可能动态大小写。
from hanlp.
现在HanLP已经支持了这个特性,在hanlp.properties中加入
#是否执行字符正规化(繁体->简体,全角->半角,大写->小写),切换配置后必须删缓存
Normalization=true
即可。
或者试试com/hankcs/demo/DemoNormalization.java这个例子。
HanLP.Config.Normalization = true;
CustomDictionary.insert("爱听4G", "nz 1000");
Segment segment = new ViterbiSegment();
System.out.println(segment.seg("爱听4g"));
System.out.println(segment.seg("爱听4G"));
System.out.println(segment.seg("爱听4G"));
System.out.println(segment.seg("爱听4G"));
System.out.println(segment.seg("愛聽4G"));
from hanlp.
测试发现对标准分词的支持还不是太好,如下:
代码:
public static void main(String[] args)
{
HanLP.Config.Normalization = true;
CustomDictionary.insert("爱听4G", "nz 1000");
System.out.println("标准分词:"+StandardTokenizer.segment("爱听4G"));
System.out.println("标准分词:"+StandardTokenizer.segment("爱听4g"));
System.out.println("索引分词:"+IndexTokenizer.segment("爱听4G"));
}
======================结果===================================
标准分词:[爱/v, 听/v, 4/m, G/nx]
标准分词:[爱听4g/nz]
索引分词:[爱听4g/nz, 4g/nz]
from hanlp.
昨天修复了这个问题,忘了提交了。现在已经没问题了:74050be
from hanlp.
Related Issues (20)
- 索引与查找使用相同的analyzer,结果无法命中 HOT 4
- 无法下载CTB9_POS_ELECTRA_SMALL_TF HOT 2
- 解析失败,提示升级hanlp HOT 1
- 依存分析的模型要么下载不了,要么刚开始下载非常慢,然后就下不了了(dep的四个模型都是) HOT 1
- No module named 'hanlp.datasets.parsing.ctb'
- 中文名包含多音字时生成的拼音只有一个,例如 ‘李娜’ 生成拼音为 ‘Li Nuo’ HOT 1
- 执行open_small.py时报'utf-8' codec can't decode byte 0xb4 in position 0: invalid start byte HOT 1
- ================================ERROR LOG BEGINS================================ HOT 1
- When I runing the example occurred error HOT 1
- Add a custom dictionary type that supports spaces HOT 3
- Smatch provide wrong and random scores HOT 2
- portable 1.8.4的更新 请尽快推到portable分支 现在分支上还是1.8.3
- 中文分词(粗分)错误:New in version 3.3. HOT 1
- 中文分词错误:左右捕盜廳以『邪學罪人安敦伊、吳伯多祿、閔유아욱가、黃錫斗、張周基,押付公忠水營,梟警』啓。 HOT 5
- NER模型加载问题 HOT 1
- cpu docker部署安装依赖cuda环境 HOT 1
- 悄悄地问:分词模型能否“理解”语意? HOT 3
- phraseTree引发的import error HOT 2
- AttributeError: module 'keras._tf_keras.keras.layers' has no attribute 'AbstractRNNCell' HOT 3
- 本地单任务模型,加载amr时失败 HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from hanlp.