はじめに
社内ハッカソン2017のマグナムトルネードチームです。
内容的には、音声データの機械学習を1日でどこまで出来るのかという実践記録です。
目標は「ある発声において、良い発声と悪い発声があるとした場合、未知の発声の正否判定ができるか?」という点です。
音声の題材はチーム名から察してください。
作業内容
- データ作成
- 良いデータと悪いデータの仮定を議論
- 特徴点抽出
- mfcc
- 機械学習
- SVM
- DeepLeaning
- 評価
データ作成
データをさくせいするだ 、とにかくデータをさくせいするだ 。。。
- 動画データより音声データを抜き出し、元データを作成
- 約 2 ~ 3 秒のデータ
- 良い、悪いという判定をするためにラベル付け
- 話数が小さい時の発声は、話数が大きい時の発声に比べて習熟度が小さい
- 本編に使われているものは正、モノマネは負
- など
作成したデータ数は20件です。この時点で( ry
特徴点抽出 mfcc
今回は、音声認識の特徴量として、一般的な メル周波数ケプストラム係数 というものを利用しています。
この特性としては「人間の音声知覚の特徴を考慮した尺度」=メル尺度というものらしく、音声認識の解説記事などでは比較的メジャーな尺度です。
python のライブラリとか割りと実装しなくてもなんとかなります(なりました)。
- scipy
- scikits.talkbox.features の mfcc
mfcc へ変換(最小限サンプル)
import os import numpy import scipy from scipy import io from scipy.io import wavfile from scikits.talkbox.features import mfcc input="XXXX.wav" output="XXXX.wav.ceps" rate,audio = io.wavfile.read(input) ceps,mspec,spec = mfcc(audio) numpy.save(output,ceps) print ceps print numpy.mean(ceps[:],axis=0) # 簡単化の為、平均を利用します 次元は減らさない
機械学習 SVM
SVM は、与えられたデータ(教師データ)から2値の判断モデルを作成する分類です。
今回は pyothon の sklearn を利用して実験しました。
学習サンプル
from sklearn.metrics import confusion_matrix from sklearn.svm import LinearSVC from sklearn.utils import resample from sklearn import svm INPUT,LABEL = [],[] # INPUT = [ 13要素 ceps, ... ] => [[1, ... 13], ...] # LABEL = [ "OK", "NG", ] # numpy で File を読み込み、配列データにする # LABEL はそれぞれ 正負など sv = svm.SVC(kernel='rbf') # SVM 学習 sv.fit(INPUT,LABEL) # 実際の学習 prediction = sv.predict(numpy.array([ceps,...)) # 未知データを入れて print prediction # 予知結果
機械学習 tensorflow
tensorflow とは、 google が開発している、 deepLearning のフレームワークです。
tflearn は tensorflow のラッパーです。 細かい調整はできないかもしれないですが、 導入やとにかく使ってみたい場合、かなり楽にできるはずです。
今回は tflearn を利用して実験しました。
学習サンプル
import tflearn import tensorflow as tf INPUT,LABEL = [],[] # INPUT = [ 13要素 ceps, ... ] => [[1, ... 13], ...] # LABEL = [ ["OK"], ["NG"], ] # numpy で File を読み込み、配列データにする # LABEL はそれぞれ 正負など net = tflearn.input_data(shape=[None, 13]) net = tflearn.fully_connected(net, 13, activation='sigmoid') net = tflearn.fully_connected(net, 1, activation='sigmoid') net = tflearn.regression(net, optimizer='sgd', learning_rate=2., loss='mean_square') # すいません、層の構築は適当にやってしまっています model = tflearn.DNN(net) model.fit(INPUT, LABEL, n_epoch=20000, snapshot_epoch=False) # 学習 print model.predict([test_ceps]) # 未知の入力での予測
評価
評価をしたかったのですが… 流石にデータ数が足りず、どんな結果が出ても、判断することはどう考えてもムリゲーでした。 正直、データが少なすぎて過学習と言うか…同じ入力をいれたらそうなるってモデルになっている気がします。
感想
とにかくデータ量が必要な領域とはわかっていたが、勢いでやった。 データ量がちゃんとあるところでリベンジをしたいです。 ただ、誰か一人でも「この記事が参考になった」という方がおられましたら、とてもありがたいです。