我唯一可以同时做它们的时间是如果我将字符作为一个长序列传递([t,h,e,s,h,o,p,i,s,o,p,e ,n])
基本上,你要做的是:
- 将句子拆分成单词(每个句子都有(或将有)各自的
nn.Embedding)
- 将每个单词拆分为单个字母(本质上是添加另一个维度)
关于第二点
比较词级嵌入:
[商店正在营业]
这是一个例子,假设每个单词都用300 维向量编码。所以你得到了(1, 4, 300) 的形状(首先是批处理,还需要像往常一样使用 RNN 进行填充)。 这些数据可以直接进入一些 RNN 或类似的“文本”模型。
[[T,h,e], [s,h,o,p], [i,s], [o,p,e,n]]
在这种情况下,我们将有形状数据(假设50 单个字母的维向量)(1, 4, 4, 50)。 请注意,我已根据长度填充到最长的单词!
这样的输入不能进入RNNs,原因很明显(它是4D,而不是3D)。但是可以注意到,每个单词都可以独立处理(作为不同的样本),因此我们可以选择形状(4, 4, 50)(需要转置),其中第零维对应于单个单词,第一个对应于该单词中包含的字母,最后一个是向量维数。
批量数据
一般来说,字级编码非常简单,因为你总是有(batch, timesteps, embedding)。
对于字符级,你应该将你的数据形成(batch, word_timesteps, character_timesteps, embedding)形状的向量,它必须转换成(batch * word_timesteps, character_timesteps, embedding)。
这需要一些有趣的填充,并且批次的大小增长非常快,因此可能需要数据拆分。
字符级 LSTM 的输出
您应该得到 (batch * word_timesteps, network_embedding) 作为输出(记得从每个单词中获取最后一个时间步长!)。在我们的例子中,它将是 (4, 50)。
鉴于此,您可以将reshape 这个矩阵转换为(batch, timesteps, dimension)(在我们的例子中为(1, 4, 50))。
最后,您可以连接此嵌入与字级嵌入跨最后一维,得到(1, 4, 350) 输出矩阵的总和。您可以将其传递到另一个 RNN 层,或者您希望继续
附加点
如果您希望在字符级嵌入的单词之间保留信息,则必须将hidden_state 批量传递给N 元素(其中N 是句子中的单词数)。这可能有点困难,但应该是可行的,只要记住 LSTM 的有效容量为100-1000 AFAIK,而且长句很容易超过这个字母数。