LSTMレイヤーに続く1D-Convレイヤーを使用して、16チャネル400タイムステップ信号を分類したいと思います。
入力形状は次のもので構成されます。
X = (n_samples, n_timesteps, n_features)
、ここで_n_samples=476
_、_n_timesteps=400
_、_n_features=16
_は、信号のサンプル、タイムステップ、および機能(またはチャネル)の数です。
y = (n_samples, n_timesteps, 1)
。各タイムステップには、0または1(バイナリ分類)のラベルが付けられます。
次の図に示すように、1D-Convを使用して時間情報を抽出します。 _F=32
_および_K=8
_はフィルターおよびkernel_sizeです。 1D-MaxPoolingは、1D-Convの後に使用されます。 32ユニットLSTMは信号分類に使用されます。モデルはy_pred = (n_samples, n_timesteps, 1)
を返す必要があります。
コードスニペットは次のように表示されます。
_input_layer = Input(shape=(dataset.n_timestep, dataset.n_feature))
conv1 = Conv1D(filters=32,
kernel_size=8,
strides=1,
activation='relu')(input_layer)
pool1 = MaxPooling1D(pool_size=4)(conv1)
lstm1 = LSTM(32)(pool1)
output_layer = Dense(1, activation='sigmoid')(lstm1)
model = Model(inputs=input_layer, outputs=output_layer)
_
モデルの概要を以下に示します。
ただし、次のエラーが発生しました。
_ValueError: Error when checking target: expected dense_15 to have 2 dimensions, but got array with shape (476, 400, 1).
_
問題は間違った形状だったと思います。修正方法を教えてください。
もう1つの質問は、タイムステップの数です。 _input_shape
_は1D-Convで割り当てられているため、タイムステップが400でなければならないことをLSTMに知らせるにはどうすればよいですか?
@todayの提案に基づいてモデルグラフを追加したいと思います。この場合、LSTMのタイムステップは98になります。この場合、TimeDistributedを使用する必要がありますか? Conv1DでTimeDistributedを適用できませんでした。
とにかく、タイムステップの代わりにチャネル間の畳み込みを実行する方法はありますか?たとえば、下図に示すように、フィルター(2、1)は各タイムステップを横断します。
ありがとう。
タイムステップごとに1つの値を予測する場合、2つのわずかに異なるソリューションが思い浮かびます。
1)MaxPooling1D
レイヤーを削除し、padding='same'
引数をConv1D
レイヤーに追加し、return_sequence=True
引数をLSTMに追加して、LSTMが出力を返すようにします各タイムステップの:
from keras.layers import Input, Dense, LSTM, MaxPooling1D, Conv1D
from keras.models import Model
input_layer = Input(shape=(400, 16))
conv1 = Conv1D(filters=32,
kernel_size=8,
strides=1,
activation='relu',
padding='same')(input_layer)
lstm1 = LSTM(32, return_sequences=True)(conv1)
output_layer = Dense(1, activation='sigmoid')(lstm1)
model = Model(inputs=input_layer, outputs=output_layer)
model.summary()
モデルの概要は次のとおりです。
Layer (type) Output Shape Param #
=================================================================
input_4 (InputLayer) (None, 400, 16) 0
_________________________________________________________________
conv1d_4 (Conv1D) (None, 400, 32) 4128
_________________________________________________________________
lstm_4 (LSTM) (None, 400, 32) 8320
_________________________________________________________________
dense_4 (Dense) (None, 400, 1) 33
=================================================================
Total params: 12,481
Trainable params: 12,481
Non-trainable params: 0
_________________________________________________________________
2)高密度レイヤーのユニット数を400に変更し、y
を(n_samples, n_timesteps)
に変更します。
from keras.layers import Input, Dense, LSTM, MaxPooling1D, Conv1D
from keras.models import Model
input_layer = Input(shape=(400, 16))
conv1 = Conv1D(filters=32,
kernel_size=8,
strides=1,
activation='relu')(input_layer)
pool1 = MaxPooling1D(pool_size=4)(conv1)
lstm1 = LSTM(32)(pool1)
output_layer = Dense(400, activation='sigmoid')(lstm1)
model = Model(inputs=input_layer, outputs=output_layer)
model.summary()
モデルの概要は次のとおりです。
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_6 (InputLayer) (None, 400, 16) 0
_________________________________________________________________
conv1d_6 (Conv1D) (None, 393, 32) 4128
_________________________________________________________________
max_pooling1d_5 (MaxPooling1 (None, 98, 32) 0
_________________________________________________________________
lstm_6 (LSTM) (None, 32) 8320
_________________________________________________________________
dense_6 (Dense) (None, 400) 13200
=================================================================
Total params: 25,648
Trainable params: 25,648
Non-trainable params: 0
_________________________________________________________________
どちらの場合も、'binary_crossentropy'
('categorical_crossentropy'
ではなく)を損失関数として使用する必要があることを忘れないでください。このソリューションは、ソリューション#1よりも精度が低いと予想されます。ただし、解決しようとしている特定の問題と持っているデータの性質に完全に依存するため、両方を試してパラメーターを変更する必要があります。
更新:
1つのタイムステップとk個の隣接フィーチャのみをカバーする畳み込み層を要求しました。はい、Conv2Dレイヤーを使用して実行できます。
# first add an axis to your data
X = np.expand_dims(X) # now X has a shape of (n_samples, n_timesteps, n_feats, 1)
# adjust input layer shape ...
conv2 = Conv2D(n_filters, (1, k), ...) # covers one timestep and k features
# adjust other layers according to the output of convolution layer...
なぜこれを行うのかわかりませんが、畳み込み層の出力((?, n_timesteps, n_features, n_filters)
)を使用するための1つの解決策は、TimeDistributed層の内側にラップされたLSTM層を使用することです。最後の2つの軸。
入力と出力の形状は(476、400、16)と(476、1)です。つまり、完全なシーケンスごとに1つの値を出力するだけです。
LSTMはシーケンスを再取得していません(return_sequences = False)。ただし、LSTMが入力を圧縮する前にConv1DとMaxPoolingを実行しても。したがって、LSTM自体は(98,32)のサンプルを取得します。
入力ステップごとに1つの出力が必要であると想定しています。
Conv1DとMaxPoolingが入力データに関連していると仮定すると、最初のN/wの出力を別のネットワークに与えて400個の出力を取得するseq to seqアプローチを試すことができます。
エンコーダーデコーダーseq2seqネットワークのようないくつかのモデルを以下のように見ることをお勧めします
https://blog.keras.io/a-ten-minute-introduction-to-sequence-to-sequence-learning-in-keras.html