はじめに

社内ハッカソン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値の判断モデルを作成する分類です。

SVM

今回は 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 のフレームワークです。

tensorflow

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]) # 未知の入力での予測

評価

評価をしたかったのですが… 流石にデータ数が足りず、どんな結果が出ても、判断することはどう考えてもムリゲーでした。 正直、データが少なすぎて過学習と言うか…同じ入力をいれたらそうなるってモデルになっている気がします。

感想

とにかくデータ量が必要な領域とはわかっていたが、勢いでやった。 データ量がちゃんとあるところでリベンジをしたいです。 ただ、誰か一人でも「この記事が参考になった」という方がおられましたら、とてもありがたいです。