NLP新手入门-第N5周:seq2seq详解

一、课题背景和开发环境

📌第N5周:seq2seq详解📌

  • Python 3.8.12
  • numpy==1.21.5 -> 1.24.3
  • pytorch==1.8.1+cu111

📌本周任务:📌

    1. 了解seq2seq是什么?
    1. 基于RNN的seq2seq模型如何处理文本/长文本序列?
    1. seq2seq模型处理长文本序列有哪些难点?
    1. 基于RNN的seq2seq模型如何结合attention来改善模型效果?
    1. 可以先尝试着自己编写代码

二、seq2seq是什么

seq2seq(sequence to sequence)是一种常见的NLP模型结构,翻译为“序列到序列”,即:从一个文本序列得到一个新的文本序列。典型的任务有:机器翻译任务,文本摘要任务。谷歌翻译在2016年末开始使用seq2seq模型,并发表了2篇开创性的论文,感兴趣的同学可以阅读原文进行学习。

无论是否读过上述两篇谷歌的文章,NLP初学者想要充分理解并实现seq2seq模型很不容易。因为,我们需要拆解一系列相关的NLP概念,而这些NLP概念又是是层层递进的,所以想要清晰的对seq2seq模型有一个清晰的认识并不容易。但是,如果能够把这些复杂生涩的NLP概念可视化,理解起来其实就更简单了。因此,本文希望通过一系列图片、动态图帮助NLP初学者学习seq2seq以及attention相关的概念和知识。

首先看seq2seq干了什么事情?seq2seq模型的输入可以是一个(单词、字母或者图像特征)序列,输出是另外一个(单词、字母或者图像特征)序列。一个训练好的seq2seq模型如下图所示:
seq2seq模型

如下图所示,以NLP中的机器翻译任务为例,序列指的是一连串的单词,输出也是一连串单词。
NLP中的机器翻译任务

三、seq2seq原理

将上图中蓝色的seq2seq模型进行拆解,如下图所示:seq2seq模型由编码器(Encoder)和解码器(Decoder)组成。绿色的编码器会处理输入序列中的每个元素并获得输入信息,这些信息会被转换成为一个黄色的向量(称为context向量)。当我们处理完整个输入序列后,编码器把 context向量 发送给紫色的解码器,解码器通过context向量中的信息,逐个元素输出新的序列。
seq2seq模型组成
在机器翻译任务中,seq2seq模型实现翻译的过程如下图所示。seq2seq模型中的编码器和解码器一般采用的是循环神经网络RNN,编码器将输入的法语单词序列编码成context向量(在绿色encoder和紫色decoder中间出现),然后解码器根据context向量解码出英语单词序列。关于循环神经网络,建议阅读 Luis Serrano写的循环神经网络精彩介绍.(youtube网址)
seq2seq模型实现翻译的过程
黄色的context向量本质上是一组浮点数。而这个context的数组长度是基于编码器RNN的隐藏层神经元数量的。下图展示了长度为4的context向量,但在实际应用中,context向量的长度是自定义的,比如可能是256,512或者1024。在下文中,我们会可视化这些数字向量,使用更明亮的色彩来表示更高的值,如下图右边所示
context向量对应上图中间浮点数向量
那么RNN是如何具体地处理输入序列的呢?

  1. 假设序列输入是一个句子,这个句子可以由 n n n 个词表示: s e n t e n c e = { w 1 , w 2 , . . . , w n } sentence = \{w_1,w_2,...,w_n\} sentence={ w1,w2,...,wn}
  2. RNN首先将句子中的每一个词映射成为一个向量得到一个向量序列: X = { x 1 , x 2 , . . . , x n } X = \{x_1,x_2,...,x_n\} X={ x1,x2,...,xn} ,每个单词映射得到的向量通常又叫做:word embedding。
  3. 然后在处理第 t ∈ [ 1 , n ] t\in[1,n] t[1,n] 个时间步的序列输入 x t x_t xt 时,RNN网络的输入和输出可以表示为: h t = R N N ( x t , h t − 1 ) h_t = RNN(x_t, h_{t-1}) ht=RNN(xt,ht1)
    • 输入:RNN在时间步 t t t 的输入之一为单词 w t w_t wt 经过映射得到的向量 x t x_t xt
    • 输入:RNN另一个输入为上一个时间步 t − 1 t-1 t1 得到的hidden state向量 h t − 1 h_{t-1} ht1 ,同样是一个向量。
    • 输出:RNN在时间步 t t t 的输出为 h t h_t ht hidden state向量。
      word embedding例子
      我们在处理单词之前,需要将单词映射成为向量,通常使用 word embedding 算法来完成。一般来说,我们可以使用提前训练好的 word embeddings,或者在自有的数据集上训练word embedding。为了简单起见,上图展示的word embedding维度是4。上图左边每个单词经过word embedding算法之后得到中间一个对应的4维的向量。

进一步可视化一下基于RNN的seq2seq模型中的编码器在第1个时间步是如何工作:
Recurrent Neural Nework
RNN在第2个时间步,采用第1个时间步得到hidden state#10(隐藏层状态)和第2个时间步的输入向量input#1,来得到新的输出hidden state#1。

看下面的动态图,详细观察一下编码器如何在每个时间步得到hidden sate,并将最终的hidden state传输给解码器,解码器根据编码器所给予的最后一个hidden state信息解码处输出序列。注意,最后一个 hidden state实际上是我们上文提到的context向量。编码器逐步得到hidden state并传输最后一个hidden

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
", &tol); // allocate memory for solution ocp_nlp_out* out = ocp_nlp_out_create(solver_caps你可以使用 awk 命令来计算两个日期时间之间的时间差。 假设你有两个日期时间字符串 "ule->dims); ocp_nlp_solver_memory* solver_mem = ocp_nlp_solver_memory_create(solver_capsule->dims); 2023-05-29 15:22:10.845" 和 "2023-05-30 15:12:11 // set up simulation loop int sim_time = 1000; double x_current[NX]; double u_current[NU.747",你可以使用以下 awk 命令计算它们之间的时间差: ``` awk 'BEGIN { start]; double x_reference[NX]; double u_reference[NU]; double x_traj[(NN+1)*NX]; double u = mktime("2023 05 29 15 22 10.845"); end = mktime("2023 05 30_traj[NN*NU]; double t_current = 0.0; double t_next; // run simulation loop for 15 12 11.747"); diff = end - start; days = int(diff / 86400); hours = int((diff % 86400) / 3600); minutes = int((diff % 3600) / 60); (int i = 0; i < sim_time; i++) { // get current state for (int j = seconds = diff % 60; printf("Time difference: %d days %02d:%02d:%02d\n", days,0; j < NX; j++) { x_current[j] = ocp_nlp_out_get(out, i, "x", hours, minutes, seconds); }' ``` 这个命令将会输出 "Time difference: 1 days 23:50:00 j); } // calculate reference trajectory t_next = t_current + T; x_reference[0] = cos(",表示两个日期时间之间相差了 1 天 23 小时 50 分钟 0 秒。 解释2*PI*t_next); x_reference[1] = sin(2*PI*t_next); x_reference[2] = -一下这个命令: - `mktime("2023 05 29 15 22 10.845")` 和2*PI*sin(2*PI*t_next); x_reference[3] = 2*PI*cos(2*PI*t_next `mktime("2023 05 30 15 12 11.747")` 用于将日期时间字符串转换); // update reference trajectory for (int j = 0; j < NN; j++) { for (int k为秒数。 - `end - start` 用于计算两个日期时间之间的时间差(单位为秒) = 0; k < NX; k++) { x_traj[j*NX+k] = ocp_nlp_out_get(out,。 - `int(diff / 86400)` 用于计算时间差中包含的天数。 - `int((diff j+i, "x", k); } for (int k = 0; k < NU; k++) { u % 86400) / 3600)` 用于计算时间差中不足一天的小时数。 - `int_traj[j*NU+k] = ocp_nlp_out_get(out, j+i, "u", k); } } for((diff % 3600) / 60)` 用于计算时间差中不足一小时的分钟数。 - `diff % 60` 用于计算时间差中不足一分钟的秒数。 - `printf("Time difference: % (int j = 0; j < NX; j++) { x_traj[NN*NX+j] = x_reference[j]; d days %02d:%02d:%02d\n", days, hours, minutes, seconds)` 用于输出时间差。 你 } // update solver parameters status = ocp_nlp_solver_set_parameter(solver_capsule, "x0", x可以根据自己的需求修改日期时间字符串和输出格式。如果你想计算更为复杂的时间差,_current); status = ocp_nlp_solver_set_parameter(solver_capsule, "p", u_reference); status = ocp_n比如跨越多个月或多年的时间差,可以使用更为高级的方式来处理日期时间。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值