NLG解码策略

news2024/11/15 13:30:15

NLG解码策略

自然语言生成(Natural Language Generation,简称NLG),是自然语言处理领域的一个重要分支,在文本摘要生成任务中,另一个重要的分支是自然语言理解(Natural Language Understanding,简称NLU)。前面我们已经学习了seq2seq模型结构,其主要分为Encoder和Decoder两大组件,其实正是对应了NLUNLG两大分支,seq2seq模型最后经过一个softmax层,在每个时间步均得到一个词表大小的概率分布,如何利用这些概率分布得到最终的预测句子就是本节学习的解码策略

上篇构建文本摘要baseline时,我们就有提到过解码方法,当时采用的Teacher forcing的技巧,使用了真实标签,避免前面的步骤预测出错被无限放大的问题,但是在实际预测时因为没有真实标签,往往实际预测效果不一定好,所以寻找可行的解码策略是一项重点工作。

暴力解法

seq2seq模型最后经过一个softmax层,在每个时间步均得到一个词表大小的概率分布,但是这些时间步的概率分布并非同一时间得到的,后面时间步的概率分布生成受前面时间步的概率分布的影响,还记得在seq2seq模型中decoder部分,上一时间步的输出会作为输入的一部分进入下一个时间步,所以并不是说直接取每个时间步概率最大的词就得到了最佳的预测结果(虽然greedy search是这样做的)。这种情况下,我们常想到的办法就是把每个时间步,每个预测词都作为一种可能性,然后不断地去生成后面的词,最终计算每个句子总概率值(分值score),选择概率最大的作为预测结果。

在这里插入图片描述

这种方法也是我们刷Leetcode,没有好的方法时常采用的暴力解法,缺点就是时间复杂度太高,就像这里,每个时间步有V种可能性(V表示词表大小),一共T个时间步,总共有V的T次方种可能性,计算量太大,可行性差。

Greedy Search

在这里插入图片描述

greedy search的想法就比较简单了,也就是我上面说的,直接选取每个时间步的最大概率的词,但是有个缺点就是前面的选错了会影响后面的,导致错误被一直传递下去,但是依然是一种简单可行的方法,下面通过一段模拟模型生成的代码来实现greedy search。

import numpy as np
import matplotlib.pyplot as plt


# 定义词典(就是26个英文字母)
dictionary = []
for c in range(ord('a'), ord('z')+1):
    dictionary.append(chr(c))

print(f'词典:{dictionary}')


# 模拟一个已经被训练好的LM
class LanguageModel:
    def __init__(self, dictionary):
        self.dictionary = dictionary

    def predict(self):
        output = np.random.rand(len(dictionary))
        output = output/output.sum()
        return output


model = LanguageModel(dictionary)

predictions = model.predict()
plt.bar(dictionary, predictions)
plt.show()


def greedy_search(conditional_probability):
    return np.argmax(conditional_probability)


next_token = greedy_search(predictions)
print("sample token: ", dictionary[next_token])


输出:
词典:['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
sample token:  w

当模型生成<END>标志时,通常表示解码结束。

Beam Search

greedy search中因为只选取一个最大的概率词,那么生成的结果会比较单一,为了让生成的结果更多样性,基于greedy search有一种更好的方法就是在每个时间步选取概率分布最大的n个词(n值一般取5~10),俗称top-n(注意与后续的top-k sampling做区分)。

Beam search的具体流程:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

重复以上步骤,直至最终生成了k个句子,然后选取一个分数值最高的句子作为最终输出。

在这里插入图片描述

停止条件

其实与greedy search中类似,当模型在某个时间步输出<END>时,表示该假设已经结束,但是因为不同的假设的终止时间步可能不一致,所以当某个假设结束时,不会影响其他假设,其他假设会继续生成。

但是存在极低的可能性模型一直无法输出<END>,所以一般会设置超参-最大的时间步,也就是达到最大时间步后该假设自动终止;同样地,也会设置超参要生成多少个假设,生成的假设数量够了就不再生成新的假设。

代码实现

同样使用上面的模拟词典和模拟概率

def beam_search_decoder(data, k):
    sequences = [[list(), 0.0]]
    # 迭代序列中的每一步
    for row in data:
        all_candidates = list()
        # 计算每种hypotheses的分值,并存储到all_candidates
        for i in range(len(sequences)):
            seq, score = sequences[i]
            for j in range(len(row)):
                candidate = [seq + [j], score - np.log(row[j])]
                all_candidates.append(candidate)
        # 对所有的候选序列,通过score排序
        ordered = sorted(all_candidates, key=lambda tup: tup[1])
        # 选择k个分score 最高的
        sequences = ordered[:k]
    return sequences


t = 10  # 总共10个时间步
data = []
for i in range(t):
    prediction = model.predict()
    data.append(prediction)

data = np.array(data)
result = beam_search_decoder(data, 5)
for seq in result:
    print(seq)

    
[[13, 21, 16, 11, 20, 7, 14, 7, 16, 2], 25.78893247277384]
[[13, 21, 16, 11, 20, 7, 14, 16, 16, 2], 25.792550613854544]
[[21, 21, 16, 11, 20, 7, 14, 7, 16, 2], 25.792704168774012]
[[21, 21, 16, 11, 20, 7, 14, 16, 16, 2], 25.796322309854716]
[[13, 21, 16, 11, 20, 7, 14, 7, 11, 2], 25.81314273033993]

k的选择

当k是一个比较小的值时,生成的句子可能会不符合语法规则,不自然,无意义,不正确;

特殊地,当k=1时,变成greedy search

当k是一个比较大的值时,可以减少上述问题,但是会增加大量的运算;但是还有带来另外的问题:

  • 对于机器翻译任务来说,如果k增大的过多,BLEU score下降的特别快,主要是因为k越大,生成的句子会越短(句子短的会得分高);
  • 在闲聊对话系统中(chit-chat),越大的k约会偏离主题,虽然生成的句子确实会更通顺,(看下图)。

在这里插入图片描述

所以K的选取对结果影响很大,需要根据自己的任务进行实验。

Penalize longer sequences

在这里插入图片描述

观察分值score的计算公式,首先P是一个小于1的值,那么log§就是一个负值,所以我们会发现,生成的句子越长,得分就会越小,这明显不是我们期望看到的,可以通过以下两种方式解决。

在这里插入图片描述

其中第二种方法在这篇论文中被提出。

Repetitive Problem

在文本生成领域,重复生成的问题是一个非常常见的问题,有研究发现,当生成重复的句子时,损失值会不断减小,一般有以下三种方法来解决重复的问题:

  1. 通过写代码来控制模型减少生成重复词,刚开始可以尝试此种方法,锻炼编码能力;

  2. 更改loss,通过增加额外的损失来降低已生成句子(ht-m)和后续生成句子(ht)的相似度

在这里插入图片描述

  1. 不使用基于极大似然的损失函数,这篇论文中有详细描述

在这里插入图片描述

  1. F² softmax,源自这篇文章,主要是先根据频率将词表分组,然后使用两次softmax来选词,即先确定从哪一组选词,再确定选取该组中哪个词。

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/83582.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

传奇GOM引擎版本架设

传奇GOM引擎版本架设 传奇GOM引擎版本我们架设游戏需要用到的工具&#xff1a; 版本&#xff08;游戏类型服务端&#xff09;、DBC2000&#xff08;游戏数据库&#xff09;、RAR&#xff08;解压工具&#xff09;、传奇客户端、服务器、网盘 先把这些架设工具准备好&#xff…

性能测试——

目录 测试的分类 性能测试的指标 性能测试需求分析 ​编辑 性能测试计划及方案 ​编辑​编辑 测试用例设计及执行 梳理系统架构 压力测试报告 测试的分类 性能测试的指标 性能测试需求分析 性能测试计划及方案 测试用例设计及执行 估算系统的qps要了解什么&#xff1a; 系…

Hot100-最小路径和

1 前言 1.1 题目描述 给定一个包含非负整数的 m x n 网格 grid &#xff0c;请找出一条从左上角到右下角的路径&#xff0c;使得路径上的数字总和为最小。 说明&#xff1a;每次只能向下或者向右移动一步。 如下图所示&#xff1a; 输入&#xff1a;grid [[1,3,1],[1,5,1…

ConversionService转换服务使用

前言 在最近分析和写的SpringBoot源码分析(面试官&#xff1a;你说说Springboot的启动过程吧(5万字分析启动过程))中&#xff0c;给自己留了一个关于ConversionService的使用的作业&#xff0c;这不就来补作业了。 使用出处 这个转换服务我这里的例子很简单&#xff0c;就是…

计算机研究生就业方向之去大厂做架构师

我一直跟学生们说你考计算机的研究生之前一定要想好你想干什么&#xff0c;如果你只是转码&#xff0c;那么你不一定要考研&#xff0c;至少以下几个职位研究生是没有啥优势的&#xff1a; 1&#xff0c;软件测试工程师&#xff08;培训一下就行&#xff09; 2&#xff0c;前…

RocketMQ详解及开发用例

概念 Apache RocketMQ作为阿里开源的一款高性能、高吞吐量的分布式消息中间件。 支持Broker和Consumer端消息过滤&#xff0c;支持发布订阅模型和点对点&#xff0c;支持拉pull和推push两种消息模式&#xff0c;单一队列百万消息、亿级消息堆积&#xff0c;支持单master节点&a…

力扣202.快乐数(java语言HashSet方法,类双指针方法)

前言&#xff1a;此题被分类到散列表算法题目中&#xff0c;但乍一看此题实在想不到如何去使用散列表&#xff0c;直到看了官方给的答案。。。。。。 题目描述&#xff1a; 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为&#xff1a; 对于一个正整数&#…

C++ 基本语法

&#x1f4d2;博客主页&#xff1a; ​​开心档博客主页​​ &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐留言&#x1f4dd; &#x1f4cc;本文由开心档原创&#xff01; &#x1f4c6;51CTO首发时间&#xff1a;&#x1f334;2022年12月12日&#x1f334; ✉…

Python40个自动化办公实战案例,终于实现下班自由啦~

拿来就能用&#xff0c;这么爽的吗&#xff1f;&#xff01; 今天我想聊聊&#xff0c;如何通过Python自动化工具&#xff0c;解决工作中常见的办公效率低下的问题。 你有没有想过&#xff0c;下班晚&#xff0c;加班&#xff0c;可能是因为自己工作比较低效&#xff1f; 回…

wireshark 分析理解DHCP流程

DHCP概念&#xff1a; 动态主机配置协议 DHCP&#xff08;Dynamic Host Configuration Protocol&#xff0c;动态主机配置协议&#xff09;&#xff0c;是一个应用层协议。该协议允许服务器向客户端动态分配 IP 地址和配置信息。 知识补充&#xff1a; BOOTP&#xff08;Boots…

PVE使用cloud-init快速启动虚拟机

这里写目录标题关于cloud-init云镜像&#xff08;cloud image&#xff09;下载创建虚拟机模板&#xff0c;可反复使用DebianUbuntuCentOS使用模板关于cloud-init 传统ISO镜像装机时&#xff0c;需要一步一步规定虚拟机&#xff0c;比如系统盘安装在哪个磁盘里&#xff0c;ip是…

Vue Material - 基于谷歌 Material Design 打造的前端组件库,用 Vue 开发海外应用的绝佳选择

一位朋友问我用 vue 开发 APP 在谷歌商店上架&#xff0c;有什么简单的 UI 组件库&#xff0c;我推荐了这款&#xff0c;同样推荐给各位。 关于 Vue Material Vue Material 是一款简单、轻量级的 Vue 组件&#xff0c;组件的设计完全按照 Google Material Design 规范构建&am…

氟尿嘧啶/琥珀酰化壳聚糖偶联载药体(SUCS-5-FuOH)

氟尿嘧啶/琥珀酰化壳聚糖偶联载药体(SUCS-5-FuOH) 产品描述&#xff1a;以自制的琥珀酰化壳聚糖 (SUCS)和羟甲基-5-氟尿嘧啶(5-FuOH)为原料,制备了壳聚糖偶联载药体(SUCS-5-FuOH).结果表明,SUCS和5-FuOH间通过酯键化学键合,接枝率(载药率)为18.7%,在模拟体液和酶存在条件下均有…

Redis高可用全景一览

前言 前几天我在知乎看到一个问题&#xff1a;如何建立自己的知识体系和观点&#xff1f;[1] 在一篇高赞回答中讲述了建立“外脑”是关键&#xff0c;文章观点认为&#xff1a;大脑是用来思考的&#xff0c;不是用来记忆的。 我很认同这样的看法&#xff0c;我的账号名为“杨同…

电脑怎么滚动截图的方法

电脑截图常见的有矩形截图、任意形状截图、全屏幕截图、窗口截图等等&#xff0c;那你知道怎么在电脑上滚动截图吗&#xff1f;有时候可能会需要用到滚动截长图&#xff0c;但是很多 用户都不清楚怎么操作&#xff0c;下面小编就来教教大家电脑怎么滚动截图的方法&#xff08;除…

云存储--2

那么&#xff0c;根据我们上一版块的延续&#xff0c;我们来讲讲实际在linux中需要如何进行存储方面的一个操作吧。 那么我使用的是RHEL9.1 红帽作为在linux领域具有绝对的话语权和强大的市场&#xff0c;所以使用该系统还是有点原因哒~ 那么可能会有同学有疑问&#xff1a;欸&…

多目标遗传算法NSGAII求解环境经济调度(Python代码实现)

目录 1 电力系统环境经济调度数学模型 2 算例——IEEE10节点 2.1 数据​ 2.2 Python代码学习 3 一点拓展知识 1 电力系统环境经济调度数学模型 2 算例——IEEE10节点 2.1 数据 我弄成一个表格&#xff0c;方便编程读写&#xff1a; 2.2 Python代码学习 多目标遗传算法N…

【Flutter 组件】002-基础组件:文本与样式

【Flutter 组件】002-基础组件&#xff1a;文本与样式 文章目录【Flutter 组件】002-基础组件&#xff1a;文本与样式一、Text1、概述2、属性列表3、构造方法4、示例代码演示运行结果二、TextStyle1、概述2、属性列表3、构造方法4、示例代码示例运行结果三、TextSpan1、概述2、…

数字图像处理(入门篇)十 边缘检测

目录 一 边缘检测算子 1 Roberts算子 2 Sobel算子 3 Prewitt算子 二 实践 &#xff08;1&#xff09;代码 &#xff08;2&#xff09;结果图 边缘检测是计算机视觉中的基本问题&#xff0c;边缘检测的难点就在于如何又快又准确地提取图像的边缘信息。 边缘检测的基本方法…

流媒体分析之webrtc之rtcp

TCP作为RTP控制协议&#xff0c;对于弱网下音视频质量和会话控制具有重要的作用。 1. RTCP Header V&#xff1a;RTCP的版本号&#xff0c;一定等于2&#xff1b; P&#xff1a;如果设置&#xff0c;填充位表示数据包包含末尾的附加填充八位字节&#xff0c;不属于控制信息&am…