作業中のメモ

よく「計算機」を使って作業をする.知らなかったことを中心にまとめるつもり.

音声認識による赤外線機器の操作 その 4【文法辞書作成編】

どうも,筆者です.

以前,辞書を作成したが,決まった単語のみの組み合わせだけだった.今回は,もう少し柔軟に対応できるように辞書を作成する.

関連ページ

workspacememory.hatenablog.com

文法認識の考え方

復習となるが,以前は,以下のような単語のパターンを入力していた.

電気つけて
電気オフ
明るくして
暗くして
こだまにして
テレビオン
テレビ切って

この場合,「電気オフ」と「テレビ切って」や「電気つけて」と「テレビオン」等を使い分ける必要があった.この場合,命令をすべて覚える必要があるが,以下のように認識できれば多少の揺れにも対応できる.

# 電気をつけたい場合
電気つけて
電気をつけて
電気オン
# テレビを付けたい場合
テレビつけて
テレビをつけて
テレビオン

上のパターンは「[家電の名前][操作方法]」という形式で置き換えられる. ここから,家電の名前と操作方法を定義し,これらに対応する文法を定義することで,上記のパターンに対応できることになる.

# 家電の名前
電気
テレビ
# 操作方法
つけて
オン
# 文法
[家電の名前][操作方法]

Julius では,この考え方を用いて音声認識が行える.

記述文法認識キット

今回は,記述文法認識キット(grammar kit)を利用して,文法認識を行う.

語彙の作成

「~/juliusKit/grammarKit」以下に「controller」というディレクトリを作成し,この中で作業を行う.まずは,単語とその読みを「yomiWord.list」というファイルに定義する.この時,上記で用いる単語の組み合わせを考え,定義する.

~ $ pushd ~/juliusKit/grammarKit
~/juliusKit/grammarKit $ mkdir controller
~/juliusKit/grammarKit $ pushd controller
~/juliusKit/grammarKit/controller $ touch yomiWord.list
~/juliusKit/grammarKit/controller $ vim yomiWord.list # エディタは自分の使いやすいものを利用する
# === ここから ===
電気  でんき
テレビ  テレビ
つけて  つけて
オン    おん
オフ    おふ
切って  きって
明るくして あかるくして
暗くして    くらくして
こだまにして  こだまにして
# === ここまで ===

そして,以下のコマンドで,読み方をローマ字形式に変換し,結果を「utf8_controller.voca」に格納する.

~/juliusKit/grammarKit/controller $ cat yomiWord.list | iconv -f utf8 -t eucjp | perl ../bin/linux/yomi2voca.pl | nkf -wLu > utf8_controller.voca
### 出力結果 ###
# 電気   d e N k i
# テレビ    t e r e b i
# つけて    ts u k e t e
# オン   o N
# オフ   o f u
# 切って    k i q t e
# 明るくして  a k a r u k u sh i t e
# 暗くして k u r a k u sh i t e
# こだまにして   k o d a m a n i sh i t e

ここから,出力した「utf8_controller.voca」を編集していく.やることとしては,先程「家電の名前」や「操作方法」という呼び名をつけたように,出力データにも名前を付ける.名前を付ける際は「% [名称]」という形式にする.今回は,以下のようにした.

# この行はコメント扱いとなる
# 家電データ
% KADEN
電気  d e N k i
テレビ   t e r e b i
# 追加の助詞
を w o
# 家電の操作
% MODE_KADEN
つけて   ts u k e t e
オン  o N
オフ  o f u
切って   k i q t e
# 電気に対する操作
% MODE_LIGHT
明るくして a k a r u k u sh i t e
暗くして    k u r a k u sh i t e
こだまにして  k o d a m a n i sh i t e
# 文頭と文末を表すデータ
% NS_B
silB    silB
% NS_E
silE    silE

ここで,必ず必要なのが末尾の「文頭と文末を表すデータ」である.これは,Julius で入力の無音区間と休止区間を表すために必要となる.

文法ファイルの作成

先程作成した語彙ファイルを利用して,文法ファイルを作成する.辞書ファイルの形式を以下に示す.

# 辞書ファイルの形式
# 文法は複数定義できる
S : NS_B [文法1] NS_E # 文法1
S : NS_B [文法2] NS_E # 文法2
S : NS_B [文法3] NS_E # 文法3

今回は,家電の操作と電気に対する操作を定義することを考える.この場合,以下のような文法を作成すればよい.

S : NS_B [家電の名前] [操作方法] NS_E
S : NS_B [電気に対する操作] NS_E

これを上に挙げた名称で置き換えれば,文法を作成したことになる.

S : NS_B KADEN MODE_KADEN NS_E
S : NS_B MODE_LIGHT NS_E

これでも良いが,「テレビつけて」と「テレビをつけて」の両方に対応するため,上の文法を少し弄る.

S : NS_B KADEN_ MODE_KADEN NS_E
S : NS_B MODE_LIGHT NS_E
# KADEN_ の定義(「_」が付いていることに注意)
KADEN_  : KADEN
KADEN_  : KADEN WO

これを,「utf8_controller.grammar」として保存する.ここまでのディレクトリ構成を以下に示す.

~/juliusKit
   |--dictationKit_v4.3.1
       |--word.dic
       |--word.jconf
   |--grammarKit
   |   |--controller
   |        |--utf8_controller.grammar
   |        |--utf8_controller.voca
   |--outYomi.sh
   |--word.yomi

# utf8_controller.grammar の中身
# === ここから ===
S : NS_B KADEN_ MODE_KADEN NS_E
S : NS_B MODE_LIGHT NS_E
# KADEN_ の定義(「_」が付いていることに注意)
KADEN_  : KADEN
KADEN_  : KADEN WO
# === ここまで ===

語彙ファイルと文法ファイルから Julius で利用するデータを作成

語彙ファイルと文法ファイルから Julius で利用するデータを作成する.そのために,Julius をインストールした際のディレクトリから以下の 2 つをコピーしてくる.

~/juliusKit/grammarKit/controller $ cp -f ~/julius/gramtools/mkdfa/mkfa-1.44-flex/mkfa ./
~/juliusKit/grammarKit/controller $ cp -f ~/julius/gramtools/mkdfa/mkdfa.pl ./

そして,データ生成用の Shell Script を作成する.ここでは,「compile.sh」という名前で保存する.

~/juliusKit/grammarKit/controller $ touch compile.sh
~/juliusKit/grammarKit/controller $ vim compile.sh # エディタは自分の使いやすいものを利用する
# === ここから ===
#!/bin/bash
# compile.sh

controller="controller"
grammarFile=utf8_${controller}.grammar
vocaFile=utf8_${controller}.voca

nkf -sLw ${grammarFile} > ${controller}.grammar
nkf -sLw ${vocaFile} > ${controller}.voca
perl mkdfa.pl ${controller}
rm -f ${controller}.grammar ${controller}.voca
# === ここまで ===

ここまでのディレクトリ構成を以下に示す.

~/juliusKit
   |--dictationKit_v4.3.1
       |--word.dic
       |--word.jconf
   |--grammarKit
   |   |--controller
   |        |--compile.sh
   |        |--mkdfa.pl
   |        |--mkfa
   |        |--utf8_controller.grammar
   |        |--utf8_controller.voca
   |--outYomi.sh
   |--word.yomi

後は,Shell Script に実行権限をつけ,以下のように実行すると,メッセージが出力され,「controller.dfa」,「controller.term」,「controller.dict」が生成される.

~/juliusKit/grammarKit/controller $ chmod +x compile.sh
~/juliusKit/grammarKit/controller $ ./compile.sh
### 出力結果
# controller.grammar has xx rules
# controller.voca    has xx categories and yy words
# ---
# Now parsing grammar file
# Now modifying grammar to minimize states[ww]
# Now parsing vocabulary file
# Now making nondeterministic finite automaton[zz/zz]
# Now making deterministic finite automaton[zz/zz] 
# Now making triplet list[zz/zz]
# xx categories, zz nodes, bb arcs
# -> minimized: aa nodes, cc arcs
# ---
# generated: controller.dfa controller.term controller.dict

設定ファイルの作成

ひとつ上のディレクトリに戻り,以下に示す設定ファイルを作成する.ここでは,「controller.jconf」として保存した.

~/juliusKit/grammarKit/controller $ popd
~/juliusKit/grammarKit $ touch controller.jconf
~/juliusKit/grammarKit $ vim controller.jconf # エディタは自分の使いやすいものを利用する
# === ここから ===
######################################################################
#### 入出力指定
######################################################################
-charconv SJIS UTF8

######################################################################
#### ファイル指定
######################################################################
##
## DFA ファイル:文法から生成
## これは別途指定のこと(ヘッダの例を参照)
##
-dfa controller/controller.dfa

##
## 単語辞書ファイル
## これは別途指定のこと(ヘッダの例を参照)
##
-v controller/controller.dict

##
## gram の指定
##
-gram controller/controller

##
## 音響HMM定義ファイル
##
## triphoneモデル
# asciiフォーマット,もしくは "mkbinhmmで" 作成したバイナリ形式
# (自動判別される)
-h model/phone_m/hmmdefs_ptm_gid.binhmm   # PTM triphone
-hlist model/phone_m/logicalTri

######################################################################
#### 言語モデル詳細設定
######################################################################
##
## 単語挿入ペナルティを指定
##
#-penalty1 0.0     # 第1パス
#-penalty2 0.0     # 第2パス

######################################################################
#### 単語辞書詳細設定
######################################################################
##
## エラー単語を無視して続行する
##
-forcedict

######################################################################
#### 音響モデル詳細設定
######################################################################
##
## Julius が triphone/monophone の自動判別に失敗する場合,
## 以下を試してみてください.
##
#-no_ccd       # 音素環境依存性を(強制的に)考慮しない
#-force_ccd        #    〃      (強制的に)考慮する

##
## 特徴パラメータの型チェックをスキップしたい場合は,
## 以下を試してみてください.
##
#-notypecheck
#

##
## PTM/triphone 使用時,第1パスの単語間triphoneの音響尤度計算方法を指定する.
##
#-iwcd1 best N # 同コンテキストtriphoneの上位N個の平均値
#-iwcd1 max    # 同コンテキストtriphoneの最大値
-iwcd1 avg  # 同コンテキストtriphoneの平均値 (default)

######################################################################
#### Gaussian Pruning パラメータ(tied-mixture, PTMでのみ有効)
######################################################################
## コードブックあたり計算するガウス分布計算数(上位N個)
## 以下のデフォルト値は IPA99 の PTM モデル(1コードブックあたり64混合)
## に合わせた値
-tmix 2

## Gaussian pruning 法の選択
## 高速版ではbeam,それ以外ではsafeがデフォルトです
-gprune safe        # safe pruning 上位N個が確実に求まる.正確.
#-gprune heuristic # heuristic pruning
#-gprune beam      # beam pruning 次元ごとに足切り.高速.
#-gprune none      # pruning を行わない

######################################################################
#### Gaussian Mixture Selection パラメータ
######################################################################
#-gshmm hmmdefs        # GMS 用モノフォン音響モデルを指定
            # 指定なし = GMS OFF
#-gsnum 24     # GMS使用時の選択状態数

######################################################################
#### 探索パラメータ
######################################################################
#-b 400            # 第1パスのビーム幅(ノード数) monophone
-b 800         # 第1パスのビーム幅(ノード数) triphone,PTM
#-b 1000       # 第1パスのビーム幅(ノード数) triphone,PTM,engine=v2.1
-b2 30         # 第2パスの仮説数ビームの幅(仮説数)
-sb 80.0        # score beam envelope threshold
-s 5000            # 第2パスの最大スタック数 (仮説数)
-m 2000        # 第2パスの仮説オーバフローのしきい値
-lookuprange 5     # 第2パスで単語展開時のトレリス制約緩和幅(フレーム数)
-n 5           # 第2パスで見つける文の数(文数)
#-n 10         #   ('standard' 設定時のデフォルト)
-output 1      # 第2パスで見つかった文のうち出力する数 (文数)
#-looktrellis      # 単語仮説を完全にトレリス内の単語だけに絞る

######################################################################
#### 単語間ショートポーズ
######################################################################
##
## (マルチパス版のみ)
##
#-iwsp         # コンテキスト独立な単語間ショートポーズを付与
#-iwsppenalty 0.0  # ショートポーズへの遷移ペナルティ
#-spmodel "sp"       # ショートポーズ音響モデルの名前

######################################################################
#### 音声入力ソース
######################################################################
## どれかを選んでください(デフォルト:mfcfile)
#-input mfcfile        # HTK形式のパラメータファイル(MFCC)
#-input rawfile        # 音声波形データファイル(フォーマット自動判別)
            # 形式:WAV(16bit) または
            #  RAW(16bit(signed short),mono,big-endian)
            #  16kHz以外のファイルは -smpFreq で周波数指定
-input mic      # マイクから直接入力
#-input netaudio -NA host:0    # host上のDatLink(NetAudio)から入力
#-input adinnet -adport portnum # adinnet クライアントからの入力
#-input stdin      # 標準入力からの入力

#-filelist filename    # 認識対象ファイルのリスト

-nostrip        # ゼロ続きの無効な入力部の除去をOFFにする
            # (default: 無効な入力部分は除去される)
-zmean          # DC成分の除去を行う (-input mfcfile時無効)

######################################################################
#### 音声録音
######################################################################
#-record directory # 認識した音声データを連続したファイルに自動保存

######################################################################
#### 入力の棄却
######################################################################
-rejectshort 800   # 指定ミリ秒以下の長さの入力を棄却する

######################################################################
#### 音声区間検出
######################################################################
#-pausesegment     # レベル・零交差による音声区間検出の強制ON
#-nopausesegment   # レベル・零交差による音声区間検出の強制OFF
            # (default: mic または adinnet は ON, file は OFF)
-lv 3000       # レベルのしきい値 (0-32767)
#-headmargin 300   # 音声区間開始部のマージン(単位: msec)
#-tailmargin 400   # 音声区間終了部のマージン(単位: msec)
#-zc 60            # 1秒あたりの零交差数のしきい値

######################################################################
#### 音響分析
######################################################################
#-smpFreq 16000        # サンプリング周波数(Hz)
#-smpPeriod 625        # サンプリング周期(ns) (= 10000000 / smpFreq)
#-fsize 400        # 窓サイズ(サンプル数)
#-fshift 160       # フレームシフト幅(サンプル数)
#-delwin 2     # デルタウィンドウ幅 (フレーム数)
#-hifreq -1        # 高域カットオフの周波数(Hz) (-1: disable)
#-lofreq -1        # 低域カットオフの周波数(Hz) (-1: disable)
#-cmnsave filename # CMNパラメータをファイルに保存(1入力毎に上書き)
#-cmnload filename # 初期CMNパラメータを起動時ファイルから読み込む

######################################################################
#### スペクトルサブトラクション (SS)
######################################################################
#-sscalc       # 先頭の無音部を利用して SS を行う(ファイル入力のみ)
#-sscalclen 300        # SSに用いる先頭の無音部の長さ (msec)
#-ssload filename       # ファイルからノイズスペクトルを読み込む
#-ssalpha 2.0      # アルファ係数
#-ssfloor 0.5      # フロアリング係数

######################################################################
#### Forced alignment
######################################################################
#-walign       # 認識結果の単語ごとのアラインメント結果を出力
#-palign       # 認識結果の音素ごとのアラインメント結果を出力
#-salign       # 認識結果のHMM状態ごとのアラインメント結果を出力

######################################################################
#### 単語信頼度計算
######################################################################
#-cmalpha 0.05     # スムージング係数を指定

######################################################################
#### 出力スタイル
######################################################################
#-separatescore        # 言語スコアと音響スコアを分けて出力する
#-progout      # 第1パスで解析途中から漸次的に結果を出力
#-proginterval 300 # -progout 時の出力のインターバル(単位:msec)
-quiet          # 第1パス・第2パスの認識結果のみ出力
#-demo         # "-progout -quiet" と同じ
#-debug            # 探索中の内部状態を出力させる(デバッグ用)

######################################################################
#### サーバーモジュールモード
######################################################################
#-module       # サーバーモジュールモードで起動
#-module 5530      # (ポート番号を指定する場合)
#-outcode WLPSC        # モジュールに出力する情報を選択 (WLPSCwlps)
# === ここまで ===

動作確認

以下のディレクトリでコマンドを実行したい際に,「<<< please speak >>>」が出力され,音声が認識されていれば成功である.

~/juliusKit/grammarKit $ ALSADEV="plughw:0,0" julius -C controller.jconf -demo