見出し画像

ガバキックの将来を予測する

こんにちは、Quarkです。

突然ですが、ガバキックの将来って気になりませんか?


画像1

ガバキックに限らずですが、これ以上音源が伸びない時、「この音源に続きがあれば・・・クソッ!」ってなる時、あると思います。

この続き、予測できるんじゃないかなと思ったのでやってみました。


データを用意する

まずはデータが必要です。データは、私が以前オーディオで書き出して、以降続きのないガバキックを使います。

音はこんな感じです。



Pythonで音声ファイルを読み込み、数値の配列に変換します。

import wave
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

gabbakick = wave.open('gabbakick test.wav','r')
buf = gabbakick.readframes(gabbakick.getnframes())

data = np.frombuffer(buf, dtype='int16')
with mpl.rc_context():
   mpl.rc('figure', figsize=(20, 5))
   plt.plot(data)
   plt.title('ガバキック')


波形を表示します。これの将来を予測します。

ガバキック_画像


音源の続きのことを「将来」と言っているのは、音の波形も周期性があり、時系列予測と同じ形で予測できるからです。


学習させる

予測するにあたって用いるデータ箇所ですが、下記画像の水色+黄色の部分を用いて、赤の部分を予測したいと思います。

予測・学習には、LightGBMを使います。くわしくはGistにコードをアップしているので、気になる方は見てみてください。

予測箇所


データは、自己回帰的なことをさせるためにガバキックデータ配列のt列目に対して、-1t~-5000tまでのラグを取得し、追加します。

import pandas as pd
df = pd.DataFrame(data)[15000:].reset_index(drop=True)

#5000回ほどずらしていく
def columns_shift(df, shift_number):
   df_list = []
   df_list.append(df)
   for i in range(1, shift_number + 1):
       shift_column_name = int('-' + str(i))
       df_list.append(df.shift(i).rename(columns={0:shift_column_name}))
   return pd.concat([df_list[d] for d in range(len(df_list))], axis=1)
   
df_1 = columns_shift(df, 5000)
df_2 = df_1.dropna().reset_index(drop=True)

画像の0列目データがtです。

画像4


まずは、精度を確認・学習させるために、水色部分のデータを用いて、黄色部分のデータを予測します。

import lightgbm as lgb
y = 0 #目的変数
x = df_2.drop(0, axis=1).columns #説明変数

#時系列データなので、一旦テストでindex 10000~以降を予測して、精度をチェックする
train_x = df_2[x][:10000]
train_y = df_2[y][:10000]
valid_x = df_2[x][10000:]
valid_y = df_2[y][10000:]

lgb_train = lgb.Dataset(train_x, train_y)
lgb_valid = lgb.Dataset(valid_x, valid_y)
params = {
   'n_jobs': -1,
   'max_depth': 7,
   'task':'train',
   'boosting_type':'gbdt',
   'metric':'rmse',
   'learning_rate': 0.01,
   'feature_fraction': 0.8,
   'bagging_fraction': 0.8,
   'objective': 'regression_l1'
}
model = lgb.train(params, lgb_train, num_boost_round=4000, valid_sets=[lgb_train, lgb_valid], early_stopping_rounds=100, verbose_eval=100)

test_pred_y = model.predict(valid_x)


赤線が学習させて、予測した結果です。ぱっと見、結構合ってますね。

トレーニング結果

精度は、R2_scoreで0.993,RMSEで1561.01です。とても良いと思います。

トレーニングデータ精度


小ネタですが、今回の波形は、周期的に[-2t,-4040t,-2020t,-4042t,-1t,-4044t]あたりが、予測精度の向上に貢献しているみたいですね。このあたりは、フーリエ変換の際の高周波成分と結び付けられそうですね。

予測精度向上パラメータ


予測する

学習が終了したので、将来の波形を予測します。

tに対して-1t~-5000tのラグを用いているので、一気に波形の予測はできません。なので、流れとしては

次の波形1つ分を予測する予測結果を-1tとして用いるその次の波形1つを予測する→予測結果を-1tとして用いる→繰り返し

な形です。

def gabbakick_predict(predict_df, length):
   from tqdm import tqdm
   df_array = df[::-1].T.values[0]
   for i in tqdm(range(length)):
       predict_array = df_array[:5000].reshape(-1, 5000)
       predict_y = model.predict(predict_array)[0]
       df_array = np.insert(df_array, 0, predict_y) #df_arrayを上書き
   return df_array
   
predict_result = gabbakick_predict(df, 20000) #20000先まで、予測・-1tとして結合を繰り返す


結果

ガバキック将来予測結果

赤線の部分がLightGBMを用いて、ガバキックの将来を予測した部分です。

なんと、このガバキックの将来は若干減衰していくんですね!なるほど!(厳密にはすべての-1~-5000tが予測値で代替される以降の正確性はわからないです)

とりあえず、ガバキックの将来が予測できたので、書き出して聴いてみようと思います。


おお~違和感ないですね、ちょっと途中で「ジリッ」とした音が聞こえますが、これが逆にいい味を出しているかも。

今回はガバキックで行いましたが、割といろんな音に使えるかもしれないですね、これは。



ああ~!予測の音ォ~!!

いいなと思ったら応援しよう!