*音素自動ラベリング((本ページの内容は '''[[理研コーパス班自動ラベリング勉強会:http://lld.fiw-web.net/pukiwiki_lld/index.php?%E8%87%AA%E5%8B%95%E3%83%A9%E3%83%99%E3%83%AA%E3%83%B3%E3%82%B0%E5%8B%89%E5%BC%B7%E4%BC%9A]]''' の資料をまとめなおしたものです。)) [#a0ec10fa]
-&color(red){最終更新 : 2014/07/17};
#contents
**はじめに [#z8e107b8]
-連続音声ファイルに含まれる音素(分節音)の開始・終了時間を、[[大語彙連続音声認識エンジン Julius:http://julius.sourceforge.jp/]]((Copyright (c) 1991-2009 京都大学 河原研究室, Copyright (c) 1997-2000 情報処理振興事業協会(IPA), Copyright (c) 2000-2005 奈良先端科学技術大学院大学 鹿野研究室, Copyright (c) 2005-2009 名古屋工業大学 Julius開発チーム)) を利用して自動認識する(音素自動ラベリング、アノテーション)方法について説明しています。
-最初に用意するもの
--Julius+単語・音素セグメンテーションキット(下でインストールします)
--下記の教科書「IT Text 音声認識システム」(IPA音響モデル・言語モデルが収録されています)
--自動ラベリングを行いたい音声ファイルと、発話内容の書き下しファイル
---本ページでは[[日本語話し言葉コーパス(CSJ):http://www.ninjal.ac.jp/csj/]]に収録されたファイルを使用しています。CSJでは、音声ファイルは .wav 形式、書き下しファイルは Praat標準の形式(([[Praat:http://shower.human.waseda.ac.jp/~m-kouki/pukiwiki_public/41.html]] 形式。それ以外の形式も提供されています。どのような形式でも良いのですが、本ページでは説明の都合上、Praat標準のを使用します。)) で提供されています。
--[[Praat:http://shower.human.waseda.ac.jp/~m-kouki/pukiwiki_public/41.html]] (書き下しファイルにPraat標準の形式を使う場合のみ)
-教科書
--「IT Text 音声認識システム」, 情報処理学会【編】, 鹿野清宏, 伊藤克亘, 河原達也, 武田一哉, 山本幹雄【編著】, オーム社, 2001.
--[[Juliusの使い方/音素セグメンテーション(音素自動ラベリング):http://www.f.waseda.jp/kikuchi/tips/julius.html]](早稲田大 菊池先生)
--[[菊池英明, 前川喜久雄, 五十嵐陽介, 米山聖子, 藤本雅子, "日本語話し言葉コーパスの音声ラベリング," 音声研究, Vol.7, No.3, pp.16-26, 2003.12.:http://ci.nii.ac.jp/naid/110008762893]]
**ソフトウェアのインストール [#be7f9759]
-任意の場所(たとえば、Cygwinのホームディレクトリ直下)に Juliusフォルダを作っておきます(以下「''JULIUS/''」)。
-まず、CygwinとPerlの実行環境をインストールします。[[ここ:http://shower.human.waseda.ac.jp/~m-kouki/pukiwiki_public/index.php?Julius%E3%81%A8Julian#hc3104bf]]を参考にして下さい。
-続いて、音声認識エンジン Julius をインストールします。リンク先で説明しているので、[[基本セット:http://shower.human.waseda.ac.jp/~m-kouki/pukiwiki_public/24.html#f6afb47e]]、[[ディクテーション実行キット:http://shower.human.waseda.ac.jp/~m-kouki/pukiwiki_public/24.html#e77dd584]]、[[単語・音素セグメンテーションキット:http://shower.human.waseda.ac.jp/~m-kouki/pukiwiki_public/24.html#cb2d81f0]]のインストールを完了してください。
-続いて、音声認識に使用する情報処理振興事業協会(IPA)フォーマット(([[国際音声記号:http://ja.wikipedia.org/wiki/%E5%9B%BD%E9%9A%9B%E9%9F%B3%E5%A3%B0%E8%A8%98%E5%8F%B7]]の略称もIPAですが、別物です。))の音響モデル((IPA音響モデルと呼ばれています。これは情報処理振興事業協会(IPA)の[[「日本語ディクテーション基本ソフトウェア99年度版」プロジェクト:http://winnie.kuis.kyoto-u.ac.jp/dictation/]]の成果物で、[[日本音響学会 新聞記事読み上げ音声コーパス(JNAS):http://research.nii.ac.jp/src/JNAS.html]]から作られた音響モデルです。モデルの構築手順の詳細は [[JNAS CDROMからIPA音響モデルの作成法:http://www.cyb.mei.titech.ac.jp/nakadai/nakadai/acoustic/index.html]]を参照して下さい。菊池, 前川, 五十嵐, 米山, 藤本, 2003. によれば、「読み上げ音声の音素自動ラベリングには一般的にIPAモデルが用いられる。CSJにおいては講演音声に対してもこの音響モデルが最も有効であった」とのこと。なお、音響モデルは自分で作ることもできます([[参照:http://shower.human.waseda.ac.jp/~m-kouki/pukiwiki_public/92.html]])。))、言語モデルを入手します。
--「IT Text 音声認識システム」付属CD-ROMの phone_m フォルダ を phone_m_IPA にリネームして、JULIUS/ 以下にコピーしておきます。
-必要に応じて((宮澤がTextGridのテキストを整形するために作ったツールがJavaで動くというだけですので、テストデータを試すだけなら不要です。なお、コマンドラインで「javac」と入れてみてエラーが出たら未インストール状態です。)) [[Javaの実行環境:http://shower.human.waseda.ac.jp/~m-kouki/pukiwiki_public/63.html#q74f27ae]] もインストールしておきます。
**自動ラベリング [#x67087a4]
***Juliusのサンプル音響モデル・テストデータセットで試す [#wf35980d]
-JULIUS/segment_julius4.pl の以下の行を書き換えます。
--JULIUS/bin/julius-*****.exe のバージョン番号に書き換え。2014/07/17 時点では以下の通り。
16行目 $julius4bin="./bin/julius-4.1.5";
> $julius4bin="./bin/julius-4.3.1";
---パスの区切り記号は%%「/」でなく「\\」で記述して下さい%%。((「'C:'は、内部コマンドまたは外部コマンド~」エラーが出て実行できず。)) → &color(red){※ PCによって違うようです。「/」「\」「\\」のうち、ご自分の環境に合わせた(エラーの出ない)記述をして下さい。};
---絶対パスで記述して下さい。((相対パスは「'.'は、内部コマンドまたは外部コマンド~」エラーが出て実行できず。)) → &color(red){※ PCによっては相対パスでもうまくいくようです。JULIUS/ のところを ./ と記述してエラーが出なければ、以降そのように表記してかまいません(絶対パスでもOK)};
--音響モデルの正しい場所を指定。ご自分の環境に合わせて書き換えてください。
19行目 $hmmdefs="./models/hmmdefs_monof_mix16_gid.binhmm"; # monophone model
> $hmmdefs="./model/phone_m/hmmdefs_monof_mix16_gid.binhmm"; # monophone model
-コマンドラインで以下を実行します。
cd JULIUS/
perl segment_julius4.pl JULIUS/sample/sample.wav JULIUS/sample/sample.trans
--Array @words missing the @ ... の警告は、69行目の word を @word に書き換えれば消えますが、とりあえずどちらでも問題ありません([[詳細:http://perldoc.jp/docs/perl/5.6.1/perldiag.pod]])。
--ここではパスの区切り記号は「/」でも「\」でも「\\」でもOK。
#ref(segmentation01.png,,60%);
--入力データは音声ファイル sample.wav と、書き下しファイル sample.trans です。
---sample.trans の中身
silB ky o: w a i i t e N k i d a silE
---音素の記述形式が、音響モデル hmmdefs_monof_mix16_gid.binhmm の記述形式と一致している必要があります(後述)。
-成功すれば、JULIUS/sample 以下に sample.trans.log と sample.trans.align ができます。
--%%sample.trans.align の例%% → .trans.align ファイルにはアラインメント情報が書き出されず。原因が不明ですが((Linux環境では.alignにも書き出されるようです。))、''sample.trans.log'' には以下のように書き出されています。
(略)
--- transcription ---
silB ky o: w a i i t e N k i d a silE
(略)
=== begin forced alignment ===
-- phoneme alignment --
id: from to n_score unit
----------------------------------------
[ 0 22] -19.594139 silB
[ 23 31] -25.734671 ky
[ 32 55] -20.839849 o:
[ 56 67] -23.585581 w
[ 68 75] -27.564896 a
[ 76 87] -26.436453 i
[ 88 97] -23.435047 i
[ 98 106] -23.542698 t
[ 107 116] -24.730494 e
[ 117 126] -24.588940 N
[ 127 138] -24.642313 k
[ 139 143] -25.039257 i
[ 144 149] -24.957642 d
[ 150 159] -24.341919 a
[ 160 203] -19.249168 silE
re-computed AM score: -4603.678711
=== end forced alignment ===
(略)
---データの詳細は、セグメンテーションキットのReadmeか、[[juliusbook/アラインメント出力:http://julius.sourceforge.jp/juliusbook/ja/desc_search.html#id2541965]]を参照して下さい。
---開始時間・終了時間はフレーム単位([[参考:http://shower.human.waseda.ac.jp/~m-kouki/pukiwiki_public/index.php?MATLAB%20Note%2F%E9%9F%B3%E5%A3%B0%E3%81%AE%E5%88%86%E6%9E%90#o5c30647]])で表示されていることに注意して下さい。[[フレーム数データを時間データに変換する:http://shower.human.waseda.ac.jp/~m-kouki/pukiwiki_public/119.html#c56db81c]] も参照してください。
---n_scoreは音響尤度をあらわし、この値が大きいほど推定結果の精度が高いと解釈できます。
***IPA音響モデルで試す [#s201f90b]
-[[IPA音響モデル:http://shower.human.waseda.ac.jp/~m-kouki/pukiwiki_public/119.html#be7f9759]] に差し替えて実行してみましょう。JULIUS/segment_julius4.pl を以下のように書き換えて下さい。
19行目 $hmmdefs="./models/hmmdefs_monof_mix16_gid.binhmm"; # monophone model
> $hmmdefs="./model/phone_m_IPA/model/monof/mix16/female/hmmdefs.gz";
--IPA音響モデルの中には、モノフォン4,8,16混合、各種トライフォンモデルがあります。((モノフォンは音素1種類について1つのモデルが対応します。トライフォンは前後の音素の組み合わせが違うものは全て別の音素のモデルとして扱います。)) 菊池先生の自動ラベリングでは monof/mix16/gid を使っています。((gidは性別非依存モデル。femaleでもgidでもあまり精度の差はないとのこと。[[理研日本語母子会話コーパス:http://ci.nii.ac.jp/naid/110006163026]]の話者は全員女性なので、今回の説明ではfemaleを使用しています。))トライフォンよりモノフォンのほうが精度がいいようです。((なぜmonophoneの方が精度が良いのかについては、当時学会で議論していろいろな解釈がありましたが、どの解釈が最も適切かまではわかりませんでした by菊池先生))詳しくは [[菊池, 前川, 五十嵐, 米山, 藤本, 2003:http://ci.nii.ac.jp/naid/110008762893]] を参照。
-コマンドラインで以下を実行します。
cd JULIUS/
perl segment_julius4.pl JULIUS/sample/sample.wav JULIUS/sample/sample.trans
--%%sample.trans.align%% ''sample.trans.log'' は以下のようになります。
(略)
=== begin forced alignment ===
-- phoneme alignment --
id: from to n_score unit
----------------------------------------
[ 0 22] -19.406990 silB
[ 23 29] -26.072439 ky
[ 30 55] -21.184967 o:
[ 56 67] -24.465780 w
[ 68 75] -28.106598 a
[ 76 86] -27.601252 i
[ 87 98] -23.418436 i
[ 99 106] -23.046021 t
[ 107 116] -25.631763 e
[ 117 126] -25.530054 N
[ 127 138] -24.519287 k
[ 139 143] -24.817968 i
[ 144 149] -24.728354 d
[ 150 161] -25.318420 a
[ 162 203] -18.564754 silE
re-computed AM score: -4603.678711
=== end forced alignment ===
(略)
---フレーム数はほぼ変化なしですが、n_scoreが少し変わりました。
***IPA音響モデル+CSJのサンプルデータで試す [#db9943be]
-.wavファイルと.transファイルがあれば音素の自動ラベリングができます。
-ただし以下に注意
--長すぎる.wavファイルは処理できないため、無声部「#」で区切って別々の.wavと.transを作る必要があります。
--音素の記述はIPA音響モデルの形式(phone_m/parms/monophones)に準拠する必要があります。
#ref(monophones.txt);
---無音を表す記号は3種類あり、.transの文頭に"/silB/"、文末に"/silE/"を記述する必要があります。%%"/sp/"は無音区間と判断された場所に自動的に付加されるので、.transで記述する必要はない(はず)です。%% /sp/は発話中のショートポーズ([[参考:http://julius.sourceforge.jp/index.php?q=doc/iwsp.html]])で、音素自動ラベリングでは明記する必要があります。(([[Juliusにおける入力の無音区間・休止の扱い/自動アラインメント機能との関係:http://julius.sourceforge.jp/index.php?q=doc/iwsp.html]] によれば、"sp" の挿入/非挿入の自動推定も可能?未確認です。))
---モーラ表は「IT Text 音声認識システム」の p.45 などを参照。((Juliusの[[孤立単語認識キット:http://shower.human.waseda.ac.jp/~m-kouki/pukiwiki_public/index.php#ua541108]] に付属している make_dict.pl を使えば、モーラ(ひらがな)表記からIPA音響モデル形式の音素表記に自動変換してくれます。このページではTextGridから手動で音素表記を作るため、make_dict.pl は使用しません。))
-CSJのA06F0075の冒頭約10秒を自動認識してみましょう
--.wavファイル '''[[A06F0075_short.wav:http://shower.human.waseda.ac.jp/~m-kouki/pg/segmentation/A06F0075_short.wav]]'''
--.TextGridファイル '''[[A06F0075_short.TextGrid:http://shower.human.waseda.ac.jp/~m-kouki/pg/segmentation/A06F0075_short.TextGrid]]'''
--ちなみに、スピーチの内容
0001 00000.279-00000.462 L:
はい & ハイ
0002 00000.531-00002.539 L:
(F えー) & (F エー)
それでは & ソレデワ
始めさせていただきます & ハジメサセテイタダキマス
0003 00002.933-00009.229 L:
(F え) & (F エ)
予稿集の & ヨコーシューノ
方 & (W ホ;ホー)
八十二ページからなんですが & ハチジューニページカラナンデスガ
最初に & サイショニ
(F あの) & (F アノ)
申し訳ございませんが & モーシワケゴザイマセンガ
ミススペルが & ミススペルガ
ございまして & ゴザイマシテ
#ref(segmentation02.png,,50%);
-今回は手動で必要なファイルを揃えます。
-まずは、「#」記号の開始時間~終了時間の間のどこかで .wav を分割します。
--'''[[A06F0075_short_1.wav:http://shower.human.waseda.ac.jp/~m-kouki/pg/segmentation/A06F0075_short_1.wav]]''' '''[[A06F0075_short_2.wav:http://shower.human.waseda.ac.jp/~m-kouki/pg/segmentation/A06F0075_short_2.wav]]'''
--「ハイ」と「エーソレデワハジメサセテイタダキマス」の間にも発話の区切りがあるのですが、「ハイ」が短いので、今回はまとめて一つのファイルにしました。
-続いて、.TextGridの音素ラベルを横に並べて.transフォーマットのテキストファイルを作ります。
--.TextGridファイルをPraatで読み込んで、以下の[[Praatスクリプト:http://shower.human.waseda.ac.jp/~m-kouki/pukiwiki_public/41.html#oebdbd17]]を実行して、実行結果のファイルから「'」と「# 」を除外すると良いでしょう(JULIUS/ のところは書き換えて下さい)。
#geshi(bash){{
# ファイルを読み込む
Read from file... JULIUS/A06F0075_short.TextGrid
select TextGrid A06F0075_short
# 書きだすファイルを初期化
filedelete JULIUS/A06F0075_short.txt
# item[2](seg層)の intervals の総数(seg要素の総数)を得る
number_of_intervals = Get number of intervals... 2
# intervals(各要素)を順番に処理していく
for i from 1 to number_of_intervals
select TextGrid A06F0075_short
# item[2] の intervals[i] の text を得る
interval_label$ = Get label of interval... 2 'i'
# ファイルに書き出す
fileappend "JULIUS/A06F0075_short.txt" 'interval_label$'' '
endfor
select TextGrid A06F0075_short
Remove
}}
---なお、seg層がまだ記述されていない.TextGridファイルなら、word層を取り出す設定に変えて(itemの数値を変えて)、ここか後で音素で分割する処理を追加する必要があります。
--結果
# h a i # eH s o r e <cl> d e,w,a h a <cl> zj i m e s a s e <cl> t e,i <cl> t a <cl> d a <cl> kj i m a s,U # e y o <cl> k oH sy uH n o h o h a <cl> cj i zy uH nj i <cl> p eH zj i <cl> k a r a n a N <cl>,d e s u <cl>,g a s a,i sy o nj i,a n o m oH sj,I w,a <cl> k e <cl>,g o z a i m a s e N <cl>,g a m i s u s,U <cl> p e r u <cl>,g a <cl>,g o z a i m a sj,I <cl> t e
---上述したIPA音響モデルの形式とはかなりずれています。これを手動で修正していきます。
--修正した結果(1発話目)
silB h a i e: s o r e d e w a h a j i m e s a s e t e i t a d a k i m a s u silE
#ref(A06F0075_short_1.trans);
※A06F0075_short_2.trans は自作してみて下さい。
-コマンドラインで以下を実行します。
cd JULIUS/segmentation-kit-v4.0
perl segment_julius4.pl JULIUS\A06F0075_short_1.wav JULIUS\A06F0075_short_1.trans
--A06F0075_short_1.trans.align は以下のようになります。
--- transcription ---
silB h a i e: s o r e d e w a h a j i m e s a s e t e i t a d a k i m a s u silE
(略)
=== begin forced alignment ===
-- phoneme alignment --
id: from to n_score unit
----------------------------------------
[ 0 7] -23.644579 silB
[ 8 54] -26.340855 h
[ 55 57] -27.499634 a
[ 58 62] -25.551952 i
[ 63 70] -24.827682 e:
[ 71 79] -23.284899 s
[ 80 82] -28.166138 o
[ 83 85] -25.924316 r
[ 86 88] -26.113281 e
[ 89 93] -25.907177 d
[ 94 97] -27.854980 e
[ 98 100] -27.261719 w
[ 101 103] -31.947754 a
[ 104 110] -24.703440 h
[ 111 115] -24.811621 a
[ 116 123] -26.681671 j
[ 124 126] -28.597412 i
[ 127 131] -23.906055 m
[ 132 134] -28.595215 e
[ 135 146] -25.724039 s
[ 147 149] -27.833578 a
[ 150 159] -25.979931 s
[ 160 164] -27.291992 e
[ 165 170] -25.116373 t
[ 171 174] -24.063599 e
[ 175 179] -25.904882 i
[ 180 187] -25.971191 t
[ 188 191] -25.661865 a
[ 192 197] -26.334229 d
[ 198 204] -27.668247 a
[ 205 215] -26.290794 k
[ 216 218] -27.065430 i
[ 219 226] -24.325378 m
[ 227 232] -25.482422 a
[ 233 245] -23.292480 s
[ 246 248] -26.724447 u
[ 249 270] -22.294079 silE
(略)
---「ハイ」と「エーソレデワハジメサセテイタダキマス」の間の無音区間は抽出できていません。より精密な結果を得たいなら、全ての「#」でファイルを分割することを検討して下さい。
--A06F0075_short_2.trans.align もやってみて下さい。
***分析パラメータを変更する [#k5094393]
-segment_julius4.pl では、音響モデルファイルを指定するのみで、詳細な Julius のパラメータは指定していません(全てデフォルトパラメータで実行している)。
-任意のパラメータファイル(例えば segment.jconf)を指定したい場合、segment_julius4.pl に以下を追記します。
# パラメータファイル
$paramfile = "./segment.jconf";
-続いて、segment_julius4.pl のコマンド実行行(130行目付近)を以下に書き換えます。
$command = "echo $speechfile | $julius4bin -C $paramfile -h $hmmdefs -dfa $TMPDIR/tmp.dfa -v $TMPDIR/tmp.dict";
**フレーム数データを時間データに変換する [#c56db81c]
-最後に、.trans.align 形式ファイルで出力された開始・終了フレーム数の情報を、時間情報に変換する方法について説明します。
--[[Juliusのデフォルト設定:http://julius.sourceforge.jp/refman/julius.html.ja]] では、サンプリング周波数(smpPeriod period)は16,000Hz((1秒あたり16,000個(サンプル)のデータがあるということです))、フレームサイズ(窓サイズ、fsize sample)は400サンプル、フレームシフトサイズ(fshift sample)は160サンプルです。(([[MFCCパラメータの設定 - Julius:http://julius.sourceforge.jp/index.php?q=doc/param.html]] によれば、Juliusの音響解析パラメータは音響モデルの設定と合わせる必要があるため、勝手に変えるべきではありません。Juliusの設定はHTKによる音響モデル構築のデフォルト設定と合わせているようです。))
--上記より1サンプルの時間長は 1/16000秒 なので、フレームサイズの時間長は以下のように求められます。
400サンプル = (1 / 16000) * 400 = 1 / 40 [秒] = 25 [ミリ秒]
--フレームシフトサイズの時間長は以下のようになります。
160サンプル = (1 / 16000) * 160 = 1 / 100 [秒] = 10 [ミリ秒]
--イメージ図
#ref(julius_framesize.png,,80%);
--したがって、例えば .trans.align ファイルの開始・終了フレームが [1 3] になっていたら、「第1フレームの開始から第3フレームの終わりまで」という意味なので、開始時間は 「フレームシフトサイズ × フレーム番号 = 10 * 1 = 10 [ミリ秒]」になります。終了時間は「フレームシフトサイズ × フレーム番号 + フレームサイズ = 10 * 3 + 25 = 55 [ミリ秒]」になります。
---【備考】(1)実際のファイルの総時間、(2).trans.align で書き出されるファイル総時間(ALIGNMENT RESULT部)、(3)上記の計算で求まる最終音素の終了時間、は一致しません。(2)は小数第三位で四捨五入するため、(3)はフレームで切り出した結果余った最後の部分が分析されないためです。
---【備考】上記の計算だと、前の音素の終了時間のほうが、後の音素の開始時間よりも遅れるため、Praat等で処理する際に不都合です。その場合、終了時間を単に「フレームシフトサイズ × フレーム番号」とみなします。((自動ラベリングの結果を人手で修正する場合などは、この対処で十分です。その際、一度自動ラベリング結果を(Praat標準の形式に変換するなどして)視認して、系統的にずれていることがなければ、問題がないとみなしてかまいません('''[[菊池先生のご指摘:http://shower.human.waseda.ac.jp/~m-kouki/pg/segmentation/20120706_segmentation_timeframe.txt]]'''による)))
--以上を自動化して、Praat標準の形式で書き出すperlスクリプト &ref(transalign2textgrid.pl);
---単純なCSVで書き出したい場合は &ref(transalign2csv.pl);
-A06F0075_short_1.trans.align を時間情報に変えてみましょう。Excelを活用すると良いでしょう。