1d-CNNとりあえずやってみる

モジュールをインポート

import numpy as np
import matplotlib.pyplot as plt
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.layers.convolutional import Conv1D, UpSampling1D
from keras.layers.pooling import MaxPooling1D

サンプルデータ生成

LEN_DATA=10000
timeline = np.arange(LEN_DATA)
raw_data = np.sin(timeline * 1 / 100) + np.cos(timeline * 3 / 100)/2
raw_data = raw_data + (np.random.rand(len(timeline)) * 0.3)# ノイズ項
plt.style.use(['default'])
plt.plot(timeline[:5000], raw_data[:5000])
plt.xlabel("time")
plt.ylabel("data")
plt.show()

入力データに変換

LEN_INPUT=64
LEN_OUTPUT=16
LEN_TEST=5000
DATA_MAX=1.8
DATA_MIN=-1.5
input_data = []
output_data = []
raw_data=(raw_data-DATA_MIN)/(DATA_MAX-DATA_MIN)
raw_data=np.clip(raw_data,0.0,1.0)
for n in range(LEN_DATA-LEN_INPUT-LEN_OUTPUT):
    input_data.append(raw_data[n:n+LEN_INPUT])
    output_data.append(raw_data[n+LEN_INPUT:n+LEN_INPUT+LEN_OUTPUT])

input_data = np.array(input_data[:LEN_TEST])
output_data = np.array(output_data[:LEN_TEST])
print(input_data.shape)
print(output_data.shape)

train_X = np.reshape(input_data, (-1, LEN_INPUT, 1))
train_Y = np.reshape(output_data, (-1, LEN_OUTPUT, 1))
print(train_X.shape)
print(train_Y.shape)

NNモデル定義

model = Sequential()
model.add(Conv1D(64, 8, padding='same', input_shape=(64, 1), activation='relu'))
model.add(MaxPooling1D(2, padding='same'))
model.add(Conv1D(64, 8, padding='same', activation='relu'))
model.add(MaxPooling1D(2, padding='same'))
model.add(Conv1D(32, 8, padding='same', activation='relu'))
model.add(Conv1D(1, 8, padding='same', activation='tanh'))

model.compile(loss='mse', optimizer='adam')
model.summary()

学習

EPOCHS=100
#学習
history = model.fit(train_X, train_Y, validation_split=0.1, epochs=EPOCHS)
#損失プロット
plt.plot(range(EPOCHS), history.history['loss'], label='loss')
plt.plot(range(EPOCHS), history.history['val_loss'], label='val_loss')
plt.xlabel('epoch')
plt.ylabel('loss')
plt.legend() 
plt.show()

推論テスト

start = LEN_TEST
sheed = np.reshape(raw_data[start:start+LEN_INPUT], (1, LEN_INPUT, 1))
prediction = sheed
sheed2=sheed
prediction2 = sheed2

for i in range(20):
    res = model.predict(sheed)
    sheed = np.concatenate((sheed[:, 16:, :], res), axis=1)
    prediction = np.concatenate((prediction, res), axis=1)

    res2 = model.predict(sheed2)
    sheed2 = np.reshape(raw_data[start+(i+1)*16:start+64+(i+1)*16], (1, 64, 1))
    prediction2 = np.concatenate((prediction2, res2), axis=1)

print(prediction.shape)
print(prediction2.shape)
predictor = np.reshape(prediction, (-1))
predictor2 = np.reshape(prediction2, (-1))
print(predictor.shape)
print(predictor2.shape)
plt.plot(range(len(predictor)), raw_data[start:start + len(predictor)], label='real')
plt.plot(range(len(predictor)), predictor, label='predict')
plt.plot(range(len(predictor2)), predictor2, label='predict2')
plt.legend() 
plt.show()

参考:
時系列予測を一次元畳み込みを使って解く with Keras - Qiita