如何将 2D 和 1D 类(分别为单热编码和常规整数)的混合输入到 Keras 顺序模型中?

How does one input a mixture of 2D and 1D classes (one-hot encoded & regular integers respectively) into the Keras Sequential Model?

我有一个 pandas DataFrame,有 849743 行和 13 列,即形状为 (849743,13)。

这些列中的大多数只包含整数,但是,其中 3 个具有单热编码的分类变量。它们 不是 使用 Keras 或 sklearn(或任何其他库)的一次性 encoding/embedding 功能编码,我只是在 python 中手动完成。

例如,df['d'] 是一个带有单热编码变量的列,这里是摘录:

1082077    [0, 1, 0, 0, 0, 0, 0]
995216     [1, 0, 0, 0, 0, 0, 0]
924611     [0, 0, 0, 0, 1, 0, 0]
1171772    [0, 0, 0, 1, 0, 0, 0]
96796      [0, 0, 1, 0, 0, 0, 0]

请忽略无意义的 Pandas 索引。

这是列中的第一行:

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

可以看出,这个DataFrame的列的元素都是嵌套的numpy数组。

为了进一步了解 Pandas DataFrame 的结构,这里是第一个 的所有元素:

a                    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
b                                  [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
c                                                                     1
d                                                 [1, 0, 0, 0, 0, 0, 0]
e                                                               1.53079
f                                                             -0.415253
g                                                             -0.425906
h                                                             -0.355143
i                                                             -0.249699
j                                                              -0.13448
k                                                              0.882726
l                                                               1.23091

随后,我使用以下方法将其转换为 numpy 数组:

x_train = df.values

这保留了 DataFrame 的原始尺寸,即 (849743,13)。

我创建了一个荒谬的 Keras Sequential 模型只是为了测试输入是否有效,这就是我最初发现错误的方式。模型如下:

# create model
model = Sequential()
model.add(Dense(130, input_dim=13, kernel_initializer='normal', 
          activation='relu'))
model.add(Dense(1, kernel_initializer='normal'))
# Compile model
model.compile(loss='mean_squared_error', optimizer='adam')

input_dim 已设置为 13,因为 DataFrame/numpy 数组中有 13 列,但是,我认为问题出在 3 个单热编码中的嵌套 numpy 数组列。

我将原始的 13 列 numpy 数组(称为 x_train)与 y_train(观察变量)一起输入到 model.fit 函数中:

model.fit(x_train, y_train,
          epochs=20,
          batch_size=128)

我收到以下错误:

    Bad input argument to theano function with name "train_function" at index 0 (0-based).  
Backtrace when that variable is created:

  File "C:\Users\Studying\AppData\Local\conda\conda\envs\Tensorflow-gpu\lib\site-packages\spyder\utils\site\sitecustomize.py", line 101, in execfile
    exec(compile(f.read(), filename, 'exec'), namespace)
  File "C:/Users/Studying/Documents/GitHub/IFN665/Machine Learning/keras_regression_practice.py", line 106, in <module>
    model = baseline_model(input_shape)
  File "C:/Users/Studying/Documents/GitHub/IFN665/Machine Learning/keras_regression_practice.py", line 23, in baseline_model
    model.add(Dense(130, input_dim=1, kernel_initializer='normal', activation='relu'))
  File "C:\Users\Studying\AppData\Local\conda\conda\envs\Tensorflow-gpu\lib\site-packages\keras\models.py", line 432, in add
    dtype=layer.dtype, name=layer.name + '_input')
  File "C:\Users\Studying\AppData\Local\conda\conda\envs\Tensorflow-gpu\lib\site-packages\keras\engine\topology.py", line 1426, in Input
    input_tensor=tensor)
  File "C:\Users\Studying\AppData\Local\conda\conda\envs\Tensorflow-gpu\lib\site-packages\keras\legacy\interfaces.py", line 87, in wrapper
    return func(*args, **kwargs)
  File "C:\Users\Studying\AppData\Local\conda\conda\envs\Tensorflow-gpu\lib\site-packages\keras\engine\topology.py", line 1337, in __init__
    name=self.name)
  File "C:\Users\Studying\AppData\Local\conda\conda\envs\Tensorflow-gpu\lib\site-packages\keras\backend\theano_backend.py", line 222, in placeholder
    x = T.TensorType(dtype, broadcast)(name)
setting an array element with a sequence.

已经通过删除所有单热编码列并相应地调整input_dim变量来尝试它,它确实工作(在不会导致错误的意义上工作,该模型显然是垃圾预测器)。

我认为(尽管缺乏搜索)不可能有一个 numpy 数组,其中某些元素是二维的,有些是一维的,例如将嵌套的 numpy、单热编码数组更改为二维列表并允许所有其他变量保持一维。

我在这个网站上搜索过类似的问题,但是,我发现的关于 Keras 和单热编码变量的所有内容似乎都在询问它是什么,或者如何去做,不是 如何混合使用单热编码和一维整数输入。

如何做到这一点?我错过了一些明显的东西吗?

问题是因为您的数据不统一,当您将其转换为 NumPy 数组时,一些条目又是数组,即热编码的条目,这会导致形状/类型不匹配。根据您希望如何处理数据,您有 2 个选项:

  1. 展平内部数组,所以你的最终形状是(样本,>13)。通过展平我的意思是在 NumPy 数组中有更多列用于单热编码数据。一行看起来像混合体 [0,0,1,0,0,..., 2.3492,1.3483,...],因此形状是一致的。那么你的input_dim=len(data[0])
  2. 如果你真的想要单独的输入,也许你想以不同的方式处理它们,比如传递到不同的 Dense 层等,你将需要升级到 functional API。这将是一个多输入模型,文档对其进行了很好的解释。