当前位置: 首页 > news >正文

产品展示网站系统做墙绘一般在哪个网站

产品展示网站系统,做墙绘一般在哪个网站,什么是网站域名,俄外长抵达北京生成式聊天机器人 -- 基于Pytorch Global Attention 双向 GRU 实现的SeqToSeq模型 -- 下 训练Masked 损失单次训练过程迭代训练过程 测试贪心解码(Greedy decoding)算法实现对话函数 训练和测试模型完整代码 生成式聊天机器人 – 基于Pytorch Global Attention 双向 GRU 实… 生成式聊天机器人 -- 基于Pytorch Global Attention 双向 GRU 实现的SeqToSeq模型 -- 下 训练Masked 损失单次训练过程迭代训练过程 测试贪心解码(Greedy decoding)算法实现对话函数 训练和测试模型完整代码 生成式聊天机器人 – 基于Pytorch Global Attention 双向 GRU 实现的SeqToSeq模型 – 上 训练 Masked 损失 encoder 和 decoder 的 forward 函数实现之后我们就需要计算loss。seq2seq有两个RNNEncoder RNN是没有直接定义损失函数的它是通过影响Decoder从而影响最终的输出以及loss。 Decoder输出一个序列前面我们介绍的是Decoder在预测时的过程它的长度是不固定的只有遇到EOS才结束。给定一个问答句对我们可以把问题输入Encoder然后用Decoder得到一个输出序列但是这个输出序列和”真实”的答案长度并不相同。而且即使长度相同并且语义相似也很难直接知道预测的答案和真实的答案是否类似。 那么我们怎么计算loss呢 比如输入是”What is your name?”训练数据中的答案是”I am LiLi”。假设模型有两种预测”I am fine”和”My name is LiLi”。从语义上显然第二种答案更好但是如果字面上比较的话可能第一种更好。 但是让机器知道”I am LiLi”和”My name is LiLi”的语义很接近这是非常困难的所以实际上我们通常还是通过字面上进行比较。我们会限制Decoder的输出使得Decoder的输出长度和”真实”答案一样然后逐个时刻比较。Decoder输出的是每个词的概率分布因此可以使用交叉熵损失函数。但是这里还有一个问题因为是一个batch的数据里有一些是padding的因此这些位置的预测是没有必要计算loss的因此我们需要使用前面的mask矩阵把对应位置的loss去掉我们可以通过下面的函数来实现计算Masked的loss。 # 带掩码的负对数似然损失函数 # 一次求出一个Time step一批词的预测损失 # inp(batch_size,7826),词汇表总共7826个词 # target(batch_size,),给出当前批次中各个批当前Time step正确输出词在词汇表中的索引ID # mask(batch_size,),给出当前批次中各个批当前Time step对应的词是否为padding填充词 def maskNLLLoss(inp, target, mask):# 计算实际的词的个数因为padding是0非padding是1因此sum就可以得到词的个数nTotal mask.sum()# 计算交叉熵损失,返回结果维度: (batch_size,) crossEntropy -torch.log(torch.gather(inp, 1, target.view(-1, 1)).squeeze(1))# 通过mask矩阵筛选出非padding词的预测损失,然后求和算平均损失# 此处计算得到的平均损失是某个Time Step输入的一批词的平均损失loss crossEntropy.masked_select(mask).mean()loss loss.to(device)return loss, nTotal.item()这段代码有两个函数比较难理解下面来重点讲解一下首先是gather函数: 为了实现交叉熵这里使用了gather函数这是一种比较底层的实现方法更简便的方法应该使用CrossEntropyLoss或者NLLLoss其中CrossEntropy等价与LogSoftmaxNLLLoss。 交叉熵的定义为 H ( p , q ) − ∑ p ( x ) l o g q ( x ) H(p,q)−∑p(x)logq(x) H(p,q)−∑p(x)logq(x)。其中p和q是两个随机变量的概率分布这里是离散的随机变量如果是连续的需要把求和变成积分。在我们这里p是真实的分布也就是one-hot的而q是模型预测的softmax的输出。因为p是one-hot的所以只需要计算真实分类对应的那个值。 比如假设一个5分类的问题当前正确分类是 2 2 2(下标从 0 0 0~ 4 4 4)而模型的预测是 ( 0.1 , 0.1 , 0.4 , 0.2 , 0.2 ) (0.1,0.1,0.4,0.2,0.2) (0.1,0.1,0.4,0.2,0.2)则 H − l o g ( 0.4 ) H-log(0.4) H−log(0.4)。用交叉熵作为分类的 L o s s Loss Loss是比较合理的正确的分类是2那么模型在下标为2的地方预测的概率 q 2 q_{2} q2​越大则 − l o g q 2 −logq_{2} −logq2​越小也就是 l o s s loss loss越小。 假设inp是 0.3 0.2 0.4 0.1 0.2 0.1 0.4 0.3也就是batch2而分类数(词典大小)是4inp是模型预测的分类概率。 而target [2,3] 表示第一个样本的正确分类是第三个类别(概率是0.4第二个样本的正确分类是第四个类别(概率是0.3)。因此我们需要计算的是 − l o g ( 0.4 ) − l o g ( 0.3 ) -log(0.4) - log(0.3) −log(0.4)−log(0.3)。怎么不用for循环求出来呢我们可以使用torch.gather函数首先把0.4和0.3选出来 inp torch.tensor([[0.3, 0.2, 0.4, 0.1], [0.2, 0.1, 0.4, 0.3]]) target torch.tensor([2, 3]) selected torch.gather(inp, 1, target.view(-1, 1)) print(selected)输出 tensor([[ 0.4000],[ 0.3000]])关于masked_select函数我们来看一个例子: x torch.randn(3, 4)x tensor([[ 0.3552, -2.3825, -0.8297, 0.3477],[-1.2035, 1.2252, 0.5002, 0.6248],[ 0.1307, -2.0608, 0.1244, 2.0139]])mask x.ge(0.5)mask tensor([[ 0, 0, 0, 0],[ 0, 1, 1, 1],[ 0, 0, 0, 1]], dtypetorch.uint8)torch.masked_select(x, mask) tensor([ 1.2252, 0.5002, 0.6248, 2.0139])它要求mask和被mask的tensor的shape是一样的然后从crossEntropy选出mask值为1的那些值。输出的维度会减1。 单次训练过程 函数train实现一个batch数据的训练。前面我们提到过在训练的时候我们会限制Decoder的输出使得Decoder的输出长度和”真实”答案一样长。但是我们在训练的时候如果让Decoder自行输出那么收敛可能会比较慢因为Decoder在t时刻的输入来自t-1时刻的输出。 如果前面预测错了那么后面很可能都会错下去。另外一种方法叫做teacher forcing它不管模型在t-1时刻做什么预测都把t-1时刻的正确答案作为t时刻的输入。但是如果只用teacher forcing也有问题因为真实的Decoder是没有老师来帮它纠正错误的。所以比较好的方法是追加一个teacher_forcing_ratio参数随机的来确定本次训练是否teacher forcing。 另外使用到的一个技巧是梯度裁剪(gradient clipping) 。这个技巧通常是为了防止梯度爆炸(exploding gradient)它把参数限制在一个范围之内从而可以避免梯度的梯度过大或者出现NaN等问题。注意虽然它的名字叫梯度裁剪但实际它是对模型的参数进行裁剪它把整个参数看成一个向量如果这个向量的模大于max_norm那么就把这个向量除以一个值使得模等于max_norm因此也等价于把这个向量投影到半径为max_norm的球上。它的效果如下图所示。 单次具体训练过程为: 把整个batch的输入传入encoder把decoder的输入设置为特殊的初始隐状态设置为encoder最后时刻的隐状态decoder每次处理一个时刻的forward计算如果是teacher forcing把上个时刻的正确的词作为当前输入否则用上一个时刻的输出作为当前时刻的输入计算loss反向计算梯度对梯度进行裁剪更新模型(包括encoder和decoder)参数 注意PyTorch的RNN模块(RNN, LSTM, GRU)也可以当成普通的非循环的网络来使用。在Encoder部分我们是直接把所有时刻的数据都传入RNN让它一次计算出所有的结果但是在Decoder的时候(非teacher forcing)后一个时刻的输入来自前一个时刻的输出因此无法一次计算。 # input_var维度:(max_length,batch_size) # target_var维度: (max_length,batch_size) # lengths维度: (batch_size) # mask维度: (max_length,batch_size) def train(input_variable, lengths, target_variable, mask, max_target_len, encoder, decoder, embedding,encoder_optimizer, decoder_optimizer, batch_size, clip, max_lengthMAX_LENGTH):# 梯度清空encoder_optimizer.zero_grad()decoder_optimizer.zero_grad()# 设置device从而支持GPU当然如果没有GPU也能工作。input_variable input_variable.to(device)lengths lengths.to(device)target_variable target_variable.to(device)mask mask.to(device)# 初始化变量loss 0print_losses []n_totals 0# encoder的Forward计算 --- 输入数据维度: (max_len,batch_size) , (batch_size)encoder_outputs, encoder_hidden encoder(input_variable, lengths)# Decoder的初始输入是SOS我们需要构造(1, batch)的输入表示第一个时刻batch个输入。decoder_input torch.LongTensor([[SOS_token for _ in range(batch_size)]])decoder_input decoder_input.to(device)# 注意Encoder是双向的而Decoder是单向的因此从下往上取n_layers个decoder_hidden encoder_hidden[:decoder.n_layers]# 确定是否teacher forcinguse_teacher_forcing True if random.random() teacher_forcing_ratio else False# 一次处理一个时刻if use_teacher_forcing:for t in range(max_target_len):decoder_output, decoder_hidden decoder(decoder_input, decoder_hidden, encoder_outputs)# Teacher forcing: 下一个时刻的输入是当前正确答案decoder_input target_variable[t].view(1, -1)# 计算累计的lossmask_loss, nTotal maskNLLLoss(decoder_output, target_variable[t], mask[t])loss mask_lossprint_losses.append(mask_loss.item() * nTotal)n_totals nTotalelse:for t in range(max_target_len):decoder_output, decoder_hidden decoder(decoder_input, decoder_hidden, encoder_outputs)# 不是teacher forcing: 下一个时刻的输入是当前模型预测概率最高的值_, topi decoder_output.topk(1)decoder_input torch.LongTensor([[topi[i][0] for i in range(batch_size)]])decoder_input decoder_input.to(device)# 计算累计的lossmask_loss, nTotal maskNLLLoss(decoder_output, target_variable[t], mask[t])loss mask_lossprint_losses.append(mask_loss.item() * nTotal)n_totals nTotal# 反向计算loss.backward()# 对encoder和decoder进行梯度裁剪_ torch.nn.utils.clip_grad_norm_(encoder.parameters(), clip)_ torch.nn.utils.clip_grad_norm_(decoder.parameters(), clip)# 更新参数encoder_optimizer.step()decoder_optimizer.step()return sum(print_losses) / n_totals迭代训练过程 最后是把前面的代码组合起来进行训练。函数trainIters用于进行n_iterations次minibatch的训练。 值得注意的是我们定期会保存模型我们会保存一个tar包包括encoder和decoder的state_dicts(参数),优化器(optimizers)的state_dicts, loss和迭代次数。这样保存模型的好处是从中恢复后我们既可以进行预测也可以进行训练(因为有优化器的参数和迭代的次数)。 def trainIters(model_name, voc, pairs, encoder, decoder, encoder_optimizer, decoder_optimizer,embedding, encoder_n_layers, decoder_n_layers, save_dir, n_iteration, batch_size,print_every, save_every, clip, corpus_name, loadFilename):# 随机选择n_iteration个batch的数据(pair)# 一次性生成n_iteration轮迭代需要的全部数据 (n_iteration,batch)# batch 表示当前轮迭代需要的大小为batch_size的数据training_batches [batch2TrainData(voc, [random.choice(pairs) for _ in range(batch_size)])for _ in range(n_iteration)]# 初始化print(Initializing ...)start_iteration 1print_loss 0if loadFilename:start_iteration checkpoint[iteration] 1# 训练print(Training...)for iteration in range(start_iteration, n_iteration 1):training_batch training_batches[iteration - 1]# input_var维度:(max_length,batch_size)# target_var维度: (max_length,batch_size)# lengths维度: (batch_size)# mask维度: (max_length,batch_size)input_variable, lengths, target_variable, mask, max_target_len training_batch# 训练一个batch的数据loss train(input_variable, lengths, target_variable, mask, max_target_len, encoder,decoder, embedding, encoder_optimizer, decoder_optimizer, batch_size, clip)print_loss loss# 进度if iteration % print_every 0:print_loss_avg print_loss / print_everyprint(Iteration: {}; Percent complete: {:.1f}%; Average loss: {:.4f}.format(iteration, iteration / n_iteration * 100, print_loss_avg))print_loss 0# 保存checkpointif (iteration % save_every 0):directory os.path.join(save_dir, model_name, corpus_name, {}-{}_{}.format(encoder_n_layers, decoder_n_layers, hidden_size))if not os.path.exists(directory):os.makedirs(directory)torch.save({iteration: iteration,en: encoder.state_dict(),de: decoder.state_dict(),en_opt: encoder_optimizer.state_dict(),de_opt: decoder_optimizer.state_dict(),loss: loss,voc_dict: voc.__dict__,embedding: embedding.state_dict()}, os.path.join(directory, {}_{}.tar.format(iteration, checkpoint)))测试 模型训练完成之后我们需要测试它的效果。最简单直接的方法就是和chatbot来聊天。因此我们需要用Decoder来生成一个响应。 贪心解码(Greedy decoding)算法 最简单的解码算法是贪心算法也就是每次都选择概率最高的那个词然后把这个词作为下一个时刻的输入直到遇到EOS结束解码或者达到一个最大长度。但是贪心算法不一定能得到最优解因为某个答案可能开始的几个词的概率并不太高但是后来概率会很大。因此除了贪心算法我们通常也可以使用Beam-Search算法也就是每个时刻保留概率最高的Top K个结果然后下一个时刻尝试把这K个结果输入(当然需要能恢复RNN的状态)然后再从中选择概率最高的K个。 为了实现贪心解码算法我们定义一个GreedySearchDecoder类。这个类的forwar的方法需要传入一个输入序列(input_seq)其shape是(input_seq length, 1) 输入长度input_length和最大输出长度max_length。过程如下 把输入传给Encoder得到所有时刻的输出和最后一个时刻的隐状态。把Encoder最后时刻的隐状态作为Decoder的初始状态。Decoder的第一时刻输入初始化为SOS。定义保存解码结果的tensor。循环直到最大解码长度。 把当前输入传入Decoder。得到概率最大的词以及概率。把这个词和概率保存下来。把当前输出的词作为下一个时刻的输入。返回所有的词和概率。 import torch from torch import nn from Trainer import device, decoder, encoder from utils import SOS_token, normalizeString, indexesFromSentence, MAX_LENGTH, vocclass GreedySearchDecoder(nn.Module):def __init__(self, encoder, decoder):super(GreedySearchDecoder, self).__init__()self.encoder encoderself.decoder decoder# input_seq维度: (max_len,batch_size)def forward(self, input_seq, input_length, max_length):# Encoder的Forward计算encoder_outputs, encoder_hidden self.encoder(input_seq, input_length)# 把Encoder最后时刻的隐状态作为Decoder的初始值decoder_hidden encoder_hidden[:decoder.n_layers]# 因为我们的函数都是要求(time,batch)因此即使只有一个数据也要做出二维的。# Decoder的初始输入是SOSdecoder_input torch.ones(1, 1, devicedevice, dtypetorch.long) * SOS_token# 用于保存解码结果的tensorall_tokens torch.zeros([0], devicedevice, dtypetorch.long)all_scores torch.zeros([0], devicedevice)# 循环这里只使用长度限制后面处理的时候把EOS去掉了。for _ in range(max_length):# Decoder forward一步decoder_output, decoder_hidden self.decoder(decoder_input, decoder_hidden,encoder_outputs)# decoder_outputs是(batch1, vob_size)# 使用max返回概率最大的词和得分decoder_scores, decoder_input torch.max(decoder_output, dim1)# 把解码结果保存到all_tokens和all_scores里all_tokens torch.cat((all_tokens, decoder_input), dim0)all_scores torch.cat((all_scores, decoder_scores), dim0)# decoder_input是当前时刻输出的词的ID这是个一维的向量因为max会减少一维。# 但是decoder要求有一个batch维度因此用unsqueeze增加batch维度。decoder_input torch.unsqueeze(decoder_input, 0)# 返回所有的词和得分。return all_tokens, all_scores实现对话函数 解码方法完成后我们写一个函数来测试从终端输入一个句子然后来看看chatbot的回复。我们需要用前面的函数来把句子分词然后变成ID传入解码器得到输出的ID后再转换成文字。我们会实现一个evaluate函数由它来完成这些工作。 我们需要把一个句子变成输入需要的格式——shape为(max_length , batch)即使只有一个输入也需要增加一个batch维度。我们首先把句子分词然后变成ID的序列然后转置成合适的格式。此外我们还需要创建一个名为lengths的tensor虽然只有一个来表示输入的实际长度。接着我们构造类GreedySearchDecoder的实例searcher然后用searcher来进行解码得到输出的ID最后我们把这些ID变成词并且去掉EOS之后的内容。 另外一个evaluateInput函数作为chatbot的用户接口当运行它的时候它会首先提示用户输入一个句子然后使用evaluate来生成回复。然后继续对话直到用户输入”q”或者”quit”。如果用户输入的词不在词典里我们会输出错误信息(当然还有一种办法是忽略这些词)然后提示用户重新输入。 def evaluate(encoder, decoder, searcher, voc, sentence, max_lengthMAX_LENGTH):# 把输入的一个batch句子变成idindexes_batch [indexesFromSentence(voc, sentence)]# 创建lengths tensorlengths torch.tensor([len(indexes) for indexes in indexes_batch])# 转置 -- (max_len,batch_size)input_batch torch.LongTensor(indexes_batch).transpose(0, 1)# 放到合适的设备上(比如GPU)input_batch input_batch.to(device)lengths lengths.to(device)# 用searcher解码tokens, scores searcher(input_batch, lengths, max_length)# ID变成词。decoded_words [voc.index2word[token.item()] for token in tokens]return decoded_wordsdef evaluateInput(encoder, decoder, searcher, voc):input_sentence while(1):try:# 得到用户终端的输入input_sentence input()# 是否退出if input_sentence q or input_sentence quit: break# 句子归一化input_sentence normalizeString(input_sentence)# 生成响应Evaluate sentenceoutput_words evaluate(encoder, decoder, searcher, voc, input_sentence)# 去掉EOS后面的内容words []for word in output_words:if word EOS:breakelif word ! PAD:words.append(word)print(Bot:, .join(words))except KeyError:print(Error: Encountered unknown word.)训练和测试模型 不论是我们是训练模型还是测试对话我们都需要初始化encoder和decoder模型参数。在下面的代码我们从头开始训练模型或者从某个checkpoint加载模型。读者可以尝试不同的超参数配置来进行调优。 USE_CUDA torch.cuda.is_available() device torch.device(cuda if USE_CUDA else cpu)model_name cb_model attn_model dot # attn_model general # attn_model concat hidden_size 500 encoder_n_layers 2 decoder_n_layers 2 dropout 0.1 batch_size 64# 从哪个checkpoint恢复如果是None那么从头开始训练。 #loadFilename data/save/cb_model/cornell movie-dialogs corpus/2-2_500/4000_checkpoint.tar loadFilename None checkpoint_iter 4000# 如果loadFilename不空则从中加载模型 if loadFilename:# 如果训练和加载是一条机器那么直接加载checkpoint torch.load(loadFilename)# 否则比如checkpoint是在GPU上得到的但是我们现在又用CPU来训练或者测试那么注释掉下面的代码# checkpoint torch.load(loadFilename, map_locationtorch.device(cpu))encoder_sd checkpoint[en]decoder_sd checkpoint[de]encoder_optimizer_sd checkpoint[en_opt]decoder_optimizer_sd checkpoint[de_opt]embedding_sd checkpoint[embedding]voc.__dict__ checkpoint[voc_dict]print(Building encoder and decoder ...) # 初始化word embedding embedding nn.Embedding(voc.num_words, hidden_size) if loadFilename:embedding.load_state_dict(embedding_sd) # 初始化encoder和decoder模型 encoder EncoderRNN(hidden_size, embedding, encoder_n_layers, dropout) decoder GlobalAttnDecoderRNN(attn_model, embedding, hidden_size, voc.num_words,decoder_n_layers, dropout) if loadFilename:encoder.load_state_dict(encoder_sd)decoder.load_state_dict(decoder_sd) # 使用合适的设备 encoder encoder.to(device) decoder decoder.to(device) print(Models built and ready to go!)训练前我们需要设置一些训练的超参数。初始化优化器最后调用函数trainIters进行训练。 # 配置训练的超参数和优化器 clip 50.0 teacher_forcing_ratio 1.0 learning_rate 0.0001 decoder_learning_ratio 5.0 n_iteration 4000 print_every 1 save_every 500# 设置进入训练模式从而开启dropout encoder.train() decoder.train()# 初始化优化器 print(Building optimizers ...) encoder_optimizer optim.Adam(encoder.parameters(), lrlearning_rate) decoder_optimizer optim.Adam(decoder.parameters(), lrlearning_rate * decoder_learning_ratio) if loadFilename:encoder_optimizer.load_state_dict(encoder_optimizer_sd)decoder_optimizer.load_state_dict(decoder_optimizer_sd)# 开始训练 print(Starting Training!) trainIters(model_name, voc, pairs, encoder, decoder, encoder_optimizer, decoder_optimizer,embedding, encoder_n_layers, decoder_n_layers, save_dir, n_iteration, batch_size,print_every, save_every, clip, corpus_name, loadFilename)训练完毕后我们使用下面的代码进行测试。 # 进入eval模式从而去掉dropout。 encoder.eval() decoder.eval()# 构造searcher对象 searcher GreedySearchDecoder(encoder, decoder)# 测试 evaluateInput(encoder, decoder, searcher, voc)下面是测试的一些例子 hello Bot: hello .whats your name? Bot: jacob .I am sorry. Bot: you re not .where are you from? Bot: southern .q完整代码 码云仓库链接
http://www.hkea.cn/news/14435828/

相关文章:

  • 制作网站用的域名滨州正规网站建设哪家好
  • 建设部注册中心网站湘潭商城网站建设定制
  • 网站建设是属于软件开发费吗做电商
  • 唐山快速建站公司网站建设手机
  • 韩国食品网站设计欣赏wordpress用户导入数据库表
  • 公司网站建设需要什么资质模板建站影响网站的优化排名
  • 沧州瑞智网站建设软文广告文案案例
  • 大学生做的网站网站维护建设费入什么科目
  • 牙科医院网站建设方案网站实名审核中心
  • 网站空间不能读数据库硬笔书法网站是谁做的
  • 东莞关键词优化外包网站如何做进一步优化
  • 查学校去哪个网站中国建筑集团有限公司校园招聘
  • 网站维护费广告设计与制作专升本考试科目
  • 农业建设管理信息网站手机有软件做ppt下载网站有哪些内容
  • 东莞软件设计谷歌seo详细教学
  • 建个平台需要多少资金如何做好网站针对搜索引擎的seo
  • 网站建设程序员做什么ota平台网站建设
  • 玩具公司网站建设方案做网站怎么让字居右
  • 成都建设路小学网站诸城做网站公司
  • 网站定制开发建设seo快速软件
  • wordpress建站中英文冠县网站制作
  • 哪家建设公司网站网站做迅雷下载链接
  • 营口市住房建设保障办官方网站光明网
  • 中文网站的seo怎么做淮北论坛招聘最新信息
  • 政务网站建设管理工作总结网站首页设计特点有哪些
  • 广州网站优化推荐宁德蕉城城乡建设网站
  • 北京网站建设服务器维护萝岗区营销型网站建设
  • 网站iis7.5配置网站开发注意事项
  • 网站开发售后工作代理记账 营销型网站
  • wordpress与微信小程序成都seo技术