人工知能に関する断創録

このブログでは人工知能のさまざまな分野について調査したことをまとめています(更新停止: 2019年12月31日)

SPTKの使い方 (6) MFCCの抽出

SPTKの使い方 (5)(2012/8/1)の続き。

今回は、音声認識の特徴量としてよく使われるメル周波数ケプストラム係数 MFCC(2012/2/25)をSPTKで抽出してみました。使うコマンドは、mfccです*1

x2x +sf < data.short| frame -l 640 -p 160 | \
mfcc -l 640 -f 16 -m 12 -n 20 -a 0.97 > data.mfc

パラメータの意味は、

-l 640 フレーム長は640サンプル
-f 16 サンプリング周波数は16kHz
-m 12 MFCCの次元は12次元
-n 20 メルフィルタバンクのチャンネル数は20
-a 0.97 プリエンファシス係数は0.97

です。まあ、-lと-fと-m以外はデフォルトでいいかな?mfccコマンドには、-c 22(リフタリング係数)というオプションもあったのですが、これは何だろう?私が認識していたMFCCの抽出手順は、

  1. プリエンファシスフィルタで波形の高域成分を強調する(-a)
  2. 窓関数をかけた後にFFTして振幅スペクトルを求める(-l, -f)
  3. 振幅スペクトルにメルフィルタバンクをかけて圧縮する(-n)
  4. 上記の圧縮した数値列を信号とみなして離散コサイン変換する
  5. 得られたケプストラムの低次成分がMFCC(-m)

だったのですが、リフタリングはどこでするのだろう・・・一番最後で低次成分をとるところなのかな?私の認識だとDCTしたあとに出てくる係数を単純に上から-m個とったもの(=低次成分のみ取り出す)がmfccだと思っているのだけど、それだと-cとはどこで使うのだろう?どなたか知ってたら教えてください。

先のコマンドを実行すると各フレームのMFCCが抽出されます。data.mfcはバイナリファイルなので文字列で出力するPythonスクリプトを書きました。

#coding:utf-8
import struct
import sys
import numpy as np

# print_mfcc.py

if len(sys.argv) != 3:
    print "usage: python print_mfcc.py [mfcc_file] [m]"
    sys.exit()

mfccfile = sys.argv[1]
m = int(sys.argv[2])

mfcc = []
f = open(mfccfile, "rb")
while True:
    b = f.read(4)
    if b == "": break;
    val = struct.unpack("f", b)[0]
    mfcc.append(val)
f.close()

mfcc = np.array(mfcc)
numframe = len(mfcc) / m

if numframe * m != len(mfcc):
    print "ERROR: #mfcc:%d #frame:%d m:%d" % (len(mfcc), numframe, m)
    sys.exit(1)

mfcc = mfcc.reshape(numframe, m)
for i in range(len(mfcc)):
    print "\t".join("%.2f" % x for x in mfcc[i,])

第二引数は、MFCCの次元数です。実行すると、

> python print_mfcc data.mfc 12
-11.75	-0.31	-6.73	0.24	4.32	3.89	-1.38	2.27	3.07	8.11	-0.63	-1.65
-12.45	0.51	-5.58	1.54	2.47	1.90	-1.73	2.38	7.31	8.20	-1.47	-2.40
-13.48	1.95	-3.17	4.40	4.20	1.41	-1.68	1.34	5.90	6.95	-0.02	-0.27
-14.92	5.96	-0.64	5.05	3.75	-0.11	-0.73	1.75	2.97	3.35	1.52	-1.77
・・・

こんな感じに各フレームのMFCCの12次元ベクトルが表示されます。各行がフレームです。

-Eオプションをつけると、MFCCに加えてエネルギーも出力することができます。MFCCの12次元+エネルギーで13次元ベクトルにするって設定はよく見かけますね。

x2x +sf < data.short| frame -l 640 -p 160 | \ 
mfcc -l 640 -f 16 -m 12 -n 20 -a 0.97 -E > data.mfc

表示してみます。

> python print_mfcc.py data.mfc 13
-11.75	-0.31	-6.73	0.24	4.32	3.89	-1.38	2.27	3.07	8.11	-0.63	-1.65	10.51
-12.45	0.51	-5.58	1.54	2.47	1.90	-1.73	2.38	7.31	8.20	-1.47	-2.40	11.07
-13.48	1.95	-3.17	4.40	4.20	1.41	-1.68	1.34	5.90	6.95	-0.02	-0.27	11.42
-14.92	5.96	-0.64	5.05	3.75	-0.11	-0.73	1.75	2.97	3.35	1.52	-1.77	11.75

13列目がエネルギーです。MFCCに比べて少し大きい値になってます。

音声認識では、MFCC12次元+エネルギーの13次元ベクトルにさらに動的特徴量としてΔMFCCの13次元とΔΔMFCCの13次元を加えて39次元ベクトルにすることが多いと思いますが、これはdeltaコマンドを使うとできます。SPTKのマニュアルのmfccコマンドのところにdeltaを使った例が書いてありました。これは別の機会に試してみます。

MFCCの抽出は、他にもHTKというツールキットのHCopyコマンドでもできました(MFCC解析のツール)が、SPTKの方が使うの簡単かも。というか、HCopyが出力するmfccのバイナリフォーマットがよくわからなかった・・・HTKのマニュアルに書いてあるのかな?

*1:例題集の3章にあるメルケプストラム(mcepコマンド)をMFCCと勘違いしていたのですが違うものでした・・・