3darray训练/测试TensorFlow RNN LSTM

时间:2017-07-24 21:44:57

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

(我正在测试我写短篇但有效的问题的能力,所以让我知道我在这里做的事情)

我正在尝试训练/测试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秒记录时间步长的一定时间间隔内,我形成1d阵列,每个时间步长对比记录在该时间步骤记录的特征。然后,我围绕与赛道上一辆一级方程式赛车相对应的所有时间步骤形成一个二维阵列。我创建了一个包含所有F1赛车及其时间序列数据的最终3D阵列。我想训练和测试一个模型,以检测新车赛道上F1常见轨迹的异常情况。

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

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

2 个答案:

答案 0 :(得分:4)

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

您将进行三维测量:

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)

既然您可以这样做,您可以格式化它们,但是您需要为您正在使用的网络进行格式化(必要时转换行和列,一次呈现单个样本或同时呈现所有样本等)< / p>

您要做的事情(如果我正确地阅读第二篇论文)很可能需要序列来对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!")

答案 1 :(得分:1)

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

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

<强> 2。时间特征异常:      此处输入取决于您何时测量特征。您当前的功能可能取决于之前测量的功能。例如,可能存在一个特征,如果它在时间0出现,则其值是异常值,但如果它在时间上看起来不是异常则不是异常值。在这种情况下,您将每条路径与重叠时间窗口分开,并形成一个[batch, time_window, features]形式的特征集。

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

对于(2),您可以使用seq2seq模型关注您提到的第二篇论文,其中您的解码器错误将确定哪些功能是异常值。您可以查看this以了解此类模型的实施情况。

相关问题