作者qrtt1 (有些事,有时候。。。)
看板Soft_Job
标题Re: [请益] 英文单字还原的lib (snowball)
时间Sat Sep 1 00:00:22 2018
感觉是个有趣的东西,刚好用过 Lucene 也来玩玩。
顺便工商一下
JCConf 早鸟票发售中....
※ 引述《asleepme (500年没换昵称了)》之铭言:
: 有没有对语言有研究的大大,用过snowball这套演算法?
: 我们在做语言相关的研究,遇到一个很基本也很重要的问题
: 就是时态问题,过去式、原型、单复数...
: 为了简化处理,希望能把动词还原原型、复数还原单数
: 简单的ed、s、ly之类的都还算好处理,没有lib也可以自己算
: 网路上找了一阵,最多人讨论的就是snowball的演算法,也有很多语言的lib
: 但是遇到y结尾的变化,他只是去ed而已
: 例如replied => repli,没有还原成reply
: 但是我们系统资料库通常是纪录 reply,这样就会match不到
: 但是像loving、loved这种又还原的很好成love
: 至於不规则变化,snowball看起来是完全不处理
: 想知道大家用snowball都是怎麽用的?
: 我们的状况是会有很多单字的原型跟相关的资料
: 然後要对进来的资料mapping,给他相关资料
: 不论来的东西是原型、过去式、单复数,都要对的起来
: 或是我们也把自己的资料全部用snowball算一次存起来
: 然後进来的资料也用一样的算法处理,再一路mapping回原本的资料 XD
: 还是乾脆自己建适合自己应用的表?
因为不知道你用什麽 library,假设是比较热门的 Lucene !?
(或可能是 scikit-learn 内的 stemmr),我先用 Java 的 Lucene 来探索一下好了。
先上个简单的程式测了一下:
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.core.LowerCaseFilter;
import org.apache.lucene.analysis.snowball.SnowballFilter;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
public class Lab {
public static void showTerms(String text) throws IOException {
List<String> terms = new ArrayList<>();
try (StandardAnalyzer analyzer = new StandardAnalyzer()) {
TokenStream input = new LowerCaseFilter(
analyzer.tokenStream("field", new StringReader(text)));
// 选用 en 常用的 Porter Stemmer
try (TokenStream tokenizer = new SnowballFilter(input, "Porter")) {
CharTermAttribute term =
tokenizer.addAttribute(CharTermAttribute.class);
tokenizer.reset();
while (tokenizer.incrementToken()) {
terms.add(term.toString());
}
tokenizer.end();
}
}
System.out.println("input: " + text + " => " + terms);
}
public static void main(String[] args) throws IOException {
// 测试一些动词变化
showTerms("replied reply");
showTerms("become became become");
showTerms("be/am/are/is");
showTerms("was/were/was");
showTerms("been");
}
}
======================================================================
输出结果是:
input: replied reply => [repli, repli]
input: become became become => [becom, becam, becom]
这组看起来失败了
input: be/am/are/is => [am]
看起来 standard analzyer 吃掉了什麽
input: was/were/was => [were]
input: been => [been]
因为这东西主要是要建 search index 的 term,
观察起来原始资料主要是给人看的,
在 index 内是建 tokenized 的资料,
使用者输入要查询时,也需要用建 index 一样的 tokenizer setting
才能查到一致的结果。
所以,就算上面的结果不完全是对的(或说一致),
但因为歪的一致那搜出来的结果应该也会歪得一致
若是你想要有原始的字,那其实多加上原来的位置对应就好。
// 增加 OffsetAttribute
CharTermAttribute term = tokenizer.addAttribute(CharTermAttribute.class);
OffsetAttribute offset = tokenizer.addAttribute(OffsetAttribute.class);
tokenizer.reset();
while (tokenizer.incrementToken()) {
terms.add(term.toString());
// 印出原来的字串
System.err.println(term + " => "
+ text.substring(offset.startOffset(), offset.endOffset()));
}
tokenizer.end();
结果的范例:
repli => replied
repli => reply
becom => become
becam => became
becom => become
am => am
were => were
been => been
PS. 有些 be 动词被吃掉应该是 StandardAnalyzer 搞的
另外,在 en 部分的 stemmer 还有不同的实作,可能就要再一一测试了
https://github.com/apache/lucene-solr/tree/master/
lucene/analysis/common/src/java/org/apache/lucene/analysis/en
短:
http://bit.ly/2LIF9Nu
--
各位开发者朋友们安安。
2018 年度的
#JCConf 活动开跑罗。对
#JVM 生态系有兴趣的朋友千万别错过捏。
今年稿件更多了
#kotlin 与
#coroutine 相关主题,还有许多国外讲者参与活动。
另外提醒,
企业票与
早鸟票同时开卖,需要公司报帐的参与者,
请购买
#企业票。我们无法提供非企业票购买者发票呦。
若因为买错票种而需要重新购买的情况,
在退票时其中有 10% 的手续费需付给 #kktix。
https://www.facebook.com/jcconf/posts/1556238624522012
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 59.115.99.70
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/Soft_Job/M.1535731224.A.A85.html
※ 编辑: qrtt1 (59.115.99.70), 09/01/2018 00:03:11
※ 编辑: qrtt1 (59.115.99.70), 09/01/2018 00:05:02
※ 编辑: qrtt1 (59.115.99.70), 09/01/2018 00:10:39
※ 编辑: qrtt1 (59.115.99.70), 09/01/2018 01:12:11
1F:推 alihue: 要不要加一下 syntax highlight,良葛格(误 09/01 17:54
我是不良葛格xd
※ 编辑: qrtt1 (36.231.232.3), 09/01/2018 18:23:00