Keras中带有RNN / LSTM的InvalidArgumentError

时间:2018-07-03 10:43:55

标签: python machine-learning keras

我将自己投入到机器学习中,并希望将Keras用于时间紧迫的大学项目。我意识到最好学习单个概念和构建基块,但重要的是要尽快完成。

我正在与一个对机器学习有一定经验和兴趣的人一起工作,但是我们似乎没有比这更进一步的了。以下代码改编自GitHub code中提到的a guide in Machine Learning Mastery

对于上下文,我从多个物理传感器(每个传感器为一列)中获取数据,这些传感器中的每个样本均以一行表示。我希望使用机器学习来确定在任何给定时间跟踪谁的传感器。我试图将大约80%的行分配给培训,将20%的行分配给测试,并创建自己的“ y”数据集(前521,549行来自一个参与者,其余行来自另一个参与者)。我的数据(培训和测试)共有1,019,802行,共有16列(均已填充),但是如果需要,可以减少列数。

我想知道以下内容:

  1. 在我要实现的目标范围内,此错误是什么意思?如何更改代码以避免这种情况?
  2. 下面的代码是否适合我想要实现的目标?
  3. 在我对机器学习(通常还是专门)旨在实现的理解上,这段代码是否代表任何特定的基本缺陷?

以下是我尝试运行以利用机器学习的Python代码:

x_all = pd.read_csv("(redacted)...csv",
                delim_whitespace=True, header=None, low_memory=False).values
y_all = np.append(np.full((521549,1), 0), np.full((498253,1),1))
limit = 815842
x_train = x_all[:limit]
y_train = y_all[:limit]
x_test = x_all[limit:]
y_test = y_all[limit:]

max_features = 16
maxlen = 80
batch_size = 32

model = Sequential()
model.add(Embedding(500, 32, input_length=max_features))
model.add(LSTM(128, dropout=0.2, recurrent_dropout=0.2))
model.add(Dense(1, activation='sigmoid'))

model.compile(loss='binary_crossentropy',
              optimizer='adam',
              metrics=['accuracy'])

model.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=15,
          validation_data=(x_test, y_test))
score, acc = model.evaluate(x_test, y_test,
                            batch_size=batch_size)

这是代码中引用的CSV的摘录:

6698.486328125  4.28260869565217    4.6304347826087 10.6195652173913    2.4392579293836 2.56134051466188    9.05326152004788    0.0 1.0812  924.898261191267    -1.55725190839695   -0.244274809160305  0.320610687022901   -0.122938530734633  0.490254872563718   0.382308845577211   
6706.298828125  4.28260869565217    4.58695652173913    10.5978260869565    2.4655894673848 2.50867743865949    9.04368641532017    0.0 1.0812  924.898261191267    -1.64885496183206   -0.366412213740458  0.381679389312977   -0.122938530734633  0.490254872563718   0.382308845577211   
6714.111328125  4.26086956521739    4.64130434782609    10.5978260869565    2.45601436265709    2.57809694793537    9.03411131059246    0.0 1.0812  924.898261191267    -0.931297709923664  -0.320610687022901  0.320610687022901   -0.125937031484258  0.493253373313343   0.371814092953523   

运行此错误:

tensorflow.python.framework.errors_impl.InvalidArgumentError: indices[0,0] = 972190 is not in [0, 500)
         [[Node: embedding_1/embedding_lookup = GatherV2[Taxis=DT_INT32, Tindices=DT_INT32, Tparams=DT_FLOAT, _class=["loc:@training/Adam/Assign_2"], _device="/job:localhost/replica:0/task:0/device:CPU:0"](embedding_1/embeddings/read, embedding_1/Cast, training/Adam/gradients/embedding_1/embedding_lookup_grad/concat/axis)]]

作为参考,我使用的是2017年的27英寸iMac Retina 5K,它具有4.2 GHz i7、32 GB RAM和Radeon Pro 580 8 GB。

1 个答案:

答案 0 :(得分:1)

关于机器学习精通的其他一些教程,您想要完成的事情 https://machinelearningmastery.com/convert-time-series-supervised-learning-problem-python/ https://machinelearningmastery.com/time-series-prediction-lstm-recurrent-neural-networks-python-keras/

然后,我将简要介绍您可能想做的事情。

现在看来,您正在为模型中的X和y输入使用完全相同的数据。 y输入是标签,在您的情况下是“传感器正在跟踪谁”。因此,在有2个可能的人的二进制情况下,第一人称设置为0,第二人称设置为1。

在最后一层上的S型激活将输出一个介于0和1之间的数字。如果该数字低于0.5,则表明传感器正在跟踪人0,如果该值大于0.5,则表明它预测了人1。这将在准确性得分中表示出来。

您可能不希望使用嵌入层,您可能会愿意,但我首先将其删除。尽管将数据标准化后再将其输入网络以改进训练。如果您需要快速的解决方案,Scikit-Learn为此提供了很好的工具。 http://scikit-learn.org/stable/modules/preprocessing.html

使用时间序列数据时,您通常希望在一个时间点窗口而不是单个时间点内输入数据。如果将时间序列发送到Keras model.fit(),则它将使用单点作为输入。

为了将时间窗口作为输入,您需要将数据集中的每个示例重新组织为一个完整的窗口,或者如果生成器将占用大量内存,则可以使用生成器。我链接的“机器学习精通”页面对此进行了描述。 Keras有一个名为TimeseriesGenerator

的生成器,您可以使用它
from keras.preprocessing.sequence import TimeseriesGenerator
timeseries_generator = TimeseriesGenerator(data, targets, length, sampling_rate)

数据是特征的时间序列,目标是标签的时间序列。 如果使用时间序列生成器,则在拟合时必须使用fit_generator

model.fit_generator(timeseries_generator)

与使用Evaluation_generator()进行评估相同

如果您的数据设置正确,则您的模型应该可以使用

model = Sequential()
model.add(LSTM(128, dropout=0.2, recurrent_dropout=0.2))
model.add(Dense(1, activation='sigmoid'))

您还可以尝试使用更简单的密集模型

model = Sequential()
model.add(Flatten())
model.add(Dense(64, dropout=0.2, activation='relu'))
model.add(Dense(1, activation='sigmoid'))

我看到的另一个问题是,看来您将要分离出仅包含一种标签类型的测试集,这不仅是一种不好的做法,而且还会使您的训练集偏重于另一种可能会损害结果的标签。

希望这可以帮助您入门。确保正确设置数据!