Python 用于文本生成的Keras LSTM不断重复一行或一个序列

Python 用于文本生成的Keras LSTM不断重复一行或一个序列,python,deep-learning,keras,lstm,recurrent-neural-network,Python,Deep Learning,Keras,Lstm,Recurrent Neural Network,我大致遵循了本教程: 一个显著的区别是,我使用了两个带有dropout的LSTM层。我的数据集不同(abc表示法中的音乐数据集)。我确实生成了一些歌曲,但在生成过程中经过一定数量的步骤(可能从30步到几百步)后,LSTM会一次又一次地生成完全相同的序列。例如,它曾经陷入为歌曲生成URL的困境: F: 等等 它也曾一度被困于生成相同的两首歌(这两首歌是一个大约300个字符的序列)。起初,它创作了3-4首好歌,但后来,它几乎无限期地重复这两首歌 我想知道,有人对可能发生的事情有什么见解吗? 我想澄

我大致遵循了本教程:

一个显著的区别是,我使用了两个带有dropout的LSTM层。我的数据集不同(abc表示法中的音乐数据集)。我确实生成了一些歌曲,但在生成过程中经过一定数量的步骤(可能从30步到几百步)后,LSTM会一次又一次地生成完全相同的序列。例如,它曾经陷入为歌曲生成URL的困境:

F:

等等

它也曾一度被困于生成相同的两首歌(这两首歌是一个大约300个字符的序列)。起初,它创作了3-4首好歌,但后来,它几乎无限期地重复这两首歌

我想知道,有人对可能发生的事情有什么见解吗?

我想澄清的是,无论是重复还是非重复生成的任何序列似乎都是新的(模型并没有记忆)。验证损失和培训损失按预期减少。 Andrej Karpathy能够生成一个包含数千个字符的文档,我无法找到这种无限期卡住的模式


不要在预测输出中使用argmax,尝试引入一些随机性,如下所示:

np.argmax(prediction_output)[0])

我在这个重复序列问题上苦苦挣扎了一段时间,直到我发现了这个Colab笔记本,在那里我找到了为什么他们的模型能够生成一些非常好的样本:


在我改变了这一行之后,我的模型从一次又一次地生成几个单词变成了一些真正有趣的东西

要使用和训练文本生成模型,请执行以下步骤:

  • 根据到目前为止可用的文本,从模型中得出下一个字符的概率分布(这将是我们的预测分数)
  • 重新称量分配至特定“温度”(见下面的代码)
  • 根据重新加权的分布随机采样下一个字符(参见下面的代码)
  • 在可用文本末尾添加新字符
  • 请参见示例函数:

    def sample(preds, temperature=1.0):
        preds = np.asarray(preds).astype('float64')
        preds = np.log(preds) / temperature
        exp_preds = np.exp(preds)
        preds = exp_preds / np.sum(exp_preds)
        probas = np.random.multinomial(1, preds, 1)
        return np.argmax(probas)
    
    在培训过程中,您应使用示例函数,如下所示:

    for epoch in range(1, 60):
        print('epoch', epoch)
        # Fit the model for 1 epoch on the available training data
        model.fit(x, y,
                  batch_size=128,
                  epochs=1)
    
        # Select a text seed at random
        start_index = random.randint(0, len(text) - maxlen - 1)
        generated_text = text[start_index: start_index + maxlen]
        print('--- Generating with seed: "' + generated_text + '"')
    
        for temperature in [0.2, 0.5, 1.0, 1.2]:
            print('------ temperature:', temperature)
            sys.stdout.write(generated_text)
    
            # We generate 400 characters
            for i in range(400):
                sampled = np.zeros((1, maxlen, len(chars)))
                for t, char in enumerate(generated_text):
                    sampled[0, t, char_indices[char]] = 1.
    
                preds = model.predict(sampled, verbose=0)[0]
                next_index = sample(preds, temperature)
                next_char = chars[next_index]
    
                generated_text += next_char
                generated_text = generated_text[1:]
    
                sys.stdout.write(next_char)
                sys.stdout.flush()
            print()
    
    低温会产生极其重复和可预测的文本,但本地结构非常真实:特别是,所有单词(单词是本地字符模式)都是真实的英语单词。随着温度的升高,生成的文本变得更有趣、更令人惊讶,甚至更有创意


    查看此

    尝试使用有状态模式来连接连续的几代人。嗯,我试图避免这种情况,但我会尝试。感谢您的建议:)我发现增加组成我的长序列的样本长度(子批次)会产生很大的差异,而不必使用stateful。一个可能值得尝试的简单修复方法。@Phil你能谈谈你的工作和观察结果吗?什么是应用程序域,输入序列在之前和之后有多长时间?在您增加输入的“回顾”大小之前,您的模型是否生成相同的输出?我很好奇,因为我现在面临着同样的问题@MarcinMożejko你能说更多关于为什么将
    stateful
    设置为True有助于防止模型记忆输入和循环返回看到的值吗?@duhaime我有一段时间没有接触过该项目,但下面是我可以从记忆中告诉你的。该域在时间序列的每一步生成多达16个参数(为语音生成提供声码器)。这就是说,我想我最终还是设法调试了有状态使用,但它并没有真正帮助我。如果您感兴趣,项目说明如下:
    for epoch in range(1, 60):
        print('epoch', epoch)
        # Fit the model for 1 epoch on the available training data
        model.fit(x, y,
                  batch_size=128,
                  epochs=1)
    
        # Select a text seed at random
        start_index = random.randint(0, len(text) - maxlen - 1)
        generated_text = text[start_index: start_index + maxlen]
        print('--- Generating with seed: "' + generated_text + '"')
    
        for temperature in [0.2, 0.5, 1.0, 1.2]:
            print('------ temperature:', temperature)
            sys.stdout.write(generated_text)
    
            # We generate 400 characters
            for i in range(400):
                sampled = np.zeros((1, maxlen, len(chars)))
                for t, char in enumerate(generated_text):
                    sampled[0, t, char_indices[char]] = 1.
    
                preds = model.predict(sampled, verbose=0)[0]
                next_index = sample(preds, temperature)
                next_char = chars[next_index]
    
                generated_text += next_char
                generated_text = generated_text[1:]
    
                sys.stdout.write(next_char)
                sys.stdout.flush()
            print()