【论文精读】用于多文档摘要生成的层次Transformer方法

news2024/9/20 20:32:47

前言

论文分享 来自2019ACL的多文档摘要生成方法论文,作者来自英国爱丁堡大学,引用数310
Hierarchical Transformers for Multi-Document Summarization 代码地址hiersumm

多文档摘要抽取的难点在于没有合适的数据集,同时过长的文档文本也导致现在硬件水平无法支撑模型的训练,Generating Wikipedia by summarizing long sequences.提出了WikiSum数据集,以维基百科的第一段内容作为摘要,以标题+引用的文章或根据标题在网页搜索的前10篇文章(除去wikipedia本文)作为相同主题的文章集(document cluster)输入,提出WikiSum的作者采用二步结构,先抽取式选择一部分重要的段落,然后将这些重要的段落拼接成一个段落后,采用生成式模型进行生成

作者指出,这种将所有重要段落拼接成一个段落的方式忽略了段落之间的层次信息,作者的创新点在于设计了学习文章间层次结构的transformer,并发现对输入文章进行排序能够增强模型效果

模型

首先作者构建了一个段落排序模型,采用基于LSTM的回归模型,以标题和段落作为输入,以段落与目标摘要的ROUGE-2分数作为输出进行拟合,得到一个可以根据标题和段落生成分数的预测模型,在测试时,段落会根据回归模型生成的分数进行排序,最后筛选出 L ′ L' L个段落作为最终摘要模型的输入,这里其实是摘要式方法的一种变种,可以有很多选择,整体模型的过程如下图所示,将排序后的 L ′ L' L个段落输入到encoder-decoder中最终输出生成式摘要
在这里插入图片描述
编码层: 编码层将字转化成向量,并加入位置信息,位置信息为三角函数编码
在这里插入图片描述
其中由于输入的位置包括字的位置信息和段落的位置信息,因此作者将两个三角函数位置信息通过拼接的方式,拼接到每一个字向量后,i为段落位置,j为字位置,拼接后得到位置编码 p e i j pe_{ij} peij, w i j w_{ij} wij为字向量, x i j 0 x_{ij}^0 xij0代表第0层,第i个段落第j个字符的向量
在这里插入图片描述
局部Transformer层: 和普通的Transformer一样,由多头注意力层和前向连接层构成
在这里插入图片描述
全局Transformer层: 全局Transformer层通过self-attention让每一个段落收集其他段落的信息,得到一个获取上下文信息的全局向量,其由多头池化(Multi head pooling),段落间注意力机制(inter paragraph attention mechanism)和前向连接层构成
多头池化: 是论文的创新点之一,其计算每一个字的分布,根据不同字的权重编码整个句子,是将序列字编码成单一向量的好方法,公式如下
在这里插入图片描述
由局部Transformer编码的向量维度为 [ b a t c h , s e q l e n , d i m ] [batch, seqlen, dim] [batch,seqlen,dim],通过两个全连接层分别映射到注意力值 a a a,维度为 [ b a t c h , n h e a d , s e q l e n , 1 ] [batch,n_{head},seqlen,1] [batch,nhead,seqlen,1]和值 b b b,维度为 [ b a t c h , n h e a d , s e q l e n , , d h e a d ] [batch,n_{head},seqlen,,d_{head}] [batch,nhead,seqlen,,dhead],注意力分数通过对注意力值进行softmax得到
在这里插入图片描述
将注意力分数和字向量进行相乘后,在序列长度维度进行相加和归一化后,得到每一个段落不同head的表征,多头池化代码如下,输入为 [ b a t c h , s e q l e n , d i m ] [batch, seqlen, dim] [batch,seqlen,dim],输出为 [ b a t c h , h e a d , d i m ] [batch,head,dim] [batch,head,dim]

class MultiHeadedPooling(nn.Module):
    def __init__(self, head_count, model_dim, dropout=0.1, use_final_linear=True):
        assert model_dim % head_count == 0
        self.dim_per_head = model_dim // head_count
        self.model_dim = model_dim
        super(MultiHeadedPooling, self).__init__()
        self.head_count = head_count
        self.linear_keys = nn.Linear(model_dim,
                                     head_count)
        self.linear_values = nn.Linear(model_dim,
                                       head_count * self.dim_per_head)
        self.softmax = nn.Softmax(dim=-1)
        self.dropout = nn.Dropout(dropout)
        if (use_final_linear):
            self.final_linear = nn.Linear(model_dim, model_dim)
        self.use_final_linear = use_final_linear

    def forward(self, key, value, mask=None):
        batch_size = key.size(0)
        dim_per_head = self.dim_per_head
        head_count = self.head_count

        def shape(x, dim=dim_per_head):
            """  projection """
            return x.view(batch_size, -1, head_count, dim) \
                .transpose(1, 2)

        def unshape(x, dim=dim_per_head):
            """  compute context """
            return x.transpose(1, 2).contiguous() \
                .view(batch_size, -1, head_count * dim)

        scores = self.linear_keys(key)
        value = self.linear_values(value)

        scores = shape(scores, 1).squeeze(-1)
        value = shape(value)
        # key_len = key.size(2)
        # query_len = query.size(2)
        #
        # scores = torch.matmul(query, key.transpose(2, 3))

        if mask is not None:
            mask = mask.unsqueeze(1).expand_as(scores)
            scores = scores.masked_fill(mask, -1e18)

        # 3) Apply attention dropout and compute context vectors.
        attn = self.softmax(scores)
        drop_attn = self.dropout(attn)
        context = torch.sum((drop_attn.unsqueeze(-1) * value), -2)
        if (self.use_final_linear):
            context = unshape(context).squeeze(1)
            output = self.final_linear(context)
            return output
        else:
            return context

不输出head维度,直接输出单一的段落向量方法,输入为 [ b a t c h , s e q l e n , d i m ] [batch, seqlen, dim] [batch,seqlen,dim],输出为 [ b a t c h , d i m ] [batch,dim] [batch,dim]

class MultiHeadPoolingLayer( nn.Module ):
    def __init__( self, embed_dim, num_heads  ):
        super().__init__()
        self.num_heads = num_heads
        self.dim_per_head = int( embed_dim/num_heads )
        self.ln_attention_score = nn.Linear( embed_dim, num_heads )
        self.ln_value = nn.Linear( embed_dim,  num_heads * self.dim_per_head )
        self.ln_out = nn.Linear( num_heads * self.dim_per_head , embed_dim )
    def forward(self, input_embedding , mask=None):
        a = self.ln_attention_score( input_embedding )
        v = self.ln_value( input_embedding )
        
        a = a.view( a.size(0), a.size(1), self.num_heads, 1 ).transpose(1,2)
        v = v.view( v.size(0), v.size(1),  self.num_heads, self.dim_per_head  ).transpose(1,2)
        a = a.transpose(2,3)
        if mask is not None:
            a = a.masked_fill( mask.unsqueeze(1).unsqueeze(1) , -1e9 ) 
        a = F.softmax(a , dim = -1 )

        new_v = a.matmul(v)
        new_v = new_v.transpose( 1,2 ).contiguous()
        new_v = new_v.view( new_v.size(0), new_v.size(1) ,-1 ).squeeze(1)
        new_v = self.ln_out( new_v )
        return new_v

段落间注意力: 段落间注意力是采用自注意力机制(scale dot product)对每一个段落的head表征进行学习,目的是让每一个段落学习到其他段落的关联信息,最终得到段落i,注意力头z的上下文表征 c o n t e x t i z context_i^z contextiz在这里插入图片描述
前向连接层: 前向连接层的输入为一个段落多个head的拼接, 最终输出和全局Transformer层输入一样维度的输出
在这里插入图片描述在这里插入图片描述
段落间注意力的注意力分数其实是段落间的关系系数,因此可以采用已学习好的图表征来代替,例如句法关系图(Lexical Relation Graph)和(近似对画图)Approximate Discourse Graph,有兴趣的读者可以看论文附录,替代方式如下
在这里插入图片描述

实验

在这里插入图片描述
作者比较了不同数量段落的情况下,tf-idf cosine similarity和使用回归模型排序选择方式下,抽取段落和真实摘要之间的ROUGE-L 召回值,可以发现回归模型能够选择更好的段落
在这里插入图片描述
作者比较了层次Transformer模型与Flat Transformer和Transformer Decoder with Memory Compression attention之间的性能,HT相比T-DMCA在更少的字符数下能够有些微的提升,同时,在1600长度文本训练的模型,在3000字输入的情况下能够获得更好的结果,近1个点的ROUGE提升
在这里插入图片描述
作者还做了消融实验,表明位置编码,多头池化和全局Transformer都是有用的

结论

论文中采用多头池化的方式获得多头上下文表征,并将不同段落的多头上下文表征进行相互学习

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

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

相关文章

Makefile模板和工程模板(消息队列和共享内存)的使用

一、 Makefile模板 #指定生成的文件名 OJB_OUT test#指定每一个c文件对应的.o文件 OBJS a.o b.o main.o#指定编译器 CC gcc#指定需要的库 ULDFLAGS ########################################### #以下的内容不需要修改 ########################################### all:…

行业追踪,2023-08-01

自动复盘 2023-08-01 凡所有相,皆是虚妄。若见诸相非相,即见如来。 k 线图是最好的老师,每天持续发布板块的rps排名,追踪板块,板块来开仓,板块去清仓,丢弃自以为是的想法,板块去留让…

leetcode-143-重排链表

题意描述: 给定一个单链表 L 的头节点 head ,单链表 L 表示为: L0 → L1 → … → Ln - 1 → Ln 请将其重新排列后变为: L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → … 不能只是单纯的改变节点内部的值,而是需要…

cmake+pybind11打包c++库成python wheel安装包

目录 写在前面准备1、pybind11获取源码编译安装 2、conda demo官方源码修改CMakeLists.txt编译生成安装测试 参考完 写在前面 1、本文内容 有时候我们需要用c代码,供python调用,本文提供将c库封装成python接口的方法,并将库打包成可通过pip安…

Apikit 自学日记:API 异常监控-创建 API 监控

如何在apikit中,创建 API 监控呢? 创建并开启监控API 一、手动创建监控API Eolink API 网络监控平台支持从 Eolink API Management(API管理产品)中导入API信息,或者手动创建监控API。 进入API监控页面,点击…

23款奔驰S450 4MATIC升级原厂流星雨智能数字大灯,让智能照亮您前行的路

凭借智能数字大灯 (DIGITAL LIGHT),您可体验根据其他道路使用者和周围环境进行优化调节的理想照明条件。这款包含130万像素模块大灯,进一步扩展了几何多光束 LED 大灯的功能。其高分辨率的照明可有针对性地点亮各个区域。解锁车辆时,大灯将通…

快速制作美容行业预约小程序

随着科技的不断进步,移动互联网的快速发展,小程序成为了很多行业迅速发展的利器。对于美容行业来说,一款美容预约小程序不仅可以方便用户进行预约,还可以提升美容店铺的服务质量和管理效率。下面,我们来介绍一下如何快…

23 设计模式(详细介绍附DEMO)

设计模式在Java中的应用与实现 🚀🚀🚀1.创建型模式1. 工厂方法模式(Factory Pattern)2.抽象工厂模式(Abstract Factory Pattern)3. 单例模式(Singleton Pattern)4.原型模…

rfid资产盘点管理系统软件

很多企业开始规划固定资产的总结,或者现在开始总结资产。面对众多不同种类的固定资产,总结已经成为一项工程量大、耗时长的任务。采用轻松的RFID固定资产管理系统后,可以大大提高这种总结工作的效率,获得比过去更清晰的资产清单和…

三菱plcCCLINK转profinet与西门子PLC通讯案例分析

用三菱PLC的控制系统需要和西门子的PLC控制系统交互数据,捷米JM-PN-CCLK 是自主研发的一款 PROFINET 从站功能的通讯网关。该产品主要功能是将各种 CCLINK 总线和 PROFINET 网络连接起来。 捷米JM-PN-CCLK总线中做为从站使用,连接到 CCLINK 总线中做为…

【C++】基于多设计模式下的同步异步日志系统

✍作者:阿润021 📖专栏:C 文章目录 一、项目介绍二、项目实现准备工作1.日志系统技术实现策略2.相关技术知识补充2.1 不定参函数设计2.2 设计模式 三、日志项目框架设计1.模块划分2.各模块关系图 四、详细代码实现1.实用工具类设计2.日志等级…

StampedLock使用及源码分析:号称比读写锁还要快的锁

文章目录 一、StampedLock锁概述1、StampedLock锁简介2、ReentrantReadWriteLock回顾3、ReentrantReadWriteLock导致锁饥饿问题4、锁饥饿问题的缓解5、StampedLock与ReentrantReadWriteLock的对比6、StampedLock特点7、StampedLock的缺点 二、StampedLock的使用1、StampedLock的…

基于PHP校园疫情防控信息管理系统-计算机毕设 附源码12057

PHP校园疫情防控信息管理系统 摘 要 如今计算机行业的发展极为快速,搭载于计算机软件运行的数据库管理系统在各行各业得到了广泛的运用,其在数据管理方面具有的准确性和高效性为大中小企业的日常运营提供了巨大的帮助。自从2020年新冠疫情爆发以来&…

ArduPilot H743 Dual BMI270 Mark4 四轴DIY简单功能验证

ArduPilot H743 Dual BMI270 Mark4 四轴DIY简单功能验证 1. 源由2. 梳理2.1 基本配置2.2 滤波配置2.3 FPV-VTX配置2.4 FPV操控2.5 自适应PID调参2.6 电传配置 3. 视频3.1 FPV操控性3.2 路点巡航3.3 救援模式 4. 总结5. 参考资料6. 补充说明--问题集中回答 1. 源由 基于Mark4机…

易上手的数据报表工具有哪些?奥威BI零编程

易上手的数据报表功能有哪些?实际上,国产的BI报表工具都算得上是易上手的,因为它们大多都是低代码的BI报表工具,只需掌握基础SQL即可。但奥威BI报表工具却是零编程做大数据分析的BI报表工具。要说易上手,奥威BI报表工具…

Spark-统一内存模型

总结: Spark的内存模型分为4部分,分别是存储内存,计算内存,其他内存,预留内存; 其中存储内存和计算内存可以动态占用,当己方内存不足对方空余则可占用对方的内存,计算内存被存储内…

Attention机制竟有bug,Softmax是罪魁祸首,影响所有Transformer

大模型开发者,你们错了! 「我发现注意力公式里有个 bug,八年了都没有人发现。所有 Transformer 模型包括 GPT、LLaMA 都受到了影响。」 昨天,一位名叫 Evan Miller 的统计工程师的话在 AI 领域掀起了轩然大波。 我们知道&#x…

解决单节点es索引yellow

现象 单节点的es,自动创建索引后,默认副本个数为1,索引状态为yellow 临时解决 修改副本个数为0 永久解决 方法1、修改elasticsearch.yml文件,添加配置并重启es number_of_replicas:副本分片数,默认…

UG\NX二次开发 创建分割面、细分面

文章作者:里海 来源网站:https://blog.csdn.net/WangPaiFeiXingYuan 简介: 群友问“UF没有分割面吗” 这个是有的,下面就是分割面(细分面)的演示效果和c++源代码。 效果: 代码: #include "me.hpp" #include <stdio.h> #include <string.h> #i…

财报解读:英特尔二季度业绩回暖,IFS业务增长势能已然释放?

英特尔终于看到了盈利曙光。 北京时间7月28日&#xff0c;英特尔公布了2023财年第二季度财报&#xff0c;数据显示公司业绩超出市场预期&#xff0c;财报一经发布&#xff0c;第二个交易日英特尔股价上涨6.6%&#xff0c;最终报收36.83美元。 &#xff08;图片来源&#xff1a…