您的位置:首页 > 健康 > 养生 > 模板建站是什么意思_河南如何优化网站_东莞seoseo关键词排名优化_百度seo培训

模板建站是什么意思_河南如何优化网站_东莞seoseo关键词排名优化_百度seo培训

2025/7/7 19:26:54 来源:https://blog.csdn.net/qq_67200497/article/details/146896173  浏览:    关键词:模板建站是什么意思_河南如何优化网站_东莞seoseo关键词排名优化_百度seo培训
模板建站是什么意思_河南如何优化网站_东莞seoseo关键词排名优化_百度seo培训

系列文章目录

第六章 1:基于RNN生成文本      

第六章 2:seq2seq模型的实现

第六章 3:seq2seq模型的改进     

第六章 4:seq2seq模型的应用   


文章目录

  • 系列文章目录

目录

系列文章目录

文章目录

前言

一、seq2seq的理论

1.seq2seq的原理

2.时序数据转换的简单尝试

3.可变长度的时序数据

4.加法数据集

二、seq2seq的实现

1.Encoder类

2.Decoder类

3.Seq2seq类 

4.seq2seq的评价

总结

本次内容较多,但是如果你能耐心看完,请一定给博主大大滴三连加关注!


前言

这一节内容其实不多,主要是因为”代码“也占字数,导致字数超了10000,但莫慌!

这个世界充满了时序数据。文本数据、音频数据和视频数据都是时序数据。另外,还存在许多需要将一种时序数据转换为另一种时序数据的任务, 比如机器翻译、语音识别等。其他的还有进行对话的聊天机器人应用、将源代码转为机器语言的编译器等。 像这样,世界上存在许多输入输出均为时序数据的任务。从现在开始, 我们会考虑将时序数据转换为其他时序数据的模型。作为它的实现方法,将介绍使用两个RNN的seq2seq模型。(理论大概看看,实现详细看看


一、seq2seq的理论

1.seq2seq的原理

seq2seq 模型也称为Encoder-Decoder 模型。顾名思义,这个模型有两个模块——Encoder(编码器)和Decoder(解码器)。编码器对输入数据进行编码,解码器对被编码的数据进行解码。(其实就是transformer的雏形)

现在,我们举一个具体的例子来说明seq2seq的机制。这里考虑将日语翻译为英语,比如将“吾輩は猫である”翻译为“I am a cat”。此时,如下图所示,seq2seq基于编码器和解码器进行时序数据的转换。

如上图所示,编码器首先对“吾輩は猫である”这句话进行编码,然后将编码好的信息传递给解码器,由解码器生成目标文本。此时,编码器编码的信息浓缩了翻译所必需的信息,解码器基于这个浓缩的信息生成目标文本(其实你可以搜一下transformer,它的原理也就是这样,大模型亦如此)

以上就是seq2seq的全貌图。编码器和解码器协作,将一个时序数据转换为另一个时序数据。另外,在这些编码器和解码器内部可以使用RNN。 下面我们来看一下细节。首先来看编码器,它的层结构如下图所示。

由上图可以看出,编码器利用RNN将时序数据转换为隐藏状态h。 这里的RNN使用的是LSTM,不过也可以使用“简单RNN”或者GRU等。 另外,这里考虑的是将日语句子分割为单词进行输入的情况。 上图的编码器输出的向量h是LSTM层的最后一个隐藏状态,其中编码了翻译输入文本所需的信息。这里的重点是,LSTM的隐藏状态h是一个固定长度的向量。说到底,编码就是将任意长度的文本转换为一个固定长度的向量(是不是越来越觉得跟大模型远离很相似?如下图)。

如上图所示,编码器将文本转换为固定长度的向量。那么,解码器是如何“处理”这个编码好的向量,从而生成目标文本的呢?其实,我们已经知道答案了。因为我们只需要直接使用上一节讨论的进行文本生成的模型即可,(上图中①的中文是“还没有名字”,②的中文是“不记得是在哪里出生的”)

如下图所示。

从上图中可以看出,解码器的结构和上一节的神经网络完全相同。 不过它和上一节的模型存在一点差异,就是LSTM层会接收向量h。在 上一节的语言模型中,LSTM层不接收任何信息(硬要说的话,也可以说 LSTM的隐藏状态接收“0向量”)。这个唯一的、微小的改变使得普通的语言模型进化为可以驾驭翻译的解码器。

(注:上图中使用了<eos>这一分隔符(特殊符号)。这个分隔符被用作通知解码器开始生成文本的信号。另外,解码器采样到<eos>出现为止,所以它也是结束信号。也就是说,分隔符可以用 来指示解码器的“开始/结束”,当然不仅仅局限于此,还可以用别的符号表示开始或者结束,比如SOS_token等)

现在我们连接编码器和解码器,并给出它的层结构,具体如下图。

如上图所示,seq2seq由两个LSTM层构成,即编码器的LSTM和解码器的LSTM。此时,LSTM层的隐藏状态是编码器和解码器的“桥梁”。 在正向传播时,编码器的编码信息通过LSTM层的隐藏状态传递给解码器; 在反向传播时,解码器的梯度通过这个“桥梁”传递给编码器。

2.时序数据转换的简单尝试

下面我们来实现seq2seq,不过在此之前,首先说明一下我们要处理的问题。这里我们将“加法”视为一个时序转换问题。具体来说,如下图所示,在seq2seq学习后,如果输入字符串“57+5”, seq2seq要能正确回答“62”。顺便说一下,这种为了评价机器学习而创建的简单问题,称为 “toy problem”(玩具问题)。

在我们看来,这里做的加法运算是非常简单的问题,但是seq2seq对加法(更确切地说是加法的逻辑)一无所知。seq2seq从加法的例子(样本) 中学习出现的字符模式,这样真的可以学习到加法运算的规则吗?这正是本次实验的看头。 顺便说一下,在之前的word2vec和语言模型中,我们都把文本以单词为单位进行了分割,但并非必须这样做。对于本节的这个问题,我们将不以单词为单位,而是以字符为单位进行分割。在以字符为单位进行分割的情况 下 ,“ 57 +5”这样的输入会被处理为['5', '7', '+', '5']这样的列表。(大模型确实也类似这样,大模型并不是真正意义上理解了你说的话,它仍然是一个没有感情的草莓头(抱歉说错了),是没有感情的机器)

3.可变长度的时序数据

我们将“加法”视为字符(数字)列表。这里需要注意的是,不同的加法问题(“57+5”或者“628+521”等)及其回答(“62”或者“1149”等) 的字符数是不同的。比如,“57+5”共有4个字符,而“628+521”共有 7 个字符。 如此,在加法问题中,每个样本在时间方向上的大小不同。也就是说, 加法问题处理的是可变长度的时序数据。因此,在神经网络的学习中,在进 行mini-batch 处理时,需要想一些应对办法。

在基于mini-batch 学习可变长度的时序数据时,最简单的方法是使用填充(padding)。所谓填充,就是用无效(无意义)数据填入原始数据,从而使数据长度对齐。就上面这个加法的例子来说,,如下图所示,在多余位置插入无效字符(这里是空白字符),从而让所有输入数据的长度对齐。

本次的问题处理的是0~999的两个数的加法。因此,包括“+”在内,输入的最大字符数是7。另外,加法的结果最大是4个字符(最大为 “999 +999 =1998”)。因此,对监督数据也进行类似的填充,从而对齐所有样本数据的长度。另外,在本次的问题中,在输出的开始处加上了分隔符 “_”(下划线),使得输出数据的字符数统一为5。这个分隔符作为通知解码器开始生成文本的信号使用。

像这样,通过填充对齐数据的大小,可以处理可变长度的时序数据。But,因为使用了填充,seq2seq需要处理原本不存在的填充用字符,所以如果追求严谨,使用填充时需要向seq2seq添加一些填充专用的处理。比如, 在解码器中输入填充时,不应计算其损失(这可以通过向Softmax with Loss 层添加mask功能(掩码功能)来解决)。再比如,在编码器中输入填充时,LSTM 层应按原样输出上一时刻的输入。这样一来,LSTM层就可以像不存在填充一样对输入数据进行编码。

这里的内容有一些复杂,大佬们无法理解也没有关系。(咱们了解大概的流程即可),为了便于理解, 我们将填充用字符(空白字符)作为普通数据处理,不进行特别处理。

4.加法数据集

这里绍的加法的学习数据预先存放在了dataset/addition.txt中。如下图所示,这个文本文件中含有50000个加法样本。(其实你不用下载,我们在这里看看就行了)

为了使用Python轻松处理seq2seq的学习数据(文本文件),提供了一个专用模块(dataset/sequence.py),这个模块有load_data()和get_ vocab() 两个方法。

load_data(file_name, seed) 读入由 file_name 指定的文本文件,并将文本转换为字符ID,返回训练数据和测试数据。该方法内部设有随机数种子 seed 以打乱数据,分割训练数据和测试数据。另外,get_vocab()方法返回字符与ID的映射字典(实际上返回char_to_id和id_to_char)。现在我们来看一下实际的使用示例。(你看看关键的代码就欧克了,没必要死记硬背哈)

import sys
sys.path.append('..')
from dataset import sequence
"""
# dataset/sequence.py 文件内容如下
# coding: utf-8
import os
import numpyid_to_char = {}
char_to_id = {}def _update_vocab(txt):chars = list(txt)for i, char in enumerate(chars):if char not in char_to_id:tmp_id = len(char_to_id)char_to_id[char] = tmp_idid_to_char[tmp_id] = chardef load_data(file_name='addition.txt', seed=1984):file_path = os.path.dirname(os.path.abspath(__file__)) + '/' + file_nameif not os.path.exists(file_path):print('No file: %s' % file_name)return Nonequestions, answers = [], []for line in open(file_path, 'r'):idx = line.find('_')questions.append(line[:idx])answers.append(line[idx:-1])# create vocab dictfor i in range(len(questions)):q, a = questions[i], answers[i]_update_vocab(q)_update_vocab(a)# create numpy arrayx = numpy.zeros((len(questions), len(questions[0])), dtype=numpy.int32)t = numpy.zeros((len(questions), len(answers[0])), dtype=numpy.int32)for i, sentence in enumerate(questions):x[i] = [char_to_id[c] for c in list(sentence)]for i, sentence in enumerate(answers):t[i] = [char_to_id[c] for c in list(sentence)]# shuffleindices = numpy.arange(len(x))if seed is not None:numpy.random.seed(seed)numpy.random.shuffle(indices)x = x[indices]t = t[indices]# 10% for validation setsplit_at = len(x) - len(x) // 10(x_train, x_test) = x[:split_at], x[split_at:](t_train, t_test) = t[:split_at], t[split_at:]return (x_train, t_train), (x_test, t_test)def get_vocab():return char_to_id, id_to_char"""(x_train, t_train), (x_test, t_test) = sequence.load_data('addition.txt', seed=1984)
char_to_id, id_to_char = sequence.get_vocab()print(x_train.shape, t_train.shape)
print(x_test.shape, t_test.shape)
# (45000, 7) (45000, 5)
# (5000, 7) (5000, 5)print(x_train[0])
print(t_train[0])
# [ 3  0  2  0  0 11  5]
# [ 6  0 11  7  5]print(''.join([id_to_char[c] for c in x_train[0]]))
print(''.join([id_to_char[c] for c in t_train[0]]))

运行结果如下:

像这样,使用sequence模块,可以轻松地读入seq2seq用的数据。这 里,x_train 和 t_train 存放的是字符ID。另外,字符ID和字符之间的映 射可以使用char_to_id和id_to_char。

二、seq2seq的实现

seq2seq 是组合了两个RNN的神经网络。这里我们首先将这两个RNN 实现为Encoder类和Decoder类,然后将这两个类组合起来,来实现seq2seq 类。我们先从Encoder类开始介绍

1.Encoder类

如下图所示,Encoder类接收字符串,将其转化为向量h。

如前所述,我们使用RNN实现编码器。这里,使用LSTM层实现下图的层结构。

如上图所示,Encoder 类由Embedding层和LSTM层组成。Embedding层将字符(字符ID)转化为字符向量,然后将字符向量输入LSTM层。 LSTM层向右(时间方向)输出隐藏状态和记忆单元,向上输出隐藏状态。这里,因为上方不存在层,所以丢弃LSTM层向上的输出。如上图所示,在编码器处理完最后一个字符后,输出LSTM层的隐藏状态h。然后,这个隐藏状态h被传递给解码器。

(编码器只将LSTM的隐藏状态传递给解码器。尽管也可以把 LSTM的记忆单元传递给解码器,但我们通常不太会把LSTM的记忆单元传递给其他层。这是因为,LSTM的记忆单元被设计为 只给自身使用。)

顺便说一下,我们已经将时间方向上进行整体处理的层实现为了Time LSTM层和Time Embedding层。(前几节实现过,可以回去看看自然语言处理(18:(第五章3.)LSTM的实现)-CSDN博客)使用这些Time层,(TimeEmbedding如下):

class TimeAffine:def __init__(self, W, b):self.params = [W, b]self.grads = [np.zeros_like(W), np.zeros_like(b)]self.x = Nonedef forward(self, x):N, T, D = x.shapeW, b = self.paramsrx = x.reshape(N*T, -1)out = np.dot(rx, W) + bself.x = xreturn out.reshape(N, T, -1)def backward(self, dout):x = self.xN, T, D = x.shapeW, b = self.paramsdout = dout.reshape(N*T, -1)rx = x.reshape(N*T, -1)db = np.sum(dout, axis=0)dW = np.dot(rx.T, dout)dx = np.dot(dout, W.T)dx = dx.reshape(*x.shape)self.grads[0][...] = dWself.grads[1][...] = dbreturn dx

我们的编码器将如下图:

Encoder 类如下所示。这个Encoder类有初始化__init__()、正向传播 forward() 和反向传播backward() 这 3 个方法。首先,我们来看一下初始化方法:

class Encoder:def __init__(self, vocab_size, wordvec_size, hidden_size):V, D, H = vocab_size, wordvec_size, hidden_sizern = np.random.randnembed_W = (rn(V, D) / 100).astype('f')lstm_Wx = (rn(D, 4 * H) / np.sqrt(D)).astype('f')lstm_Wh = (rn(H, 4 * H) / np.sqrt(H)).astype('f')lstm_b = np.zeros(4 * H).astype('f')self.embed = TimeEmbedding(embed_W)self.lstm = TimeLSTM(lstm_Wx, lstm_Wh, lstm_b, stateful=False)self.params = self.embed.params + self.lstm.paramsself.grads = self.embed.grads + self.lstm.gradsself.hs = None

初始化方法接收vocab_size、wordvec_size 和 hidden_size 这 3 个参数。 vocab_size 是词汇量,相当于字符的种类。顺便说一下,这次共有13种字符(数字0~9、“ +”、“ ”(空白字符)、“ _”)。此外,wordvec_size对应于字符向量的维数,hidden_size对应于LSTM层的隐藏状态的维数。 这个初始化方法进行权重参数的初始化和层的生成。最后,将权重参数和梯度分别归纳在成员变量params和grads的列表中。因为这次并不保持Time LSTM 层的状态,所以设定stateful=False。

接着来看forward()方法和backward()方法

 def forward(self, xs):xs = self.embed.forward(xs)hs = self.lstm.forward(xs)self.hs = hsreturn hs[:, -1, :]def backward(self, dh):dhs = np.zeros_like(self.hs)dhs[:, -1, :] = dhdout = self.lstm.backward(dhs)dout = self.embed.backward(dout)return dout

编码器的正向传播调用Time Embedding层和Time LSTM层的 forward() 方法,然后取出Time LSTM层的最后一个时刻的隐藏状态,将 它作为编码器的forward()方法的输出。 在编码器的反向传播中,LSTM层的最后一个隐藏状态的梯度是dh,这个dh是从解码器传来的梯度。在反向传播的实现中,先生成元素为0的 张量dhs,再将dh存放到这个dhs中的对应位置。剩下的就是调用Time Embedding 层和Time LSTM层的backward()方法。以上就是Encoder类的实现。

2.Decoder类

下面,我们继续Decoder类的实现。如图7-16所示,Decoder类接收 Encoder 类输出的h,输出目标字符串。

如前所述,解码器可以由RNN实现。和编码器一样,这里也使用 LSTM层,此时解码器的层结构如下图所示。

上图显示了解码器在学习时的层结构。这里使用了监督数据_62进行学习,此时输入数据是['_', '6', '2', ' '],对应的输出是['6', '2', ' ', ' ']。

顺便说一句,在自然语言处理(21:(第六章1.)基于RNN生成文本)-CSDN博客这一节,在进行文本生成时,我们基于Softmax函数的概率分布进行了采样,因此生成的文本会随机变动。因为这次的问题是加法,所以我们想消除这种概率性的“波动”,生成“确定性的”答案。为此, 这次我们仅选择得分最高的字符。也就是说,是“确定性”地选择,而不是 “概率性”地选择。图7-18显示了解码器生成字符串的过程。

如上图所示,这里出现了新的argmax节点,这是获取最大值的索引(本例中是字符ID)的节点。上图的结构和上一节展示的文本生成时的结构相同。不过这次没有使用Softmax层,而是从Affine层输出的得分中选择了最大值的字符ID。

(Softmax层对输入的向量进行正规化。此时,向量元素的值虽然被改变,但是它们的大小关系没有变化。因此,在上图的情况下,可以省略Softmax层。)

如上所述,在解码器中,在学习时和在生成时处理Softmax层的方式 是不一样的。因此,Softmax with Loss层交给此后实现的Seq2seq类处理。 如下图所示,Decoder类仅承担Time Softmax with Loss 层之前的部分。

由上图可以看出,Decoder类由Time Embedding、Time LSTM和Time Affine这3个层构成。下面,我们来看一下Decoder层的实现。这里 一起给出它的初始化__init__()方法、正向传播forward()方法和反向传播 backward()方法


class Decoder:def __init__(self, vocab_size, wordvec_size, hidden_size):V, D, H = vocab_size, wordvec_size, hidden_sizern = np.random.randnembed_W = (rn(V, D) / 100).astype('f')lstm_Wx = (rn(D, 4 * H) / np.sqrt(D)).astype('f')lstm_Wh = (rn(H, 4 * H) / np.sqrt(H)).astype('f')lstm_b = np.zeros(4 * H).astype('f')affine_W = (rn(H, V) / np.sqrt(H)).astype('f')affine_b = np.zeros(V).astype('f')self.embed = TimeEmbedding(embed_W)self.lstm = TimeLSTM(lstm_Wx, lstm_Wh, lstm_b, stateful=True)self.affine = TimeAffine(affine_W, affine_b)self.params, self.grads = [], []for layer in (self.embed, self.lstm, self.affine):self.params += layer.paramsself.grads += layer.gradsdef forward(self, xs, h):self.lstm.set_state(h)out = self.embed.forward(xs)out = self.lstm.forward(out)score = self.affine.forward(out)return scoredef backward(self, dscore):dout = self.affine.backward(dscore)dout = self.lstm.backward(dout)dout = self.embed.backward(dout)dh = self.lstm.dhreturn dh

这里仅对反向传播进行一些补充说明。在backward()的实现中,从上方的Softmax with Loss 层接收梯度dscore,然后按Time Affine层、Time LSTM层和Time Embedding层的顺序传播梯度。Time LSTM层将时间方向上的梯度保存在Time LSTM层的成员变量dh中(可以参考自然语言处理(18:(第五章3.)LSTM的实现)-CSDN博客), 因此取出时间方向上的梯度dh,将其作为Decoder类的backward()的输出。 如前所述,Decoder类在学习时和在生成文本时的行为不同。上面的 forward() 方法是假定在学习时使用的。我们将Decoder类生成文本时的方法实现为generate()。

 def generate(self, h, start_id, sample_size):sampled = []sample_id = start_idself.lstm.set_state(h)for _ in range(sample_size):x = np.array(sample_id).reshape((1, 1))out = self.embed.forward(x)out = self.lstm.forward(out)score = self.affine.forward(out)sample_id = np.argmax(score.flatten())sampled.append(int(sample_id))return sampled

这个generate() 方法有3个参数,分别是从编码器接收的隐藏状态h、 最开始输入的字符ID start_id和生成的字符数量sample_size。这里重复如下操作:输入一个字符,选择Affine层输出的得分中最大值的字符ID。以上就是Decoder类的实现。

3.Seq2seq类 

最后来看Seq2seq类的实现。话虽如此,这里需要做的只是将Encoder 类和Decoder 类连接在一起,然后使用Time Softmax with Loss层计算损 失而已。Seq2seq类的实现如下所示


class Seq2seq(BaseModel):def __init__(self, vocab_size, wordvec_size, hidden_size):V, D, H = vocab_size, wordvec_size, hidden_sizeself.encoder = Encoder(V, D, H)self.decoder = Decoder(V, D, H)self.softmax = TimeSoftmaxWithLoss()self.params = self.encoder.params + self.decoder.paramsself.grads = self.encoder.grads + self.decoder.gradsdef forward(self, xs, ts):decoder_xs, decoder_ts = ts[:, :-1], ts[:, 1:]h = self.encoder.forward(xs)score = self.decoder.forward(decoder_xs, h)loss = self.softmax.forward(score, decoder_ts)return lossdef backward(self, dout=1):dout = self.softmax.backward(dout)dh = self.decoder.backward(dout)dout = self.encoder.backward(dh)return doutdef generate(self, xs, start_id, sample_size):h = self.encoder.forward(xs)sampled = self.decoder.generate(h, start_id, sample_size)return sampled

Encoder 和 Decoder 的各类中已经实现了主要的处理,因此这里只是将它们组合起来。以上就是Seq2seq类的实现。下面我们使用这个Seq2seq类, 来挑战一下加法问题。

4.seq2seq的评价

Seq2seq的学习和基础神经网络的学习具有相同的流程。

基础神经网络的学习流程如下:

1. 从训练数据中选择一个mini-batch

2. 基于mini-batch 计算梯度

3. 使用梯度更新权重

seq2seq针对每个epoch求解测试数据(生成字符串),并计算正确率。seq2seq的学习 代码如下所示

# coding: utf-8
import sys
sys.path.append('..')
import numpy as np
import matplotlib.pyplot as plt
from dataset import sequence
from common.optimizer import Adam
from common.trainer import Trainer
from common.util import eval_seq2seq
from seq2seq import Seq2seq
from peeky_seq2seq import PeekySeq2seq# 读入数据集
(x_train, t_train), (x_test, t_test) = sequence.load_data('addition.txt')
char_to_id, id_to_char = sequence.get_vocab()# Reverse input? =================================================
# is_reverse = True  
# if is_reverse:
#     x_train, x_test = x_train[:, ::-1], x_test[:, ::-1]
# ================================================================# 设定超参数
vocab_size = len(char_to_id)
wordvec_size = 16
hidden_size = 128
batch_size = 128
max_epoch = 25
max_grad = 5.0# Normal or Peeky? ==============================================
model = Seq2seq(vocab_size, wordvec_size, hidden_size)
# model = PeekySeq2seq(vocab_size, wordvec_size, hidden_size)
# ================================================================
optimizer = Adam()
trainer = Trainer(model, optimizer)acc_list = []
for epoch in range(max_epoch):trainer.fit(x_train, t_train, max_epoch=1,batch_size=batch_size, max_grad=max_grad)correct_num = 0for i in range(len(x_test)):question, correct = x_test[[i]], t_test[[i]]verbose = i < 10correct_num += eval_seq2seq(model, question, correct,id_to_char, verbose, )# is_reverseacc = float(correct_num) / len(x_test)acc_list.append(acc)print('val acc %.3f%%' % (acc * 100))# 绘制图形
x = np.arange(len(acc_list))
plt.plot(x, acc_list, marker='o')
plt.xlabel('epochs')
plt.ylabel('accuracy')
plt.ylim(0, 1.0)
plt.show()

这里显示的代码和基础神经网络的学习用代码是一样的,不过这里采用正确率(正确回答了多少问题)作为评价指标。具体来说,就是针对每个 epoch 对正确回答了测试数据中的多少问题进行统计。 为了测量上述实现的正确率,我们使用common/util.py中的eval_ seq2seq(model, question, correct, id_to_char, verbose, is_reverse) 方法。 这个方法向模型输入问题,生成字符串,并判断它是否与答案相符。如果模 型给出的答案正确,则返回1;如果错误,则返回0.

运行上述代码后,下图所示的结果会显示在控制台上。

如上图所示,在终端上,每个epoch显示一次结果。每行有类似“Q 600+257”这样的问题语句,它的下方是“T 857”这样的正确答案。上图中,“ X 818”是我们的模型给出的答案。如果我们的模型给出了正确答案, 则终端上会显示类似下图的答案“O 864”。(如下图)

运行后从结果中可知, seq2seq最开始没能顺利回答问题。但是,随着学习不断进行,它在慢慢靠 近正确答案,然后变得可以正确回答一些问题。下面,来绘制一下每个 epoch的正确率,结果如下图。

由上图可知,随着学习的积累,正确率稳步提高。本次的实验只进行了25次,最后的正确率约为9.46%。从图中的变化趋势可知,如果继续学习,正确率应该还会进一步上升。不过,为了能更好地学习相同的问题(加法问题),这里我们暂停本次学习,下一节对seq2seq进行一些改进.


总结

本次内容较多,但是如果你能耐心看完,请一定给博主大大滴三连加关注

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com