gpt4 book ai didi

tensorflow - 使用 LSTM 进行多元二进制序列预测

转载 作者:行者123 更新时间:2023-12-04 01:49:21 29 4
gpt4 key购买 nike

我正在研究序列预测问题,但我在这方面没有太多经验,所以下面的一些问题可能很幼稚。

仅供引用:我创建了一个关注 CRF 的后续问题 here

我有以下问题:

我想预测多个非独立变量的二进制序列。

输入:

我有一个包含以下变量的数据集:

  • 时间戳
  • A组和B组
  • 对应于特定时间戳的每个组的二进制信号

  • 此外,假设以下情况:
  • 我们可以从时间戳(例如一天中的小时)中提取额外的属性,这些属性可以用作外部预测器
  • 我们认为 A 组和 B 组不是独立的,因此联合建模它们的行为可能是最佳的
  • binary_signal_group_Abinary_signal_group_B是我想使用(1)它们过去的行为和(2)从每个时间戳中提取的附加信息来预测的 2 个非独立变量。

    到目前为止我做了什么:
    # required libraries
    import re
    import numpy as np
    import pandas as pd
    from keras import Sequential
    from keras.layers import LSTM

    data_length = 18 # how long our data series will be
    shift_length = 3 # how long of a sequence do we want

    df = (pd.DataFrame # create a sample dataframe
    .from_records(np.random.randint(2, size=[data_length, 3]))
    .rename(columns={0:'a', 1:'b', 2:'extra'}))
    # NOTE: the 'extra' variable refers to a generic predictor such as for example 'is_weekend' indicator, it doesn't really matter what it is

    # shift so that our sequences are in rows (assuming data is sorted already)
    colrange = df.columns
    shift_range = [_ for _ in range(-shift_length, shift_length+1) if _ != 0]
    for c in colrange:
    for s in shift_range:
    if not (c == 'extra' and s > 0):
    charge = 'next' if s > 0 else 'last' # 'next' variables is what we want to predict
    formatted_s = '{0:02d}'.format(abs(s))
    new_var = '{var}_{charge}_{n}'.format(var=c, charge=charge, n=formatted_s)
    df[new_var] = df[c].shift(s)

    # drop unnecessary variables and trim missings generated by the shift operation
    df.dropna(axis=0, inplace=True)
    df.drop(colrange, axis=1, inplace=True)
    df = df.astype(int)
    df.head() # check it out

    # a_last_03 a_last_02 ... extra_last_02 extra_last_01
    # 3 0 1 ... 0 1
    # 4 1 0 ... 0 0
    # 5 0 1 ... 1 0
    # 6 0 0 ... 0 1
    # 7 0 0 ... 1 0
    # [5 rows x 15 columns]

    # separate predictors and response
    response_df_dict = {}
    for g in ['a','b']:
    response_df_dict[g] = df[[c for c in df.columns if 'next' in c and g in c]]

    # reformat for LSTM
    # the response for every row is a matrix with depth of 2 (the number of groups) and width = shift_length
    # the predictors are of the same dimensions except the depth is not 2 but the number of predictors that we have

    response_array_list = []
    col_prefix = set([re.sub('_\d+$','',c) for c in df.columns if 'next' not in c])
    for c in col_prefix:
    current_array = df[[z for z in df.columns if z.startswith(c)]].values
    response_array_list.append(current_array)

    # reshape into samples (1), time stamps (2) and channels/variables (0)
    response_array = np.array([response_df_dict['a'].values,response_df_dict['b'].values])
    response_array = np.reshape(response_array, (response_array.shape[1], response_array.shape[2], response_array.shape[0]))
    predictor_array = np.array(response_array_list)
    predictor_array = np.reshape(predictor_array, (predictor_array.shape[1], predictor_array.shape[2], predictor_array.shape[0]))

    # feed into the model
    model = Sequential()
    model.add(LSTM(8, input_shape=(predictor_array.shape[1],predictor_array.shape[2]), return_sequences=True)) # the number of neurons here can be anything
    model.add(LSTM(2, return_sequences=True)) # should I use an activation function here? the number of neurons here must be equal to the # of groups we are predicting
    model.summary()

    # _________________________________________________________________
    # Layer (type) Output Shape Param #
    # =================================================================
    # lstm_62 (LSTM) (None, 3, 8) 384
    # _________________________________________________________________
    # lstm_63 (LSTM) (None, 3, 2) 88
    # =================================================================
    # Total params: 472
    # Trainable params: 472
    # Non-trainable params: 0

    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) # is it valid to use crossentropy and accuracy as metric?
    model.fit(predictor_array, response_array, epochs=10, batch_size=1)
    model_preds = model.predict_classes(predictor_array) # not gonna worry about train/test split here
    model_preds.shape # should return (12, 3, 2) or (# of records, # of timestamps, # of groups which are a and b)

    # (12, 3)

    model_preds
    # array([[1, 0, 0],
    # [0, 0, 0],
    # [1, 0, 0],
    # [0, 0, 0],
    # [1, 0, 0],
    # [0, 0, 0],
    # [0, 0, 0],
    # [0, 0, 0],
    # [0, 0, 0],
    # [0, 0, 0],
    # [1, 0, 0],
    # [0, 0, 0]])

    问题:

    这里的主要问题是: 我如何让它工作,以便模型预测两组的下 N 个序列?

    另外,我想问以下几个问题:
  • 预计 A 组和 B 组是互相关的,但是,尝试通过单个模型输出 A 和 B 序列是否有效,或者我应该拟合 2 个单独的模型,一个预测 A,另一个预测 B,但都使用历史 A 和 B 数据作为输入?
  • 虽然我在模型中的最后一层是形状为 (None, 3, 2) 的 LSTM,但预测输出的形状为 (12, 3),而我预期它为 (12, 2) -- 我在做什么错在这里,如果是这样,我将如何解决这个问题?
  • 就输出LSTM层而言,这里使用激活函数是不是一个好主意,比如sigmoid?为什么/为什么不?
  • 使用分类类型损失(二进制交叉熵)和度量(准确性)来优化序列是否有效?
  • LSTM 模型是这里的最佳选择吗?有没有人认为 CRF 或一些 HMM 类型的模型在这里工作得更好?

  • 非常感谢!

    最佳答案

    我会依次回答所有问题

    how do I get this working so that the model would forecast the next N sequences for both groups?



    我建议对您的模型进行两次修改。
    第一 在最后一层使用 sigmoid 激活。

    为什么?? 考虑二元交叉熵损失函数(我从 here 借用了方程)
    eq
    哪里 L是计算损失, p是网络预测和 y是目标值。

    损失定义为 eq .
    如果 p 在这个开放区间范围之外,则损失是不确定的。 keras is tanh中lstm层的默认激活它的输出范围是 (-1, 1)。这意味着模型的输出不适合二元交叉熵损失。如果您尝试训练模型,您最终可能会得到 nan为损失。

    第二个修改(是第一次修改的一部分)要么在最后一层之前添加 sigmoid 激活。为此,您有三个选择。
  • 在输出和最后一个 lstm 层之间添加具有 sigmoid 激活的密集层。
  • 或者把lstm层的激活改为sigmoid。
  • 或者在输出层之后添加带有 sigmoid 激活的激活层。

  • 即使所有情况都可以工作,我还是建议使用带有 sigmoid 激活的密集层,因为它几乎总是效果更好。
    现在具有建议更改的模型将是
    model = Sequential()
    model.add(LSTM(8, input_shape=(predictor_array.shape[1],predictor_array.shape[2]), return_sequences=True))
    model.add(LSTM(2, return_sequences=True))
    model.add(TimeDistributed(Dense(2, activation="sigmoid")))
    model.summary()

    ... is it valid to attempt to output both A and B sequences by a single model or should I fit 2 separate models ... ?



    理想情况下,这两种情况都可以工作。但是最新的研究是这样的 this one表明前一种情况(您对两组使用单个模型)往往表现更好。该方法一般称为 Multi Task Learning .背后的理念 多任务学习 非常广泛,为简单起见,它可以被认为是通过强制模型学习多个任务常见的隐藏表示来增加归纳偏差。

    ... the prediction output is of shape (12, 3) when I would have expected it to be (12, 2) -- am I doing something wrong here ... ?



    你得到这个是因为你正在使用 predict_classes方法。与 predict 方法不同, predict_classes 方法返回 channel 轴的最大索引(在您的情况下为第三个索引)。正如我上面所解释的,如果您对最后一层使用 sigmoid 激活并将 predict_classes 替换为 predict,您将得到您所期望的。

    As far as the output LSTM layer is concerned, would it be a good idea to use an activation function here, such as sigmoid? Why/why not?



    我希望我已经在上面解释了这一点。答案是肯定的。

    Is it valid to use a classification type loss (binary cross-entropy) and metrics (accuracy) for optimizing a sequence?



    由于您的目标是二进制信号(分布为 Bernoulli distribution),是的,使用二进制损失和准确度指标是有效的。 This answer gives关于为什么二元交叉熵对此类目标变量有效的更多详细信息。

    Is an LSTM model an optimal choice here? Does anyone think that a CRF or some HMM-type model would work better here?



    这取决于可用数据和您选择的网络的复杂性。 CRF 和 HMM 网络很简单,如果可用数据很少,效果会更好。但是如果可用数据集很大,LSTM 几乎总是优于 CRF 和 HMM。我的建议是,如果您有大量数据,请使用 LSTM。但是如果你有小数据或寻找简单的模型,你可以使用 CRF 或 HMM。

    关于tensorflow - 使用 LSTM 进行多元二进制序列预测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53977695/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com