安装
http://www.openfst.org/twiki/bin/view/GRM/ThraxQuickTour
http://cslu.ogi.edu/~sproatr/Courses/TextNorm/tutorial.html
http://www.openfst.org/twiki/pub/GRM/ThraxDownload/thrax-1.2.7.tar.gz
thrax-1.2.5以上要求openfst-1.6.6以上
thrax-1.2.4要求openfst-1.6.0以上
MAKE SURE YOU CONFIGURE OpenFst WITH THE --enable-far, --enable-pdt AND --enable-mpdt FLAGS.
cd openfst
make clean
./configure -enable-far --enable-pdt --enable-mpdt
make -j24
sudo make install
使用--enable-pdt选项make时 pdtreplace.cc:(.text+0x245): undefined reference to `fst::script::FstClass::Read(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)' pdtreplace.cc:(.text+0x3f1): undefined reference to `fst::script::FstClass::Read(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)' pdtreplace.cc:(.text+0x4ac): undefined reference to `fst::script::VectorFstClass::VectorFstClass(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)' ./.libs/libfstpdtscript.so: undefined reference to `fst::FstHeader::Write(std::ostream&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const' ./.libs/libfstpdtscript.so: undefined reference to `fst::ConvertToLegalCSymbol(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*)' ./.libs/libfstpdtscript.so: undefined reference to `fst::AddAuxiliarySymbols(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, long, long, fst::SymbolTable*)' |
需要make clean
cd thrax
./configure --enable-static=no
make -j 8 -Wall -Wno-sign-compare
make错误
./../include/thrax/evaluator.h:257:15: error: request for member 'InputSymbols' in 'far_reader->fst::FarReader<A>::GetFst<fst::ArcTpl<fst::TropicalWeightTpl<float> > >()', which is of pointer type 'const fst::Fst<fst::ArcTpl<fst::TropicalWeightTpl<float> > >*' (maybe you meant to use '->' ?)
*far_reader->GetFst().InputSymbols())) {
^
./../include/thrax/evaluator.h:277:56: error: no matching function for call to 'fst::VectorFst<fst::ArcTpl<fst::TropicalWeightTpl<float> > >::VectorFst(const fst::Fst<fst::ArcTpl<fst::TropicalWeightTpl<float> > >*)'
MutableTransducer tmpfst(far_reader->GetFst());
^
…
Makefile:582: recipe for target 'main/compiler-stdarc.lo' failed
make[3]: *** [main/compiler-stdarc.lo] Error 1
make[3]: Leaving directory '/media/jarvan/ST2000DM001/kaldi.git.new/tools/thrax-1.2.1/src/lib'
Makefile:344: recipe for target 'all-recursive' failed
make[2]: *** [all-recursive] Error 1
make[2]: Leaving directory '/media/jarvan/ST2000DM001/kaldi.git.new/tools/thrax-1.2.1/src'
Makefile:400: recipe for target 'all-recursive' failed
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory '/media/jarvan/ST2000DM001/kaldi.git.new/tools/thrax-1.2.1'
Makefile:323: recipe for target 'all' failed
make: *** [all] Error 2
使用thrax-1.2.4替换thrax-1.2.1:
wget http://www.openfst.org/twiki/pub/GRM/ThraxDownload/thrax-1.2.4.tar.gz
即可解决编译错误
QuickTour
http://www.openfst.org/twiki/bin/view/GRM/ThraxQuickTour
如果安装了GNU readline,则可以在configure时加上(--enable-readline)选项以启用readline功能。
这样,使用thraxrewrite-tester时,支持内联的输入编辑以及保存历史。可以使用--history_file选项指定历史文件(默认为.rewrite-tester-history)。
工具集
thraxmakedep
thrax的语法依赖关系生成工具
该工具以top-level-grammar作为主语法文件(相当于main.c);
根据语法文件的调用关系,以thraxcompiler为编译器,生成makefile;
Usage: src/bin/thraxmakedep [-s/--save_symbols] [-a/--arc_type (default: standard)] top-level-grammar [makefile-target=Makefile]
--save_symbols和--arc_type选项将被传递给thraxcompiler
[-s/--save_symbols]
表示是否保留输入和输出的原始符号;
若保留,则FSTs中使用原始符号作为弧之上的权重;
否则,FSTs使用标识符代替原始符号;
如果设定了--save_symbols,编译时,符号表将得以保留。
符号的选择基于用于编译FSTs的每条字符串的解析模式。
符号表可以是一个byte符号表、utf8符号表 或 用户自定义符号表。
当需要从fst档案文件中提取FSTs并使用fstprint或fstdraw显示时,可以指定此参数。但是可能会出现一些bugs。
[-a/--arc_type (default: standard)]
--arc_type选项支持与OpenFST相同的弧类型:standard (tropical), log 和 log64。
通常,我们需要弧的类型为热带半环,因此一般情况下不需要设定此参数。
注意,thraxrewrite-tester只支持--arc_type standard,否则,将不能进行测试。
thraxcompiler
用于将语法文件编译为FST
PROGRAM FLAGS:
--arc_type: type = string, default = "standard"
编译FSTs的弧类型
--emit_ast_only: type = bool, default = false
解析输入,将语法文件的AST打印到标准输出,不生成FST档案
--input_grammar: type = string, default = ""
输入的语法文件
--output_far: type = string, default = ""
输出的FST档案目标位置
thraxrewrite-tester
thrax改写/重写测试工具
该工具根据规则文件在标准输入上向用户请求一个或多个输入;
然后将用户的输入以某种规则输入到FSTs中;
获取FSTs的输出,并输出到标准输出。
Flags from: rewrite-tester-utils.cc
--far: type = string, default = ""
far, fsts archive, fst档案文件
要测试的fst档案文件,后缀名一般为".far"
--history_file: type = string, default = ".rewrite-tester-history"
历史文件的位置
--input_mode: type = string, default = "byte"
输入的编码,可以是"byte"、"utf8"或是一个符号表。
--noutput: type = int64, default = 1
对于每个输入,最多输出的字符串的个数
--output_mode: type = string, default = "byte"
输出的编码,可以是"byte"、"utf8"或是一个符号表。
--rules: type = string, default = ""
重写规则文件名
规则文件的内容为 以逗号为分隔符的规则列表
这些规则将与标准输入(或随机生成器)一起构成FSTs的输入
这类似于Bash的字符串替换:echo "Hello $you_name, my name is $my_name."
--show_details: type = bool, default = false
当指定了多个规则文件时(比如:--rules=FST1,FST2,FST3)
将显示每个transducer的输出结果,可用于调试。
thraxrandom-generator
thrax随机生成器
该工具根据规则文件随机生成最多noutput个输入;
然后将生成的输入以某种规则输入到FSTs中;
获取FSTs的输出,并输出到标准输出。
注:使用后进先出转换器(pushdown transducer)规则时,该工具将会生成无意义的结果。
PROGRAM FLAGS:
--far: type = string, default = ""
要测试的fst档案文件,后缀名一般为".far"
--input_mode: type = string, default = "byte"
输入的编码,可以是"byte"、"utf8"或是一个符号表。
--noutput: type = int64, default = 1
要生成的最大输出映射(output mappings)数
--output_mode: type = string, default = "byte"
输出的编码,可以是"byte"、"utf8"或是一个符号表。
--rule: type = string, default = ""
重写规则文件名
Thrax使用示例
使用thraxmakedep工具分析主语法文件的依赖关系,生成Makefile;
$ thraxmakedep example.grm
使用Automake中的make对Makefile解决依赖并生成fst档案(.far);
$ make
使用thraxwrite-tester,根据"--rules"指定的规则文件,对fst档案进行输入输出的测试;
$ thraxrewrite-tester --far=example.far --rules=TOKENIZER
Input string: Well, I can't eat muffins in an agitated manner.
Output string: Well , I ca n't eat muffins in an agitated manner .
Input string: Mr. Ernest Worthing, B. 4, The Albany.
Output string: Mr. Ernest Worthing , B. four , The Albany .
Input string: Lieutenant 1840,
Output string: Lieutenant eighteen forty ,
Input string: Uncle Jack!
Output string: Uncle Ernest !
从far中抽取fst
farextract numbers.far
目录中将生成NUMBERS
fstinfo ./NUMBERS
fstprint ./NUMBERS
http://openfst.org/twiki/bin/view/Forum/GrmThraxForum
LoadFst: load fst from a file or extracting from a FAR.
LoadFst['/path/to/fst']
LoadFstFromFar['/path/to/far', 'fst_name']
http://blog.csdn.net/visionfans/article/details/50408846
Thrax语法规则
Imports
导入语句由import声明列表组成,导入声明如下:
import 'path/to/file.grm' as alias;
编译器将先搜索提供的文件并加载其中的所有函数以及所有导出的符号。
从编译目标FST档案(file.far)中加载的符号(FSTs)必须与导入的源文件在同一目录下。
导入后,主文件中就可以使用别名来引用函数和符号。
因此,如果file.grm提供了一个名为foo的函数,那么可以使用语法alias.foo[...]来调用这一函数。
注意,要导入的文件本身也可能导入的其他文件。要访问这些文件和FSTs,可以使用以下别名语法:
alias.utils.common.kUpperCaseLetters.
import语法示例:
import 'path/to/file.grm' as alias;
这相当于C语言中的'#include "path/to/file.grm"'和'typedef file.grm alias',grm是源文件。但是,在"file.h"同一目录下需要提供file.far,一个Fst ARchive文件,该文件是编译好的FST文件,相当于C语言中的lib库。当import该源文件后,调用file.grm中定义的函数。比如:alias.foo[…]。当file.grm中也调用了其他源文件,比如"import utils.common.kUpperCaseLetters",要在当前源文件中加入"alias.utils.common.kUpperCaseLetters."即可调用。
Functions
使用func关键字来定义函数,紧接一个函数描述符(函数名)以及一个由方括号包裹的、由逗号分隔的参列表,紧接是有花括号包裹的函数体。函数中,可以使用return语句返回一个对象(通常是一个FST)。
示例:
func UnionWithTriple[fst] { fst3 = fst fst fst; result = fst | fst3; return result; } |
要调用此函数,可以使用函数名与参数列表以调用:
export a_or_a3 = UnionWithTriple["a"];
注意,函数不会引用局部环境的变量,以下语句是不合法的:
abc = "abc";
func AddAbc[fst] { return fst abc; } |
可以引用在其他模块中定义的变量。这一,如果模块"foo"定义了"abc",则可以:
func AddAbc[fst] { return fst foo.abc; } |
示例:
func UnionWithTriple[fst] {
fst3 = fst fst fst;
result = fst | fst3;
return result;
}
函数用func关键字定义,后接函数名,参数表用方括号包裹,主函数体用花括号包裹,每一个指令以分号结尾。
调用该函数:
export a_or_a3 = UnionWithTriple["a"];
Grm源文件中主体部分(主函数)中生成FST的语句
主体中其他元素都是用于生成FSTs的语句,这些输出的FSTs将被导入到FST档案中作为输出。每一个语句由一个以分号结尾的赋值操作构成:
foo = "abc"; export bar = foo | "xyz"; |
声明语句可以用export关键词来修饰;该语法会把变量的内容写入到最终输出档案中。无export关键词修饰的变量声明将不会被输出。
标注库函数、运算和常量
StringFile:从文件中加载字符串列表或者字符串二元组的列表,将其编译成一个表示这些字符串的并集的FST。相当于 ("string1 | string2 | string3 | ...")
如果该文件每一行只有一个字符串,则编译的FST是accpetor;如果每一行为由制表符隔开的字符串二元组,则编译的FST是transducer。解析模式由StringFile函数的第二个参数指定:
StringFile['strings_file', 'byte', my_symbols]
example.grm
# CDRewrite:给定一个转换器和两个上下文接受器(以及字母机),该指令将返回一个新的FST,用于在给定的上下文中执行字符串替换(rewrite,重写)。
第二个(左上下文)和第三个(右上下文)参数是未加权的接受器
第四个参数(sigma_star)是用于执行"最小化"的机器。
第五个参数指定重写的方向。我们可以"left-to-right,ltr"或"right-to-left,rtl"或"simultaneously,sim"重写。
第六个参数选择重写是否可选。它可以是强制性的(obligatory,obl)也可以是可选的(optional,opt)。
指定的符号[BOS]和[EOS]可以用来分别指定表示左右上下文的正则表达式中字符串的开始和结束。
请注意,[BOS]和[EOS]只能在CDRewrite函数中使用,而且,一般只想在左上下文中使用[BOS],同样,只在正确的上下文中使用[EOS]。
# 语法
CDRewrite [tau,lambda,rho,sigma_star,'ltr'|'rtl'|'sim','obl'|'opt']
# 强制性规则在字符串末尾的"d"前改"s"为"z"
CDRewrite ["s":"z","","d [EOS]"]
# 这一规则介绍字符串分隔符标签"[EOS]"的使用。由于英文缩写和小数中都有英文句号,而我们只想对每段话末尾的英文句号(后面可能有一个空格,紧接着其他的标点符号)进行分割。那么以下的规则的作用是:当某个英文句号后面是以一串空格或标点结尾时,我们在这个英文句号处插入一个空格。对于左上下文(left context),可以将字符串的起始表示为"[BOS]",即"Beginning Of the String"。
separate_final_period = CDRewrite["" : " ",
"",
"."
(bytelib.kPunct | bytelib.kSpace)* "[EOS]",
sigma_star]
# 下面的规则对两个transducer进行组合,然后对组合的结果进行优化。优化过程是在transducer上执行的,包含:去除空"epsilon"弧、对弧的权重加和、确定化(determinizing)和最小化(minimizing)。生成的transducers将变
得更小巧且有效。特别是当语法较大时,对一些中间部分的transducer进行优化通常是一个不错的做法,这样可以明显地提高编译的速度。
first_phase = Optimize[separate_punct @ separate_final_period];
我们将"word"定义为"anyword"或者是一个数字(如上所述),由number.grm中的数字语法或(愚蠢的)ernest规则处理。 下面这条规则说明了如何使用权重。 如果该规则与输入相匹配,那就要把"123"映射为"one hundred twenty three",而不是"123"。 我们可以通过使用权重来实现,不赞成使用"anyword"分析。 对于任何非空格字符串序列,分析器将允许这两个分析,但"anyword"分析将永远不受欢迎。 所以当TOKENIZER规则(如下)由一个字符串组成时,最好的(最短路径)分析将是带有数字分析的分析(如果有的话)。 权重根据热带(+,min)半球来解释(参见http://www.openfst.org下的"FST权重"),所以如下<1.0>的权重将不合意的"anyword",其具有隐含的 权重为0,也可以使用负权重,所以可以这样写:
FST字符串输入
以双引号包裹的字符串可用于定义基本的字符串FSTs。
这些字符串可以通过以下几种方式之一来解析:
- "abc".utf8
- "abc".byte
- arctic_symbol_table = SymbolTable['/path/to/bears.symtab'];
"abc".arctic_symbol_table;
双引号字符串中,允许以反斜线修饰的特殊字符:
, newline
, line feed
, tab
关键词和符号
保留关键字和符号列表如下:
= 用于将右侧的对象赋值给左侧的对象;
exprt 用于指定要输出到FST档案中的FST符号(规则);
() 用于修饰需要进行预计算的表达式,优先级较高;
; 表示一个语句的结尾
# 注释
. 用于指定字符串FST的解析模式(默认为byte)
<> 用于指定FST的权重。放置在FST之后,将不带方括号的权重防止在该方括号中;
foo = "aaa" <1>;
goo = "aaa" : "bbb" <-1>;
import 用于导入其他grm文件中的函数和导出的FSTs
as 用于设定其他grm文件的别名
func 声明和定义函数;
[,,] 指定函数参数
return 将对象返回给调用者,文件主体中不可用。
标准库函数、运算以及常数
以下是带有特殊语法的内建函数,用于对FSTs进行运算。函数以优先度降序排列。
除非特别说明,所有的运算符都是左结合的,所有函数都将参数展开为VectorFst。
Closure
重复参数FST任意多次:
fst* 接收fst 0到多次
fst+ 接收fst 1到多次
fst? 接收fst 0或1次
fst{x,y} 接收fst最少x次,最多y次
Concatenation
将第二个FST拼接到第一个FST的末尾。该运算符是右结合的。
该函数还有一个不展开参数的延迟版。
foo bar
Concat[foo, bar]
ConcatDelayed[foo, bar]
Composition
将左侧的FST输出作为右侧FST的输入,两个FST合二为一。
使用显式的函数名则能指定排序方式。
foo @ bar
对右侧的FST的输入弧进行排序,相当于Compose[foo, bar, 'right']
Compose[foo, bar]
不进行弧的排序
Compose[foo, bar, 'left'|'right'|'both']
left:对左侧FST的输出排序
right:对右侧FST的输入排序
both:同时对左侧FST的输出和右侧FST的输入排序
Union
接收两者任意之一的FST。延迟版不展开参数
foo | bar
Union[foo, bar]
UnionDelayed[foo, bar]
Rewrite
将与第一个FST相匹配的字符串重写到第二个FST中(又称:向量积)
foo : bar
Rewrite[foo, bar]
Weight
在指定FST中附加权重
fst <weight>
ArcSort
对一个FST的所有状态的所有弧根据弧的输入或输出进行排序
ArcSort[fst, 'input'|'output']
Connect
使得FST变得全连接图,移除不可达的状态和路径
CDRewrite
给定一个转换器、2个上下文接收器(以及字母表机),会生成一个在给定上下文中任意位置进行重写的新FST。
第二个(左上文)、第三个(右下文)和第四个(sigma star)函数是不带权接收器
第五个参数选择重写的方向。我们既可以左到右重写(ltr)也可以右到左重写(rtl),或者同时重写。
CDRewrite[tau, lambda, rho, sigma_star, 'ltr'|'rtl'|'sim', 'obl'|'opt']
## ltr obligatory rule changing "s" into "z" before a "d" at the end of a string
CDRewrite["s" : "z", "", "d[EOS]", sigma_star]
Determinize
使得一个FST变得确定化
Determinize[fst]
RmEpsilon
将给定FST中的所有epsilon(label 0)移除
RmEpsilon[fst]
Expand
显式地将提供的FST展开为VectorFst
Expand[fst]
Invert
将给定的FST倒置
Invert[fst]
Minimize
FST最小化
Minimize[fst]
Optimize
FST优化
Optimize[fst]
Project
将FST投影到输入维数或输出维数
Project[fst, 'input'|'output']
Reverse
反转FST
Reverse[fst]
RmWeight
移除FST的所有权重
RmWeight[myfst]
LoadFst
从文件中或FAR中加载FSTs
LoadFst['path/to/fst']
LoadFstFromFar['path/to/far', 'fst_name']
StringFile
加载由字符串列表或字符串二元组组成的文件,并将其编译(以byte模式)编译为表示这些字符串的联合的FST。这相当于"string1 | string2 | string3 | ...",但这样更高效。
StringFile['strings_file']
rws@catarina:~/tmp$ cat foo.sym <eps> 0 얼룩말 1 개 2 딩고 3 코끼리 4 rws@catarina:~/tmp$ cat foo.grm foo_syms = SymbolTable['foo.sym']; export foo = StringFile['foo.txt', 'byte', foo_syms]; rws@catarina:~/tmp$ cat foo.txt dingo 딩고 dog 개 zebra 얼룩말 elephant 코끼리 |
高级功能
先进后出转换器(Pushdown Transducer,PDT)
多栈先进后出转换器(Multi-Pushdown Transducer,MPDT)
功能与范式
功能
范式
替换转换器
小贴士
来自 <http://www.opengrm.org/twiki/bin/view/GRM/ThraxQuickTour>