使用LSTM生成助记符 | 如何确保我的模型使用损失函数生成有意义的句子?

我正在进行一个生成助记符的项目。我的模型遇到了问题。

我的问题是,如何确保我的模型使用损失函数生成有意义的句子?

项目的目标

为一个词汇列表生成助记符。给定用户想要记住的一个词汇列表,模型将输出一个有意义、简单且易于记忆的句子,该句子包含用户想要记住的词汇的前一两个字母。模型只接收用户想要记住的词汇的前两个字母,因为这些字母包含了生成助记符所需的所有信息。enter image description here

数据集

我正在使用Kaggle的55000+歌词数据,这些歌词中的句子包含5到10个词,而我想生成的助记符也包含相同数量的词。

输入/输出预处理

我正在迭代处理所有句子,移除标点符号和数字,并从每个句子的每个词中提取前两个字母,并从预定义的字典中为这些字母对分配一个唯一编号,该字典包含键值对,其中键为字母对,值为唯一编号。这些唯一编号的列表将作为输入,而这些词的GloVe向量将作为输出。在每个时间步,LSTM模型将接收这些分配给词的唯一编号,并输出相应词的GloVe向量。

enter image description here

模型架构

我正在使用10个时间步的LSTM。在每个时间步,输入将是与字母对关联的唯一编号,输出将是相应词的GloVe向量。

enter image description here

optimizer=rmsprop(lr=0.0008)model=Sequential()model.add(Embedding(input_dim=733,output_dim=40,input_length=12))model.add(Bidirectional(LSTM(250,return_sequences=True,activation='relu'),merge_mode='concat'))Dropout(0.4)model.add(Bidirectional(LSTM(350,return_sequences=True,activation='relu'),merge_mode='concat'))Dropout(0.4)model.add(TimeDistributed(Dense(332, activation='tanh')))model.compile(loss='cosine_proximity',optimizer=optimizer,metrics=['acc'])

结果:

我的模型输出的助记符与输入中每个词的前两个字母匹配。但生成的助记符几乎没有意义。我意识到这个问题是由于我的训练方式造成的。词汇的字母提取顺序已经准备好用于句子形成,但在测试时情况并非如此。我输入的词汇字母提取顺序可能没有形成句子的高概率。因此,我为我的数据构建了一个二元模型,并将具有最高句子形成概率的排列输入到我的助记符生成模型中。尽管有了一些改进,但整个句子仍然没有任何意义。我现在卡在这里了。

输入

输入

输出

输出

我的问题是,

如何确保我的模型生成有意义的句子?使用损失函数


回答:

首先,我有一些不相关的建议。我认为你不应该输出每个词的GloVe向量。为什么?Word2Vec方法旨在封装词的含义,可能不会包含关于其拼写的信息。然而,含义也有助于生成有意义的句子。因此,我建议让LSTM在读取每个词的前两个字母后生成自己的隐藏状态(就像你目前所做的那样)。然后,我会将该序列展开(就像你目前所做的那样)成维度为1的序列(索引到词的映射)。然后,我会将该输出通过一个嵌入层处理,该层将词索引映射到它们的GloVe嵌入,并通过另一个输出LSTM生成更多的索引。你可以根据需要堆叠这些层 – 但2到3层应该足够了。

即使有了这些更改,要生成易于记忆的句子仍然不太可能。对于这个主要问题,我认为一般有两种方法。第一种是通过某种方式增强你的损失函数,使生成的句子成为’有效的英文句子’。你可以通过POS标记输出句子,并根据它是否遵循标准句子结构(主语谓语状语直接宾语等)来增加损失。这种方法可能比下面的替代方法更容易实现,但可能不会产生真正自然的结果。

我建议,除了以当前方式训练你的模型外,还可以使用GAN来判断输出句子是否是自然句子。有许多关于Keras GANs的资源,所以我认为你不需要在答案中提供具体代码。然而,以下是你的模型逻辑上应该如何训练的概要:

  1. 在当前训练中增加两个额外的阶段。
    • 首先训练鉴别器来判断输出句子是否自然。你可以通过让LSTM模型读取句子并给出一个sigmoid输出(0/1)来判断它们是否’自然’。然后,你可以在这个数据集上训练这个模型,使用真实句子标记为1,你的句子标记为0,大约50/50的比例。
    • 然后,除了当前用于实际生成助记符的损失函数外,增加一个损失函数,即生成句子的二元交叉熵得分,标记为1(真)。显然,在进行此操作时要冻结鉴别器模型。

继续迭代这两个步骤(每次训练一个epoch),直到你开始看到更合理的结果。你可能需要调整生成器(你的模型)中每个损失项的权重,以获得正确平衡正确的助记符和易于记忆的句子之间的权衡。

Related Posts

在使用k近邻算法时,有没有办法获取被使用的“邻居”?

我想找到一种方法来确定在我的knn算法中实际使用了哪些…

Theano在Google Colab上无法启用GPU支持

我在尝试使用Theano库训练一个模型。由于我的电脑内…

准确性评分似乎有误

这里是代码: from sklearn.metrics…

Keras Functional API: “错误检查输入时:期望input_1具有4个维度,但得到形状为(X, Y)的数组”

我在尝试使用Keras的fit_generator来训…

如何使用sklearn.datasets.make_classification在指定范围内生成合成数据?

我想为分类问题创建合成数据。我使用了sklearn.d…

如何处理预测时不在训练集中的标签

已关闭。 此问题与编程或软件开发无关。目前不接受回答。…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注