【问题标题】:3darray training/testing TensorFlow RNN LSTM3darray 训练/测试 TensorFlow RNN LSTM
【发布时间】:2017-12-30 15:06:21
【问题描述】:

(我正在测试我编写简短但有效的问题的能力,所以请告诉我我是怎么做的)

我正在尝试训练/测试一个 TensorFlow 循环神经网络,特别是一个 LSTM,对以下 ndarray 格式的时间序列数据进行一些试验:

[[[time_step_trial_0, feature, feature, ...]
  [time_step_trial_0, feature, feature, ...]]                  
 [[time_step_trial_1, feature, feature, ...]
  [time_step_trial_1, feature, feature, ...]]
 [[time_step_trial_2, feature, feature, ...]
  [time_step_trial_2, feature, feature, ...]]]

这个 3darray 的 1d 部分包含一个时间步长以及在该时间步长观察到的所有特征值。 2d 块包含在一次试验中观察到的所有 1d 数组(时间步长)。 3d 块包含为时间序列数据集记录的所有 2d 块(试验)。对于每个试验,时间步长频率是恒定的,并且所有试验的窗口间隔相同(0 到 50 秒、0 到 50 秒等)。

例如,我得到了一级方程式赛车的数据,例如扭矩、速度、加速度、转速等。在一定的时间间隔内,每 0.5 秒记录一次时间步长,我将每个时间步长与在那个时间步记录的特征。然后我围绕与一辆一级方程式赛车在赛道上的运行相对应的所有时间步长形成一个二维数组。我创建了一个包含所有 F1 赛车及其时间序列数据的最终 3D 数组。我想训练和测试一个模型,以检测新车赛道上 F1 常见轨迹中的异常情况。

我目前知道 TensorFlow 模型支持二维数组进行训练和测试。我想知道我必须经过哪些程序才能在这个 3darray 中包含的所有独立试验(2d)上训练和测试模型。此外,我将在未来增加更多的试验。那么,为了不断用新的数据/试验更新我的模型以加强我的 LSTM,需要经历哪些正确的程序。

这是我最初尝试复制的模型,用于人类活动以外的其他目的:https://github.com/guillaume-chevalier/LSTM-Human-Activity-Recognition。另一个更可行的模型是我更愿意在时间序列数据中进行异常检测的模型:https://arxiv.org/abs/1607.00148。我想建立一个异常检测模型,在给定一组非异常时间序列训练数据的情况下,我们可以检测测试数据中的异常,其中部分数据随着时间的推移被定义为“不合时宜”。

【问题讨论】:

  • 你能告诉我们你到目前为止所做的尝试吗?考虑编写minimal reproducible example,进一步阐明您目前面临的特定问题的输入和预期结果。问题的某些部分不清楚或过于开放,例如询问“为了训练这个模型必须经过哪些程序”。
  • @E_net4 我尝试复制 Guillaume 的 LSTM,但我遇到了维度问题。我将在上面发布我正在寻找的示例。
  • @E_net4 已更新。
  • @JulianRachman 感谢您的链接。我设法运行了 LSTM-Human-Activity-Recognition。正如您所说的“我正在尝试复制”,您是否设法掌握了他们的文件结构/输入张量?有一些重塑。
  • @ClemensTolboom 嗯。我只是想知道这个模型如何处理 3d 数组,以便我可以将其应用到关于不可预测模式异常检测的第二篇论文中。第二篇论文是最终目标。

标签: python python-3.x tensorflow neural-network lstm


【解决方案1】:

您的输入形状和相应的模型取决于您要检测的异常类型的原因。你可以考虑:

1.仅功能异常: 在这里,您考虑各个特征并决定它们中的任何一个是否异常,而不考虑何时测量。在您的示例中,如果一个或多个相对于其他特征是异常值,则特征 [扭矩,速度,加速度,...] 是异常值。在这种情况下,您的输入格式应为 [batch, features]

2。时间特征异常: 在这里,您的输入取决于您测量特征的时间。您当前的功能可能取决于随时间测量的先前功能。例如,可能有一个特征,如果它出现在时间 0,则其值为异常值,但如果它在时间上出现,则不是异常值。在这种情况下,您将每个路径划分为重叠的时间窗口,并形成[batch, time_window, features] 形式的特征集。

(1) 开始使用自动编码器应该非常简单,您可以在其中训练自动编码器,并且根据输入和输出之间的误差,您可以选择像 2 标准偏差这样的阈值从平均值来确定它是否是异常值。

对于(2),您可以按照您提到的第二篇论文使用 seq2seq 模型,其中您的解码器错误将确定哪些特征是异常值。您可以在this 上查看此类模型的实现。

【讨论】:

    【解决方案2】:

    我认为对于大多数 LSTM,您会希望以这种方式考虑您的数据(因为它很容易用作网络的输入)。

    您将进行 3 维测量:

    feature_size = 不同特征的数量(扭矩、速度等)

    number_of_time_steps = 为单辆车收集的时间步数

    number_of_cars = 汽车数量

    将您的数据作为一组矩阵读取最容易,其中每个矩阵对应一个完整样本(一辆汽车的所有时间步长)。

    您可以排列这些矩阵,使每一行是一个观察值,每一列是一个不同的参数(或者相反,您可能需要转置矩阵,看看您的网络输入是如何格式化的)。

    所以每个矩阵的大小为: number_of_time_steps x feature_size (#rows x #columns)。您将拥有 number_of_cars 个不同的矩阵。每个矩阵都是一个样本。

    要将您的数组转换为这种格式,您可以使用这段代码(注意,您已经可以使用 A[n] 访问数组中的单个样本,但这使得访问元素的形状是你期望):

    import numpy as np
    
    A = [[['car1', 'timefeatures1'],['car1', 'timefeatures2']],
         [['car2', 'timefeatures1'],['car2', 'timefeatures2']], 
         [['car3', 'timefeatures1'],['car3', 'timefeatures2']]
        ]
    
    easy_format = np.array(A)
    

    现在您可以使用 easy_format[n] 获取单个样本,其中 n 是您想要的样本。

    easy_format[1] prints
    
    array([['car2', 'timefeatures1'],
           ['car2', 'timefeatures2']],
          dtype='|S12')
    
    easy_format[1].shape = (2,2)
    

    现在您可以做到这一点,您可以根据您使用的网络的需要对它们进行格式化(必要时转置行和列,一次呈现单个样本或一次呈现所有样本等)

    您要做的事情(如果我正确地阅读了第二篇论文)很可能需要一个序列来对 lstm 或 rnn 进行排序。您的原始序列是给定试验的时间序列,并且您正在生成一组中间权重(嵌入),可以重新创建该原始序列且错误率很低。你正在为所有的试验做这件事。您将在一系列合理正常的试验中训练这个 lstm 并让它表现良好(准确地重建序列)。然后,您可以使用同一组嵌入来尝试重建一个新序列,如果它具有很高的重建误差,您可以假设它是异常的。

    查看此 repo 以获取您想要的示例以及如何使用它以及代码在做什么的说明(它仅将整数序列映射到另一个整数序列,但可以轻松扩展为 map向量序列到向量序列):https://github.com/ichuang/tflearn_seq2seq 您定义的模式只是您的原始序列。你也可以看看自动编码器来解决这个问题。

    最终编辑:检查此存储库:https://github.com/beld/Tensorflow-seq2seq-autoencoder/blob/master/simple_seq2seq_autoencoder.py

    我稍微修改了其中的代码,以便在最新版本的 tensorflow 上工作,并使一些变量名称更清晰。您应该能够修改它以在您的数据集上运行。现在我只是让它自动编码一个随机生成的 1 和 0 数组。您将对数据的大部分子集执行此操作,然后查看其他数据是否被准确重建(比平均值高得多的错误可能意味着异常)。

    import numpy as np
    import tensorflow as tf
    
    
    learning_rate = 0.001
    training_epochs = 30000
    display_step = 100
    
    hidden_state_size = 100
    samples = 10
    time_steps = 20
    step_dims = 5
    test_data = np.random.choice([ 0, 1], size=(time_steps, samples, step_dims))
    
    initializer = tf.random_uniform_initializer(-1, 1)
    
    seq_input = tf.placeholder(tf.float32, [time_steps, samples, step_dims])
    
    encoder_inputs = [tf.reshape(seq_input, [-1, step_dims])]
    
    
    decoder_inputs = ([tf.zeros_like(encoder_inputs[0], name="GO")]
                      + encoder_inputs[:-1])
    targets = encoder_inputs
    weights = [tf.ones_like(targets_t, dtype=tf.float32) for targets_t in targets]
    
    cell = tf.contrib.rnn.BasicLSTMCell(hidden_state_size)
    _, enc_state = tf.contrib.rnn.static_rnn(cell, encoder_inputs, dtype=tf.float32)
    cell = tf.contrib.rnn.OutputProjectionWrapper(cell, step_dims)
    dec_outputs, dec_state = tf.contrib.legacy_seq2seq.rnn_decoder(decoder_inputs, enc_state, cell)
    
    y_true = [tf.reshape(encoder_input, [-1]) for encoder_input in encoder_inputs]
    y_pred = [tf.reshape(dec_output, [-1]) for dec_output in dec_outputs]
    
    loss = 0
    for i in range(len(y_true)):
        loss += tf.reduce_sum(tf.square(tf.subtract(y_pred[i], y_true[i])))
    optimizer = tf.train.AdamOptimizer(learning_rate).minimize(loss)
    
    init = tf.initialize_all_variables()
    
    with tf.Session() as sess:
        sess.run(init)
        x = test_data
        for epoch in range(training_epochs):
            #x = np.arange(time_steps * samples * step_dims)
            #x = x.reshape((time_steps, samples, step_dims))
            feed = {seq_input: x}
            _, cost_value = sess.run([optimizer, loss], feed_dict=feed)
            if epoch % display_step == 0:
                print "logits"
                a = sess.run(y_pred, feed_dict=feed)
                print a
                print "labels"
                b = sess.run(y_true, feed_dict=feed)
                print b
    
                print("Epoch:", '%04d' % (epoch+1), "cost=", "{:.9f}".format(cost_value))
    
    print("Optimization Finished!")
    

    【讨论】:

    • 我了解这个设置。您能否举例说明我将如何使用此设置来训练(任何)模型?在我看到一个例子之前,我现在还没有真正看到它的适用性。我也不太明白'timefeatures' 是什么。
    • 你可以使用我发给你的两个链接。
    • 'timefeatures' 只是您正在查看的任何参数的代表。例如,您的时间序列可能类似于:['timestamp', 'torque', 'velocity', 'etc'] 我只是将其称为汽车名称和时间特征,以便更清楚地引用哪个样本。
    • 看看我的最后两段,看看是否能澄清任何事情。
    • 好的,我们快到了。您能否向我展示一个应用于简单神经网络的示例,我的理解将发挥其全部潜力。