在 keras 中使用 LSTM 进行预测

Posted

技术标签:

【中文标题】在 keras 中使用 LSTM 进行预测【英文标题】:prediction with LSTM in keras 【发布时间】:2021-09-15 13:12:16 【问题描述】:

我的 LSTM 遇到了问题。我想做的是:

我有一个表格中的数据集:

0.04,-9.77,0.71,1,0,0,0
...
...

前三个参数是加速度计采集的数据:X加速度、Y加速度、Z加速度

最后四列是标签:

[1,0,0,0] [0,1,0,0] [0,0,1,0] [0,0,0,1] [0,0,0,0]

每个代表一个不同的类。

我的网络声明如下:

 class Config:
        def __init__(self):
            """network parameters"""
            self.batch_size = 16
            self.input_size = 3
            self.seq_max_len = 20
            self.rnn_size = 50
            self.keep_prob = 1
            self.mlp_hidden_size = 100
            self.mlp_projection_activation = tf.nn.tanh
            self.num_classes = 4
            self.learning_rate = 0.001
            self.epochs = 10
    
    
        model = tf.keras.Sequential([
        tf.keras.layers.InputLayer(input_shape=(config.seq_max_len, config.input_size)),
        tf.keras.layers.LSTM(units=config.rnn_size, return_sequences=True, return_state=False),
        tf.keras.layers.Dense(units=config.mlp_hidden_size, activation=config.mlp_projection_activation),
        tf.keras.layers.Dense(units=config.num_classes, activation='softmax'),
    ])
    
    loss_fn = tf.keras.losses.CategoricalCrossentropy(from_logits=True)
    model.compile(optimizer='adam', loss=loss_fn, metrics=['accuracy'])
    
    model.fit(x_train, y_train, batch_size=config.batch_size, epochs=config.epochs)

现在,问题是这不像我想的那样工作。当我尝试预测时,假设使用数组:

arr = np.array([(-0.12,-9.85,0.82),(-1.33,-10,1.61),(-1.57,-10.04,0.9),(0.08,-9.14,0.51),(3.77,-8.36,-0.55),(6.71,-8.43,-1.69),
(9.22,-8.28,-2.63),(10.75,-7.65,-2.98),(9.26,-7.61,-2.35),(6.16,-7.85,-1.77),(2.35,-8.51,-0.78),(-1.10,-8.87,0.71),(-3.61,-9.14,2.31),
                (-5.49,-9.65,3.69),
                (-5.33,-9.49,3.14),
                (-4.24,-9.26,3.30),
                (-2.43,-9.06,2.24),
                (-0.39,-8.87,1.29),
                (3.61,-8.55,-1.22),
                (7.10,-8.28,-1.57)])

由 20 个三元组的 3d 向量(加速度)组成,我得到的是

predictions = model.predict_classes(arr)
[[0 2 2 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 0 0]]

这是一个向量,表示对 arr 向量中每个三元组的预测。我想要的是只有一个预测,在 20 个三元组之后。这是因为我的数据代表一个时间序列,我感兴趣的是知道网络是否能够在一定数量的加速向量(本例中为 20 个)之后对数据进行分类。

可以帮帮我吗?

编辑

完整代码:

import tensorflow as tf
import numpy as np
import pandas as pd
import random
import sys
np.set_printoptions(threshold=sys.maxsize)

def get_dataset(filename, config):
    df = pd.read_csv(filename, header=None, skiprows=1)
    x = df[[0, 1, 2]].values
    y = df[[3, 4, 5, 6]].values
    dataset_x, dataset_y = [],[]

    for i in range(x.shape[0]//config.seq_max_len):
        sequence_x, sequence_y = [],[]
        for j in range(config.seq_max_len):
            sequence_x.append(x[i*config.seq_max_len + j])
            sequence_y.append(y[i*config.seq_max_len + j])
        dataset_x.append(sequence_x)
        dataset_y.append(sequence_y)

    return np.array(dataset_x), np.array(dataset_y)


class Config:
    def __init__(self):
        """definizione dei parametri della rete"""
        self.batch_size = 16
        self.input_size = 3
        self.seq_max_len = 20
        self.rnn_size = 50
        self.keep_prob = 1
        self.mlp_hidden_size = 100
        self.mlp_projection_activation = tf.nn.tanh
        self.num_classes = 4
        self.learning_rate = 0.001
        self.epochs = 10

config = Config()

x_train, y_train = get_dataset('data_new.csv', config)

arr = np.array([(-0.12,-9.85,0.82),(-1.33,-10,1.61),(-1.57,-10.04,0.9),(0.08,-9.14,0.51),(3.77,-8.36,-0.55),(6.71,-8.43,-1.69),
(9.22,-8.28,-2.63),(10.75,-7.65,-2.98),(9.26,-7.61,-2.35),(6.16,-7.85,-1.77),(2.35,-8.51,-0.78),(-1.10,-8.87,0.71),(-3.61,-9.14,2.31),
                (-5.49,-9.65,3.69),
                (-5.33,-9.49,3.14),
                (-4.24,-9.26,3.30),
                (-2.43,-9.06,2.24),
                (-0.39,-8.87,1.29),
                (3.61,-8.55,-1.22),
                (7.10,-8.28,-1.57)])
arr2 = np.reshape(arr,(1,20,3))
print(arr2.shape)


model = tf.keras.Sequential([
    tf.keras.layers.InputLayer(input_shape=(config.seq_max_len, config.input_size)),
    tf.keras.layers.LSTM(units=config.rnn_size, return_sequences=True, return_state=False),
    tf.keras.layers.Dense(units=config.mlp_hidden_size, activation=config.mlp_projection_activation),
    tf.keras.layers.Dense(units=config.num_classes, activation='softmax'),
])


loss_fn = tf.keras.losses.CategoricalCrossentropy(from_logits=True)
model.compile(optimizer='adam', loss=loss_fn, metrics=['accuracy'])

model.fit(x_train, y_train, batch_size=config.batch_size, epochs=config.epochs)
predictions = model.predict(arr2)
predictions = np.argmax(predictions, axis=-1)
print("PREDIZIONI---------")
print(predictions.shape)
print(predictions)

【问题讨论】:

【参考方案1】:

有两个可能的问题。一个是如果你设置

tf.keras.layers.LSTM(units=.., return_sequences=True, return_state=False)

如果您在模型的最后一层打印model. summary(),您将得到如下结果。这可能不是你想要的最后一层。

dense_5 (Dense)              (None, 20, 4)             404       
=================================================================

所以,你应该使用return_sequence = False 来得到最终的层输出形状如下:

dense_7 (Dense)              (None, 4)                 404       
=================================================================

其次,您在损失函数中设置

 ....CategoricalCrossentropy(from_logits=True)

但您在最后一层设置activation='softma' 以获取概率而不是logits。

....Dense(units=config.num_classes, activation='softmax')

所以,基于此设置参数如下:

....LSTM(units=.., return_sequences=False, return_state=False)
...
....CategoricalCrossentropy(from_logits=False) # compute probabilities 
...
y_pred = model.predict(arr)
y_pred = np.argmax(y_pred, axis=-1)

【讨论】:

如果我尝试您的建议,我会得到:ValueError: Shapes (None, 20, 4) and (None, 4) are incompatible 模型的最后一层输出形状是什么?你的标签是什么形状的?两者都必须是形状大小,例如模型输出(None, 4) 和标签形状(None, 4) 你能用虚拟数据(在 colab 中)分享可重现的代码吗? drive.google.com/file/d/1S_G_lgElL3kOeK_k7vfVVlhfmE8sO1aC/… 这里是数据集 我已经在主要问题中添加了完整的代码

以上是关于在 keras 中使用 LSTM 进行预测的主要内容,如果未能解决你的问题,请参考以下文章

使用 LSTM 和 keras 进行时间序列预测的分类变量

Keras中的LSTM

如何让 Keras LSTM 在多变量设置中对多个时间序列进行预测?

如何处理keras中多元LSTM中的多步时间序列预测

使用 Keras LSTM 进行多步提前时间序列预测的多个输出

Keras LSTM 预测的时间序列被挤压和移位