为啥 OpenFST 似乎没有“运行”或“接受”或“转导”命令?

Posted

技术标签:

【中文标题】为啥 OpenFST 似乎没有“运行”或“接受”或“转导”命令?【英文标题】:Why OpenFST does not seem to have 'run' or 'accept' or 'transduce' command?为什么 OpenFST 似乎没有“运行”或“接受”或“转导”命令? 【发布时间】:2017-07-20 11:15:44 【问题描述】:

我听说过很多关于 OpenFST 的好消息,但我很难让它发挥作用。我正在构建一个 FST 自动机(fstcompile),我想将其用作接受器来检查一组字符串是否匹配(非常类似于正则表达式,但具有 OpenFST 提供的自动机优化所提供的优势)。事情是这样的: 如何检查生成的自动机是否接受字符串? 我发现a suggestion 输入字符串应该变成一个简单的自动机并与接受自动机组合以获得结果。我发现它非常麻烦和奇怪。有没有更简单的方法(通过 cmd 行或 Python/C++)?

【问题讨论】:

创建一个指定线性自动机的python脚本并不难。不知道为什么它没有包含在 OpenFST 本身中 没错!该文档是根据抽象数学编写的,这对新用户来说是相当吓人的。把用户从其他非常好的库中吓跑是很遗憾的! 【参考方案1】:

这里有一个快速示例,说明如何使用Open FST's Python wrapper 测试自动机是否接受字符串。事实上,你必须将你的输入变成一个自动机,而 Open FST 甚至不会为你创建这个“线性链自动机”!幸运的是,自动化这个过程很简单,如下所示:

def linear_fst(elements, automata_op, keep_isymbols=True, **kwargs):
    """Produce a linear automata."""
    compiler = fst.Compiler(isymbols=automata_op.input_symbols().copy(), 
                            acceptor=keep_isymbols,
                            keep_isymbols=keep_isymbols, 
                            **kwargs)

    for i, el in enumerate(elements):
        print >> compiler, "  ".format(i, i+1, el)
    print >> compiler, str(i+1)

    return compiler.compile()

def apply_fst(elements, automata_op, is_project=True, **kwargs):
    """Compose a linear automata generated from `elements` with `automata_op`.

    Args:
        elements (list): ordered list of edge symbols for a linear automata.
        automata_op (Fst): automata that will be applied.
        is_project (bool, optional): whether to keep only the output labels.
        kwargs:
            Additional arguments to the compiler of the linear automata .
    """
    linear_automata = linear_fst(elements, automata_op, **kwargs)
    out = fst.compose(linear_automata, automata_op)
    if is_project:
        out.project(project_output=True)
    return out

def accepted(output_apply):
    """Given the output of `apply_fst` for acceptor, return True is sting was accepted."""
    return output_apply.num_states() != 0

让我们定义一个只接受“ab”系列的简单Acceptor:

f_ST = fst.SymbolTable()
f_ST.add_symbol("<eps>", 0)
f_ST.add_symbol("a", 1)
f_ST.add_symbol("b", 2)
compiler = fst.Compiler(isymbols=f_ST, osymbols=f_ST, keep_isymbols=True, keep_osymbols=True, acceptor=True)

print >> compiler, "0 1 a"
print >> compiler, "1 2 b"
print >> compiler, "2 0 <eps>"
print >> compiler, "2"
fsa_abs = compiler.compile()
fsa_abs

现在我们可以简单地使用:

accepted(apply_fst(list("abab"), fsa_abs))
# True
accepted(apply_fst(list("ba"), fsa_abs))
# False

要了解如何使用传感器,请查看我的other answer

【讨论】:

感谢您提供详细示例。我想知道是否真的需要将f_ST.add_symbol("c", 3) 中的c 添加到传感器词汇表中?在我看来这有点多余。 @sophros 很好,我修改了我的示例,但忘记更新符号表。我现在已经对其进行了编辑。

以上是关于为啥 OpenFST 似乎没有“运行”或“接受”或“转导”命令?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 struc 中的 bool 成员不接受用户输入?

如何将 OpenFST 链接到 tensorflow 自定义操作?

为啥我的 prop 没有记录或在 React Native 中传递?

为啥没有事件侦听器或引用的封闭 NetConnection 会留在内存中?

为啥我会收到错误:无法在 macOS Catalina 下运行 PySide2 程序的“uic”:“execvp:没有这样的文件或目录”?

为啥我必须费心在每个文件的末尾添加换行符?