LSTM 预处理:根据 ID 从 pandas 数据帧构建 3d 数组

2023-12-31

我是 keras 机器学习的新手,我计划进行一项机器学习实验,该实验基于具有 lstm 层的循环神经网络来预测视频游戏比赛中购买的前 10 件物品的序列。

假设一个示例表预先排序gameId,sideand timestamp给出:

       gameId   side   timestamp  itemId 
   3030038208    100        4260    1055 
   3030038208    100        4648    2010 
   3030038208    100        5036    3340 
   3030038208    100      291561    1001 
   3030038208    100      295807    1083 
   3030038208    100      296457    2010 
   3030038208    200        3257    1055 
   3030038208    200        3516    2003 
   3030038208    200        3775    3340 
   3030038208    200      321461    1038 
   3030038208    200      321818    2003 
   3030038208    200      321979    2003 
   3030038208    200      491099    3006 
   3030038208    200      492238    1042 
   3030038208    200      743864    3086 
   3030038208    200      744773    1043
         ....

我现在想将数据帧重塑为两个(x 和 y)3d numpy 数组,其中第三维描述购买序列的长度(ItemId) - 这样基本上结果序列中的每个 2d numpy 数组都构成了相同的表gameId, side pair

在训练神经网络之前,我还需要插入一个填充,因为上面提到的时间序列为 10。在本例中,填充值为 0 似乎没问题,但在实际场景中,我正在使用一个稀疏矩阵,其中包括很多0值。

现在有一些问题:

1)是否有 numpy、pandas 甚至 keras 的内置函数可以有效地实现我既定的目标。我想不出有什么东西不需要我花很长时间才能想出一个合理的预处理函数。

2)还有其他需要注意的事项吗?特别是在填充的情况下。在处理稀疏矩阵时,填写“-999”不是更有意义吗?

3)假设模型看起来像这样

model = Sequential()
model.add(LSTM(128, dropout=0.2, recurrent_dropout=0.2, input_dim=1))
model.add(Dense(y.shape[1], activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['acc'])
monitor = EarlyStopping(monitor='val_loss', min_delta=1e-3, patience=5, verbose=0, mode='auto')
checkpointer = ModelCheckpoint(filepath=filepath + "best_weights.hdf5", verbose=0, save_best_only=True)

With:

history = model.fit(x_train, y_train, epochs=2, validation_split=0.33, callbacks=[monitor, checkpointer], verbose=0).history

我如何才能正确使用遮罩层来处理填充?

预先感谢您在该线程上花费的任何时间!

edit: 根据要求,这里是我想得到的结果 numpy 数组(我认为),以便预测itemId基于timestamp使用 keras 中带有 lstm 层的神经网络填充前:

y = [
[1055, 2010, 3340, 1001, 1083, 2010],
[1055, 2003, 3340, 1038, 2003, 2003, 3006, 1042, 3086, 1043],
...
]

x = [
[[4260], [4648], [5036], [291561], [295807], [296457]],
[[3257], [3516], [3775], [321461], [321818], [321979], [491099], [492238], [743864], [744773] ],
...
]

and after填充:

y = [
[1055, 2010, 3340, 1001, 1083, 2010, 0, 0, 0, 0],
[1055, 2003, 3340, 1038, 2003, 2003, 3006, 1042, 3086, 1043],
...
]

x = [
[[4260], [4648], [5036], [291561], [295807], [296457], [0], [0], [0], [0]],
[[3257], [3516], [3775], [321461], [321818], [321979], [491099], [492238], [743864], [744773] ],
...
]

然而,在实际的例子中,除了时间戳之外,还会有更多的功能。


您可以通过几个步骤通过从 pandas groupby 对象中提取数据来实现此目的。在前两步中,我们将创建 groupby 对象,以便稍后在代码中对其进行操作。从groupby对象中,我们会找到最大的组,这样我们就可以相应地用零填充

gb = df.groupby(['gameId','side']) # Create Groupby object
mx = gb['side'].size().max() # Find the largest group

创建 x 和 y 的步骤非常相似。我们可以使用列表理解来循环每个组,将数据帧转换为 numpy 数组并使用零填充np.pad() https://docs.scipy.org/doc/numpy/reference/generated/numpy.pad.html。然后将每个数组重塑为 3d

x = np.array([np.pad(frame['timestamp'].values,
                     pad_width=(0,mx-len(frame)),
                     mode='constant',
                     constant_values=0) 
                     for _,frame in gb]).reshape(-1,mx,1)

y = np.array([np.pad(frame['itemId'].values,
                     pad_width=(0,mx-len(frame)),
                     mode='constant',
                     constant_values=0) 
                     for _,frame in gb]).reshape(-1,mx,1)

在此示例中,设置适用于多对多 lstm。在评论中,我指出您当前的设置不支持 3d 输出值,因为在 lstm 层中您没有参数return_sequence=True.

目前尚不清楚您在这个问题中寻找哪种结构。在决定使用哪个 LSTM 网络时,我喜欢参考下图。上面的代码将支持多对多网络,假设您添加return_sequence=True到你的 LSTM 层。如果您想要多对一,请放弃.reshape(-1,mx,1)来自 y,现在您有一个网络mx输出。


对于任一设置,您都需要修改input_shape你的模型的论点。该参数必须指定 x 的第二个和第三个维度的形状,即

                                                        # v Use input_shape here
model.add(LSTM(128, dropout=0.2, recurrent_dropout=0.2, input_shape=x.shape[1:]))
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

LSTM 预处理:根据 ID 从 pandas 数据帧构建 3d 数组 的相关文章