LoginSignup
5
2

More than 5 years have passed since last update.

Kaldiに関する処理を日本語のドキュメントでまとめてみた(特徴量抽出編)3

Last updated at Posted at 2015-04-15

前回

1:http://qiita.com/GushiSnow/items/cc1440e0a8ea199e78c5

2:http://qiita.com/GushiSnow/items/a24cad7231de341738ee

スクリプト解説の続きです。

MFCC特徴量を抽出します。

MFCC
音声認識に必要な特徴量を取得する処理。

解説記事
http://recognition.web.fc2.com/tips/mfcc.html

for x in train test; do                                                     
  steps/make_mfcc.sh --cmd "$train_cmd" --nj $njobs \                        
  data/$x exp/make_mfcc/$x $mfccdir || exit 1;                                
  steps/compute_cmvn_stats.sh data/$x exp/make_mfcc/$x $mfccdir || exit 1;   
done

上記のスクリプトを動作させることで、MFCC特徴量を出力することが可能

1:データが正しいかを調査

check_sorted_and_uniq $data/utt2spk

ユーザーの発話が対応しているファイルが正しいか判断

check_sorted_and_uniq $data/spk2utt  

話者と発話が正しいかを判断

num_utts=`cat $tmpdir/utts | wc -l`
if [ -f $data/text ]; then
  check_sorted_and_uniq $data/text
  text_len=`cat $data/text | wc -l`
  illegal_sym_list="<s> </s> #0"
  for x in $illegal_sym_list; do
    if grep -w "$x" $data/text > /dev/null; then
      echo "$0: Error: in $data, text contains illegal symbol $x"
      exit 1;
    fi
  done
  awk '{print $1}' < $data/text > $tmpdir/utts.txt
  if ! cmp -s $tmpdir/utts{,.txt}; then
    echo "$0: Error: in $data, utterance lists extracted from utt2spk and text"
    echo "$0: differ, partial diff is:"
    partial_diff $tmpdir/utts{,.txt}
    exit 1;
  fi
fi

ユーザーの発話とテキストが一致しているかをチェック、もし一致していない場合は不一致の部分を出力

if [ -f $data/wav.scp ]; then
  check_sorted_and_uniq $data/wav.scp

  if [ -f $data/segments ]; then

    check_sorted_and_uniq $data/segments
    # We have a segments file -> interpret wav file as "recording-ids" not utter
ance-ids.
    ! cat $data/segments | \
      awk '{if (NF != 4 || ($4 <= $3 && $4 != -1)) { print "Bad line in segments
 file", $0; exit(1); }}' && \
      echo "$0: badly formatted segments file" && exit 1;

    segments_len=`cat $data/segments | wc -l`
    if [ -f $data/text ]; then
      ! cmp -s $tmpdir/utts <(awk '{print $1}' <$data/text) && \
        echo "$0: Utterance list differs between $data/text and $data/segments "
 && \
        echo "$0: Lengths are $segments_len vs $num_utts";
    fi

    cat $data/segments | awk '{print $2}' | sort | uniq > $tmpdir/recordings
    awk '{print $1}' $data/wav.scp > $tmpdir/recordings.wav
    if ! cmp -s $tmpdir/recordings{,.wav}; then
      echo "$0: Error: in $data, recording-ids extracted from segments and wav.scp"
      echo "$0: differ, partial diff is:"
      partial_diff $tmpdir/recordings{,.wav}
      exit 1;
    fi

1:セグメントファイルが正常データかを判定
2:セグメントファイルのフォーマットが適切かを判定
3:セグメントとテキストを比較
4:セグメントファイルのidとwavファイルのidが一致するかを見る。

    if [ -f $data/reco2file_and_channel ]; then
      # this file is needed only for ctm scoring; it's indexed by recording-id.
      check_sorted_and_uniq $data/reco2file_and_channel
      ! cat $data/reco2file_and_channel | \
        awk '{if (NF != 3 || ($3 != "A" && $3 != "B" )) { 
                if ( NF == 3 && $3 == "1" ) {
                  warning_issued = 1;
                } else {
                  print "Bad line ", $0; exit 1; 
                }
              }
            } 
            END {
              if (warning_issued == 1) {
                print "The channel should be marked as A or B, not 1! You should change it ASAP! "
              }
            }' && echo "$0: badly formatted reco2file_and_channel file" && exit 1;
      cat $data/reco2file_and_channel | awk '{print $1}' > $tmpdir/recordings.r2fc
      if ! cmp -s $tmpdir/recordings{,.r2fc}; then
        echo "$0: Error: in $data, recording-ids extracted from segments and reco2file_and_channel"
        echo "$0: differ, partial diff is:"
        partial_diff $tmpdir/recordings{,.r2fc}
        exit 1;
      fi
    fi
  else
    # No segments file -> assume wav.scp indexed by utterance.
    cat $data/wav.scp | awk '{print $1}' > $tmpdir/utts.wav
    if ! cmp -s $tmpdir/utts{,.wav}; then
      echo "$0: Error: in $data, utterance lists extracted from utt2spk and wav.scp"
      echo "$0: differ, partial diff is:"
      partial_diff $tmpdir/utts{,.wav}
      exit 1;
    fi

    if [ -f $data/reco2file_and_channel ]; then
      # this file is needed only for ctm scoring; it's indexed by recording-id.
      check_sorted_and_uniq $data/reco2file_and_channel
      ! cat $data/reco2file_and_channel | \
        awk '{if (NF != 3 || ($3 != "A" && $3 != "B")) { print "Bad line ", $0; exit 1; }}' && \
        echo "$0: badly formatted reco2file_and_channel file" && exit 1;
      cat $data/reco2file_and_channel | awk '{print $1}' > $tmpdir/utts.r2fc
      if ! cmp -s $tmpdir/utts{,.r2fc}; then
        echo "$0: Error: in $data, utterance-ids extracted from segments and reco2file_and_channel"
        echo "$0: differ, partial diff is:"
        partial_diff $tmpdir/utts{,.r2fc}
        exit 1;
      fi
    fi
  fi
fi

1:音声ファイルとチャネルのチェックを行う(ユニークでソートされているか)
2:セグメントファイルと音声ファイルのidを抽出し、合致しているかを確認する。
3:レコードファイルがソートされているかユニークかをチェックする。
4:セグメントファイルとレコードファイルのidを抽出し、合致しているかを確認する。

-f $data/feats.scp #特徴量
-f $data/cmvn.scp #cmvn
-f $data/spk2gender #話者の性別
-f $data/spk2warp #不明
-f $data/utt2warp #不明
-f $data/$f         #その他データ

特徴量とcmvn、話者の性別などをチェックしたい場合は下記オプションを追加する必要あり

for n in $(seq $nj); 
do                   
    # the next command does nothing unless $mfccdir/storage/ exists, see      
    # utils/create_data_link.pl for more info.                                
    utils/create_data_link.pl $mfccdir/raw_mfcc_$name.$n.ark                  
 done      

2:シンボリックリンクの作成を行う。

for n in $(seq $nj); do
  # the next command does nothing unless $mfccdir/storage/ exists, see
  # utils/create_data_link.pl for more info.
  utils/create_data_link.pl $mfccdir/raw_mfcc_$name.$n.ark
done

3:mfccファイルの作成を行う。

セグメントありかなしかでオプションがつくかどうかが異なる。

#セグメントあり
if [ -f $data/segments ]; then
  echo "$0 [info]: segments file exists: using that."

  split_segments=""
  for n in $(seq $nj); do
    split_segments="$split_segments $logdir/segments.$n"
  done

#scpファイルを分割 
  utils/split_scp.pl $data/segments $split_segments || exit 1;
  rm $logdir/.error 2>/dev/null

  $cmd JOB=1:$nj $logdir/make_mfcc_${name}.JOB.log \
    extract-segments scp,p:$scp $logdir/segments.JOB ark:- \| \
    compute-mfcc-feats $vtln_opts --verbose=2 --config=$mfcc_config ark:- ark:- \| \
    copy-feats --compress=$compress ark:- \
      ark,scp:$mfccdir/raw_mfcc_$name.JOB.ark,$mfccdir/raw_mfcc_$name.JOB.scp \
     || exit 1;
#セグメントなし
else
  echo "$0: [info]: no segments file exists: assuming wav.scp indexed by utterance."
  split_scps=""
  for n in $(seq $nj); do
    split_scps="$split_scps $logdir/wav_${name}.$n.scp"
  done

  utils/split_scp.pl $scp $split_scps || exit 1;


  # add ,p to the input rspecifier so that we can just skip over
  # utterances that have bad wave data.

  $cmd JOB=1:$nj $logdir/make_mfcc_${name}.JOB.log \
    compute-mfcc-feats  $vtln_opts --verbose=2 --config=$mfcc_config \
     scp,p:$logdir/wav_${name}.JOB.scp ark:- \| \
      copy-feats --compress=$compress ark:- \
      ark,scp:$mfccdir/raw_mfcc_$name.JOB.ark,$mfccdir/raw_mfcc_$name.JOB.scp \
      || exit 1;
fi

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2