31、自然语言理解与生成问题的深度学习应用

自然语言理解与生成问题的深度学习应用

1. 机器翻译

机器翻译(MT)是自然语言理解(NLU)领域广为人知的应用。研究人员和科技巨头们正大量试验,试图打造一个能翻译任何语言的单一机器翻译系统,即通用机器翻译系统。长远目标是构建一个既能将英语翻译成德语,又能将英语翻译成法语的系统。下面来看看研究人员为构建通用机器翻译系统所做的努力和实验。

1954 年,首次进行了机器翻译演示,实现了 250 个俄语和英语单词的翻译。这是基于词典的方法,通过源语言和目标语言的单词映射来进行翻译,逐词翻译,无法捕捉句法信息,因此准确性不佳。

随后出现了中间语言方法,该方法将源语言转换为一种中间语言,对源语言的句法、语法等规则进行编码和表示,再从中间语言生成目标语言。与第一种方法相比,这种方法有所改进,但很快被统计机器翻译(SMT)技术取代。

IBM 使用了 SMT 方法,将文本分割成片段,然后与对齐的双语语料库进行比较,再利用统计技术和概率选择最可能的翻译。世界上最常用的 SMT 是谷歌翻译,最近谷歌发表论文称其机器翻译系统使用深度学习取得了很好的效果。

我们使用电影字幕作为数据集,该数据集包含德语和英语。我们将构建一个能实现德语和英语互译的模型。可以从 http://opus.lingfil.uu.se/OpenSubtitles.php 下载数据,这里使用 pickle 格式的数据,借助 Python 的 pickle 依赖库可以对数据集进行序列化。

以下是构建模型的步骤:
1. 数据预处理 :使用 LSTM 网络来处理长短期依赖关系,利用 TensorFlow 的内置 data_utils 类对数据进行预处理。
2. 定义词汇表大小 :由于数据集词汇量较小,可考虑使用数据集中的所有单词,但也可定义如 30,000 个单词的词汇表大小,即使用一小部分训练数据集。使用 data_utils 类从数据目录读取数据,该类会提供两种语言的分词和格式化后的单词。
3. 定义编码器和解码器 :定义 TensorFlow 的占位符作为编码器和解码器的输入,它们是表示离散值的整数张量,并嵌入到密集表示中。将词汇表中的单词输入编码器,将学习到的编码表示输入解码器。代码可参考这个 GitHub 链接:https://github.com/jalajthanaki/NLPython/tree/master/ch9/MT/Machine_Translation_GR_EN 。

下面是机器翻译模型构建的流程图:

graph TD;
    A[下载数据集] --> B[数据预处理];
    B --> C[定义词汇表大小];
    C --> D[定义编码器和解码器];
    D --> E[构建模型];
2. 编码器 - 解码器系统

谷歌最近发表论文讨论了其集成到翻译系统中的神经机器翻译(NMT),这是一种基于编码器 - 解码器的新架构。以前,谷歌先将语言 A 翻译成英语,再从英语翻译成语言 B,现在谷歌翻译可以直接在两种语言之间进行翻译。

使用简单的基于 LSTM 的编码器 - 解码器架构时,可使用 LSTM 循环神经网络对语言 A 的句子进行编码,RNN 会分割出一个隐藏状态 S,它代表句子的向量化内容,然后将这个向量化形式传递给解码器,逐词生成语言 B 的翻译句子。然而,这种架构存在一些缺点,它的记忆能力有限,LSTM 的隐藏状态 S 通常只有几百个浮点数长,需要将整个待翻译的句子塞进这个固定维度中,若强制句子适应这个固定维度,网络会损失更多信息。虽然可以增加 LSTM 的隐藏大小来处理长时依赖,但这会使训练时间呈指数级增长,因此不建议使用收敛时间过长的架构。

为解决上述问题,引入了基于注意力机制的编码器 - 解码器模型。就像人类翻译长句子时会多次回看源句子以确保捕捉所有细节一样,我们希望神经网络也能存储和参考 LSTM 的先前输出。当存储了编码器的 LSTM 输出后,可以查询每个输出与解码器当前计算的相关性,每个编码器输出会得到一个相关性分数,可使用 softmax 激活函数将其转换为概率分数,然后提取一个上下文向量,它是编码器输出的加权求和,权重取决于相关性。

要实现基于注意力机制的功能,可使用 TensorFlow 的内置嵌入注意力序列到序列函数,该函数将编码器和解码器的输入作为参数,还需要一些额外的超参数。代码片段可参考相关文档。也可参考这个链接 https://www.tensorflow.org/tutorials/seq2seq 运行机器翻译示例,而无需编写自定义代码。具体操作步骤如下:
1. 从 http://www.statmt.org/wmt10/training-giga-fren.tar 下载 2.4GB 的训练数据集 giga-fren.tar。
2. 将数据存储在 data_dir 目录中,并定期保存训练好的模型,为此需要在 train_dir 中创建一个检查点目录。
3. 执行命令:python translate.py –data_dir [your_data_directory] –train_dir [checkpoints_directory] –en_vocab_size=40000 –fr_vocab_size=40000。
4. 如果上述命令占用大量 GPU 内存,可执行命令:python translate.py –data_dir [your_data_directory] –train_dir [checkpoints_directory] –size=256 –num_layers=2 –steps_per_checkpoint=50。
5. 当训练轮数达到 340K 且批量大小为 64 时,可使用模型进行翻译,在此之前也可使用,但准确性会有所不同。执行命令:python translate.py –decode –data_dir [your_data_directory] –train_dir [checkpoints_directory] 。

我们的德语 - 英语翻译模型只进行一轮训练就能得到相当不错的结果,但要达到谷歌翻译的准确性,需要使用如 100 个 GPU 连续运行数周来训练模型。

若输出没有为编码的源句子提供足够的上下文信息,模型就无法给出好的翻译结果。此时,需要提供关于未来单词的信息,使编码器的输出由左右两侧的单词决定。在机器层面,可通过包含双向编码器来实现,它包含两个循环神经网络(RNN),一个正向遍历句子,另一个反向遍历,对于每个单词,将两个方向的向量输出拼接起来,得到包含两侧上下文的向量。谷歌的模型在编码器中包含一个双向 RNN 层和七个单向层,解码器有八个单向 RNN 层。增加层数会增加训练时间,这里只使用一个双向层,因为如果所有层都是双向的,整个层在其他层依赖开始计算之前必须完成计算,而单向层可以并行计算。

3. 深度学习技术与自然语言生成(NLG)

接下来将构建一个简单但直观的 NLG 应用,为短文章生成一句话摘要。这个应用训练时间较长,可将模型放在 CPU 上训练,同时做其他事情。

这里有一个练习,尝试通过提供一些起始字符序列来生成维基百科文章。可使用的数据集为:https://einstein.ai/research/the-wikitext-long-term-dependency-language-modeling-dataset ,下载名为 Download WikiText - 103 word level(181 MB)的数据集。提示可参考链接:https://github.com/kumikokashii/lstm-text-generator 。

4. 食谱摘要生成与标题生成

在开始编码之前,先了解一下文本摘要的背景知识。语义在自然语言处理中非常重要,随着文本数据密度的增加,信息也会增多。如今,人们希望能在短时间内有效地说出最重要的事情。

文本摘要始于 90 年代,加拿大政府构建了一个名为预测生成器(FoG)的系统,它利用天气预报数据生成摘要,这是一种基于模板的方法,机器只需填充某些值。例如,“Saturday will be sunny with 10% chances of rain”,其中“sunny”和“10%”是由 FoG 生成的。摘要在金融、医疗等领域也有重要应用,在现代,医生发现对患者病史进行摘要总结非常有用,能更高效地诊断病情。

文本摘要主要有两种类型:
| 摘要类型 | 说明 |
| ---- | ---- |
| 抽取式 | 从文章中选择现有的一组单词来创建摘要。 |
| 抽象式 | 构建对所读内容的内部语义表示,再根据该表示进行文本摘要。 |

过去大多数摘要工具是抽取式的,而人类在总结时会采用抽象式方法。下面使用 Keras 构建一个抽象式摘要工具,Keras 是 TensorFlow 和 Theano 的高级包装器,这个示例需要多个 GPU 运行超过 12 小时,如果要在本地复现结果,需要强大的计算能力。

以下是编码的步骤:
1. 克隆 GitHub 仓库:https://github.com/jalajthanaki/recipe - summarization 。
2. 初始化子模块:git submodule update –init -recursive 。
3. 进入文件夹:python src/config.p 。
4. 安装依赖项:pip install -r requirements.txt 。
5. 设置目录:python src/config.py 。
6. 从网络抓取食谱或使用现有链接的食谱:wget -P recipe - box/data https://storage.googleapis.com/recipe - box/recipes_raw.zip; unzip recipe - box/data/recipes_raw.zip -d recipe - box/data 。
7. 对数据进行分词:python src/tokenize_recipes.py 。
8. 使用 GloVe 向量初始化单词嵌入:
- 获取 GloVe 向量训练模型:wget -P data http://nlp.stanford.edu/data/glove.6B.zip; unzip data/glove.6B.zip -d data 。
- 初始化嵌入:python src/vocabulary - embedding.py 。
9. 训练模型:python src/train_seq2seq.py 。
10. 进行预测:use src/predict.ipynb 。

这里使用 GloVe 进行向量化,因为我们希望为摘要任务获得单词的全局表示,并使用序列到序列模型(Seq2Seq 模型)训练数据,该模型与机器翻译部分讨论的模型相同。

如果本地机器内存不足,可使用谷歌云、亚马逊网络服务(AWS)等云服务。此外,还有一个与 NLG 领域相关的应用可参考 GitHub 链接:https://github.com/tensorflow/models/tree/master/im2txt ,该应用为图像生成标题,是计算机视觉和 NLG 的结合应用。

下面是食谱摘要生成的流程图:

graph TD;
    A[克隆仓库] --> B[初始化子模块];
    B --> C[进入文件夹];
    C --> D[安装依赖项];
    D --> E[设置目录];
    E --> F[抓取或使用食谱数据];
    F --> G[数据分词];
    G --> H[初始化单词嵌入];
    H --> I[训练模型];
    I --> J[进行预测];

自然语言理解与生成问题的深度学习应用

5. 梯度下降优化策略

在深度学习中,优化算法的选择对模型的训练效果和效率至关重要。TensorFlow 为我们提供了多种基于梯度下降算法的变体。了解这些不同变体的工作原理、优缺点后,我们就能更轻松地为深度学习算法的优化选出最佳选项。

梯度下降算法的基本思想是通过计算损失函数关于模型参数的梯度,然后沿着梯度的反方向更新参数,逐步降低损失函数的值,从而找到模型的最优参数。以下是几种常见的梯度下降算法变体及其特点:
| 算法名称 | 说明 | 优点 | 缺点 |
| ---- | ---- | ---- | ---- |
| 随机梯度下降(SGD) | 每次只随机选择一个样本计算梯度并更新参数 | 计算速度快,适合大规模数据集 | 收敛过程可能不稳定,易陷入局部最优 |
| 小批量梯度下降(Mini - Batch SGD) | 每次选择一小批量样本计算梯度并更新参数 | 结合了 SGD 的速度和批量梯度下降的稳定性 | 超参数(批量大小)的选择需要经验 |
| 动量梯度下降(Momentum) | 在更新参数时,除了考虑当前梯度,还考虑之前的梯度方向 | 加速收敛,减少震荡 | 可能会跳过局部最优,但也可能错过全局最优 |
| Adagrad | 根据每个参数的历史梯度平方和自适应调整学习率 | 自动调整学习率,适合处理稀疏数据 | 学习率可能会过早减小,导致收敛变慢 |
| Adadelta | 改进了 Adagrad 学习率过早减小的问题 | 无需手动设置全局学习率 | 实现相对复杂 |
| Adam | 结合了动量梯度下降和 Adagrad 的优点,自适应调整学习率 | 收敛速度快,效果好,广泛应用 | 计算复杂度较高,内存需求较大 |

在实际应用中,选择合适的优化算法需要根据具体的任务和数据集来决定。例如,如果数据集非常大,SGD 或 Mini - Batch SGD 可能是不错的选择;如果希望加速收敛并减少震荡,动量梯度下降或 Adam 可能更合适。

以下是一个使用 TensorFlow 实现简单梯度下降优化的示例代码:

import tensorflow as tf

# 定义模型参数
W = tf.Variable([.3], dtype=tf.float32)
b = tf.Variable([-.3], dtype=tf.float32)

# 定义输入和输出
x = tf.placeholder(tf.float32)
linear_model = W * x + b
y = tf.placeholder(tf.float32)

# 定义损失函数
loss = tf.reduce_sum(tf.square(linear_model - y))

# 选择优化器
optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)

# 训练数据
x_train = [1, 2, 3, 4]
y_train = [0, -1, -2, -3]

# 训练模型
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)
for i in range(1000):
    sess.run(train, {x: x_train, y: y_train})

# 输出训练后的参数
curr_W, curr_b, curr_loss = sess.run([W, b, loss], {x: x_train, y: y_train})
print("W: %s b: %s loss: %s" % (curr_W, curr_b, curr_loss))

下面是梯度下降优化过程的流程图:

graph TD;
    A[定义模型参数和损失函数] --> B[选择优化器];
    B --> C[初始化参数];
    C --> D[输入训练数据];
    D --> E[计算梯度并更新参数];
    E --> F{是否达到收敛条件};
    F -- 否 --> D;
    F -- 是 --> G[输出最优参数];
6. 总结与展望

通过前面的介绍,我们了解了自然语言处理中机器翻译和自然语言生成的相关技术,以及深度学习中的梯度下降优化策略。在机器翻译方面,从早期的基于词典和中间语言的方法,发展到如今的神经机器翻译,模型的性能和翻译质量有了显著提升。基于注意力机制的编码器 - 解码器模型解决了传统 LSTM 架构记忆能力有限的问题,使翻译更加准确和流畅。

在自然语言生成领域,我们学习了如何使用 Keras 构建抽象式摘要工具,为短文章生成摘要。同时,还了解到图像生成标题等结合计算机视觉和 NLG 的应用,展示了 NLG 的广泛应用前景。

而梯度下降优化策略则是深度学习训练过程中的关键环节,不同的优化算法各有优缺点,需要根据具体情况进行选择。

未来,随着硬件计算能力的不断提升和算法的不断创新,自然语言处理和深度学习技术有望取得更大的突破。例如,通用机器翻译系统可能会更加完善,能够实现更高效、准确的跨语言翻译;自然语言生成的质量也会进一步提高,生成的文本更加自然、连贯。同时,新的优化算法可能会不断涌现,提高深度学习模型的训练效率和性能。

总之,自然语言处理和深度学习领域充满了机遇和挑战,我们需要不断学习和探索,以跟上技术发展的步伐。

希望通过本文的介绍,能帮助读者更好地理解自然语言处理和深度学习中的相关技术,并在实际应用中选择合适的方法和工具。如果你对这些内容感兴趣,可以进一步深入研究相关的文献和代码,进行实践和探索。

以上就是关于自然语言理解与生成问题的深度学习应用的全部内容,希望对你有所帮助!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值