LSTM:层顺序的输入0与层不兼容

时间:2020-07-05 09:36:34

标签: python pandas tensorflow keras lstm

我知道这里有几个问题,但是我还没有找到完全适合我的问题的问题。 我试图用来自Pandas DataFrames的数据来拟合LSTM,但是对于我必须提供它们的格式感到困惑。 我创建了一个小代码片段,它将向您展示我的尝试:

import pandas as pd, tensorflow as tf, random
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense

targets = pd.DataFrame(index=pd.date_range(start='2019-01-01', periods=300, freq='D'))
targets['A'] = [random.random() for _ in range(len(targets))]
targets['B'] = [random.random() for _ in range(len(targets))] 
features = pd.DataFrame(index=targets.index)
for i in range(len(features)) :
    features[str(i)] = [random.random() for _ in range(len(features))] 

model = Sequential()
model.add(LSTM(units=targets.shape[1], input_shape=features.shape))
model.compile(optimizer='adam', loss='mae')

model.fit(features, targets, batch_size=10, epochs=10)

这导致:

ValueError:层顺序的输入0与该层不兼容:预期ndim = 3,找到的ndim = 2。收到的完整图形:[10,300]

我希望

与所提供的功能 DataFrame的尺寸有关。我猜想一旦解决此问题,下一个错误就会提及 targets DataFrame。

据我了解,第一层的“单位”参数定义了此模型的输出尺寸。输入必须具有3D形状,但是我不知道如何在数据框的2D世界之外创建它们。 希望您能帮助我理解Python中的重塑机制以及如何将其与Pandas DataFrames结合使用。 (我是Python的新手,来自R)

预先感谢

3 个答案:

答案 0 :(得分:1)

让我们看看使用LSTMs的几种流行方式。

多对多

示例:您有一个句子(由单词顺序组成)。给出您希望预测每个单词的词性(POS)的这些单词顺序。

enter image description here

因此,您有n个单词,并且每个时间步将每个单词提供给LSTM。每个LSTM时间步长(也称为LSTM解包)将产生并输出。单词由一组通常为单词嵌入的特征表示。因此,LSTM的输入大小为bath_size X time_steps X features

Keras代码:

inputs = keras.Input(shape=(10,3))
lstm = keras.layers.LSTM(8, input_shape = (10, 3), return_sequences = True)(inputs)
outputs = keras.layers.TimeDistributed(keras.layers.Dense(5, activation='softmax'))(lstm)
model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(loss='categorical_crossentropy', optimizer='adam')

X = np.random.randn(4,10,3) 
y = np.random.randint(0,2, size=(4,10,5))

model.fit(X, y, epochs=2)
print (model.predict(X).shape)

多对一

示例:同样,您有一个句子(按顺序由单词组成)。如果您希望判断句子的正面或负面,请给出这些词的顺序。

enter image description here

Keras代码

inputs = keras.Input(shape=(10,3))
lstm = keras.layers.LSTM(8, input_shape = (10, 3), return_sequences = False)(inputs)
outputs =keras.layers.Dense(5, activation='softmax')(lstm)
model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(loss='categorical_crossentropy', optimizer='adam')

X = np.random.randn(4,10,3) 
y = np.random.randint(0,2, size=(4,5))

model.fit(X, y, epochs=2)
print (model.predict(X).shape)

许多到多头

示例:您有一个句子(由单词顺序组成)。给出您希望预测句子情感以及句子作者的这些单词顺序。

这是一种多头模型,其中一个负责人预测情绪,另一个负责人预测作者。两个头共享相同的LSTM主干。

enter image description here

Keras代码

inputs = keras.Input(shape=(10,3))
lstm = keras.layers.LSTM(8, input_shape = (10, 3), return_sequences = False)(inputs)
output_A = keras.layers.Dense(5, activation='softmax')(lstm)
output_B = keras.layers.Dense(5, activation='softmax')(lstm)

model = keras.Model(inputs=inputs, outputs=[output_A, output_B])
model.compile(loss='categorical_crossentropy', optimizer='adam')

X = np.random.randn(4,10,3) 
y_A = np.random.randint(0,2, size=(4,5))
y_B = np.random.randint(0,2, size=(4,5))

model.fit(X, [y_A, y_B], epochs=2)
y_hat_A, y_hat_B = model.predict(X)
print (y_hat_A.shape, y_hat_B.shape)

您正在寻找的是多头对多头模型,其中一个头对A的预测将由一个头做出,而另一个头对B的预测将做出

答案 1 :(得分:0)

LSTM的输入数据必须为3D。

如果打印数据框的形状,则会得到:

targets : (300, 2)
features : (300, 300)

输入数据必须重塑为(samples, time steps, features)。这意味着目标特征必须具有相同的形状。

您需要为问题设置许多时间步长,换句话说,将使用多少样本进行预测。

例如,如果您有300天和2个功能,则时间步长可以为3。因此,三天将用于做出一个预测(您可以任意选择)。这是用于重塑数据的代码(还有一些其他更改):

import pandas as pd
import numpy as np
import tensorflow as tf
import random
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense

data = pd.DataFrame(index=pd.date_range(start='2019-01-01', periods=300, freq='D'))
data['A'] = [random.random() for _ in range(len(data))]
data['B'] = [random.random() for _ in range(len(data))]

# Choose the time_step size.
time_steps = 3
# Use numpy for the 3D array as it is easier to handle.
data = np.array(data)

def make_x_y(ts, data):
    """
    Parameters
    ts : int
    data : numpy array

    This function creates two arrays, x and y. 
    x is the input data and y is the target data.
    """
    x, y = [], []
    offset = 0
    for i in data:
        if offset < len(data)-ts:
            x.append(data[offset:ts+offset])
            y.append(data[ts+offset])
            offset += 1
    return np.array(x), np.array(y)

x, y = make_x_y(time_steps, data)

print(x.shape, y.shape)

nodes = 100  # This is the width of the network.
out_size = 2  # Number of outputs produced by the network. Same size as features.

model = Sequential()
model.add(LSTM(units=nodes, input_shape=(x.shape[1], x.shape[2])))
model.add(Dense(out_size))  # For the output a Dense (fully connected) layer is used.
model.compile(optimizer='adam', loss='mae')
model.fit(x, y, batch_size=10, epochs=10)

答案 2 :(得分:0)

嗯,为了最终解决这个问题,我想提供一个我同时努力的解决方案。 tf.keras中的TimeseriesGenerator类。...使我很容易将正确形状的数据提供给LSTM模型

from keras.preprocessing.sequence import TimeseriesGenerator
import numpy as np

window_size   = 7
batch_size    = 8
sampling_rate = 1

train_gen = TimeseriesGenerator(X_train.values, y_train.values,
                               length=window_size, sampling_rate=sampling_rate,
                               batch_size=batch_size)

valid_gen = TimeseriesGenerator(X_valid.values, y_valid.values,
                               length=window_size, sampling_rate=sampling_rate,
                               batch_size=batch_size)
test_gen  = TimeseriesGenerator(X_test.values, y_test.values,
                               length=window_size, sampling_rate=sampling_rate,
                               batch_size=batch_size)

还有许多其他实现生成器的方法,例如使用提供功能 windowed 的more_itertools,或使用tensorflow.Dataset及其功能 window 。 对我来说, TimeseriesGenerator 足以满足我所做的测试。 如果您希望看到一个基于某些股票为DAX建模的示例,我将在Github上共享一个notebook