【问题标题】:LSTM Auto Encoder, use first LSTM output as the target for the decoderLSTM Auto Encoder,使用第一个 LSTM 输出作为解码器的目标
【发布时间】:2021-08-31 06:53:34
【问题描述】:

具有 10 天的传感器事件序列和一个真/假标签,指定传感器是否在 10 天内触发警报:

sensor_id timestamp feature_1 feature_2 10_days_alert_label
1 2020-12-20 01:00:34.565 0.23 0.1 1
1 2020-12-20 01:03:13.897 0.3 0.12 1
2 2020-12-20 01:00:34.565 0.13 0.4 0
2 2020-12-20 01:03:13.897 0.2 0.9 0

95% 的传感器不会触发警报,因此数据不平衡。我正在考虑使用自动编码器模型来检测异常(触发警报的传感器)。由于我对解码整个序列不感兴趣,只是 LSTM 学习了上下文向量,所以我在想类似下图的东西,其中解码器正在重建编码器输出:

我搜索了一下,发现了这个简单的 LSTM 自动编码器示例:

# lstm autoencoder recreate sequence
from numpy import array
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM
from tensorflow.keras.layers import Dense
from tensorflow.keras.layers import RepeatVector
from tensorflow.keras.layers import TimeDistributed
from tensorflow.keras.utils import plot_model
# define input sequence
sequence = array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
# reshape input into [samples, timesteps, features]
n_in = len(sequence)
sequence = sequence.reshape((1, n_in, 1))
# define model
model = Sequential()
model.add(LSTM(100, activation='relu', input_shape=(n_in,1)))
model.add(RepeatVector(n_in))
model.add(LSTM(100, activation='relu', return_sequences=True))
model.add(TimeDistributed(Dense(1)))
model.compile(optimizer='adam', loss='mse')
# fit model
model.fit(sequence, sequence, epochs=300, verbose=0)
plot_model(model, show_shapes=True, to_file='reconstruct_lstm_autoencoder.png')
# demonstrate recreation
yhat = model.predict(sequence, verbose=0)
print(yhat[0,:,0])

我想修改上面的示例,以便将第一个 LSTM 输出用作解码器目标。比如:

# lstm autoencoder recreate sequence
from numpy import array
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM
from tensorflow.keras.layers import Dense
from tensorflow.keras.layers import RepeatVector
from tensorflow.keras.layers import TimeDistributed
from tensorflow.keras.utils import plot_model
# define input sequence
sequence = array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
# reshape input into [samples, timesteps, features]
n_in = len(sequence)
sequence = sequence.reshape((1, n_in, 1))
# define model
model = Sequential()
model.add(LSTM(100, activation='relu', input_shape=(n_in,1)))

model.add(Dense(100, activation='relu')) # First LSTM output
model.add(Dense(32, activation='relu')) # Bottleneck 
model.add(Dense(100, activation='sigmoid')) # Decoded vector

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

# fit model
model.fit(sequence, FIRST_LSTM_OUTPUT, epochs=300, verbose=0) # <--- ???

问:我可以使用第一个 LSTM 输出向量作为目标吗?

【问题讨论】:

    标签: python tensorflow machine-learning keras lstm


    【解决方案1】:

    您可以使用model.add_loss 进行操作。在add_loss 中,我们指定了我们感兴趣的损失(在我们的例子中:mse)并设置用于计算它的层(在我们的例子中:LSTM 输出和模型预测)

    下面是一个虚拟示例:

    n_sample, timesteps = 100, 9
    X = np.random.uniform(0,1, (100, 9, 1))
    
    def mse(enc_output, pred):
        return  tf.reduce_mean(tf.square(enc_output - pred))
        
    inp = Input((timesteps,1,))
    enc = LSTM(100, activation='relu')(inp)
    x = Dense(100, activation='relu')(enc)
    x = Dense(32, activation='relu')(x)
    out = Dense(100, activation='sigmoid')(x)
    model = Model(inp, out)
    
    model.add_loss(mse(enc, out))
    model.compile(optimizer='adam', loss=None)
    model.fit(X, y=None, epochs=3)
    

    Here运行代码

    【讨论】:

      【解决方案2】:

      您需要找到一种方法来计算中间层的 损失张量 或隐藏激活函数的输出(例如,在您的情况下,第一个 LSTM 和最后一个 Dense )。在 中,我们可以使用add_loss() 方法来做到这一点。它可能取决于层输入(张量)。但是,您可以从我的answer here 中详细了解此add_loss 的用途。你也可以查看thread关于这个问题的讨论。

      # data 
      sequence = array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
      n_in = len(sequence)
      sequence = sequence.reshape((1, n_in, 1))
      
      # layers 
      inputs = tf.keras.Input(shape=(n_in,1))
      lx = LSTM(100, activation=tf.nn.relu)(inputs) # first lstm 
      x = Dense(100, activation=tf.nn.relu)(lx)
      x = Dense(32, activation=tf.nn.relu)(x)
      outputs = Dense(100, activation=tf.nn.sigmoid)(x)
      model = tf.keras.Model(inputs=inputs, outputs=outputs)
      
      # add_loss - compute mse of 
      # model's last layer with output of first lstm 
      model.add_loss(tf.keras.metrics.mean_squared_error(outputs, lx))
      model.compile(optimizer='adam') 
      
      # fit model
      # no need to pass first lstm, we added it already using add_loss method 
      model.fit(sequence, epochs=3, verbose=1) 
      
      Epoch 1/3
      1/1 [==============================] - 1s 1s/step - loss: 0.2270
      Epoch 2/3
      1/1 [==============================] - 0s 18ms/step - loss: 0.2250
      Epoch 3/3
      1/1 [==============================] - 0s 15ms/step - loss: 0.2227
      
      model.predict(sequence).shape
      (1, 100)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-12-03
        • 1970-01-01
        • 2021-04-23
        • 2021-09-21
        • 2021-10-15
        • 2021-06-30
        • 2022-12-16
        相关资源
        最近更新 更多