#sentence #tokenizer #token #tokenize

nightly punkt

Punkt 句子分词器的实现

8 个版本 (5 个稳定版)

使用旧的 Rust 2015

1.0.5 2019年2月26日
1.0.4 2018年2月4日
1.0.3 2016年10月5日
1.0.2 2016年2月3日
0.0.3 2015年1月24日

#481 in 算法

42 次每月下载
3 crates 中使用

MIT/Apache

6.5MB
2K SLoC

punkt

Build Status Crates.io Docs.rs

概述

实现了 Tibor Kiss 和 Jan Strunk 的 Punkt 算法进行句子分词。结果已与使用 NLTK 分词的小型和大型文本进行了比较。

训练

可以为 SentenceTokenizer 提供 training data 以获得更好的结果。可以通过使用 Trainer 进行训练或使用 NLTK 中已编译的数据(例如:TrainingData::english())手动获取数据。

典型用法

Punkt 算法允许您从文档本身推导出所有执行句子分词所需的数据。

#
let trainer: Trainer<Standard> = Trainer::new();
let mut data = TrainingData::new();

trainer.train(doc, &mut data);

for s in SentenceTokenizer::<Standard>::new(doc, &data) {
  println!("{:?}", s);
}

rust-punkt 还提供了一些预训练数据,可以加载某些语言的预训练数据。

#
#
let data = TrainingData::english();

rust-punkt 还允许增量收集训练数据。

#
let trainer: Trainer<Standard> = Trainer::new();
let mut data = TrainingData::new();

for d in docs.iter() {
  trainer.train(d, &mut data);

  for s in SentenceTokenizer::<Standard>::new(d, &data) {
    println!("{:?}", s);
  }
}

自定义

rust-punkt 提供了多个 trait 以自定义训练器、句子分词器和内部分词器的工作方式。默认设置几乎与 Python 库中提供的设置相同,可在 punkt::params::Standard 中找到。

仅修改训练器的工作方式

#
struct MyParams;

impl DefinesInternalPunctuation for MyParams {}
impl DefinesNonPrefixCharacters for MyParams {}
impl DefinesNonWordCharacters for MyParams {}
impl DefinesPunctuation for MyParams {}
impl DefinesSentenceEndings for MyParams {}

impl TrainerParameters for MyParams {
  const ABBREV_LOWER_BOUND: f64 = 0.3;
  const ABBREV_UPPER_BOUND: f64 = 8f64;
  const IGNORE_ABBREV_PENALTY: bool = false;
  const COLLOCATION_LOWER_BOUND: f64 = 7.88;
  const SENTENCE_STARTER_LOWER_BOUND: f64 = 35f64;
  const INCLUDE_ALL_COLLOCATIONS: bool = false;
  const INCLUDE_ABBREV_COLLOCATIONS: bool = true;
  const COLLOCATION_FREQUENCY_LOWER_BOUND: f64 = 0.8f64;
}

完全修改所有工作的方式

#
struct MyParams;

impl DefinesSentenceEndings for MyParams {
  // const SENTENCE_ENDINGS: &'static Set<char> = &phf_set![...];
}

impl DefinesInternalPunctuation for MyParams {
  // const INTERNAL_PUNCTUATION: &'static Set<char> = &phf_set![...];
}

impl DefinesNonWordCharacters for MyParams {
  // const NONWORD_CHARS: &'static Set<char> = &phf_set![...];
}

impl DefinesPunctuation for MyParams {
  // const PUNCTUATION: &'static Set<char> = &phf_set![...];
}

impl DefinesNonPrefixCharacters for MyParams {
  // const NONPREFIX_CHARS: &'static Set<char> = &phf_set![...];
}

impl TrainerParameters for MyParams {
  // const ABBREV_LOWER_BOUND: f64 = ...;
  // const ABBREV_UPPER_BOUND: f64 = ...;
  // const IGNORE_ABBREV_PENALTY: bool = ...;
  // const COLLOCATION_LOWER_BOUND: f64 = ...;
  // const SENTENCE_STARTER_LOWER_BOUND: f64 = ...;
  // const INCLUDE_ALL_COLLOCATIONS: bool = ...;
  // const INCLUDE_ABBREV_COLLOCATIONS: bool = true;
  // const COLLOCATION_FREQUENCY_LOWER_BOUND: f64 = ...;
}

基准测试

我的机器规格

  • i5-4460 @ 3.20 x 4
  • 8 GB RAM
  • Fedora 20
  • SSD
test tokenizer::bench_sentence_tokenizer_train_on_document_long   ... bench: 129,877,668 ns/iter (+/- 6,935,294)
test tokenizer::bench_sentence_tokenizer_train_on_document_medium ... bench:     901,867 ns/iter (+/- 12,984)
test tokenizer::bench_sentence_tokenizer_train_on_document_short  ... bench:     702,976 ns/iter (+/- 13,554)
test tokenizer::word_tokenizer_bench_long                         ... bench:  14,897,528 ns/iter (+/- 689,138)
test tokenizer::word_tokenizer_bench_medium                       ... bench:     339,535 ns/iter (+/- 21,692)
test tokenizer::word_tokenizer_bench_short                        ... bench:     281,293 ns/iter (+/- 3,256)
test tokenizer::word_tokenizer_bench_very_long                    ... bench:  54,256,241 ns/iter (+/- 1,210,575)
test trainer::bench_trainer_long                                  ... bench:  27,674,731 ns/iter (+/- 550,338)
test trainer::bench_trainer_medium                                ... bench:     681,222 ns/iter (+/- 31,713)
test trainer::bench_trainer_short                                 ... bench:     527,203 ns/iter (+/- 11,354)
test trainer::bench_trainer_very_long                             ... bench:  98,221,585 ns/iter (+/- 5,297,733)

句子分词和基于文档的训练的 Python 结果(前 3 个测试与上面相同)

以下脚本用于基准测试 NLTK。

  • f0 是正在分词的文件内容。
  • sPunktSentenceTokenizer 的一个实例。
  • timed 是运行 tests 次测试所需的总时间。

False 正在被传递给 tokenize 以防止 NLTK 对句子边界进行对齐。此功能目前尚未实现。

timed = timeit.timeit('s.train(f0); [s for s in s.tokenize(f0, False)]', 'from bench import s, f0', number=tests)
print(timed)
print(timed / tests)
long    - 1.3414202709775418 s   = 1.34142 x 10^9 ns ~ 10.3283365927x improvement 
medium  - 0.007250561956316233 s = 7.25056 x 10^6 ns ~ 8.03950245027x improvement
short   - 0.005532620595768094 s = 5.53262 x 10^6 ns ~ 7.870283759x   improvement

许可证

根据以下任一许可证授权:

您可选择其中之一。

贡献

除非您明确声明,否则您根据 Apache-2.0 许可证定义的任何有意提交以包含在作品中的贡献,将根据上述方式双许可,无需任何额外条款或条件。

依赖项