【Python】機械学習用の時系列データを生成してみる

内容

機械学習の勉強をするためには学習・推論するためのデータが必要となります
今回はnumpyのsin関数を使って正常波形と異常波形の時系列データを生成してみます

さっそくコードを書いてみる

モジュールをインポートします

import numpy as np
import matplotlib.pyplot as plt

テストデータを生成してみます

#変数をいろいろ設定
sampling_frequency=100000 #サンプリング周波数
sampling_length=5000 #サンプリング点数
data_freq_main=1000 #データの主周波数
data_learn_num=500 #学習用生成データ数
data_test_num=50 #テスト用生成データ数
data_freq_abnomal=20000 #異常データ重畳周波数
data_amp_abnomal_1=0.05 #異常データ振幅レベル1
data_amp_abnomal_2=0.1 #異常データ振幅レベル2

#データ用配列を定義
data_nomal_learn=[] #学習用正常データ
data_nomal_test=[] #テスト用正常データ
data_abnomal_noise1=[] #高周波ノイズ レベル1
data_abnomal_noise2=[] #高周波ノイズ レベル2
data_abnomal_amp1=[] #振幅増加 レベル1
data_abnomal_amp2=[] #振幅増加 レベル2
data_abnomal_naa1=[] #高周波ノイズ + 振幅増加 レベル1
data_abnomal_naa2=[] #高周波ノイズ + 振幅増加 レベル2

#時間データ生成
timeline = np.arange(sampling_length)/sampling_frequency

#学習用データ生成
for i in range(data_learn_num):
    phase = np.random.rand()*2*np.pi
    nomal = np.sin(2*np.pi*data_freq_main*timeline + phase)
    white_noise = ((np.random.rand(len(timeline))-0.5) * 0.2)
    data_nomal_learn.append( nomal + white_noise)

#テスト用データ生成
for i in range(data_test_num):
    phase=np.random.rand()*2*np.pi
    phase_noise=np.random.rand()*2*np.pi
    nomal=np.sin(2*np.pi*data_freq_main*timeline + phase)
    white_noise = ((np.random.rand(len(timeline))-0.5) * 0.2)
    abnomal_noise = np.sin(2*np.pi*data_freq_abnomal*timeline + phase_noise)
    data_nomal = nomal + white_noise
    data_nomal_test.append(data_nomal)
    data_abnomal_noise1.append( data_nomal + abnomal_noise * data_amp_abnomal_1 ) 
    data_abnomal_noise2.append( data_nomal + abnomal_noise * data_amp_abnomal_2 ) 
    data_abnomal_amp1.append( data_nomal * (1+data_amp_abnomal_1))
    data_abnomal_amp2.append( data_nomal * (1+data_amp_abnomal_2))
    data_abnomal_naa1.append( data_nomal * (1+data_amp_abnomal_1) + abnomal_noise * data_amp_abnomal_1 )
    data_abnomal_naa2.append( data_nomal * (1+data_amp_abnomal_2) + abnomal_noise * data_amp_abnomal_2 ) 

生成データの確認をしてみます

plt.style.use(['default'])
plt.figure(figsize=(12,3))
plt.subplot(1,3,1)
plt.plot(timeline, data_nomal_learn[0])
plt.xlabel("time [sec]")
plt.ylabel("data")
plt.subplot(1,3,2)
plt.plot(timeline[:100], data_nomal_learn[0][:100])
plt.subplot(1,3,3)
plt.plot(timeline[:100], data_nomal_test[0][:100],label='nomal')
plt.plot(timeline[:100], data_abnomal_noise2[0][:100],label='noise')
plt.plot(timeline[:100], data_abnomal_amp2[0][:100],label='amp')
plt.legend()
plt.show()

生成結果

f:id:tech-foo:20220215200337p:plain
左が正常波形の全体データ、中央が正常波形の一部データ、右が正常波形と異常波形の一部データです。
なんとなく意図通りに生成できていることが確認できました



改良版

#変数をいろいろ設定
sampling_frequency = 100000 #サンプリング周波数
sampling_length = 5000 #サンプリング点数
data_train_num = 500 #学習用生成データ数
data_test_num = 50 #テスト用生成データ数

freq_nomal_low = 1000 #データの主周波数
freq_nomal_high = 15000 #正常データ重畳周波数
freq_abnomal = 11000 #異常データ重畳周波数
freq_shift_1 = 14000 
freq_shift_2 = 13000 

amp_nomal_low = 1.0 #正常データ振幅レベル
amp_nomal_high = 0.2 #正常データ振幅レベル
amp_white_noise = 0.2 #正常データ振幅レベル
amp_abnomal_noise_1 = 0.1 #異常データ振幅レベル1
amp_abnomal_noise_2 = 0.2 #異常データ振幅レベル2
amp_abnomal_level_1 = 0.5 #異常データ振幅レベル1
amp_abnomal_level_2 = 1.0 #異常データ振幅レベル2

#データ用配列を定義
data_raw_train=[] #学習用正常データ
data_raw_test={}
data_raw_test['nomal']=[] #テスト用正常データ
data_raw_test['noise_1']=[] #高周波ノイズ レベル1
data_raw_test['noise_2']=[] #高周波ノイズ レベル2
data_raw_test['amp_1']=[] #振幅増加 レベル1
data_raw_test['amp_2']=[] #振幅増加 レベル2
data_raw_test['noise_amp_1']=[] #高周波ノイズ + 振幅増加 レベル1
data_raw_test['noise_amp_2']=[] #高周波ノイズ + 振幅増加 レベル2
data_raw_test['high_shift_1']=[] #高周波ノイズ + 振幅増加 レベル1
data_raw_test['high_shift_2']=[] #高周波ノイズ + 振幅増加 レベル2

#時間データ生成
timeline = np.arange(sampling_length)/sampling_frequency

def func_make_sin(frequency):
    phase = 2 * np.pi * np.random.rand()
    return np.sin(2 * np.pi * frequency * timeline + phase)

#学習用データ生成
for i in range(data_train_num):
    nomal_low = func_make_sin(freq_nomal_low) * amp_nomal_low
    nomal_high = func_make_sin(freq_nomal_high) * amp_nomal_high
    white_noise = (np.random.rand(len(timeline))-0.5) * 2 * amp_white_noise
    data_raw_train.append(nomal_low + nomal_high + white_noise) 

#テスト用データ生成
for i in range(data_test_num):
    nomal_low = func_make_sin(freq_nomal_low) * amp_nomal_low
    nomal_high = func_make_sin(freq_nomal_high) * amp_nomal_high
    white_noise = (np.random.rand(len(timeline))-0.5) * 2 * amp_white_noise
    nomal = nomal_low + nomal_high + white_noise
    abnomal_amp_1 = nomal_high * amp_abnomal_level_1
    abnomal_amp_2 = nomal_high * amp_abnomal_level_2
    abnomal_noise_1 = func_make_sin(freq_abnomal) * amp_abnomal_noise_1
    abnomal_noise_2 = func_make_sin(freq_abnomal) * amp_abnomal_noise_2
    abnomal_shift_1 = nomal_low + func_make_sin(freq_shift_1) * amp_nomal_high + white_noise
    abnomal_shift_2 = nomal_low + func_make_sin(freq_shift_2) * amp_nomal_high + white_noise
    
    data_raw_test['nomal'].append(nomal) 
    data_raw_test['noise_1'].append( nomal + abnomal_noise_1 ) 
    data_raw_test['noise_2'].append( nomal + abnomal_noise_2 ) 
    data_raw_test['amp_1'].append( nomal + abnomal_amp_1 ) 
    data_raw_test['amp_2'].append( nomal + abnomal_amp_2 ) 
    data_raw_test['noise_amp_1'].append( nomal + abnomal_amp_1 + abnomal_noise_1 ) 
    data_raw_test['noise_amp_2'].append( nomal + abnomal_amp_2 + abnomal_noise_2 ) 
    data_raw_test['high_shift_1'].append(abnomal_shift_1) 
    data_raw_test['high_shift_2'].append(abnomal_shift_2) 

#生成データの確認
plt.style.use(['default'])
plt.figure(figsize=(12,3))
plt.subplot(1,3,1)
plt.plot(timeline, data_raw_train[0])
plt.xlabel("time [sec]")
plt.ylabel("data")
plt.subplot(1,3,2)
plt.plot(timeline[:100], data_raw_train[0][:100])
plt.subplot(1,3,3)
plt.plot(timeline[:100], data_raw_test['nomal'][0][:100],label='nomal')
plt.plot(timeline[:100], data_raw_test['noise_2'][0][:100],label='noise')
plt.plot(timeline[:100], data_raw_test['amp_2'][0][:100],label='amp')
plt.legend()
plt.show()