凹みTips

C++、JavaScript、Unity、ガジェット等の Tips について雑多に書いています。

Julius の記述文法を用いて音声認識精度をあげてみた

はじめに

未来のお部屋をつくろうプロジェクト第3弾です。とは言っても地味なところですが(でも重要です)。
前回、Julius を使って音声認識をさせてみました。が、書いたように認識精度が惨憺たる結果だったので、改善すべく第7章 言語モデルを参考にして記述文法を書いてみました。
ご意見をくださった方々ありがとうございます!

記述文法音声認識キットを試してみる

未来なお部屋の先駆者 d:id:rti7743 さんに教えてもらいました。

URL から Linux版 Julius 記述文法音声認識キット v4.1 を落としてきて展開します。そしてフォルダに入って次のコマンドで実行します。

./bin/julius -C hmm_mono.jconf -gram SampleGrammars/railroad/railroad -input mic -charconv EUC-JP UTF-8

railroad は「<駅名>から<駅名>まで」という入力を受け取る記述文法が書いてあり、その文法に特化した音声認識をしてくれます。試しに「仙台から長野まで」とか言ってみれば、そこそこの精度で所望の結果が得られると思います。

自分で文法を作ってみる

自分で家電を操作するための文法を書いてみます。第7章 言語モデルを参考にして書いてみました。

kaden.grammar
S      : NS_B KADEN_ PLEASE NS_E
KADEN_ : KADEN
KADEN_ : KADEN WO
kaden.voca
% KADEN
テレビ   t e r e b i
電気    d e n k i
% WO        
を      w o 
% PLEASE    
つけて   t u k e t e
消して   k e s i t e
切替    k i r i k a e
次      t u g i
前      m a e
% NS_B
<s>     silB
% NS_E
<s>     silE
解説

まず、grammar から書き始めます。最初に、

S      : NS_B KADEN_ PLEASE NS_E

の形でどんな文法を読み込ませたいかを定義します。KADEN_ とか PLEASE とかは自分で適当に文字を当て込みます。単なるプレースホルダです。
次にその適当に当て込んだ文字が複数パターンに分岐する場合、続く行で、

KADEN_ : KADEN
KADEN_ : KADEN WO

といったように定義します。この時点でイメージとしては次のようにツリー構造になっているような感じです。

NS_B
KADEN_
 + KADEN
 + KADEN WO
PLEASE
NS_E

KADEN_ は KADEN もしくは KADEN WO という形になるよ!ということです。
次に voca ファイルを作ります。ここでは先ほどの grammar ファイルの末端に位置するプレースホルダについて、どんな言葉が当たるかを定義します。つまり、

NS_B        *
KADEN_
 + KADEN    *
 + KADEN WO *
PLEASE      *
NS_E        *

*をつけたやつらです。ここでは複数の言葉を指定することができ、例えば KADEN は、

% KADEN
テレビ  t e r e b i
電気    d e n k i

こんな形になるわけです。他のものも全部書けば kaden.voca の完成です。ちなみに silB や silE は silent Begin と silent End だと思います、多分。
この2つのファイルで次のような定義が出来たわけですね。

NS_B
 + (音無)
KADEN_
 + KADEN
   + テレビ
   + 電気
 + KADEN WO
   + テレビ を
   + 電気 を
PLEASE
 + つけて
 + 消して
 + 切替
 + 次
 + 前
NS_E
 + (音無)
コンパイル

作った kaden.grammar と kaden.voca をコンパイルします。

./bin/mkdfa.pl kaden

これで julius に与えるための kaden.dfa と kaden.dict が生成されます。

動かしてみた

普通に試す場合には、

./bin/julius -C hmm_mono.jconf -gram kaden -input mic

でOKです。UTF-8 で編集しているので charconv オプションを付ける必要はありません。module モードで動かして前回作成したプログラムでアクセスした結果を吐き出してみます。

サーバ側
./bin/julius -C hmm_mono.jconf -gram kaden -input module
クライアント側
./julius_client
<s>電気つけて<s> 
<s>電気つけて<s> 
<s>電気つけて<s> 
<s>電気つけて<s> 
<s>テレビつけて<s> 
<s>テレビ切替<s> 
<s>テレビつけて<s> 
<s>テレビ消して<s> 
<s>テレビ次<s> 
<s>テレビつけて<s> 
<s>電気次<s> 
<s>電気つけて<s> 
<s>電気前<s> 
<s>電気消して<s> 

まだ誤認識が多いです…(#^ω^)ビキビキ。「消して」っていってるのに「つけて」になるし。もうちょっとなんだけど…。
あと「を」を認識しないんだけど何でなんですかね。

追記(2012/01/14)

「を」を認識しない問題は、grammar と voca を次のようにすることで解決しました。

kaden.grammar
S      : NS_B KADEN_ NOISE PLEASE NS_E
KADEN_ : KADEN
KADEN_ : KADEN WO
kaden.voca
% KADEN
テレビ   t e r e b i
電気    d e n k i
% WO        
を      w o 
% PLEASE    
つけて   t u k e t e
消して   k e s i t e
切替    k i r i k a e
次      t u g i
前      m a e
% NOISE
<sp>    sp
% NS_B
<s>     silB
% NS_E
<s>     silE

NOISE を入れてみれば良かったようです。