6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

深層学習以外の機械学習と応用技術 by QuantumCoreAdvent Calendar 2019

Day 17

[QoreSDK]人工知能はハーモニカの種類を聞き分けられるのか?

Last updated at Posted at 2019-12-16

はじめに

みなさんこんばんは。
Qiitaユーザーの中で最もハーモニカの所有数の多い男(推定)ことkon2です。

harmonicastrim.jpg

日々いろんなハーモニカを吹いていて、思うんですよね。
実際、メーカーや機種ごとに音、変わんなくない? って。

そう思って、同じリフを8つのハーモニカで録音してみました。

う~ん・・・。
録音を聞く限りでは、正直あんまりわからない・・・。

本当に違いがあるのか確かめるために、人工知能(QuantumCoreのQoreSDK)にこの2つのリフを聞き分けてもらいます。
ちなみにQoreSDKを使ったまじめな記事は下にあります。こっちも見てね!

QoreSDKを使ってリチウムイオン電池の劣化を予測してみた

今回の内容も全部(音源も含めて)GitHubに投稿してます!

データ概要

学習用データには2種のハーモニカ(SuzukiのManjiとHohnerのMarineBand)の以下の演奏を、

  • Walles Coleman's Liff (29 sec)
  • SecondLine Intro (12 sec)
  • Juke Intro (23 sec)
  • The Sailor & The Maid Intro (12 sec)

テスト用データは以下の演奏の別テイクを使います。

  • Walles Coleman's Liff (29 sec)

#トレーニングデータの読み込み

以下のように、Manjiによる演奏のデータを取り込みます。

path = glob.glob('./train/Manji/*.wav')
dataset = []
shapes = []
for p in path:
    sound = AudioSegment.from_file(p)
    data = np.array(sound.get_array_of_samples())
    dataset.append(data)

取り込んだデータを可視化するとこんな感じです。

fig = plt.figure(figsize=(12,5))
plt.subplots_adjust(hspace=0.35)
for i in range(4):
    plt.subplot(2,2,i+1)
    plt.title(path[i])
    x_range = np.linspace(0,dataset[i].shape[0]-1,dataset[i].shape[0])
    plt.plot(x_range/44100,dataset[i])

ダウンロード (56).png

よく見る感じのデータになってますね。
ちなみにMarineBandの演奏はこちら。

ダウンロード.png

やっぱよくわかんない。
とりあえず4つしかデータがないのではよくないので、以下の関数で各演奏をだいたい1秒ごと(44000サンプルごと)に分割して、まとめます。

# decは正解ラベル。0 or 1の値を入力。
def SplitTune(dataset,dec,width = 44000):
    print('Width:',width)
    dataset_separate = []
    for n,d in enumerate(dataset):
        start = int(d.shape[0]*0.01)
        end = int(d.shape[0]*0.99)
        num = int((end-start)/width)
        print(start,end,num)
        for i in range(num):
            hoge = d[(start+(i*width)):(start+(i*width))+width]
            if(len(hoge) == width):
                dataset_separate.append(hoge)
            else:
                pass
    dataset_separate = np.array(dataset_separate)
    answer = np.zeros(dataset_separate.shape[0])+dec
    print('Shape of separated dataset:',dataset_separate.shape)
    return(dataset_separate,answer)

正解データ(y_train)は、0がManji, 1がMarineBandに対応するようにします。

X_train_manji,y_train_manji = QoreTrain.SplitTune(dataset,dec=0)

テストデータの読み込み

トレーニングデータの読み込みと同様です。
今回は、別テイクのWallas Coleman's Riffを使います。
可視化するとこんな感じ。この2つを同様に44000サンプルで分割して、それぞれ分類します。

ダウンロード (1).png

このリフ、昔はYouTubeで公開されていたんですが、今は非公開になっちゃったんですよね。
かわりに同じ人物の超かっこいい演奏を貼っておきます。
https://www.youtube.com/watch?v=aMHjCT9Y2bs

データの前処理

パラメータを除けば、ほぼ以下の記事と同様です。
QoreSDKの紹介とQoreで不整脈検出

まず、トレーニング用、学習用データをそれぞれまとめます。
ついでに次元も確認。

X_train = np.vstack((X_train_manji,X_train_marine))
y_train = np.hstack((y_train_manji,y_train_marine))
print('X_train.shape:', X_train.shape)
print('y_train.shape:', y_train.shape)

>> X_train.shape: (157, 44000)
>> y_train.shape: (157,)

X_test = np.vstack((X_test_manji,X_test_marine))
y_test = np.hstack((y_test_manji,y_test_marine))
print('X_train.shape:', X_test.shape)
print('y_train.shape:', y_test.shape)

>>X_train.shape: (58, 44000)
>> y_train.shape: (58,)

まずは、この細切れにした音声データを、さらに分割します。

width = 11000
stepsize = 2000
X_train = sliding_window(X_train, width, stepsize)
X_test = sliding_window(X_test, width, stepsize)
print('X_train.shape:', X_train.shape)
print('X_test.shape:', X_test.shape)

>> X_train.shape: (157, 17, 11000)
>> X_test.shape: (58, 17, 11000)

その後、qore_sdk.utilsのFeaturizerを使って、分割されたそれぞれのデータから20次元の特徴量を抽出します。

n_filters = 20
featurizer = Featurizer(n_filters)
X_train = featurizer.featurize(X_train, axis=2)
X_test = featurizer.featurize(X_test, axis=2)
print('X_train.shape:', X_train.shape)
print('X_test.shape:', X_test.shape)

>> X_train.shape: (157, 17, 20)
>> X_test.shape: (58, 17, 20)

QoreSDKを用いた学習

username, password, endpointは申請が必要です。
詳細は:point_down:
深層学習以外の機械学習と応用技術 by QuantumCore Advent Calendar 2019

client = WebQoreClient(username, password, endpoint
client.classifier_train(X_train, y_train)

まずはトレーニングデータがうまく学習できているかをsklearn.metricsのclassification_reportで検証します。

res = client.classifier_predict(X_train)
report = classification_report(y_train, res['Y'])
print(report)
>>              precision    recall  f1-score   support

         0.0       0.95      0.91      0.93        79
         1.0       0.91      0.95      0.93        78

   micro avg       0.93      0.93      0.93       157
   macro avg       0.93      0.93      0.93       157
weighted avg       0.93      0.93      0.93       157

とりあえず学習はできてる、かな?
ではテストデータでの検証です。

res = client.classifier_predict(X_test)
report = classification_report(y_test, res['Y'])
print(report)

>>              precision    recall  f1-score   support

         0.0       0.86      0.83      0.84        29
         1.0       0.83      0.86      0.85        29

   micro avg       0.84      0.84      0.84        58
   macro avg       0.85      0.84      0.84        58
weighted avg       0.85      0.84      0.84        58

F1スコアで0.84! これは結構いいんじゃないでしょうか?
少なくとも自分の耳よりは……。

では、分類結果を可視化してみます。
青色が演奏のうちハーモニカの機種を正しく見分けられた部分、赤色が見分けられなかった部分です。

ダウンロード (2).png
ダウンロード (3).png

1分ちょいのトレーニングデータで、人工知能(QoreSDK)にはハーモニカの機種が聞き分けられるみたいです。

まとめ

というわけで、ちょっとしたお遊びでした。
さすがQoreは音声処理が得意というだけあり、ちょっとのデータですが一応結果を出すことができました。
実際のところ学習はちょっと不安定で、うまくいったりいかなかったりなので、データを増やすかパラメータの調整が必要だと思います。
(そのためにももっと演奏のレパートリーを増やさなければ……)

20191214_040520997_iOS.jpg

将来的には8つのハーモニカ全部で多クラス分類でもやってみたいですね。
あと、木製ボディとプラスチックボディで違いはあるのかとか、リードの材質(真鍮 or ステンレス)を見分けられるのかとか、演奏者ごとの音色にどんな特徴があるのかとか、興味は尽きません。

今後もちまちまと遊びつつ、音響処理について勉強もしていきたいなと思います。

それでは~

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?