Python×医療事務(×トロント)

#医療 / #医療事務 / #IT / #トロント / #歯科助手 / #のんびり / #備忘録 / #趣味

Paiza で期間限定で Python×AI 機械学習入門が無料だったのでしてみた チャプター6  終了

SMCF使用していく

 

短時間フーリエ変換を利用し音声の各時間に対応したパワースペクトルを取得し特徴量として使用する

このようなパワースペクトルの時間変化の情報はパワースペクトグラムと呼ぶ

前回のチャプターのコードを短時間フーリエ変換に対応させていく

 

各インポート文を(Runで)実行

f:id:chocolate22554:20200922110632p:plain

特徴量を返すget_featが短時間フーリエ変換から得られたパワースペクトグラムを返すようにする

f:id:chocolate22554:20200922111001p:plain

通常のフーリエ変換のコードを削除しlibrosaのstftを使う

#特徴量を返す

def get_feat(file_name):

 a,sr = librosa.load(file_name)

 y=np.abs(librosa.stft(a))

 return y

#変更した関数の動作確認も兼ねてサンプル音声のパワースペクトグラムを描画をする

#getfeat内にパワースペクトグラムの描画処理を追加

f:id:chocolate22554:20200922115852p:plain

 

*1

 

 

Runで実行

f:id:chocolate22554:20200922122803p:plain

(このような下記の画像を今まで学習して見てきたことないのでワクワクです)

f:id:chocolate22554:20200922122841p:plain

f:id:chocolate22554:20200922122938p:plain

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)とは、描画する、点を打つなどの意味を持つということが分かってきました)

f:id:chocolate22554:20200922124220p:plain

 

 data_Xとdata_yを求めるgetdataの呼び出しはコメントアウトを解除しておきましょう

f:id:chocolate22554:20200922122240p:plain

そしてパワースペクトグラムはナムパイ配列として取得できるのでget dataのreturn文ではナムパイ配列に変換しないように修正する 

 returnの部分を  

 return(data_X,data_y)に変更

RUNで実行 画像のような行が出る

f:id:chocolate22554:20200922135715p:plain

データを教師データとテストデータに分離する  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))

f:id:chocolate22554:20200922140315p:plain

 

教師データを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])

f:id:chocolate22554:20200922140601p:plain

現在は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を押す。学習ができた。 

f:id:chocolate22554:20200922142441p:plain


学習ができたので予測部分に取り組む

教師データには1つの音声から作られた複数のパワースペクトラムを利用するようになったのでテストでも1つのテストデータから複数のパワースペクトラムを作ってパワースペクトラム毎にテストを行う。これによって複数の異なるテスト結果が得られるが多数決をとり1つの結果にまとめる

あとは(赤枠部分の)predict関数を使用するようにコードを修正すれば予測処理は完了

f:id:chocolate22554:20200922154041p:plain

           ⇩

f:id:chocolate22554:20200922154252p:plain


実行(RUN)する

f:id:chocolate22554:20200922154335p:plain

正解数は9となり前のチャプターの10と同じぐらいの精度で予測できた

精度はあまり変わらない

精度を上げるために別の方法を試す

これまでは音声の時間ごとの特徴量としてパワースペクトグラムを使用してきたが話者認識にはメル周波数ケプストラム係数(通称 MFCC)という特徴量が人の音声認識感覚と近く有効であると言われている

そこで特徴量をMFCCに変更して学習させる。get featで計算する特徴量をMFCCに変更する

f:id:chocolate22554:20200922155056p:plain

             ⇩

MFCCはパワースペクトログラムと同様の形式で時間ごとの特徴量を計算できるのでコードはこの1行だけ(と言っているが多分2行修正。 6行目をコメントアウトにし7行目にy=librosa.feature.mfcc(y=a,sr=sr を追加。)修正

f:id:chocolate22554:20200922155202p:plain

Run!(実行)

その下のセル  「教師データとテストデータの分離」をRun!(実行)

f:id:chocolate22554:20200922161025p:plain

その下のセル 「SVMで学習」  Run!(実行)

f:id:chocolate22554:20200922161217p:plain

⇩ その下のセル 「予測する(predict)」  Run!(実行)

f:id:chocolate22554:20200922161459p:plain

⇩  満点になった

f:id:chocolate22554:20200922161538p:plain

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に渡す

f:id:chocolate22554:20200922162806p:plain

RUN!(実行)

どの値も左側の振れ幅は大きいですが4つ目(hi)から差が出ているように見える

f:id:chocolate22554:20200922162928p:plain

f:id:chocolate22554:20200922162939p:plain

f:id:chocolate22554:20200922162951p:plain

f:id:chocolate22554:20200922163003p:plain

f:id:chocolate22554:20200922163012p:plain

それぞれの声優で特徴が出ている、機械的なhiとlo・声優の声では顕著に差が出ている

違いが多き程MFCCの値も大きく異なりMFCCが音声の違いをしっかり表していると視覚的・直感的にも分かる

 

 

まとめ

SVMを使って話者認識を行う度に音声の特徴量のいくつかを利用して実験を進めた

結果

生の音声波形データよりフーリエ変換を使って周波数ごとに構成を分けた特徴量を利用したほうがより高い予測精度が得られた

1つの音声ファイルから複数の特徴量を取得する方法も扱った

最終的にはMFCCを特徴量として利用すると最も良い予測の精度が得られた

但し表のデータはrandom_stateを11813、教師・テストデータを1パターンの組み合わせに固定した時の結果 よりフェアにするには複数の値を使ったほうが良い。またSVMのパラメーターにも調整の余地あり。

f:id:chocolate22554:20200922164810p:plain

 

 

感想

声優さんの声か 自分の知識が素人なので何個か上手く聞き取れない単語があった(3-4回聞きなおした単語も複数あり。パワースペクトグラム、パワースペクトラム 等何が正しいのか分からなくなった 調べてブログを書きなおしたい。)

特徴的な声とアニメで覚えやすい

AIacademy無料テキストを1周していたのでまだ理解できたが 忘れているかAIacademyのテキストを熟知していないので知らない単語がいくつか出てきた

ブログに記載したことで流すだけでなくじっくりアウトプットは出来た

ブログの情報としては補完したい点が山ほどあるので2-3周動画をやり直しコードを覚えるぐらいにブログを書きなおしたい

演習問題は比較的簡単だった

実践では音声データを自分が使いたい音声にすり替えた方法ですれば実践的にも使用できるのではないかと思う

本来の目的が もともと有料の講座なので無料の間に書き留めて復習に使いたいと思いブログに記載した。結果的に、期間限定だったが無料で受講できてよかった 1周目では物に出来ていないとヒシヒシと感じるので9/31までなのでそれまでに2周目を終えたい

*1:

#getfeatにhi.wavとlo.wavを与えるコードのコメントアウトを解除して実行

 

f:id:chocolate22554:20200922122240p:plain

 

 画像 最後の部分3行を下記のように変更

 

#data_X,data_y = get_data('voiceset')

 

get_feat('sample/hi.wav')

 

get_feat('sample/lo.wav')