TwoModalBERT进行角色分类

你是否遇到过数据集中有多个文本特性的情况?例如,根据消息的上下文正确地对消息进行分类,即理解前面的消息。比如说我们有下面的数据集,需要对其进行分类。

当只考虑message时,你可以看到它的情绪是积极的,因为“incredible”这个词。但是当考虑到背景时,我们可以看到它时消极的

所以对于上下文来说,我们需要知道更多的信息,例如:

  • 是否值得将上下文作为一个单独的特征来考虑?
  • 将两个文本特征集中在一起是否会提高模型的性能?
  • 是否应该引入上下文和信息的权衡?如果是,合适的权重比例是多少?

本文有一个简单的实现,就是:将两个文本字段连接起来。与仅使用最新消息相比,它能给模型带来改进——但是我们应该深入研究两个文本的权重比例。所以可以创建一个神经网络,它有两种模式,每个模式上的密集层大小可调?这样,我们就能自动找到合适的权重!

这里我们介绍的TwoModalBERT支持在nn中查找两个文本模式的适当权重比例!让我们看看里面的神经网络是如何构建的。

TwoModalBERT体系结构

下面可以看到TwoModalBERT是如何构造的以及类参数

首先,在最后一个BERT层之上添加一个线性层。我们还是沿用BERT的配置,将其应用在CLS令牌之上。由于CLS令牌聚合了整个序列表示,它经常用于分类任务中。为了更好地理解,让我们看看相关的三行代码。

 outputs = self.model(input_ids=input_ids, attention_mask=attention_mask)
 last_hidden_states = outputs['hidden_states'][-1]
 # last layer size: (batch_size, seq_len, hs)
 cls_hidden_states = last_hidden_states[:, 0, :]
 last_hidden_states_reduced = linear_layer(cls_hidden_states)

线性层将隐藏大小与BERT模型相关的输入特征转换为隐藏大小等于预定义的context_size和text_size的特征,对于transformer包中可用的模型,隐藏层大小通常为768。

然后添加一个dropout层使神经网络对神经元的具体权重不那么敏感,不容易过拟合。

最后,将两个类似创建的分支组合在一起,后面跟着另一个dropout层。

TwoModalBERT包

TwoModalBERT包允许我们用上面描述的双模态神经网络体系结构快速运行实验。它允许在Pytorch和transformer库之上快速构建模型,并允许对两个输入文本的权重进行实验。

我们应该使用下表中描述的参数创建config.ini文件。

在设置了初始参数之后,我们可以查看这个示例。这里将使用包含该系列所有对话的“The Office”数据集(https://www.kaggle.com/datasets/nasirkhalid24/the-office-us-complete-dialoguetranscript)。我们的目标是验证:根据前一行和当前行对比仅当前行的文本来识别说话的角色是否具有更高的准确率。

我们对数据集进行简单的预处理后,数据集如下所示:

这里的三个列是

  • line 说话人说的话
  • context 前一位说话人所说的内容
  • label 与每个演讲者相关的数字
 # intialize modules
 DataPreparation = TwoModalDataPreparation(config=config)
 Trainer = TwoModalBertTrainer(device=DEVICE, config=config)
 # create data loaders
 (
     train_data_loader,
     train,
     val_data_loader,
     val,
     test_data_loader,
     test,
 ) = DataPreparation.prepare_data(
     df,
     text_column="line",
     context_column="context",
     label_column="label",
     train_size=0.8,
     val_size=0.1,)

在创建数据加载器之后,就可以训练模型了。这里使用的所有神经网络参数都在前面的列表中给出了。我们设置text_size = 100和context_size = 1。

 # train the model 
 model, history = Trainer.train_model(
  train_data_loader,
  train,
  val_data_loader,
  val,
  text_size=100,
  context_size=50,
  binary=False,
  text_p=0.3,
  context_p=0.3,
  output_p=0.3,
  )
  # evaluate the model on a test set
 y_pred, y_test = test_model(model, test_data_loader)
 y_pred, y_test = [e.cpu() for e in y_pred], [e.cpu() for e in y_test]

由于模型经过了训练,我们可以在测试集上对其进行评估(可以在y_pred和y_test上应用任何度量)。下面我们查看混淆矩阵。

除了Michael,模特没有学会识别任何角色。我们把context_size增加到50,看看混淆矩阵如何变化?

可以观察到,模型学会了识别 Dwight, Michael, Jim。对于一些其他角色来说,这种方法并不适用。但是与前一个选项相比,有很大的改进,并且通过配置context_size我们还有更多的提升空间

然后我们看看模型如何做推理:

 # run on new pair of text inputs
 line = "Dwight is my best friend."
 context = "What do you think about Dwight?"
 predict_on_text(model, line, context)

模型可以返回正确的结果:Stanley

总结

本文介绍的TwoModalBERT包的可以说是一个非常简单的魔改模型,它不需要对模型内部进行修改,只需要修改外部的梳理过就就可以快速提高两个输入文本字段的不同加权模式对分类神经网络性能的影响。本文的完整代码请见:https://github.com/zuzadeu/twomodalbert

作者:Zuzanna Deutschman

本文转载于网络 如有侵权请联系删除

相关文章

  • Redis 高可用篇:你管这叫 Sentinel 哨兵集群原理

    概要我们知道「主从复制是高可用的基石」,从库宕机依然可以将请求发送给主库或者其他从库,但是Master宕机,只能响应读操作,写请求无法再执行。所以主从复制架构面临一个严峻问题,主库挂了,无法执行「写操作」,无法自动选择一个Slave切换为Master,也就是无法故障自动切换。深夜与女朋友么么哒……(此处省略10000字),突然宕机,总不能提起裤子从床上爬起来手工进行主从切换,再通知其他程序员把地址重新改成新主库上线。如此一折腾自己已被女友切换成前男友了,万万使不得。所以我们必须有一个高可用的方案,为此,Redis官方提供一个高可用方案——哨兵(Sentinel)。Redis哨兵集群原理开篇寄语“技术的迭代非常的快,但是从技术中沉淀下来的思维却是受益终生的。所以不要担心什么中年危机,那些担心中年危机的人通常很难成长起来。只要我们成长,只要我们的认知在不断突破,就不用担心中年危机,这个世界始终是需要那些优秀人才的。 ”什么是哨兵(Sentinel)“65哥:码哥,虽然我没女朋友,但是,未雨绸缪我要掌握这个哨兵模式,防止当深夜与女朋友么么哒被打扰,你快说说哨兵的实现原理吧。 ”搭建实例采用三

  • javaScript 原生DOM节点操作(最实用的dom节点操作大全)

    简单介绍一下DOMDOM(DocumentObjectModel)译为文档对象模型,是HTML和XML文档的编程接口。也就是说把文档编译成了一个对象模型,例如我们写的html文件实际上是一个文档文件,通过我们的浏览器把它编译成了一个对象模型,这个模型就是document对象。DOM以树结构表达HTML文档。就好像是一个家族谱,有父级元素也有对应的子级元素,那么document对象就是我们最大的父级元素。如下图,家族谱上面的每一个元素都是一个节点,通过对这些节点的操作,我们可以对这个页面为所欲为。节点的分类元素节点属性节点文本节点节点的操作元素节点操作通过元素的id来获取相应的节点 document.getElementById("");通过元素的标签名来获取节点 document.getElementsByTagName("");通过元素的类名来获取节点 document.getElementsByClassName("");通过元素的name属性来获取节点 document.getElementsByName("&

  • 如何使用PHP创建完整的日志

    当我们想跟踪Web应用程序中执行的事件时,我们需要为其保存日志。主要有2种用于保存日志以跟踪用户事件的方法。一种是保存日志文件,另一种是保存在数据库中。通常,开发人员将IP地址和请求参数保存在DB中。在本教程中,我将向您展示如何使用PHP保存完整的日志。这种方法将帮助您添加与在Web应用程序中执行的特定事件有关的完整信息。让我们看看如何创建完整的日志。使用数据库存储自定义日志您可以使用数据库创建表以保存完整的日志创建数据库表我们已经创建了数据库或选择了已经存在的数据库。在此步骤中,我们将创建一个表来存储日志。 您可以复制以下给定的查询,并在PHPMyAdmin的SQL查询选项中使用它来创建表。CREATETABLEcomplete_log( idint(11)NOTNULL, useridint(11)DEFAULTNULL, platformvarchar(30)DEFAULTNULL, servertext, requesttext, logtimetimestampNOTNULLDEFAULTCURRENT_TIMESTAMPUPDATECURRENT_TIMESTAMP)ENG

  • 基于react/vue搭建一个通用的表单管理配置平台

    前言 熟悉我的朋友可能会知道,我一向是不写热点的。为什么不写呢?是因为我不关注热点吗?其实也不是。有些事件我还是很关注的,也确实有不少想法和观点。但我一直奉行一个原则,就是:要做有生命力的内容。这篇文章是一篇应用性极强的文章,我们通过一个实际的应用场景,去解决某一类的问题,提供一种或者几种解决方案,来探索技术的魅力。接下来笔者主要分析表单定制平台的实现思路和技术方案,来实现一个类似于金数据或者问卷星一样的表单配置平台,大家也可以基于此方案,扩展出功能更加强大的可视化平台。正文为什么要做一个这样的平台呢?一方面是因为笔者多年来一直服务于B端产品,对于动态表单以及配置化表单有一定的项目积累,并且深知配置化表单的价值所在。举一个很传统的B端表单配置化的例子:传统2B企业在提供saas服务时,为了满足不同企业的定制化需求,往往会给企业客户提供定制化或者自由配置的功能,如下图:对于saas系统而言,软件即服务,在提供基础服务的同时,同样要满足用户个性化需求,所以传统的saas软件提供商往往会提供给客户自由配置的空间,这种自由配置的桥梁就是通过表单,举一个简单的例子:通过这种方法就可以定制不同风格

  • 2-1 线性表之顺序表 及其C语言实现

    2-1线性表之顺序表0、数据结构大致包含以下几种存储结构:线性表:还可细分为顺序表、链表、栈和队列;树结构:包括普通树,二叉树,线索二叉树等;图存储结构;1、线性表线性表,全名为线性存储结构。是由n个相同类型的元素所构成的有限线性序列。线性表主要的基本操作有以下几种:①Initiate(L):初始化,设定一个空的线性表。②Length(L):对给定的线性表,函数返回值为其数据元素的个数。③Get(L,i):按给定的索引号,取出元素④Locate(L,x):定位,对给定值x,若线性表中存在某个元素等于x,返回其索引号i;若存在多个元素等于x,返回最小的索引i;若不存在,返回False⑤Insert(L,i,x):插入,对给定的线性表,在第i个位置插入新元素x,(i要在长度范围内)⑥Delete(L,i):删除,对给定的线性表,按照索引号i删除对应元素,(i要在长度范围内)这几项是线性表应当满足的基本的操作。线性表存储数据可细分为以下2种:①将数据依次存储在连续的整块物理空间中,这种存储结构称为顺序存储结构(简称顺序表);②数据分散的存储在物理空间中,通过一根线保存着它们之间的逻辑关系,这

  • ASP.NET实现文件的上传和下载

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/details/40785429     最近做的一个高校网站中涉及到了上传和下载文件的需求(具体需求为:网站公布的通知,在后台要能给每个通知添加附件,在前台要能显示并下载附件),之前只是学习过关于上传的理论知识,这里实践了一下下,与大家分享一下成果。    事先说明:这个例子采用的是简单的三层结构,层与层之间是用实体来传值。而且这种方法不但在本地测试时可以成功,并且可以部署在服务器上,供异地上传和下载文件。    专门做了一个数据库表用来存储附件的相关信息:字段说明AnnexID附件IDAnnexName附件名称AnnexAddress存储附件的地址NoticeID附件所属“通知”的ID    ASP.NET实现上传文件前端    界面十分简单,只是放一个file类型的<input>和一个按钮,并且为这个按钮添加点击事件(btnUpLoad_Click),如下图:    代码:<inputid="

  • 新技术教会聊天机器人应对不确定问题

    位于马萨诸塞州剑桥的AI创业公司Gamalon开发了一种能够教会机器处理不确定聊天问题的新技术,目前一些企业正在测试一种基于该技术的聊天机器人平台。看上去有些矛盾的是,一种包含不确定性和模糊性的人工智能方法可以帮助未来的虚拟助手减少混乱。这种技术提供了一种方法,能够处理一句话中可能传达的多种含义,从而使计算机可以进行更有意义和更连贯的对话。如果一个人说的话或键入的内容含糊不清,系统会给出一个最可能的判断。当前的虚拟助理和聊天机器人通常遵循简单的规则来回答问题。统计机器学习方面的最新进展可以通过某些方法增加上述应用的灵活性,如让机器通过搜索大量文本来找到问题的答案。然而,这两种方法都可能因为语言中经常包含的过度复杂性和含义模糊性而成为牺牲品。Gamalon的创始人兼首席执行官BenVigoda告诉麻省理工科技评论(MITTechnologyReview),他们公司的方法也依赖于规则和机器学习,但向组合中增加了一种概率技术,能够整合自动处理不确定问题的程序。在实践中,这意味着系统可以通过最好地猜测语言的含义来处理其中的不确定性。它还提供了一个会话记忆功能:在询问今天天气如何之后,你可以提问

  • Android面试题:bindService获取代理是同步还是异步

    Android中bindService是一个异步的过程,什么意思呢?使用bindService无非是想获得一个Binder服务的Proxy,但这个代理获取到的时机并非由bindService发起端控制,而是由Service端来控制,也就是说bindService之后,APP端并不会立刻获得Proxy,而是要等待Service通知APP端,具体流程可简化如下:APP端先通过bindService去AMS登记,说明自己需要绑定这样一个服务,并留下派送地址APP回来,继续做其他事情,可以看做是非阻塞的AMS通知Service端启动这个服务Service启动,并通知AMS启动完毕AMS跟住之前APP端留下的地址通知APP端,并将Proxy代理传递给APP端通过代码来看更直接voidtest(){ bindService(intent,newServiceConnection(){ @Override publicvoidonServiceConnected(ComponentNamecomponentName,IBinderiBinder){ iMyAidlInterface=IMyAidlI

  • js去掉html标签和去掉字符串文本的所有的空格

    去掉html标签的js<script>  functiondelHtmlTag(str){   returnstr.replace(/<[^>]+>/g,"");//去掉所有的html标记  } varstr="<spanstyle='display:none;'>Thisistest</span><imgsrc=''>ss</img><strong></strong><br/>"; str=delHtmlTag(str); alert(str); </script>复制为了一个title去html标签所做的修改:functiondelHtmlTag(str,obj){    vartitle=str.replace(/<[^>]+>/g,"");//去掉所有的html标记  if(title.length>300){   title=ti

  • 为何Idea 中 Debug 运行太慢?

    在项目中Debug过程中,突然发现使用Debug运行项目太慢,直接项目启动不起来了,但是Run模式则正常。 原因是在方法上打了断点,把断点去掉,Debug模式即可正常启动。 这里记录下 1.首先,我们Debug运行的时候非常慢的原因很大一部分是在方法上打了断点,而这种情况会出现Methodbreakpointsmaydramaticallyslowdowndebugging的提示。    第二步,我们点击Debug页面左侧的向右的箭头。    第三步、在点击箭头之后,出现几个选项,我们点击第一个的两个交叉的小圆。    第四步、我们将JavaMethodBreakpoints下所有选项的勾都去掉。    第五步、点击页面右侧的Done即可  

  • Kubernetes学习(五)

    五DaemonSet,Job,CronJob DaemonSet举例 apiVersion:apps/v1kind:DaemonSetmetadata:name:daemonset-examplelabels:app:daemonsetspec:selector:matchLabels:name:daemonset-exampletemplate:metadata:labels:name:daemonset-examplespec:containers:-name:daemonset-exampleimage:wangyanglinux/myapp:v4 Job举例 apiVersion:batch/v1kind:Jobmetadata:name:pispec:template:metadata:name:pispec:containers:-name:piimage:perlcommand:['perl','-Mbignum=bpi','-wle','printbpi(2000)']restartPolicy:Never        

  • 登录验证+bootStrap+jQuery+封装

    <!DOCTYPEhtml> <htmllang="en"> <head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width,initial-scale=1.0"> <title>Document</title> <linkrel="stylesheet"href="../node_modules/bootstrap/dist/css/bootstrap.css"> <scriptsrc="../node_modules/jquery/dist/jquery.js"></script> <scriptsrc="../node_modules/bootstrap/dist/js/bootstrap.js"></script> </head> <body> <divclass="col-xs-4col-xs-offset-4"&g

  • const static extern

    http://wenku.baidu.com/link?url=saMJ3WpR_Lili2oflaIK-xK7wkQhtP2I-FdEX6I_XjmNxl7m0Z8SYHJtfqyXYkSmok8hkOugcFeO2_CUyNKzsUc8sD-ycpEFIqxOXMoJ1qG const可以放在头文件里多次包含,因为它的值不会变; static最好不要放在头文件里,它会在每个包含它的文件里留下多个拷贝,值在运行中可能不一样。   在头文件中 externinta=1效果等于inta=1;多次包含会报错

  • 伪造 UDP 包源 IP 地址

    Rawsockets方式 rawsocket可通过参数 IPV6_HDRINCL或IP_HDRINCL自定义IP头——伪造UDP报文源IP就全靠它了。 限制:从xpsp2之后的所有非服务器版本的windows,都不能发送TCP,并且也不能伪造UDP的源地址。 这里使用dpkt做UDP/IP包的组装: classSyslogSenderRawScoket: def__init__(self,dst,dport,src,sport=10000): self.dst=socket.gethostbyname(dst) self.dport=dport self.src=src self.sport=sport self.sock=socket.socket(socket.AF_INET,socket.SOCK_RAW,socket.IPPROTO_UDP) self.sock.setsockopt(socket.IPPROTO_IP,socket.IP_HDRINCL,1) self.sock.connect((self.dst,1)) defSend(self,ip_pac

  • centos安装wordpress_小白上百次折腾经验

    本文由 书画小说软件 整理发布 内容与本软件无关   更惬意的读、更舒心的写、更轻松的发布最全古典小说网 由本软件发布所得             折腾了几天,终于找到很节省资源的安装wordpress方案。 复制成功搭建网站 http://www.gudianxiaoshuo.com      and   http://www.gudianbook.com同时向大家推荐下wordpress建站利器  书画小说软件4.0版  我的网站 就是用这个软件搭建的  222本书 15000余篇文章 共用8个半钟头左右。好了,转回正题,入手了一台LINUX VPS  进去一看&nbs

  • 洛谷4072 SDOI2016征途 (斜率优化+dp)

    首先根据题目中给的要求,推一下方差的柿子。 \[v\timesm^2=m\times\sumx^2-2\timessum\timessum+sum*sum \]所以\(ans=v*m^2=m\times\sumx^2-sum*sum\) 那我们实际上就是最大化平方和。 由于题目限制了要分\(m\)段。所以我们的\(dp\)状态就是\(f[i][j]\)表示前\(i\)个数分了\(j\)段。 那么一个比较显然的转移 \(dp[i][p]=min(dp[j][p-1]+(s[i]-s[j]^2))\) 然后直接套斜率优化就好了! 但是要注意的是,因为题目中对第二维有点限制,所以我们要开\(m\)个单调队列来维护。 对于\(dp[i][j]\),每次从\(j-1\)的单调队列要转移。 #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<queue> #include<ma

  • Java 判断字符串 中文是否为乱码

    importjava.util.regex.Matcher; importjava.util.regex.Pattern; publicclassChineseUtill{ privatestaticbooleanisChinese(charc){ Character.UnicodeBlockub=Character.UnicodeBlock.of(c); if(ub==Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS ||ub==Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS ||ub==Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A ||ub==Character.UnicodeBlock.GENERAL_PUNCTUATION ||ub==Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION ||ub==Character.UnicodeBlock.HALFWIDT

  • android如何释放图片缓存

      在你应用程序的UI界面加载一张图片是一件很简单的事情,但是当你需要在界面上加载一大堆图片的时候,情况就变得复杂起来。在很多情况下,(比如使用ListView,GridView或者ViewPager这样的组件),屏幕上显示的图片可以通过滑动屏幕等事件不断地增加,最终导致OOM。 为了保证内存的使用始终维持在一个合理的范围,通常会把被移除屏幕的图片进行回收处理。此时垃圾回收器也会认为你不再持有这些图片的引用,从而对这些图片进行GC操作。用这种思路来解决问题是非常好的,可是为了能让程序快速运行,在界面上迅速地加载图片,你又必须要考虑到某些图片被回收之后,用户又将它重新滑入屏幕这种情况。这时重新去加载一遍刚刚加载过的图片无疑是性能的瓶颈,你需要想办法去避免这个情况的发生。 这个时候,使用内存缓存技术可以很好的解决这个问题,它可以让组件快速地重新加载和处理图片。下面我们就来看一看如何使用内存缓存技术来对图片进行缓存,从而让你的应用程序在加载很多图片的时候可以提高响应速度和流畅性。 内存缓存技术对那些大量占用应用程序宝贵内存的图片提供了快速访问的方法。其中最核心的类是LruCache

  • 游戏编程模式

    新接触到的书籍,非常有必要看一看 https://gpp.tkchu.me

  • sql server修改默认值语句

    1):已存在默认值语法:execsp_helpconstraint@objname=表名(查看指定表相关约束详情)           altertable表名dropconstraint约束名(删除默认值)           altertable表名adddefault默认值for字段名2:):无默认值语法:altertable表名adddefault默认值for字段名

  • 用Java制作贪吃蛇小游戏

    1.贪吃蛇小游戏详解 1.1引入 游戏效果展示: 涉及技能点: 游戏图形化界面编程---》GUI图形化界面编程 GUI中的组件: GUI技术,不流行了!!! 已经被淘汰了,为什么还学? (1)提起兴趣 (2)分层思想 (3)锻炼监听器的思想 (4)举一反三 1.2将图片加载到程序中来 测试相对路径: 将图片封装: publicclassImages{ /* 现在是面向对象的语言,面向对象的思维-->>将图片进行封装,封装为一个对象,这样在程序中才可以通过操纵这个对象来操纵图片。 */ //将图片的路径封装为一个对象: publicstaticURLbodyURL=Images.class.getResource("/images/body.png");//"/"指相对路径 //将图片封装为程序中一个对象: publicstaticImageIconbodyImg=newImageIcon(bodyURL); //将图片的路径封装为一个对象: publicstaticURLdownURL=Images.class.getResour

相关推荐

推荐阅读