Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python LSTM-对部分序列进行预测_Python_Tensorflow_Machine Learning_Keras_Lstm - Fatal编程技术网

Python LSTM-对部分序列进行预测

Python LSTM-对部分序列进行预测,python,tensorflow,machine-learning,keras,lstm,Python,Tensorflow,Machine Learning,Keras,Lstm,这个问题是我一直在问的一个问题 我已经训练了一个LSTM模型来预测一个二进制类(1或0),该类包含100个样本,每个样本有3个特征,即:数据的形状是(m,100,3),其中m是批次数 数据: 目标: [ [1] [0] ... ] 型号代码: def build_model(num_samples, num_features, is_training): model = Sequential() opt = optimizers.Adam(lr=0.0005,

这个问题是我一直在问的一个问题

我已经训练了一个LSTM模型来预测一个二进制类(1或0),该类包含100个样本,每个样本有3个特征,即:数据的形状是(m,100,3),其中m是批次数

数据:

目标:

[
   [1]
   [0]
   ...
]
型号代码:

def build_model(num_samples, num_features, is_training):
    model = Sequential()
    opt = optimizers.Adam(lr=0.0005, beta_1=0.9, beta_2=0.999, epsilon=1e-08, decay=0.0001)

    batch_size = None if is_training else 1
    stateful = False if is_training else True
    first_lstm = LSTM(32, batch_input_shape=(batch_size, num_samples, num_features), return_sequences=True,
                      activation='tanh', stateful=stateful)

    model.add(first_lstm)
    model.add(LeakyReLU())
    model.add(Dropout(0.2))
    model.add(LSTM(16, return_sequences=True, activation='tanh', stateful=stateful))
    model.add(Dropout(0.2))
    model.add(LeakyReLU())
    model.add(LSTM(8, return_sequences=False, activation='tanh', stateful=stateful))
    model.add(LeakyReLU())
    model.add(Dense(1, activation='sigmoid'))

    if is_training:
        model.compile(loss='binary_crossentropy', optimizer=opt,
                      metrics=['accuracy', keras_metrics.precision(), keras_metrics.recall(), f1])
    return model
对于训练阶段,模型是有状态的。预测时,我使用的是一个有状态的模型,迭代数据并输出每个样本的概率:

for index, row in data.iterrows():
    if index % 100 == 0:
        predicting_model.reset_states()
    vals = np.array([[row[['a', 'b', 'c']].values]])
    prob = predicting_model.predict_on_batch(vals)
当观察一个批次结束时的概率时,它正是我在预测整个批次时得到的值(不是一个接一个)。然而,我预计,当新样本到达时,概率将始终保持在正确的方向上。实际发生的情况是,概率输出可能会在任意样本上突增到错误的类(见下文)


预测期间100个样品批次的两个样品(标签=1):

和标签=0:

有没有办法实现我想要的(在预测概率时避免极端峰值),或者这是一个给定的事实

如有任何解释、建议,将不胜感激


更新 多亏了@today advice,我尝试在最后一个LSTM层上使用
return\u sequence=True
为每个输入时间步使用隐藏状态输出来训练网络

现在标签看起来是这样的(形状(100100)):

模型摘要:

Layer (type)                 Output Shape              Param #   
=================================================================
lstm_1 (LSTM)                (None, 100, 32)           4608      
_________________________________________________________________
leaky_re_lu_1 (LeakyReLU)    (None, 100, 32)           0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 100, 32)           0         
_________________________________________________________________
lstm_2 (LSTM)                (None, 100, 16)           3136      
_________________________________________________________________
dropout_2 (Dropout)          (None, 100, 16)           0         
_________________________________________________________________
leaky_re_lu_2 (LeakyReLU)    (None, 100, 16)           0         
_________________________________________________________________
lstm_3 (LSTM)                (None, 100, 8)            800       
_________________________________________________________________
leaky_re_lu_3 (LeakyReLU)    (None, 100, 8)            0         
_________________________________________________________________
dense_1 (Dense)              (None, 100, 1)            9         
=================================================================
Total params: 8,553
Trainable params: 8,553
Non-trainable params: 0
_________________________________________________________________
但是,我有一个例外:

ValueError: Error when checking target: expected dense_1 to have 3 dimensions, but got array with shape (75, 100)

我需要修复什么?

注意:这只是一个想法,可能是错误的。如果您愿意,请尝试,我将非常感谢您的反馈。


有没有办法达到我想要的(在 预测概率),或者这是一个给定的事实

您可以进行此实验:将最后一个LSTM层的
return_sequences
参数设置为
True
,并复制每个样本的标签以及每个样本的长度。例如,如果一个样本的长度为100,其标签为0,则为该样本创建一个由100个零组成的新标签(您可以使用numpy函数(如
np.repeat
)轻松完成此操作)。然后重新训练你的新模型,然后在新的样本上测试它。我不确定这一点,但我希望这次会有更多单调递增/递减概率图


更新:您提到的错误是由于标签应为三维阵列(查看模型摘要中最后一层的输出形状)这一事实造成的。使用
np.展开_dims
将另一个大小为1的轴添加到末端。重复标签的正确方式如下所示,假设
y\u train
的形状为
(num\u samples,)


IMDB数据集上的实验: 实际上,我在IMDB数据集上尝试了上面建议的实验,使用了一个带有一个LSTM层的简单模型。有一次,我只对每个样本使用了一个标签(与@Shlomi的原始方法相同),而另一次我复制了标签,使每个样本的每个时间步都有一个标签(如上所述)。如果您想亲自尝试,以下是代码:

from keras.layers import *
from keras.models import Sequential, Model
from keras.datasets import imdb
from keras.preprocessing.sequence import pad_sequences
import numpy as np

vocab_size = 10000
max_len = 200
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=vocab_size)
X_train = pad_sequences(x_train, maxlen=max_len)

def create_model(return_seq=False, stateful=False):
    batch_size = 1 if stateful else None
    model = Sequential()
    model.add(Embedding(vocab_size, 128, batch_input_shape=(batch_size, None)))
    model.add(CuDNNLSTM(64, return_sequences=return_seq, stateful=stateful))
    model.add(Dense(1, activation='sigmoid'))

    model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'])
    return model

# train model with one label per sample
train_model = create_model()
train_model.fit(X_train, y_train, epochs=10, batch_size=128, validation_split=0.3)

# replicate the labels
y_train_rep = np.repeat(y_train, max_len).reshape(-1, max_len, 1)

# train model with one label per timestep
rep_train_model = create_model(True)
rep_train_model.fit(X_train, y_train_rep, epochs=10, batch_size=128, validation_split=0.3)
然后,我们可以创建训练模型的有状态副本,并在一些测试数据上运行它们,以比较它们的结果:

# replica of `train_model` with the same weights
test_model = create_model(False, True)
test_model.set_weights(train_model.get_weights())
test_model.reset_states()

# replica of `rep_train_model` with the same weights
rep_test_model = create_model(True, True)
rep_test_model.set_weights(rep_train_model.get_weights())
rep_test_model.reset_states()

def stateful_predict(model, samples):
    preds = []
    for s in samples:
        model.reset_states()
        ps = []
        for ts in s:
            p = model.predict(np.array([[ts]]))
            ps.append(p[0,0])
        preds.append(list(ps))
    return preds

X_test = pad_sequences(x_test, maxlen=max_len)
实际上,
X_检验
的第一个样本有一个0标签(即属于阴性类别),而
X_检验
的第二个样本有一个1标签(即属于阳性类别)。因此,让我们首先看看这两个样本的
测试_模型
(即,使用每个样本一个标签进行训练的模型)的状态预测是什么样的:

import matplotlib.pyplot as plt

preds = stateful_predict(test_model, X_test[0:2])

plt.plot(preds[0])
plt.plot(preds[1])
plt.legend(['Class 0', 'Class 1'])
结果是:

末尾的标签(即概率)正确(即时间步200),但在两者之间非常尖锐且波动。现在,让我们将其与
rep_test_模型的有状态预测进行比较(即,每个时间步使用一个标签进行训练的预测):

结果是:

同样,在最后,正确的标签预测,但这一次的趋势更加平滑和单调,正如预期的那样


请注意,这只是一个演示示例,因此我在这里使用了一个非常简单的模型,只有一个LSTM层,我根本没有尝试对其进行调整。我想,通过更好地调整模型(例如调整层的数量、每层中的单元数量、使用的激活函数、优化器类型和参数等),您可能会获得更好的结果。

训练精度如何?由于您使用的是
LeakyReLU
层,您是否尝试过为LSTM层设置
activation='linear'
?请不要使用“samples”而不是“timesteps”。它们是不同的东西,这会导致混乱。在您的示例中,每个样本(即序列)的形状为
(100,3)
,这意味着每个样本由100个时间步组成,其中每个时间步是长度为3的特征向量。此外,“数据的形状是
(m,100,3)
,其中
m
是批次数”有点错误:
m
是样本数(或者一个批次中的样本数),而不是批次数。每个批次可能由一个或多个样本组成。我不知道概率不应该波动或尖峰,并且随着我们处理更多的时间步长,概率应该单调增加或减少的说法是正确的还是错误的。但是,你必须考虑1)模型已经被训练在长度为100, 2的序列上。在看到所有100个时间步长之后,它已经被训练输出正确的标签;3)在训练期间,它不会为中间的时间步长产生任何输出。因此,我认为我们不应该期望预测阶段的中间输出具有特定的行为;我想我同意“今天”这个说法。我不这么认为
from keras.layers import *
from keras.models import Sequential, Model
from keras.datasets import imdb
from keras.preprocessing.sequence import pad_sequences
import numpy as np

vocab_size = 10000
max_len = 200
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=vocab_size)
X_train = pad_sequences(x_train, maxlen=max_len)

def create_model(return_seq=False, stateful=False):
    batch_size = 1 if stateful else None
    model = Sequential()
    model.add(Embedding(vocab_size, 128, batch_input_shape=(batch_size, None)))
    model.add(CuDNNLSTM(64, return_sequences=return_seq, stateful=stateful))
    model.add(Dense(1, activation='sigmoid'))

    model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'])
    return model

# train model with one label per sample
train_model = create_model()
train_model.fit(X_train, y_train, epochs=10, batch_size=128, validation_split=0.3)

# replicate the labels
y_train_rep = np.repeat(y_train, max_len).reshape(-1, max_len, 1)

# train model with one label per timestep
rep_train_model = create_model(True)
rep_train_model.fit(X_train, y_train_rep, epochs=10, batch_size=128, validation_split=0.3)
# replica of `train_model` with the same weights
test_model = create_model(False, True)
test_model.set_weights(train_model.get_weights())
test_model.reset_states()

# replica of `rep_train_model` with the same weights
rep_test_model = create_model(True, True)
rep_test_model.set_weights(rep_train_model.get_weights())
rep_test_model.reset_states()

def stateful_predict(model, samples):
    preds = []
    for s in samples:
        model.reset_states()
        ps = []
        for ts in s:
            p = model.predict(np.array([[ts]]))
            ps.append(p[0,0])
        preds.append(list(ps))
    return preds

X_test = pad_sequences(x_test, maxlen=max_len)
import matplotlib.pyplot as plt

preds = stateful_predict(test_model, X_test[0:2])

plt.plot(preds[0])
plt.plot(preds[1])
plt.legend(['Class 0', 'Class 1'])
preds = stateful_predict(rep_test_model, X_test[0:2])

plt.plot(preds[0])
plt.plot(preds[1])
plt.legend(['Class 0', 'Class 1'])