Python深度学习之LSTM文本生成

本文介绍了使用Python和Keras实现LSTM字符级文本生成的过程,包括数据准备、网络构建和训练,探讨了不同的采样策略,并提到了基于词嵌入的文本生成方法。通过对尼采作品的训练,展示了如何生成具有特定风格的文本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Deep Learning with Python

这篇文章是我学习《Deep Learning with Python》(第二版,François Chollet 著) 时写的系列笔记之一。文章的内容是从 Jupyter notebooks 转成 Markdown 的,你可以去 GitHubGitee 找到原始的 .ipynb 笔记本。

你可以去这个网站在线阅读这本书的正版原文(英文)。这本书的作者也给出了配套的 Jupyter notebooks

本文为 第8章 生成式深度学习 (Chapter 8. Generative deep learning) 的笔记之一。

8.1 Text generation with LSTM

使用 LSTM 生成文本

以前有人说过:“generating sequential data is the closest computers get to dreaming”,让计算机生成序列是很有魅力的事情。我们将以文本生成为例,探讨如何将循环神经网络用于生成序列数据。这项技术也可以用于音乐的生成、语音合成、聊天机器人对话生成、甚至是电影剧本的编写等等。

其实,我们现在熟知的 LSTM 算法,最早被开发出来的时候,就是用于逐字符地生成文本的。

序列数据的生成

用深度学习生成序列的通用方法,就是训练一个网络(一般用 RNN 或 CNN),输入前面的 Token,预测序列中接下来的 Token。

说的术语化一些:给定前面的 Token,能够对下一个 Token 的概率进行建模的网络叫作「语言模型(language model)」。语言模型能够捕捉到语言的统计结构 ——「潜在空间(latent space)」。训练好一个语言模型,输入初始文本字符串(称为「条件数据」,conditioning data),从语言模型中采样,就可以生成新 Token,把新的 Token 加入条件数据中,再次输入,重复这个过程就可以生成出任意长度的序列。

我们从一个简单的例子开始:用一个 LSTM 层,输入文本语料的 N 个字符组成的字符串,训练模型来生成第 N+1 个字符。模型的输出是做 softmax,在所有可能的字符上,得到下一个字符的概率分布。这个模型叫作「字符级的神经语言模型」(character-level neural language model)。

使用语言模型逐个字符生成文本的过程

采样策略

使用字符级的神经语言模型生成文本时,最重要的问题是如何选择下一个字符。这里有几张常用方法:

  • 贪婪采样(greedy sampling):始终选择可能性最大的下一个字符。这个方法很可能得到重复的、可预测的字符串,而且可能意思不连贯。(输入法联想)
  • 纯随机采样:从均匀概率分布中抽取下一个字符,其中每个字符的概率相同。这样随机性太高,几乎不会生成出有趣的内容。(就是胡乱输出字符的组合)
  • 随机采样(stochastic sampling):根据语言模型的结果,如果下一个字符是 e 的概率为 0.3,那么你会有 30% 的概率选择它。有一点的随机性,让生成的内容更随意富有变化,但又不是完全随机,输出可以比较有意思。

随机采样看上去很好,很有创造性,但有个问题是无法控制随机性的大小:随机性越大,可能富有创造性,但可能胡乱输出;随机性越小,可能更接近真实词句,但太死板、可预测。

为了在采样过程中控制随机性的大小,引入一个参数:「softmax 温度」(softmax temperature),用于表示采样概率分布的熵,即表示所选择的下一个字符会有多么出人意料或多么可预测:

  • 更高的温度:熵更大的采样分布,会生成更加出人意料、更加无结构的数据;
  • 更低的温度:对应更小的随机性,会生成更加可预测的数据。

对同一个概率分布进行不同的重新加权:更低的温度=更确定,更高的温度=更随机

具体的实现是,给定 temperature 值,对模型的 softmax 输出重新加权,得到新的概率分布:

import numpy as np

def rewight_distribution(original_distributon, temperature=0.5):
    '''
    对于不同的 softmax 温度,对概率分布进行重新加权
    '''
    distribution = np.log(original_distribution) / temperature
    distribution = np.exp(distribution)
    return distribution / np.sum(distribution)

字符级 LSTM 文本生成实现

理论就上面那些了,现在,我们要用 Keras 来实现字符级的 LSTM 文本生成了。

数据准备

首先,我们需要大量的文本数据(语料,corpus)来训练语言模型。可以去找足够大的一个或多个文本文件:维基百科、各种书籍等都可。这里我们选择用一些尼采的作品(英文译本),这样我们学习出来的语言模型将是有尼采的写作风格和主题的。(插:我,我以前自己写野生模型玩,都是用鲁迅😂)

# 下载语料,并将其转换为全小写

from tensorflow import keras
import numpy as np

path = keras.utils.get_file(
    'nietzsche.txt', 
    origin='https://s3.amazonaws.com/text-datasets/nietzsche.txt')
text = open(path).read().lower()
print('Corpus length:', len(text))
Downloading data from https://s3.amazonaws.com/text-datasets/nietzsche.txt
606208/600901 [==============================] - 43s 71us/step
Corpus length: 600893

接下来,我们要把文本做成数据 (向量化):从 text 里提取长度为 maxlen 的序列(序列之间存在部分重叠),进行 one-hot 编码,然后打包成 (sequences, maxlen, unique_characters) 形状的。同时,还需要准备数组 y,包含对应的目标,即在每一个所提取的序列之后出现的字符(也是 one-hot 编码的):

# 将字符序列向量化

maxlen = 60     # 每个序列的长度
step = 3        # 每 3 个字符采样一个新序列
sentences = []  # 保存所提取的序列
next_chars = [] # sentences 的下一个字符

for i in range(0, len(text) - maxlen, step):
    sentences.append(text[i: i+maxlen])
    next_chars.append(text[i+maxlen])
print('Number of sequences:', len(sentences))

chars = sorted(list(set(text)))
char_indices = dict((char, chars.index(char)) for char in chars)
# 插:上面这两行代码 6
print('Unique characters:', len(chars))

print('Vectorization...')

x = np.zeros((len(sentences), maxlen, len(chars)), dtype=np.</
### Python 中实现深度学习 BiLSTM 的方法 #### 1. BiLSTM 基本原理 BiLSTM 是一种双向循环神经网络结构,它结合了前向 LSTM 和反向 LSTM 来捕捉时间序列中的上下文信息。这种设计使得模型能够同时利用过去和未来的信息来增强特征表达能力[^2]。 #### 2. 使用 Keras 实现 BiLSTM 模型 Keras 提供了一个简单而强大的接口用于构建复杂的神经网络模型,其中包括 BiLSTM 模型。以下是基于 Keras 的 BiLSTM 模型的具体实现: ```python import numpy as np from tensorflow import keras from tensorflow.keras import layers # 定义模型架构 model = keras.Sequential() model.add(layers.Bidirectional( layers.LSTM(64, return_sequences=True), input_shape=(10, 1))) model.add(layers.Bidirectional(layers.LSTM(64))) model.add(layers.Dense(32, activation='relu')) model.add(layers.Dense(1)) # 编译模型 model.compile(optimizer='adam', loss='mse') # 打印模型摘要 print(model.summary()) ``` 上述代码定义了一种典型的 BiLSTM 结构,其中 `layers.Bidirectional` 将前向和后向的 LSTM 层组合在一起[^1]。该模型适用于具有固定长度的时间序列数据,并最终输出单个数值预测结果。 #### 3. 数据准备与训练过程 为了使 BiLSTM 模型正常工作,需要准备好适当格式的数据集并对其进行预处理。通常情况下,时间序列数据会被转换成三维张量 `(样本数, 时间步长, 特征维度)` 形式。以下是一个简单的例子展示如何生成模拟数据以及执行模型拟合操作: ```python # 创建虚拟数据 X_train = np.random.rand(1000, 10, 1).astype(np.float32) y_train = np.sin(X_train[:, :, 0]).sum(axis=1) # 训练模型 history = model.fit(X_train, y_train, epochs=10, batch_size=32, validation_split=0.2) ``` 在此示例中,我们随机生成了一些正弦波形式的目标变量作为目标值来进行回归任务的学习测试。 #### 4. 应用场景分析 BiLSTM 广泛应用于自然语言处理 (NLP)、语音识别等领域,在这些领域里往往存在较强的顺序关系或者历史依赖特性。例如情感分类问题可以借助于文本嵌入技术提取单词级别的语义特征之后再送入到 BiLSTM 进行进一步加工得到更深层次的理解;而在金融数据分析方面,则可能用来做股票价格走势预测等工作。 #### 5. 性能优化建议 - **调整超参数**:尝试不同的隐藏单元数量、层数以及其他配置选项找到最适合具体应用场景的最佳设置。 - **增加正则化手段**:如果发现过拟合现象严重的话可以通过加入 Dropout 或 L2 正则项等方式缓解这一状况。 - **采用早停策略(Early Stopping)** :当验证集上的表现不再提升时提前终止迭代以节省计算资源同时也防止过度拟合训练集合本身特点而非真实分布规律。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值