我想为我的分类特征构建一个带有嵌入的单层LSTM模型。我目前有数值特征和一些分类特征,例如位置,由于计算复杂性,不能使用pd.get_dummies()
进行一次性编码,这是我最初打算做的。
让我们想象一个例子:
示例数据
data = {
'user_id': [1,1,1,1,2,2,3],
'time_on_page': [10,20,30,20,15,10,40],
'location': ['London','New York', 'London', 'New York', 'Hong Kong', 'Tokyo', 'Madrid'],
'page_id': [5,4,2,1,6,8,2]
}
d = pd.DataFrame(data=data)
print(d)
user_id time_on_page location page_id
0 1 10 London 5
1 1 20 New York 4
2 1 30 London 2
3 1 20 New York 1
4 2 15 Hong Kong 6
5 2 10 Tokyo 8
6 3 40 Madrid 2
字符串
让我们看看访问网站的人。我跟踪的是数字数据,如页面上的时间等。分类数据包括:位置(超过1000个唯一),Page_id(> 1000个唯一),Author_id(100+个唯一)。最简单的解决方案是对所有内容进行one-hot编码,并将其放入具有可变序列长度的LSTM中,每个时间步长对应于不同的页面视图。
上面的DataFrame将生成7个训练样本,序列长度可变。例如,对于user_id=2
,我将有2个训练样本:
[ ROW_INDEX_4 ] and [ ROW_INDEX_4, ROW_INDEX_5 ]
型
假设X
是训练数据,让我们看看第一个训练样本X[0]
。
x1c 0d1x的数据
从上面的图片中,我的分类特征是X[0][:, n:]
。
在创建序列之前,我使用pd.factorize()
将分类变量分解为[0,1... number_of_cats-1]
,因此X[0][:, n:]
中的数据是与其索引对应的数字。
我是否需要为每个分类特征分别创建一个Embedding
?例如,为每个x_*n, x_*n+1, ..., x_*m
创建一个嵌入?
如果是,我如何将其放入Keras代码中?
model = Sequential()
model.add(Embedding(?, ?, input_length=variable)) # How do I feed the data into this embedding? Only the categorical inputs.
model.add(LSTM())
model.add(Dense())
model.add.Activation('sigmoid')
model.compile()
model.fit_generator() # fits the `X[i]` one by one of variable length sequences.
型
我的解决方案:
看起来像这样的东西:
的
我可以在每一个分类特征(m-n)上训练Word 2 Vec模型来向量化任何给定的值。例如,伦敦将在3维中向量化。让我们假设我使用3维嵌入。然后我将所有东西放回X矩阵,现在有n + 3(n-m),并使用LSTM模型来训练它?
我只是觉得应该有一个更简单/更聪明的方法。
2条答案
按热度按时间u59ebvdq1#
正如你提到的,一种解决方案是对分类数据进行独热编码(或者甚至以基于索引的格式使用它们),并将它们与数值数据一起沿着馈送到LSTM层。当然,这里也可以有两个LSTM层,一个用于处理数值数据,另一个用于处理分类数据(以独热编码格式或基于索引的格式),然后合并它们的输出。
另一种解决方案是为每个分类数据提供一个单独的嵌入层。每个嵌入层都可以有自己的嵌入维度(如上所述,您可以有多个LSTM层分别处理数值和分类特征):
字符串
以下是模型摘要:
型
还有另一种解决方案可以尝试:只为所有分类特征使用一个嵌入层。它涉及一些预处理:您需要重新索引所有类别,使它们彼此不同。例如,第一分类特征中的类别将从1到
size_first_cat
编号,然后第二分类特征中的类别将从size_first_cat + 1
编号到size_first_cat + size_second_cat
等等。然而,在这个解决方案中,所有的分类特征都将具有相同的嵌入维数,因为我们只使用一个嵌入层。**更新:**现在我想起来了,你也可以在数据预处理阶段甚至在模型中重塑分类特征,以摆脱
TimeDistributed
层和Reshape
层(这可能会提高训练速度):型
型号汇总:
型
至于拟合模型,你需要分别为每个输入层提供其对应的numpy数组,例如:
型
如果你想使用
fit_generator()
,没有区别:型
b4wnujal2#
我能想到的另一个解决方案是,你可以在将其提供给lstm之前,将数值特征(在标准化之后)和分类特征结合在一起。
在反向传播期间,允许梯度仅在嵌入层中流动,因为默认情况下梯度将在两个分支中流动。