Sphinx-4: fyrstu skrefin
Markmið: Að smíða lítið forrit sem er fært um að greina eina tegund af setningum.
Forkröfur eru: grunnþekking á Java og hlutbundinni forritun. Þekkja hvernig Sphinx-4 config skrár virka
Tól sem þarf:
Java SDK 1.4.2,
Sphinx-4 og einhvert þróunarumhverfi t.d.
Eclipse
Sphinx-4 er talgreinir (e. speech recognizer) sem vísindamenn við Carnegie Mellon University hafa þróað. Talgreinir er forrit sem notað er til að láta tölvu "skilja" mælt mál og greina það niður í orð. Hér á eftir verður farið í það hvernig á að nota Sphinx-4 java API (application programming interface)
til að búa til lítið java forrit sem er fært um að greina eina tegund af setningum. Við munum einnig fara í það hvernig málfræðiskráin (e. grammar file)
sem Sphinx-4 notar er byggð upp og munum við búa til eina litla þannig skrá.
Við skoðum fyrst hvernig málfræðiskráin er búin til. Málfræðiskrárnar sem Sphinx-4 notar eru á svokölluðu
BNF formi. BNF er ritháttur sem notaður er til að tákna málfræði á formlegan hátt og er gjarnan notað við að skilgreina forritunarmál. BNF er alls ekki flókið en getur virst rosalegt torf
til að byrja með. Við vonumst til að geta sýnt með nokkrum dæmum hvernig BNF rithátturinn virkar og hvernig hann er notaður til að tákna málfræðina fyrir Sphinx-4. Fyrir þá sem
vilja kynna sér formlega skilgreiningu á málfræðinni þ.e. JSGF (e. Java Grammar Format Specification) þá er hægt að nálgast upplýsingar um það
hér.
Nú skulum við líta aðeins á það hvernig BNF virkar og sjá hvernig við getum notað það til að tákna löglegt póstfang (hér er átt við venjulegt heimilisfang þ.e. nafn,
gata, póstnúmer og staður).
// skýringar á táknmáli:
//
// það sem er innan <> er skilgreining á tagi
// | stendur fyrir 'eða'
// það sem er innan [] er frjáls hluti (e. optional)
// það sem er innan "" er fyrirfram skilgreindur texti t.d. "."
// EOL stendur hér fyrir End-Of-Line
// ::= stendur fyrir 'skilgreint sem'
<póst-fang> ::= <nafn-hluti> <heimilis-hluti> <póstnúmer-hluti>
<persónu-hluti> ::= <fornafn> | <upphafsstafur> "."
<nafn-hluti> ::= [<titil-hluti> "."] <persónu-hluti> <eftir-nafn>
["og" | ","] <EOL> | <persónu-hluti> <nafn-hluti>
<heimilis-hluti> ::= [<íbúð>] <götuheiti> <húsnúmer> <EOL>
<póstnúmer-hluti> ::= <póst-númer> "," <staður> <EOL>
Hér höfum við einfalt dæmi um það hvernig hægt er að nota BNF til að skilgreina löglegt póstfang. Það er mjög mikilvægt að átta sig á því hvernig þessi skilgreining er uppbyggð.
En hvernig setningar eru löglegar miðað við þessa skilgreiningu?
Dæmi um lögleg póstföng samkvæmt skilgreiningu að ofan
Dr. Jón Jónsson
íbúð 4 Stórugötu 1
101, Reykjavík
Jón Jónsson og Anna Aradóttir
Stórugötu 1
101, Reykjavík
J. Jónsson, A. Aradóttir
Stórugötu 1
101, Reykjavík
Núna höfum við skoðað hvernig BNF virkar og til hvers er hægt að nota það. Þá skulum við líta næst á það hvernig við útbúum málfræðiskrá fyrir Sphinx-4 með þessum rithætti.
Það fyrsta sem við skilgreinum í grammar skrá er haus (e. header) þar sem við tilgreinum hvaða útgáfu af JSGF við erum að nota og hvaða táknmengi (e. character set) á að nota í
skránni. Rétt er að benda á að haus og heiti á málfræði eru ekki skrifuð með BNF rithætti.
#JSGF V1.0 ISO8859-1;
Næst tilgreinum við nafnið á þeirri málfræði (e. grammar) sem við erum að fara að skilgreina. Það er hægt að skilgreina grammar á tvo mismunandi vegu annars vegar sem hluta
af pakka (e. package) eða sem staka skrá.
// hér skilgreinum við staka málfræðiskrá
grammar simpleGrammar;
// hér skilgreinum við málfræðiskrá sem hluta af pakka
grammar packageName.simpleGrammar;
Málfræðiskráin sem við ætlum að nota er í fullri lengd:
#JSGF V1.0;
/**
* JSGF Grammar for Hello World example
*/
grammar hello;
public = ( Hello | Good Morning ) ( Dave | Bob | Anna | Susan );
Málfræði skrárnar þarf svo að vista sem .gram og vísa í þær í sphinx-4 config-skránni
Nú höfum við gengið frá öllum formlegheitum og getum farið í þetta skemmtilega þ.e. að skilgreina þá málfræði sem Sphinx-4 talgreinirinn á að skilja. Þar sem Sphinx-4 eins og
hann kemur frá þróunaraðilum skilur ekki Íslensku þá komum við til með að skilgreina málfræðina á ensku. Það er þó rétt að benda á að hægt er að breyta Sphinx-4 þannig að hann
geti skilið hvaða tungumál sem er, en það er mjög mikil vinna.
<greeting> = ( Good morning | Hello ) ( Dave | Bob | Anna | Susan );
Hér höfum við skilgreint kveðju (e. greeting) sem hefst á "Good morning" eða "Hello". Þar á eftir er svo möguleiki á að nota eitthvert af nöfnunum "Dave", "Bob", "Anna" eða
"Susan". Það sem þetta þýðir er að við getum tekið við setningum eins og "Good morning Dave". Það er að sjálfsögðu hægt að gera flóknari setningar en eftir því sem setningarnar
verða flóknari þeim mun erfiðara verður fyrir tölvuna að greina þær í sundur. Fyrir þá sem vilja spreyta sig á þessu bendum við á formlegu skilgreininguna á málfræðiskrám sem
minnst var á að ofan og hægt er að nálgast hér.
Nú þegar umfjöllun okkar um málfræðiskrár er lokið þá snúum við okkur að því að búa til forrit sem nýtir þá configskrár og málfræðiskrár. Þegar við byrjum á forritinu þurfum
við fyrst að gera Sphinx-4 sem hluta af forritinu okkar.
import edu.cmu.sphinx.frontend.util.Microphone;
import edu.cmu.sphinx.recognizer.Recognizer;
import edu.cmu.sphinx.result.Result;
import edu.cmu.sphinx.util.props.ConfigurationManager;
import edu.cmu.sphinx.util.props.PropertyException;
import java.net.URL;
import java.io.File;
Nú þegar við höfum náð í öll tól sem þarf til að nota Sphinx-4 í java-forritinu okkar þá hefjumst við handa við að nota þau. Það fyrsta sem við gerum núna er að sækja config
skránna og búa til stillingastjórnanda (e. configuration manager) sem sér um að hlaða inn stillingum úr henni.
public class SphinxExample02
{
public static void main( String[] args )
{
URL url = new File("sphinxexample01.config.xml").toURI().toURL();
ConfigurationManager cm = new ConfigurationManager(url);
Þegar stillingar hafa verið teknar inn úr skránni þá er bara eftir fyrir okkur að búa til talþekkjara og míkrófón til að hlusta á og greina hljóð úr míkrófón. Við gerum það með
því að búa til tilvik af þekkjara og míkrófón taka frá auðlindir og hefja upptöku.
Recognizer recognizer = (Recognizer) cm.lookup("recognizer");
Microphone microphone = (Microphone) cm.lookup("microphone");
recognizer.allocate();
if (microphone.startRecording())
{
while (true)
{
System.out.println("Start speaking. Press Ctrl-C to quit.\n");
Result result = recognizer.recognize();
if (result != null)
{
String resultText = result.getBestFinalResultNoFiller();
System.out.println("You said: " + resultText + "\n");
}
else
{
System.out.println("I can't hear what you said.\n");
}
}
}
Stilliskráin(e. configuration file) ásamt málfræðiskránni sem við miðum við er hægt að nálgast hér
Í sýnishorninu hér að ofan búum við til þekkjara og míkrófón, kveikjum á míkrófóninum og látum svo lykkju keyra þangað til notandi ýtir á ctrl-c. Aðferðin recognize()
sér um að hlusta og bíður þangað til líkleg setning hefur komið inn í gegnum míkrófóninn. Eftir það er setningin greind og athugað hvort hún passi við það sem er skilgreint í málfræðiskránni. Ef hljóðið passar við eitthvað í skránni
er gildi skilað til baka en annars er null skilað til baka.
Það sem þarf að hafa sérstaklega í huga þegar forritið er keyrt að það þarf að láta java sýndarvélina fá 256 megabæti þar sem sphinx þarf mikið minni til að virka. þetta er td. hægt að gera með því að bæta -mx256m við færubreytulista sýndarvélarinnar (java eða javaw).
Ef notað er Eclipse þá er hægt að sjá hvernig skal stilla það hér
Nú höfum við lokið umfjöllun um grunnvirkni á Sphinx-4. Nú ætti að vera ljóst hvernig hægt er að búa til einfalt forrit sem er fært um að hlusta á á hljóð í gegnum míkrófón,
greina hljóðið og bera saman við setningu sem við höfum skilgreint í málfræðiskrá. Allur kóðinn sem notaður er til að framkvæma það sem lýst er hér að ofan er hægt að nálgast
hér.