トップ   編集 凍結解除 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索   ヘルプ   最終更新のRSS

JuliusとJulian/音素自動ラベリング

Last-modified: 2016-02-05 (金) 07:57:16
Top / JuliusとJulian / 音素自動ラベリング

音素自動ラベリング*1

  • 最終更新 : 2014/07/17

はじめに

  • 連続音声ファイルに含まれる音素(分節音)の開始・終了時間を、大語彙連続音声認識エンジン Julius*2 を利用して自動認識する(音素自動ラベリング、アノテーション)方法について説明しています。
  • 最初に用意するもの
    • Julius+単語・音素セグメンテーションキット(下でインストールします)
    • 下記の教科書「IT Text 音声認識システム」(IPA音響モデル・言語モデルが収録されています)
    • 自動ラベリングを行いたい音声ファイルと、発話内容の書き下しファイル
      • 本ページでは日本語話し言葉コーパス(CSJ)に収録されたファイルを使用しています。CSJでは、音声ファイルは .wav 形式、書き下しファイルは Praat標準の形式*3 で提供されています。
    • Praat (書き下しファイルにPraat標準の形式を使う場合のみ)

ソフトウェアのインストール

  • 任意の場所(たとえば、Cygwinのホームディレクトリ直下)に Juliusフォルダを作っておきます(以下「JULIUS/」)。
  • まず、CygwinとPerlの実行環境をインストールします。ここを参考にして下さい。
  • 続いて、音声認識に使用する情報処理振興事業協会(IPA)フォーマット*4の音響モデル*5、言語モデルを入手します。
    • 「IT Text 音声認識システム」付属CD-ROMの phone_m フォルダ を phone_m_IPA にリネームして、JULIUS/ 以下にコピーしておきます。

自動ラベリング

Juliusのサンプル音響モデル・テストデータセットで試す

  • JULIUS/segment_julius4.pl の以下の行を書き換えます。
    • JULIUS/bin/julius-*****.exe のバージョン番号に書き換え。2014/07/17 時点では以下の通り。
      16行目 $julius4bin="./bin/julius-4.1.5";
           > $julius4bin="./bin/julius-4.3.1";
      • パスの区切り記号は「/」でなく「\\」で記述して下さい*7※ PCによって違うようです。「/」「\」「\\」のうち、ご自分の環境に合わせた(エラーの出ない)記述をして下さい。
      • 絶対パスで記述して下さい。*8※ 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 に書き換えれば消えますが、とりあえずどちらでも問題ありません(詳細)。
    • ここではパスの区切り記号は「/」でも「\」でも「\\」でもOK。
      segmentation01.png
  • 入力データは音声ファイル 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 ファイルにはアラインメント情報が書き出されず。原因が不明ですが*9sample.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 ===
      (略)

IPA音響モデルで試す

  • IPA音響モデル に差し替えて実行してみましょう。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混合、各種トライフォンモデルがあります。*10 菊池先生の自動ラベリングでは monof/mix16/gid を使っています。*11トライフォンよりモノフォンのほうが精度がいいようです。*12詳しくは 菊池, 前川, 五十嵐, 米山, 藤本, 2003 を参照。
  • コマンドラインで以下を実行します。
    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のサンプルデータで試す

  • .wavファイルと.transファイルがあれば音素の自動ラベリングができます。
  • ただし以下に注意
    • 長すぎる.wavファイルは処理できないため、無声部「#」で区切って別々の.wavと.transを作る必要があります。
    • 音素の記述はIPA音響モデルの形式(phone_m/parms/monophones)に準拠する必要があります。
      • 無音を表す記号は3種類あり、.transの文頭に"/silB/"、文末に"/silE/"を記述する必要があります。"/sp/"は無音区間と判断された場所に自動的に付加されるので、.transで記述する必要はない(はず)です。 /sp/は発話中のショートポーズ(参考)で、音素自動ラベリングでは明記する必要があります。*13
      • モーラ表は「IT Text 音声認識システム」の p.45 などを参照。*14
  • ちなみに、スピーチの内容
    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 アノ)
    申し訳ございませんが               & モーシワケゴザイマセンガ
    ミススペルが                       & ミススペルガ
    ございまして                       & ゴザイマシテ
segmentation02.png
  • 今回は手動で必要なファイルを揃えます。
  • まずは、「#」記号の開始時間~終了時間の間のどこかで .wav を分割します。
    • A06F0075_short_1.wav A06F0075_short_2.wav
    • 「ハイ」と「エーソレデワハジメサセテイタダキマス」の間にも発話の区切りがあるのですが、「ハイ」が短いので、今回はまとめて一つのファイルにしました。
  • 続いて、.TextGridの音素ラベルを横に並べて.transフォーマットのテキストファイルを作ります。
    • .TextGridファイルをPraatで読み込んで、以下のPraatスクリプトを実行して、実行結果のファイルから「'」と「# 」を除外すると良いでしょう(JULIUS/ のところは書き換えて下さい)。
      # ファイルを読み込む
      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
      ※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 もやってみて下さい。

分析パラメータを変更する

  • 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";

フレーム数データを時間データに変換する

  • 最後に、.trans.align 形式ファイルで出力された開始・終了フレーム数の情報を、時間情報に変換する方法について説明します。
    • Juliusのデフォルト設定 では、サンプリング周波数(smpPeriod period)は16,000Hz*15、フレームサイズ(窓サイズ、fsize sample)は400サンプル、フレームシフトサイズ(fshift sample)は160サンプルです。*16
    • 上記より1サンプルの時間長は 1/16000秒 なので、フレームサイズの時間長は以下のように求められます。
      400サンプル = (1 / 16000) * 400 = 1 / 40 [秒] = 25 [ミリ秒]
    • フレームシフトサイズの時間長は以下のようになります。
      160サンプル = (1 / 16000) * 160 = 1 / 100 [秒] = 10 [ミリ秒]
    • イメージ図
      julius_framesize.png
    • したがって、例えば .trans.align ファイルの開始・終了フレームが [1 3] になっていたら、「第1フレームの開始から第3フレームの終わりまで」という意味なので、開始時間は 「フレームシフトサイズ × フレーム番号 = 10 * 1 = 10 [ミリ秒]」になります。終了時間は「フレームシフトサイズ × フレーム番号 + フレームサイズ = 10 * 3 + 25 = 55 [ミリ秒]」になります。
      • 【備考】(1)実際のファイルの総時間、(2).trans.align で書き出されるファイル総時間(ALIGNMENT RESULT部)、(3)上記の計算で求まる最終音素の終了時間、は一致しません。(2)は小数第三位で四捨五入するため、(3)はフレームで切り出した結果余った最後の部分が分析されないためです。
      • 【備考】上記の計算だと、前の音素の終了時間のほうが、後の音素の開始時間よりも遅れるため、Praat等で処理する際に不都合です。その場合、終了時間を単に「フレームシフトサイズ × フレーム番号」とみなします。*17
    • 以上を自動化して、Praat標準の形式で書き出すperlスクリプト filetransalign2textgrid.pl
  • A06F0075_short_1.trans.align を時間情報に変えてみましょう。Excelを活用すると良いでしょう。

*1 本ページの内容は 理研コーパス班自動ラベリング勉強会 の資料をまとめなおしたものです。
*2 Copyright (c) 1991-2009 京都大学 河原研究室, Copyright (c) 1997-2000 情報処理振興事業協会(IPA), Copyright (c) 2000-2005 奈良先端科学技術大学院大学 鹿野研究室, Copyright (c) 2005-2009 名古屋工業大学 Julius開発チーム
*3 Praat 形式。それ以外の形式も提供されています。どのような形式でも良いのですが、本ページでは説明の都合上、Praat標準のを使用します。
*4 国際音声記号の略称もIPAですが、別物です。
*5 IPA音響モデルと呼ばれています。これは情報処理振興事業協会(IPA)の「日本語ディクテーション基本ソフトウェア99年度版」プロジェクトの成果物で、日本音響学会 新聞記事読み上げ音声コーパス(JNAS)から作られた音響モデルです。モデルの構築手順の詳細は JNAS CDROMからIPA音響モデルの作成法を参照して下さい。菊池, 前川, 五十嵐, 米山, 藤本, 2003. によれば、「読み上げ音声の音素自動ラベリングには一般的にIPAモデルが用いられる。CSJにおいては講演音声に対してもこの音響モデルが最も有効であった」とのこと。なお、音響モデルは自分で作ることもできます(参照)。
*6 MiyazawaがTextGridのテキストを整形するために作ったツールがJavaで動くというだけですので、テストデータを試すだけなら不要です。なお、コマンドラインで「javac」と入れてみてエラーが出たら未インストール状態です。
*7 「'C:'は、内部コマンドまたは外部コマンド~」エラーが出て実行できず。
*8 相対パスは「'.'は、内部コマンドまたは外部コマンド~」エラーが出て実行できず。
*9 Linux環境では.alignにも書き出されるようです。
*10 モノフォンは音素1種類について1つのモデルが対応します。トライフォンは前後の音素の組み合わせが違うものは全て別の音素のモデルとして扱います。
*11 gidは性別非依存モデル。femaleでもgidでもあまり精度の差はないとのこと。理研日本語母子会話コーパスの話者は全員女性なので、今回の説明ではfemaleを使用しています。
*12 なぜmonophoneの方が精度が良いのかについては、当時学会で議論していろいろな解釈がありましたが、どの解釈が最も適切かまではわかりませんでした by菊池先生
*13 Juliusにおける入力の無音区間・休止の扱い/自動アラインメント機能との関係 によれば、"sp" の挿入/非挿入の自動推定も可能?未確認です。
*14 Juliusの孤立単語認識キット に付属している make_dict.pl を使えば、モーラ(ひらがな)表記からIPA音響モデル形式の音素表記に自動変換してくれます。このページではTextGridから手動で音素表記を作るため、make_dict.pl は使用しません。
*15 1秒あたり16,000個(サンプル)のデータがあるということです
*16 MFCCパラメータの設定 - Julius によれば、Juliusの音響解析パラメータは音響モデルの設定と合わせる必要があるため、勝手に変えるべきではありません。Juliusの設定はHTKによる音響モデル構築のデフォルト設定と合わせているようです。
*17 自動ラベリングの結果を人手で修正する場合などは、この対処で十分です。その際、一度自動ラベリング結果を(Praat標準の形式に変換するなどして)視認して、系統的にずれていることがなければ、問題がないとみなしてかまいません(菊池先生のご指摘による)