python - ¿Cómo se puede dar una entrada FST(hecha por openFST)? ¿A dónde va la salida?
shell fsm (2)
Antes de comenzar, tenga en cuenta que estoy usando el shell de Linux (mediante el using subprocess.call()
de Python), y estoy usando openFST.
He estado revisando documentos y preguntas sobre openFST, pero parece que no puedo encontrar una respuesta a esta pregunta: ¿cómo se puede dar entrada a un FST compuesto, compilado y compuesto por openFST? ¿A dónde va la salida? ¿Simplemente ejecuto ''fstproject''? Si es así, ¿cómo le daría, digamos, una cadena para transducir e imprimir las diferentes transducciones cuando se hayan alcanzado los estados finales?
Pido disculpas si esta pregunta parece obvia. No estoy muy familiarizado con openFST todavía.
El ejemplo de Paul Dixon es genial. Como el OP usa Python, pensé que agregaría un ejemplo rápido sobre cómo se pueden "ejecutar" los transductores con el envoltorio de Python de Open FST . Es una pena que no pueda crear "autómatas de cadena lineal" con Open FST, pero es fácil de automatizar como se ve a continuación:
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
Definamos un Transductor simple que escribe en mayúsculas la letra "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
Ahora podemos simplemente aplicar el transductor usando:
apply_fst(list("abab"), caps_A)
Para ver cómo usarlo para un aceptador, mira mi otra respuesta.
Una forma es crear su máquina que realiza la transformación. Un ejemplo muy simple sería en mayúsculas una cadena.
M.wfst
0 0 a A
0 0 b B
0 0 c C
0
El archivo de símbolos adjunto contiene una línea para cada uno de los símbolos del alfabeto. La nota 0 está reservada para transiciones nulas (épsilon) y tiene un significado especial en muchas de las operaciones.
M.syms
<epsilon> 0
a 1
b 2
c 3
A 4
B 5
C 6
Luego compilar la maquina
fstcompile --isymbols=M.syms --osymbols=M.syms M.wfst > M.ofst
Para una cadena de entrada "abc" cree un autómata de cadena lineal, esta es una cadena de izquierda a derecha con un arco para cada carácter. Este es un aceptador, por lo que solo necesitamos una columna para los símbolos de entrada.
I.wfst
0 1 a
1 2 b
2 3 c
3
Compilar como aceptador
fstcompile --isymbols=M.syms --acceptor I.wfst > I.ofst
Luego componer las máquinas e imprimirlas.
fstcompose I.ofst M.ofst | fstprint --isymbols=M.syms --osymbols=M.syms
Esto dará la salida.
0 1 a A
1 2 b B
2 3 c C
3
La salida de fstcompose es una celosía de todas las transducciones de la cadena de entrada. (En este caso solo hay una). Si M.ofst es más complicado, se puede usar fstshortestpath para extraer n-cadenas usando las banderas --unique -nshortest = n. Esta salida es de nuevo un transductor, puede desechar la salida de fstprint o usar el código C ++ y la biblioteca OpenFst para ejecutar la primera búsqueda en profundidad para extraer las cadenas.
Al insertar fstproject --project_output se convertirá la salida en un aceptador que contiene solo las etiquetas de salida.
fstcompose I.ofst M.ofst | fstproject --project_output | fstprint --isymbols=M.syms --osymbols=M.syms
Da lo siguiente
0 1 A A
1 2 B B
2 3 C C
3
Este es un aceptador porque las etiquetas de entrada y salida son las mismas, las opciones --acceptor se pueden usar para generar una salida más sucinta.
fstcompose I.ofst M.ofst | fstproject --project_output | fstprint --isymbols=M.syms --acceptor