【问题标题】:How do you even give an (openFST-made) FST input? Where does the output go?您甚至如何提供(openFST 制作的)FST 输入?输出到哪里去?
【发布时间】:2012-03-12 12:42:21
【问题描述】:

在开始之前,请注意我使用的是 linux shell(来自 Python 的 using subprocess.call()),并且我使用的是 openFST。

我一直在筛选有关 openFST 的文档和问题,但我似乎无法找到这个问题的答案:实际上如何为 openFST 定义、编译和组合的 FST 提供输入?输出到哪里去?我只是执行'fstproject'吗?如果是这样,我将如何给它一个字符串来转换,并在达到最终状态时打印各种转换?

如果这个问题看起来很明显,我深表歉意。我对openFST还不是很熟悉。

【问题讨论】:

    标签: python shell fsm openfst


    【解决方案1】:

    一种方法是创建执行转换的机器。 一个非常简单的例子是将字符串大写。

    M.wfst

    0 0 a A
    0 0 b B
    0 0 c C
    0
    

    随附的符号文件包含字母表中每个符号的一行。注意 0 保留用于 null (epsilon) 转换,在许多操作中具有特殊含义。

    M.syms

    <epsilon> 0
    a 1
    b 2
    c 3
    A 4
    B 5
    C 6
    

    然后编译机器

    fstcompile --isymbols=M.syms --osymbols=M.syms M.wfst > M.ofst
    

    对于输入字符串“abc”,创建一个线性链自动机,这是一个从左到右的链,每个字符都有一条弧线。这是一个接受器,所以我们只需要一个列 输入符号。

    I.wfst

    0 1 a
    1 2 b
    2 3 c
    3  
    

    作为接受者编译

    fstcompile --isymbols=M.syms --acceptor I.wfst > I.ofst
    

    然后组装机器并打印

    fstcompose I.ofst M.ofst | fstprint --isymbols=M.syms --osymbols=M.syms 
    

    这将给出输出

    0   1   a   A
    1   2   b   B
    2   3   c   C
    3
    

    fstcompose 的输出是输入字符串的所有转换的格。 (在这种情况下只有一个)。如果 M.ofst 更复杂,则 fstshortestpath 可用于使用标志 --unique -nshortest=n 提取 n 字符串。这个输出又是一个转换器,你可以废弃 fstprint 的输出,或者使用 C++ 代码和 OpenFst 库运行深度优先搜索来提取字符串。

    插入 fstproject --project_output 会将输出转换为仅包含输出标签的接受器。

    fstcompose I.ofst M.ofst | fstproject --project_output |  fstprint --isymbols=M.syms --osymbols=M.syms 
    

    提供以下内容

    0  1  A  A
    1  2  B  B
    2  3  C  C
    3
    

    这是一个接受器,因为输入和输出标签是相同的,--acceptor 选项可以用来生成更简洁的输出。

     fstcompose I.ofst M.ofst | fstproject --project_output |  fstprint --isymbols=M.syms --acceptor
    

    【讨论】:

    • 这是一个很好的答案,示例非常有用!谢谢!
    • 我觉得 openfst 没有提供创建“线性链自动机”的方法有点难以置信。
    【解决方案2】:

    Paul Dixon 的例子很棒。由于 OP 使用 Python,我想我会添加一个快速示例,说明如何使用 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
    

    让我们定义一个大写字母“a”的简单转换器:

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

    现在我们可以使用以下方法简单地应用传感器:

    apply_fst(list("abab"), caps_A)
    

    输出:

    要了解如何将它用于接受器,请查看我的other answer

    【讨论】:

      【解决方案3】:

      更新 Yann Dubois 对 python3 的回答:

      import pywrapfst as fst
      
      print("")
      f_ST: fst.SymbolTable
      
      
      def linear_fst(elements, automata_op, keep_isymbols=True, **kwargs):
          """Produce a linear automata."""
          compiler = fst.Compiler(
              isymbols=f_ST,  # There should be some way to get this from automata_op
              acceptor=keep_isymbols,
              keep_isymbols=keep_isymbols,
              **kwargs
          )
          for i, el in enumerate(elements):
              print("{} {} {}".format(i, i + 1, el), end="", file=compiler)
          print(str(i + 1), end="", file=compiler)
          lf = compiler.compile()
          return lf
      
      
      def apply_fst(elements, automata_op, print_la=True, is_project=False, **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.
              print_la (bool, optional): print linear automata as text representation
              is_project (str, optional): whether to keep only the "input" or "output" labels.
              kwargs: Additional arguments to the compiler of the linear automata .
          """
          linear_automata = linear_fst(elements, automata_op, **kwargs)
          if print_la:
              print("Linear Automata:\n", linear_automata)
          out = fst.compose(linear_automata, automata_op)
          if is_project:
              out.project("output")
          return out
      
      
      f_ST = fst.SymbolTable()
      f_ST.add_symbol("<eps>", 0)
      f_ST.add_symbol("A", 1)
      f_ST.add_symbol("a", 2)
      f_ST.add_symbol("b", 3)
      compiler = fst.Compiler(
          isymbols=f_ST, osymbols=f_ST, keep_isymbols=True, keep_osymbols=True
      )
      
      print("0 0 a A", end="", file=compiler)
      print("0 0 b b", end="", file=compiler)
      print("0", end="", file=compiler)
      caps_A = compiler.compile()
      print("Uppercase Transducer with", caps_A.num_states(), "states:\n", caps_A)
      
      caps_I = apply_fst(list("abab"), caps_A)
      print("Output:\n", caps_I)
      

      打印出来:

      Uppercase Transducer with 1 states:
       0  0   a   A
      0   0   b   b
      0
      
      Linear Automata:
       0  1   a   2
      1   2   b   3
      2   3   a   2
      3   4   b   3
      4
      
      Output:
       0  1   a   A
      1   2   b   b
      2   3   a   A
      3   4   b   b
      4
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-29
        相关资源
        最近更新 更多