Versuch 3: Lösungen
Aufgabe 3.1 a):
Frage: Kann die Wortakkuratheit negativ werden? Kann sie einen Wert über 100% annehmen? Wenn ja, geben Sie je einen Beispielfall an.
Antwort: Klar kann sie negativ werden, wenn mehr Fehler gemacht werden als Worte zu erkennen sind (d.h. daß mindestens ein Einfügefehler gemacht wird). Z.B. zu erkennen: Hello World, erkannt one two three, das sind drei Fehler, bei zwei zu erkennenden Wötern, also eine Fehlerrate von 150% und somit eine Wortakkuratheit von 100% - 150% = -50%.
Die Wortakkuratheit kann nie mehr als 100% sein, besser als alles richtig erkennen, kann man es nicht machen.
Aufgabe 3.1 b):
Frage: Kann bei einem Satz/Hypothese-Paar, die minimale Wortfehlerrate auf verschiedene Arten (verschiedene Zusammensetzung der Fehlerarten) entstehen?
Antwort: Ja, das kann schon sein. Wenn jeder Fehler gleich viel zählt, dann kann z.B. immer wenn die Fehlerfolge "Vertauschung, Einfügung" auch "Einfügung, Vertauschung" gewält werden.
Auch andere Varianten sind machbar, die Anteile der einzelnen Fehlerrarten an der minimalen Wortfehlerrate bleibt aber gleich.
Aufgabe 3.1 c):
Schreiben Sie ein Tcl-Script align.tcl, das als Eingabe zwei Listen (erste Liste ist die zu erkennende Wortfolge, zweite Liste ist die erkannte Wortfolge) erhält und als Ausgabe die Wortfehlerrate angibt.
Antwort: Schöne Lösung einer Gruppe aus einem der vorherigen Jahrgänge:
#=======================================================================# JANUS-SR Janus Speech Recognition Toolkit
# ----------------------------------------------------------
# Author : Matthias und Roald: Gruppe 3
# Module : align.tcl
# Date : 30.10.97
#
# Remarks : Script for exercise 3.1c.
# Computes word error rate of a hypothesis against a
# reference utterance, using DTW (Viterbi) algorithm.
#
#======================================================================
# The return value is a list of the following form:
# {errorRate numErrors alignList errorList}
# errorList contains for every word of the hypothesis the error(s)
# detected between this word and its predecessor:
# d# : # deletions
# i : insertion
# s : substitution
# - : no error
# Note that d# may be combined with s,-: d#s => # deletions, followed by a
# subst. d#- => # deletions, followed by correct word.
# Note that there may be more than one possible best alignments, but
# only
# one of these is returned.
# Note that the reference as well as the hypothesis must contain at least
# one word!
proc wordErrorRate {reference hypothesis} {
;# note that START and END also belong to reference and hypothesis
set reference [linsert $reference 0 "..START.."]
lappend reference "..END.."
set reflen [llength \$reference]
set index 0
;# indexing reference words
foreach elem $reference {
set refarray([expr \$reflen - 1 - \$index]) \$elem
incr index
}
;# Initialize actual vector (diagram column)
set hypword [lindex \$hypothesis 0]
set colnum [llength \$hypothesis]
for {set index 0} {\$index < (\$reflen - 1)} {incr index} {
set value [expr \$reflen - 2 - \$index]
set actvec(\$index) \$value
if {\$value > 0} {
set eType "d\$value"
} else {set eType ""}
set refword $refarray(\$index)
if {[string compare \$refword \$hypword]} {
incr actvec(\$index)
append eType s
} else {append eType -}
set backtrack(\$colnum,\$index) [expr \$reflen - 1]
set errorType(\$colnum,\$index) \$eType
}
set index [expr \$reflen - 1]
set actvec(\$index) 1
set backtrack(\$colnum,\$index) \$index
set errorType(\$colnum,\$index) i
incr colnum -1
;# main loop: steps through hypothesis list
foreach hypword [lreplace \$hypothesis 0 0] {
for {set index 0} {\$index < \$reflen} {incr index} {
set minvalue [expr \$actvec(\$index) + 1]
set minindex \$index
set mineType i
if {[string compare \$refarray(\$index) \$hypword]} {
set offset 1
} else {
set offset 0
}
for {set j [expr \$index + 1]} {\$j < $reflen} {incr j} {
set delet [expr \$j - \$index - 1]
set value [expr \$actvec(\$j) + \$offset + \$delet]
if {\$value < \$minvalue} {
set minvalue \$value
set minindex \$j
if {\$delet > 0} {set mineType d\$delet} else {
set mineType ""
}
if {\$offset == 1} {append mineType s} else {
append mineType -
}
}
}
set actvec(\$index) \$minvalue
set backtrack(\$colnum,\$index) \$minindex ;# backtrack. link
set errorType(\$colnum,\$index) \$mineType
}
incr colnum -1
}
;# last step
set minvalue [expr \$actvec(0) + 1]
set minindex 0
for {set j 1} {\$j < \$reflen} {incr j} {
set value [expr \$actvec(\$j) + \$j - 1]
set delet [expr \$j - 1]
if {\$value < \$minvalue} {
set minvalue \$value
set minindex \$j
if {\$delet > 0} {set mineType d\$delet} else {
set mineType ""
}
}
}
;# backtracking
set alignlist {}
if {[string length \$mineType] > 0} {
set errorlist [list \$mineType]
} else {set errorlist {}}
for {set colnum 1} {\$colnum <= [llength \$hypothesis]} {incr colnum} {
set alignlist [linsert \$alignlist 0 \$refarray(\$minindex)]
set mineType \$errorType(\$colnum,\$minindex)
set errorlist [linsert \$errorlist 0 \$mineType]
set minindex \$backtrack(\$colnum,\$minindex)
}
return [list [expr 1.00*\$minvalue/(\$reflen-2)] \$minvalue \$alignlist \$errorlist]
}
# Test
set reference {Guten Morgen es ist viertel vor sechs}
set hypothesis {Puten Morgen ist vierte vor sie sechs}
puts "Reference: \$reference\nHypothesis: \$hypothesis"
set res [wordErrorRate \$reference \$hypothesis]
puts "Word error rate = [lindex \$res 0] ([lindex \$res 1] errors)."
puts "Reached with alignment: [lindex \$res 2]"
puts "Corr. error sequence: [lindex \$res 3]"
Aufgabe 3.2:
Erzeugen Sie eine Janus Datenbasis, die für jeden Satz einen Eintrag enthält ...
Antwort: (wieder von einer Gruppe aus den Vorjahren)
#=======================================================================
# JANUS-SR Janus Speech Recognition Toolkit# -----------------------------------------------------------
# Author : Matthias und Roald: Gruppe 3
# Module : makeDBase.tcl
# Date : 2.11.97
#
# Remarks : ---
#
#=======================================================================
# arbeitet auf Datei vormots im Homeverzeichnis
# diese wurde wie folgt erstellt: tr -d '.,\!?"' | tr 'A-Z' 'a-z'
# < ..bref/cprompts.iso > vormots
if { \$argc != 1 || [lindex \$argv 1] == "-help"} {
puts stderr "USAGE: \$argv0 'textfile'"
exit
}
set filename [lindex \$argv 0]
if [catch {open \$filename r} inputfile] {
puts stderr "Datei nicht gefunden."
exit
}
# ---------------------
# DBase-Objekt anlegen
# ---------------------
DBase db
db open db.dat db.idx -mode rwc
while {[gets \$inputfile line]>=0} {
set eintrag {}
set id [lindex \$line [expr [llength \$line] -1]]
set speaker "spk "
lappend speaker [string range \$id 1 2]
lappend eintrag \$speaker
set sex "sex "
lappend sex [string range \$id 3 3]
lappend eintrag \$sex
set typ "type "
lappend typ [string range \$id 4 4]
lappend eintrag \$typ
set num "num "
lappend num [string range \$id 5 8]
lappend eintrag \$num
set aussage "text "
for { set i 0} {\$i<[expr [llength \$line]-1] } {incr i 1} {
lappend aussage [lindex \$line \$i]
}
lappend eintrag \$aussage
# Eintrag in die DBase
db add \$id \$eintrag
}
db close
close \$inputfile
exit
Aufgabe 3.3: Entwerfen Sie für die 30 am häufigsten vorkommenden Wörter, die nicht im Aussprachelexikon stehen, eine Phonemsequenz.
Antwort: Darüber, wie ein Wort richtig ausgesprochen wird, läßt sich streiten (sogar unter Franzosen). Z.B. so:
ans o^autres o>tre
avait av&
c'est s{t
d'autres do>tre
d'un dy^
d'une dyn
dit di
faut fo>
font fo^
france fra^s
grande gra^de
grands gra^
j'ai j&
jours Jur
mr me/sjEU
n'a na
n'est n{t
ont o^
paris pari
peut pEU
premiere premj&re
qu'il kil
quelques k{lke
s'est s{t
seront sero^
sont so^
veut vEU
itaient {t&
itait {t&