【音声認識 超入門】 固定長音声データの分類

概要

以前から音声認識には興味があったので, その第一歩として, Yes と No の固定長の音声を機械学習を用いて分類しました. (どっちも2秒) 今回作成したソースコードはgithub上げときました.

環境

macOS, python3 (anaconda)

必要なものをインストールする.

portaudioとpyaudioをインストールする. ​​​​​​​

brew install portaudio
pip install pyaudio

他のOSの場合など詳しくはここを見てね. soundfileをインストールする.​​​​​​​

pip install soundfile​​​​​​​

データを作る

今回は自分の声を分類する分類器を作りたいから, 録音するプログラムから作りました. 録音するプログラムにimportしているrecorderのソースコードもgithubに上げたから気になったら見てください. 下のプログラムで連続して録音しました. (YesとNo, 20回ずつ)

import sys
import pyaudio
import wave

import recorder

cnt = 0
print('input prefix of output filename:')
fname = input()
print('input number to start with:')
cnt = int(input())
rec = recorder.WaveRecorder()
while True:
    print('Press enter to start recoding. Type end to finish recording.')
    if input() == 'end':
        break
    rec.record('{}_{}.wav'.format(fname, cnt))
cnt += 1

モデルの学習

分類器は, Random Forest, Gradient Boosting, Support Vector, KNNの4つを試しました. まず, それぞれのwaveデータから一次元データを作成し, くっつける.

n_datas = 20
X = []
y = []
for i in range(n_datas):
    no, _ = sf.read('no_{}.wav'.format(i))
    yes, _ = sf.read('yes_{}.wav'.format(i))
    no = no[:, 0] #2chで録音したので片方だけ取ってくる
    yes = yes[:, 0]
    X.append(no)
    X.append(yes)
    y.append(0) #Noはクラス0
    y.append(1) #Yesはクラス1

X = np.array(X)
y = np.array(y)

次に説明変数をFFTの絶対値と位相にする。

X_fft = np.array([np.fft.fft(x) for x in X])
X_fft = np.fft.fft(X)
X = np.array([np.hstack((x.real**2+x.imag**2, np.arctan2(x.real, x.imag))) for x in X_fft])

そしてcross_val_scoreで5分割して交差検証, 正答率を表示。

#ここをGradientBoostingClassifier(), SVC()やKNeighborsClassifier()に変える
clf = RandomForestClassifier()
scores = cross_val_score(clf, X, y, cv=5)
print('score:{:.3f} (+/-{:.3f})'.format(scores.mean(), scores.std()*2))

結果

Random Forest の結果は0.975 (+/-0.100), Gradient Boostingは1.000 (+/-0.000), SVCは0.700 (+/-0.339), KNNは0.675 (+/-0.436)でした. この結果から, Gradient Boostingが最も良いと考えられます. データ数がそれぞれ20個ずつしか無いのに思ったより精度が高かったです.

この理由は,

・ 分類クラスが2クラスだけ

・ 雑音がほぼなかった

・ trainもtestも自分の声しか入っていないので周波数とか似てる

だと思います. 実行するとわかると思いますが, Gradient Boostingは3手法の中では1番学習に時間がかかっています. 学習時, 全ての弱分類器が独立でないBoostingという手法を使っているのが原因だと考えられます. ただ, 学習には時間がかかっても, 実際に使うときには短時間で計算できるため, これを使っても問題はないです.

遊び

実際に学習したモデルで, 新たに録音した音声を分類させてみる.

#全データで学習
clf.fit(X, y)

rec = recorder.WaveRecorder()
yesno = ['No', 'Yes']
while True:
    print('Press enter to start recording. Type end to finish recording.')
    if input() == 'end':
        break

    rec.record('output.wav')
    wav, _ = sf.read('output.wav')
    wav = np.array(wav[:, 0])
    wf = np.fft.fft(wav)
    wav = np.hstack((wf.real**2+wf.imag**2, np.arctan2(wf.real, wf.imag)))
    pred = clf.predict(np.array([wav]))
    print(yesno[int(pred)])

実行すると次のようになった.

* recording
* done recording
Yes
Press enter to start recording. Type end to finish recording.

* recording
* done recording
Yes
Press enter to start recording. Type end to finish recording.

* recording
* done recording
No
Press enter to start recording. Type end to finish recording.

* recording
* done recording
No
Press enter to start recording. Type end to finish recording.

* recording
* done recording
Yes
Press enter to start recording. Type end to finish recording.

* recording
* done recording
No
Press enter to start recording. Type end to finish recording.
end

Yes, Yes, No, No, Yes, Noの順に発声したので全て正しく分類されていました. この程度のデータ数で自分の声だけならこれだけちゃんとできるのであれば, 家電とか声で操作するの一から作ってもそこまで難しくないかも!?

プログラミング未経験からでもAIスキルが身につくAidemy Premium




PythonやAIプログラミングを学ぶなら、オンライン制スクールのAidemy Premiumがおすすめです。
「機械学習・ディープラーニングに興味がある」
「AIをどのように活用するのだろう?」
「文系の私でもプログラミング学習を続けられるだろうか?」
少しでも気になることがございましたら、ぜひお気軽にAidemy Premiumの【オンライン無料相談会】にご参加いただき、お悩みをお聞かせください!