Как вы вообще даете (openFST-made) вход FST? Куда идет вывод? - PullRequest
18 голосов
/ 22 февраля 2012

Прежде чем начать, обратите внимание, что я использую оболочку linux (через using subprocess.call() из Python) и использую openFST.

Я просматривал документы и вопросы об openFST, но, похоже, я не могу найти ответ на этот вопрос: как на самом деле дать входные данные для FST, определенного openFST, определенного и скомпилированного и составленного? Куда идет вывод? Я просто выполняю 'fstproject'? Если да, то как, скажем, дать ему строку для преобразования и напечатать различные преобразования, когда будут достигнуты конечные состояния?

Я прошу прощения, если этот вопрос кажется очевидным. Я еще не очень знаком с openFST.

Ответы [ 2 ]

22 голосов
/ 10 марта 2012

Один из способов - создать машину, которая выполняет преобразование. Очень простым примером будет верхний регистр строки.

M.wfst

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

Файл сопровождающих символов содержит строку для каждого символа алфавита. Примечание 0 зарезервировано для нулевых (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 может использоваться для извлечения n-строк с использованием флагов --unique -nshortest = 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
1 голос
/ 07 января 2019

Пример с Полом Диксоном великолепен.Поскольку OP использует Python, я подумал, что я бы добавил небольшой пример того, как вы можете «запускать» преобразователи с Открытой оболочкой Python FST .Обидно, что вы не можете создать «линейные автоматы с цепями» с помощью 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

enter image description here

Теперь мы можем просто применить преобразователь, используя:

apply_fst(list("abab"), caps_A)

Выход: enter image description here

Чтобы увидеть, как использовать его для акцептора, посмотрите на мой другой ответ

...