SMCF使用していく
短時間フーリエ変換を利用し音声の各時間に対応したパワースペクトルを取得し特徴量として使用する
このようなパワースペクトルの時間変化の情報はパワースペクトグラムと呼ぶ
前回のチャプターのコードを短時間フーリエ変換に対応させていく
各インポート文を(Runで)実行
特徴量を返すget_featが短時間フーリエ変換から得られたパワースペクトグラムを返すようにする
通常のフーリエ変換のコードを削除しlibrosaのstftを使う
#特徴量を返す
def get_feat(file_name):
a,sr = librosa.load(file_name)
y=np.abs(librosa.stft(a))
return y
#変更した関数の動作確認も兼ねてサンプル音声のパワースペクトグラムを描画をする
#getfeat内にパワースペクトグラムの描画処理を追加
Runで実行
(このような下記の画像を今まで学習して見てきたことないのでワクワクです)
2つの音声のパワースペクトグラムが描画された
この図では横軸に時間(Time) をとっており各時間の縦方向の成分が1つのパワースペクトルに対応している
動作確認ができたので描画の部分はコメントアウト
#plt.figure(figsize=(10,4))
#librosa.display.specshow(librosa.amplitude_to_db(y,ref=np.max),y_axis='log',x_axis='time',sr=sr)
#plt colorbar(format='%+2.0f dB')
#plt.tight_layout()
(コードを書いていて段々プロット(plot)とは、描画する、点を打つなどの意味を持つということが分かってきました)
data_Xとdata_yを求めるgetdataの呼び出しはコメントアウトを解除しておきましょう
そしてパワースペクトグラムはナムパイ配列として取得できるのでget dataのreturn文ではナムパイ配列に変換しないように修正する
returnの部分を
return(data_X,data_y)に変更
RUNで実行 画像のような行が出る
データを教師データとテストデータに分離する random_stateは基準となる11813に戻す
#教師データとテストデータに分ける
train_X,test_X,train_y,test_y =train_test_split(data_X,data_y,random_state=11813)
print("{} -> {},{}".format(len(data_X),len(train_X),len(test_X))
教師データをSVCに与えていく
#clf =svm.SVC(gamma=0.0001,C=1)
clf =svm.SVC(gamma=0.0000001,C=10)
clf.fit(train_X,train_y.T[0])
現在は1つのパワースペクトログラムを1つの特徴量として扱っているが1つのパワースペクトログラムから複数のパワースペクトルに分割してそれぞれを特徴量として学習させる
⇩
#各時間に対応する成分をそれぞれ1つの特徴量として分割する
def split_feat(data_X,data_y):
data_X2=
data_y2=
for X,y in zip(data_X,data_y):
X2=X.T
y2=np.array([y[0]]*X.shape[1])
data_X2.append(X2)
data_y2.append(y2)
data_X2 = np.concatenate(data_X2)
data_y2 =np.concatenate(data_y2)
return(data_X2,data_y2)
#train_Xとtrain_yをこの関数に与え新しい教師データとしてtrain_X2とtrain_y2に取り出す
train_X2,train_y2 =split_feat(train_X,train_y)
#gammma とCを基準となる値に戻し 基準となる教師データもtrain_y2 とtrain_X2に置き換える
(#)clf =svm.SVC(gamma=0.0001,C=1)
#clf =svm.SVC(gamma=0.0000001,C=10)
clf.fit(train_X,train_y.T[0])
Runを押す。学習ができた。
学習ができたので予測部分に取り組む
教師データには1つの音声から作られた複数のパワースペクトラムを利用するようになったのでテストでも1つのテストデータから複数のパワースペクトラムを作ってパワースペクトラム毎にテストを行う。これによって複数の異なるテスト結果が得られるが多数決をとり1つの結果にまとめる
あとは(赤枠部分の)predict関数を使用するようにコードを修正すれば予測処理は完了
⇩
実行(RUN)する
正解数は9となり前のチャプターの10と同じぐらいの精度で予測できた
精度はあまり変わらない
精度を上げるために別の方法を試す
これまでは音声の時間ごとの特徴量としてパワースペクトグラムを使用してきたが話者認識にはメル周波数ケプストラム係数(通称 MFCC)という特徴量が人の音声認識感覚と近く有効であると言われている
そこで特徴量をMFCCに変更して学習させる。get featで計算する特徴量をMFCCに変更する
⇩
MFCCはパワースペクトログラムと同様の形式で時間ごとの特徴量を計算できるのでコードはこの1行だけ(と言っているが多分2行修正。 6行目をコメントアウトにし7行目にy=librosa.feature.mfcc(y=a,sr=sr を追加。)修正
⇩
Run!(実行)
⇩
その下のセル 「教師データとテストデータの分離」をRun!(実行)
⇩
その下のセル 「SVMで学習」 Run!(実行)
⇩ その下のセル 「予測する(predict)」 Run!(実行)
⇩ 満点になった
MFCCを予測で使うと高い精度で予測ができた
音声ファイルごとのMFCCの様子をグラフに描画
音声ファイルごとの各mfccの平均値をとって描画するmeanplotを作成
#mfccを描画する
def mean_plot(mfccs,name):
print(name)
mean= np.mean(mfccs.T, axis=0)
plt.plot(range(0,len(mean)),mean)
plt.show()
各声優のhigh lowのファイルを1つずつ読み込んでmeanplotに渡す
RUN!(実行)
どの値も左側の振れ幅は大きいですが4つ目(hi)から差が出ているように見える
それぞれの声優で特徴が出ている、機械的なhiとlo・声優の声では顕著に差が出ている
違いが多き程MFCCの値も大きく異なりMFCCが音声の違いをしっかり表していると視覚的・直感的にも分かる
まとめ
SVMを使って話者認識を行う度に音声の特徴量のいくつかを利用して実験を進めた
結果
生の音声波形データよりフーリエ変換を使って周波数ごとに構成を分けた特徴量を利用したほうがより高い予測精度が得られた
1つの音声ファイルから複数の特徴量を取得する方法も扱った
最終的にはMFCCを特徴量として利用すると最も良い予測の精度が得られた
但し表のデータはrandom_stateを11813、教師・テストデータを1パターンの組み合わせに固定した時の結果 よりフェアにするには複数の値を使ったほうが良い。またSVMのパラメーターにも調整の余地あり。
感想
声優さんの声か 自分の知識が素人なので何個か上手く聞き取れない単語があった(3-4回聞きなおした単語も複数あり。パワースペクトグラム、パワースペクトラム 等何が正しいのか分からなくなった 調べてブログを書きなおしたい。)
特徴的な声とアニメで覚えやすい
AIacademy無料テキストを1周していたのでまだ理解できたが 忘れているかAIacademyのテキストを熟知していないので知らない単語がいくつか出てきた
ブログに記載したことで流すだけでなくじっくりアウトプットは出来た
ブログの情報としては補完したい点が山ほどあるので2-3周動画をやり直しコードを覚えるぐらいにブログを書きなおしたい
演習問題は比較的簡単だった
実践では音声データを自分が使いたい音声にすり替えた方法ですれば実践的にも使用できるのではないかと思う
本来の目的が もともと有料の講座なので無料の間に書き留めて復習に使いたいと思いブログに記載した。結果的に、期間限定だったが無料で受講できてよかった 1周目では物に出来ていないとヒシヒシと感じるので9/31までなのでそれまでに2周目を終えたい