最短路径算法
- Dijkstra算法
- Floyd算法
应用程序 | FTP | TFTP | TELNET | SMTP | DNS | HTTP | SSH | MYSQL |
---|---|---|---|---|---|---|---|---|
熟知端口 | 21,20 | 69 | 23 | 25 | 53 | 80 | 22 | 3306 |
传输层协议 | TCP | UDP | TCP | TCP | UDP | TCP | TCP | TCP |
Cookie与Session的区别
进程阻塞的原因
进程有3个状态:就绪态、执行态、阻塞态。三种状态的转换包含有:
就绪->执行,执行->就绪,执行->阻塞,阻塞->就绪
等待I/O、进程sleep、等待解锁等原因都会导致进程暂停。
关于”时间片切换”,当进程已经获得了除cpu外所有的资源,这时的状态就是就绪态,
当分配到了时间片就成了执行态,当时间片用完之前一直未进入阻塞态的话,此后便继续进入就绪态。
页面置换算法中,会产生Belady异常现象的是
所谓Belady现象是指:采用FIFO算法时,如果对—个进程未分配它所要求的全部页面,有时就会出现分配的页面数增多但缺页率反而提高的异常现象。
FIFO的性能较差,因为较早调入的页往往是经常被访问的页,这些页在FIFO算法下会被反复调入和调出。
belady现象的原因是FIFO算法的置换特征与进程访问内存的动态特征是矛盾的,即被置换的页面并不是进程不会访问的。(局部性原理)
TCP的三次握手
第一次握手序列号是x;
第二次握手序列号y,确认号x+1;
第三次握手序列号x+1,确认号y+1
数据库语句
I/O系统硬件结构分为四级:1。设备控制器,2。I/O设备,3。处理机,4。I/O通道,按级别由高到低的顺序是?
处理机(cpu)等级显然是最高的,通道是一个独立于 CPU的专管输入/输出控制的处理机,它控制设备与内存直接进行数据交换。所以通道是第二,通道控制设备控制器,设备控制器控制设备。
网络划分与子网的计算
白盒测试又称结构测试、透明盒测试、逻辑驱动测试或基于代码的测试。属于白盒测试方法的有哪些?
随机存储设备(RAM)属于内存,硬板、U盘属于外部存储设备。
考察测试用例设计思路,从功能、性能、安全等多方面思考;结合测试用例设计方法回答。
答案要点: 功能测试 1. 正向功能; 2. 参数为空; 3. dealid不存在; 4. dealid为非数字的值; 5. quantity为0或负值; 6. quantity大于库存量; 7. token无效 8. 入参不是JSON 性能测试 1. 压力测试,考察系统在极限压力下的处理能力 2. 狭义性能测试,验证系统能够达到一定的处理能力 3. 并发测试,测试数据库和应用服务器对并发请求的处理 安全性测试 1. 伪造token攻击 2. 订单潮水攻击 3. deal遍历攻击 4. SQL注入攻击 加分项 订单复用:当同一个用户提交的dealid、quantity相同时,返回的orderID总是一样(没有重复创建订单)
已知一个IP地址为10.5.136.5, 子网掩码为255.255.64.0, 他的网络号和主机号分别是?
c语言程序题
1 |
|
哪种协议在数据链路层
ARP:链路层
ICMP:网路层
FTP:应用层
UDP:运输层
删除表A全部数据的方法,一般情况下执行速度最快的是
drop table A 是删除整个表,题目的潜在意思是删除表中的数据而并非删除整个表。
truncate table A是删除表中的数据,删除速度比delete更 快,无法撤回(回退)。
delete from A 删除数据表中的数据,可以回退,可添加where 子句。
速度,一般来说:drop> truncate > delete .
但drop是删除整个表了。
数据库完整性:
实体完整性和参照完整性适用于任何关系型数据库系统,它主要是针对关系的主关键字和外部关键字取值必须有效而做出的约束。
Http状态码,
以下http返回报头有哪几行有错误?
①HTTP/1.1 302 Moved Permanently
Cache-Control: private, no-store, no-cache, must-revalidate
②Expires: Sat, 01 Jan 2000 00:00:00 GMT
Pragma: no-cache
③Content-Type: text/html; charset=utf-8
④Connection: maintain
美团有一个API用于创建团购订单,地址如下
https://open.meituan.com/order/createorder?token=1234567890abcdefghijklmnopqrstuvwxyz
其中,token用于验证用户身份
请求方法:POST
参数类型:application/json
参数列表
1
2
3
4 {
"dealid": 90,
"quantity": 5
}传入deal ID(要购买的团购券的ID)和数量后,返回新生成的订单ID(隐去无关参数)。例如:
1
2
3
4
5 {
"success": 0, // 正常情况为0
"msg": "", // 正常情况为空
"orderid": 2910100100, // 订单id
}
功能测试
性能测试
兼容性测试:
安全性测试:
其他
每年的5月17日,点评都会在全国各大城市举办517吃货节优惠活动,如果你来负责手机端517某一个活动的测试任务,你会想到从哪些方面测试,来保证517活动的质量?
此次活动投放首页上”全城好券”活动中的每日优惠页面
- 用户领取条件:每个商户的券每个用户只能领取一次。
- 券数目限制:每个商户的每天的券有数目限制。
- 领券时间限制:只有上午10点开始可以才可以领券。
功能性测试
兼容性测试
性能相关:
前端性能:CPU,内存占用,低配置Android机体验效果
后端性能:压测对应的后端接口QPS,预测峰值及所对应集群的QPS。
每秒查询率QPS是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准
用来衡量服务器的机器性能。
网络环境模拟测试:wifi测试、3g/4g/5g,弱网络情况
其他:
## 参考教程
mysql表user已有索引:idx_name_age
(name
,age
)。查询语句select * from user where name='jack' or age = 18
是否经过此索引
private static volatile Long num; 变量num在内存中是否线程安全
jdbc statement
有关java object默认的基本方法
关键字序列为堆的是
1 100,60,70,50,32,65堆有最大堆和最小堆 把序列化为二叉树 判断根结点和左右子树的大小即可
二分查找树的时间复杂度
Java引用数据类型
Java中哪些集合是Collection派生出来的
下列代码输出结果为1的是
1 | int cestcCount=0; |
1 | 1. 排序算法的时间复杂度 |
1
2
3
4
5
6
7 给定英文句子S和字符串x,判断x是否为S中某些单词的前缀,若匹配到则输出第1个匹配单词的位置,否则输出-1。
例如:输入"this is an easy problem."和"eas",输出4
例如:输入"In love folly is always sweet"和"like",输出-1
例如:输入"Whatever is worth doing is worth doing well."和"wor",输出3
Linux下,下列哪些途径不会让程序由用户态切换到内核态
用户态到内核态的三种方式:
- 异常:如果当前进程运行在用户态,如果这个时候发生了异常事件,就会触发切换。例如:缺页异常。
- 系统调用:Linux内核中设置了一组用于实现各种系统功能的子程序,称为系统调用。用户可以通过系统调用命令在自己的应用程序中调用它们。
- 外部访问中断:当外设完成用户的请求时,会向CPU发送中断信号。
n个数值选出最大m个数(3<m<n)的最小算法复杂度是$O(N)$
部分快排 时间复杂度 O(N) 存储复杂度 O(N)
用某种排序方法对关键字序列{135,184,121,147,115,127,168,125,120}进行排序时,序列的变化情况如下:
120,115,121,125,147,127,168,135,184
115,120,121,125,135,127,147,168,184
115,120,121,125,127,135,147,168,184
使用的方法是?
完全二叉树与满二叉树
完全二叉树:
叶节点只能出现在最下层和次下层,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树
满二叉树:
1、一个层数为k 的满二叉树总结点数为:(2^k)-1。因此二叉树的结点树一定是奇数个。
2、第i层上的结点数为:2^(i-1)
3、一个层数为k的满二叉树的叶子结点个数(也就是最后一层):2^(k-1)
16个相同的糖果,分给三个人,每个人至少要得一个。有多少种不同分法?
插空法:16个糖果依次排开,中间有15个空挡 ,依次编号为空挡1-15,从这9个空挡中任意取出2 个作为分割点 ,正好能把糖果分为3份,并且保证每一份中至少有一个糖果。因为分割点并没有顺序,所以可以使用组合公式C(15,2)计算。
现有某图书管理系统,管理员可对所有权限的馆藏图书进行查询,可以根据出版社(电子工业、清华大学)、发行日期(2000-2010,2010-2020)、作者性别(男、女)进行查询,试对该查询功能设计测试用例。(本题中无需考虑无权限的情况)
按照传统设计,设计全部测试用例。(3分)
所在列 | 1 | 2 | 3 |
---|---|---|---|
因素 | 出版社 | 发行日期 | 作者性别 |
实验1 | 电子工业 | 2000-2010 | 男 |
实验2 | 电子工业 | 2000-2010 | 女 |
实验3 | 电子工业 | 2010-2020 | 男 |
实验4 | 电子工业 | 2010-2020 | 女 |
实验5 | 清华大学 | 2000-2010 | 男 |
实验6 | 清华大学 | 2000-2010 | 女 |
实验7 | 清华大学 | 2010-2020 | 男 |
实验8 | 清华大学 | 2010-2020 | 女 |
使用正交试验法设计测试用例(5分)
所在列 | 1 | 2 | 3 |
---|---|---|---|
因素 | 出版社 | 发行日期 | 作者性别 |
实验1 | 电子工业 | 2000-2010 | 男 |
实验2 | 电子工业 | 2010-2020 | 女 |
实验3 | 清华大学 | 2000-2010 | 女 |
实验4 | 清华大学 | 2010-2020 | 男 |
正交实验相当于在别的维度上缩减了实验次数
说明使用正交试验法设计测试用例的好处。
根据正交性从全面试验中挑选出部分有代表性的点进行试验,这些有代表性的特点具备了“均匀分散,整齐可比”的特点。
通过使用正交试验法减少了测试用例,合理地减少测试的工时与费用,提高测试用例的有效性。是一种高效率、快速、经济
的实验设计方法。
某在线支付平台余额提现到银行卡规则:每日累计提现金额不超1万元为快速(2小时)到账; 超过1万元为普通到账,普通到账没有额度上限限制。
要求:
1、假设账户中有5万余额,给出覆盖无效等价类的测试用例。
2、假设账户中有5万余额,给出覆盖有效等价类的测试用例。
3、使用黑盒测试的等价类划分法给出有效等价类和无效等价类。
评分标准: 快速到账和普通到账,以及一天内多次提取是主要答题点,其余根据回答情况酌情给分,总分10分。
1、假设账户中有5万余额,给出覆盖无效等价类的测试用例。
2、假设账户中有5万余额,给出覆盖有效等价类的测试用例。
使用黑盒测试的等价类划分法给出有效等价类和无效等价类。
提现功能分为快速到账和普通到账两个功能:
第一种情况:不考虑一天内多次提取,设计用例如下
第二种情况:考虑一天内多次提取,设计用例如下(6分)
软件系统几乎都是用事件触发来控制流程的,事件触发时的情景便形成了场景,而同一事件不同的触发顺序和处理结果就形成事件流。
场景法就是通过用例场景描述业务操作流程,从用例开始到结束遍历应用流程上所有基本流(基本事件)和备选流(分支事件)。
下面是对某城市“好莱坞”影院APP购票系统中会员卡使用的基本流和备选流的描述。
会员卡分为储值型会员卡和现金型会员卡两种,会员必须持本卡在本影城内进行刷卡消费,才能享受影城提供的会员购票折扣、积分优惠、积分兑奖、会员专享、会员升级等一系列的会员优惠和服务。
会员种类:
1、现金消费会员卡:6个月内累计观影6次或购影票消费达到200元者,可凭票带有效证件免费100元现金消费会员卡。
2、储值会员卡:分为200元、300元、600元、1000元四种卡。其中:200元为会员卡、300元为银卡会员、600元为金卡会员、1000元为VIP尊贵会员。
问题1:使用场景法设计测试用例,指出场景涉及到的基本流和备选流,基本流用字母A表示,备选流用题干中描述的相应字母表示。
问题2:场景中的每一个场景都需要确定测试用例,一般采用矩阵来确定和管理测试用例。
如下表所示是一种通用格式,其中行代表各个测试用例,列代表测试用例的信息。本例中的测试用例包含测试用例、ID、场景条件、测试用例中涉及的所有数据元素和预期结果等项目。
首先确定执行用例场景所需的数据元素(本例中包括账号、是否黑名单卡、输入购票数量、账面金额、余票量),然后构建矩阵,最后要确定包含执行场景所需的适当条件的测试用例。
在下面的矩阵中,是表示有效数据元素,否表示无效数据元素,n/a表示不适用。例如C01表示“成功购票”基本流。请按上述规定为其它应用场景设计用例矩阵。
问题3:假如每张票20元人民币,用户的账户金额为600元,余票量充足,那么在A4输入购票数量的过程中,
请运用边界值分析方法为A4选取合适的输入数据(即电影票数量,单位:张)。
1、使用场景法设计测试用例
共有5个场景:
场景1:A;场景2:A和B;场景3:A和C,场景4:A和D;场景5:A和E
2、设计用例矩阵
3、用边界值分析方法为A4选取合适的输入数据
1、0张;2、30张;3、31张
先取一个无效输入,再取一个边界值,然后再突破边界值
满减策略是外卖平台推出的一种为了让商家与顾客实惠,平台给予商家补贴,通过这样的营销活动来实现用户高速增长的一种模式。
以某城市外卖平台设计的麻辣香锅或麻辣烫的满减策略为例子,蔬菜成本0.5元,肉类0.8元,在设计满减的时候,可以5元一个档,例:25-13,30-15,35-17……,蔬菜定价3元,荤菜定价5元,这样,每5元一个满减档,用户就会拉高自己的客单价。报价规则如下表所示。
顾客如点的香锅合计32元,实际支付32-15=17元。
现在该商家开发一个软件,输入为实际价格P(1<P<100),输出为满减后价格D。
问题1:请采用等价类划分法为该软件设计测试用例(不考虑P为非整数的情况)
问题2:请采用边界值分析法为该软件设计测试用例(不考虑健壮性测试,既不考虑P不在1到100之间或者是非整数的情况)
问题3:列举除了等价类划分法和边界值分析法以外的三种常见的黑盒测试用例设计方法。
问题1:
设计用例时从这6个等价类中任选一个代表数据即可。
问题2
问题3:
错误推测法,因果图法,判定表驱动法,正交试验法,功能图法等。
HTTP状态码:
301状态码:被请求的资源已永久移动到新位置
401:请求要求身份验证
403:服务器已经理解请求,但拒绝他
404、请求失败,请求所希望得到的资源未被在服务器上发现
503:由于临时的服务器维护或者过载,服务器无法处理请求。
Linux文件权限:
权限项 读 写 执行 读 写 执行 读 写 执行
字符表示 r w x r w x r w x
数字表示 4 2 1 4 2 1 4 2 1
权限分配 owner group other
SQL模型查询使用Like,如要查询表user中name字段中,第2个字母为A的所有数据,sql语句为:
1 | select * from user where name like ’_A%’; |
_
代表占位符,%
代表未知字符
数据结构,强连通图
强连通图:在G中,如果对于每一对vi、vj(vi≠vj),从vi到vj和从vj到vi都存在路径。
n个顶点的有向强连通图:至少n条边(形成一个环);至多n(n-1)条边
n个顶点的无向强连通图:至少n-1条边(形成一条直线);至多n(n-1)/2条边
将50个红球和50个白球放到两个盒子中,从中抽出一个球,那么抽到的是红球的最大概率是:
一个红球放在一个箱子里,其余求全部放到另一个箱子。
这样放的概率为:0.5+0.5*(49/99) 约等于0.75(74/99)。
此时取到红球的概率最大。
测试人员要坚持原则,缺陷未修复完坚决不能上线。
如果是影响严重的缺陷,测试人员需要坚持原则(否组上线后可能引发现网事故或客户投诉);如果是小缺陷或经过专家组评估对现网无影响或风险可控,又基于版本发布的压力(外部压力如客户侧压力等),可适当灵活处理。
自动化测试能比手工测试发现更多的缺陷。
自动化测试只是提高了测试的效率,并不会因为用了自动化就会发现更多的bug。
请尽量多的列举有哪些可能的原因,会导致一个应用的用户帐号无法登录。
请设计稳定且低成本的全自动化方案,获得一台手机的启动时长。
小选线下店最近准备新上架一批长度不等的商品, 用一个数组表示商品的长度,已知货架每一层的长度固定为X。
小选线下店是一个追求生活美学的店铺,为了摆放美观,每一层至多摆放两个商品,而且商品的总长度不能比货架长度长(已知单个商品的长度都不会比货架长)
请问至少需要多少层的货架,才能漂亮的摆放这些商品呢?
分析
先对其进行排序,先考虑一层获取放两个商品的情况,
要想尽可能少用货架,就有一大搭一小,一个从前向后,一个从后向前
如果正好可以放下两个商品,则货架层数加一。然后将这两个货物取消掉。
最后处理单个的情况。
1 | def test3_2(): |
代码:输入一串字符串,返回出现次数大于3的字符
其他代码题:
- [青蛙跳台阶](70. 爬楼梯 - 力扣(LeetCode) (leetcode-cn.com))
- [从乱序序列中找到前K个最大数](347. 前 K 个高频元素 - 力扣(LeetCode) (leetcode-cn.com))
- [输入一个字符串数组,将出现次数大于5的字符串输出](692. 前K个高频单词 - 力扣(LeetCode) (leetcode-cn.com))
- [字符串找出出现次数等于3的字符并拼接为子字符串](692. 前K个高频单词 - 力扣(LeetCode) (leetcode-cn.com))
http,Https的区别
http每次请求都会断开连接吗
在http1.0 中,一个服务器在发送完一个HTTP响应后,会断开TCP连接。但是这样每次请求都会重新建立和断开Tcp连接,代价过大。于是HTTP1.1在Connection: keep-alive 的 Header 进行了持久连接的支持。
怎么设置http请求每次断开
Connection: keep-alive , 开启
Connection: close ,关闭
浏览器可向一个服务端发起多少次http请求,是否有限制
HTTP/1.1
中,单个TCP连接,在同一时间只能处理一个http请求,虽然存在Pipelining技术支持多个请求同时发送,但由于实践中存在很多问题无法解决,所以浏览器默认是关闭,所以可以认为是不支持同时多个请求。
HTTP2
提供了多路传输功能,多个http请求,可以同时在同一个TCP连接中进行传输。
页面资源请求时,浏览器会同时和服务器建立多个TCP连接,在同一个TCP连接上顺序处理多个HTTP请求。所以浏览器的并发性就体现在可以建立多个TCP连接,来支持多个http同时请求。
Chrome浏览器最多允许对同一个域名Host建立6个TCP连接,不同的浏览器有所区别。
为什么有的时候刷新页面不需要重新建立 SSL 连接?
TCP 连接有的时候会被浏览器和服务端维持一段时间。TCP 不需要重新建立,SSL 自然也会用之前的。
浏览器对同一 Host 建立 TCP 连接到数量有没有限制?
有。Chrome 最多允许对同一个 Host 建立六个 TCP 连接,不同的浏览器有一些区别。
若收到的 HTML 如果包含几十个图片标签,这些图片是以什么方式、什么顺序、建立了多少连接、使用什么协议被下载下来的呢?
- 如果图片都是 HTTPS 连接并且在同一个域名下,那么浏览器在 SSL 握手之后会和服务器商量能不能用 HTTP2,如果能的话就使用 Multiplexing 功能在这个连接上进行多路传输。不过也未必会所有挂在这个域名的资源都会使用一个 TCP 连接去获取,但是可以确定的是 Multiplexing 很可能会被用到。
- 如果发现用不了 HTTP2 呢?或者用不了 HTTPS(现实中的 HTTP2 都是在 HTTPS 上实现的,所以也就是只能使用 HTTP/1.1)。那浏览器就会在一个 HOST 上建立多个 TCP 连接,连接数量的最大限制取决于浏览器设置,这些连接会在空闲的时候被浏览器用来发送新的请求,若所有的连接都正在发送请求,那么其他的请求就只能等待。
ssl层公钥、私钥谁拿
- Https是如何加密的
- SSL层如何实现的加密
- 对称加密是有几个随机字符串拼接
- TCP UDP HTTP属于哪一层
接口调不通一直在转圈怎么测试
接口无响应:
接口有响应:但是返回了错误的HTTP状态码,需要根据不同的状态码确定具体原因
json
接口,需要添加一个信息头Content-type:application/json
一条SQL语句:一个表,含车主名和车牌号,输出拥有超过3辆车的车主名
一条SQL语句是怎么执行的
其实我们的 sql 可以分为两种,一种是查询,一种是更新(增加,更新,删除)。
查询语句:我们先分析下查询语句
1 select * from tb_student A where A.age='18' and A.name=' 张三 ';
先检查该语句是否有权限,如果没有权限,直接返回错误信息,如果有权限,在 MySQL8.0 版本以前,会先查询缓存,以这条 sql 语句为 key 在内存中查询是否有结果,如果有直接缓存,如果没有,执行下一步。
通过**分析器进行词法分析,提取 sql 语句的关键元素,比如提取上面这个语句是查询 select,提取需要查询的表名为 tb_student,需要查询所有的列,查询条件是这个表的 id=’1’**。然后判断这个 sql 语句是否有语法错误,比如关键词是否正确等等,如果检查没问题就执行下一步。
接下来就是优化器进行确定执行方案,上面的 sql 语句,可以有两种执行方案:
a. 先查询学生表中姓名为“张三”的学生,然后判断是否年龄是 18。
b. 先找出学生中年龄 18 岁的学生,然后再查询姓名为“张三”的学生。
那么优化器根据自己的优化算法进行选择执行效率最好的一个方案(优化器认为,有时候不一定最好)。那么确认了执行计划后就准备开始执行了。
进行权限校验,如果没有权限就会返回错误信息,如果有权限就会调用数据库引擎接口,返回引擎的执行结果。
以上就是一条查询 sql 的执行流程,那么接下来我们看看一条更新语句如何执行的呢?sql 语句如下:
1 update tb_student A set A.age='19' where A.name=' 张三 ';我们来给张三修改下年龄,在实际数据库肯定不会设置年龄这个字段的,不然要被技术负责人打的。其实这条语句也基本上会沿着上一个查询的流程走,只不过执行更新的时候肯定要记录日志啦,这就会引入日志模块了,MySQL 自带的日志模块是 binlog(归档日志) ,所有的存储引擎都可以使用,我们常用的 InnoDB 引擎还自带了一个日志模块 redo log(重做日志),我们就以 InnoDB 模式下来探讨这个语句的执行流程。流程如下:
- 先查询到张三这一条数据,如果有缓存,也是会用到缓存。
- 然后拿到查询的语句,把 age 改为 19,然后调用引擎 API 接口,写入这一行数据,InnoDB 引擎把数据保存在内存中,同时记录 redo log,此时 redo log 进入 prepare 状态,然后告诉执行器,执行完成了,随时可以提交。
- 执行器收到通知后记录 binlog,然后调用引擎接口,提交 redo log 为提交状态。
- 更新完成。
这里肯定有同学会问,为什么要用两个日志模块,用一个日志模块不行吗?
这是因为最开始 MySQL 并没有 InnoDB 引擎(InnoDB 引擎是其他公司以插件形式插入 MySQL 的),MySQL 自带的引擎是 MyISAM,但是我们知道 redo log 是 InnoDB 引擎特有的,其他存储引擎都没有,这就导致会没有 crash-safe 的能力(crash-safe 的能力即使数据库发生异常重启,之前提交的记录都不会丢失),binlog 日志只能用来归档。
并不是说只用一个日志模块不可以,只是 InnoDB 引擎就是通过 redo log 来支持事务的。那么,又会有同学问,我用两个日志模块,但是不要这么复杂行不行,为什么 redo log 要引入 prepare 预提交状态?这里我们用反证法来说明下为什么要这么做?
- 先写 redo log 直接提交,然后写 binlog,假设写完 redo log 后,机器挂了,binlog 日志没有被写入,那么机器重启后,这台机器会通过 redo log 恢复数据,但是这个时候 bingog 并没有记录该数据,后续进行机器备份的时候,就会丢失这一条数据,同时主从同步也会丢失这一条数据。
- 先写 binlog,然后写 redo log,假设写完了 binlog,机器异常重启了,由于没有 redo log,本机是无法恢复这一条记录的,但是 binlog 又有记录,那么和上面同样的道理,就会产生数据不一致的情况。
如果采用 redo log 两阶段提交的方式就不一样了,写完 binglog 后,然后再提交 redo log 就会防止出现上述的问题,从而保证了数据的一致性。那么问题来了,有没有一个极端的情况呢?
假设 redo log 处于预提交状态,binglog 也已经写完了,这个时候发生了异常重启会怎么样呢? 这个就要依赖于 MySQL 的处理机制了,MySQL 的处理过程如下:
- 判断 redo log 是否完整,如果判断是完整的,就立即提交。
- 如果 redo log 只是预提交但不是 commit 状态,这个时候就会去判断 binlog 是否完整,如果完整就提交 redo log, 不完整就回滚事务。
总结
- 查询语句的执行流程如下:权限校验(如果命中缓存)—>查询缓存—>分析器—>优化器—>权限校验—>执行器—>引擎
- 更新语句执行流程如下:分析器—->权限校验—->执行器—>引擎—redo log(prepare 状态)—>binlog—>redo log(commit状态)
数据库,查询前10行数据:使用limit关键字
索引有哪些
- 主键索引:数据列不允许重复,不能为NULL,一个表只能有一个主键索引
- 组合索引:有多个列值组成的索引
- 唯一索引:数据列不允许重复,可以为NULL,索引列的值必须唯一,如果是组合索引,则列值的组合必须唯一
- 全文索引:对文本的内容进行搜索
- 普通索引:基本的索引类型,可以为NULL
索引的结构
索引的数据结构主要有B+数和哈希表,对应的索引分别为B+树索引和哈希索引。InnoDB引擎的索引类型有B+树索引和哈希索引,默认的索引类型为B+树索引。
在B+树中,所有的记录节点都是按照键值大小的顺序放在叶子节点上,因为B+树具有有序性,并且所有的数据都存放在叶子节点,所以查找的效率非常高,并且支持排序和范围查找。
B+树的索引又可以分为主索引和辅助索引。其中主索引为聚簇索引,辅助索引为非聚簇索引。
聚簇索引是以主键作为B+ 树索引的键值所构成的B+树索引,聚簇索引的叶子节点存储着完整的数据记录;非聚簇索引是以非主键的列作为B+树索引的键值所构成的B+树索引,非聚簇索引的叶子节点存储着主键值。
所以使用非聚簇索引进行查询时,会先找到主键值,然后到根据聚簇索引找到主键对应的数据域。
哈希索引是基于哈希表实现的,对于每一行数据,存储引擎会对索引列通过哈希算法进行哈希计算得到哈希码,并且哈希算法要尽量保证不同的列值计算出的哈希码值是不同的,将哈希码的值作为哈希表的key值,将指向数据行的指针作为哈希表的value值。这样查找一个数据的时间复杂度就是o(1),一般多用于精确查找。
为什么不用B树
B树与B+树的区别:
- B树中的内部节点和叶子节点存放键和值,而B+树的内部节点只有键没有值,叶子节点存放所有的键和值
- B+树的叶子节点通过链表连接在一起,方便顺序检索。
不用B树的原因如下:
- B树适用于随机检索,而B+树适用于随机检索和顺序检索
- B+树的空间利用率更高,因为B树每个节点要存储键和值,而B+树的内部节点只存储键,这样B+树的一个节点就可以存储更多的索引,从而使树的高度变低,减少了I/O次数,使得数据检索速度更快。
- B+树的叶子节点都是连接在一起的,所以范围查找,顺序查找更加方便
- B+树的性能更加稳定,因为在B+树中,每次查询都是从根节点到叶子节点,而在B树中,要查询的值可能不在叶子节点,在内部节点就已经找到。
如何分析一条SQL语句执行的性能
使用[Explain](Mysql调优 - 资本可不会睡觉,同志请抓紧时间! (li-rr.github.io))关键字
什么情况下索引会失效
- 条件中有
or
,例如select * from table_name where a = 1 or b = 3
- 在索引上进行计算会导致索引失效,例如
select * from table_name where a + 1 = 2
- 索引字段上使用 is null/is not null判断时会导致索引失效,例如
select * from table_name where a is null
- 索引上使用!、=、<>进行判断时会导致索引失效,例如
select * from table_name where a != 1
- 在索引中使用函数会导致索引失效,例如
select * from table_name where abs(a) = 1
索引的最左匹配原则:
最左匹配原则:从最左边为起点开始连续匹配,遇到范围查询(<、>、between、like)会停止匹配。
例如建立索引(a,b,c),大家可以猜测以下几种情况是否用到了索引。
第一种
1
2 select * from table_name where a = 1 and b = 2 and c = 3
select * from table_name where b = 2 and a = 1 and c = 3上面两次查询过程中所有值都用到了索引,where后面字段调换不会影响查询结果,因为MySQL中的优化器会自动优化查询顺序。
第二种
1
2
3 select * from table_name where a = 1
select * from table_name where a = 1 and b = 2
select * from table_name where a = 1 and b = 2 and c = 3答案是三个查询语句都用到了索引,因为三个语句都是从最左开始匹配的。
第三种
1
2 select * from table_name where b = 1
select * from table_name where b = 1 and c = 2答案是这两个查询语句都没有用到索引,因为不是从最左边开始匹配的
第四种
1 select * from table_name where a = 1 and c = 2这个查询语句只有a列用到了索引,c列没有用到索引,因为中间跳过了b列,不是从最左开始连续匹配的。
第五种
1 select * from table_name where a = 1 and b < 3 and c < 1这个查询中只有a列和b列使用到了索引,而c列没有使用索引,因为根据最左匹配查询原则,遇到范围查询会停止。
第六种
1
2
3 select * from table_name where a like 'ab%';
select * from table_name where a like '%ab'
select * from table_name where a like '%ab%'sql题主要考察两表连接和group by
linux
查找一个文件里所有的”error”
grep -e “error” test.txt
linux
查找当下这个目录里所有文件的Error:grep -e "error" text.txt
查看服务器端口
sudo netstat -apn | grep "80"
在一个文件中查找某个字符在哪一行
grep -n "fuck" test.txt
服务器能有多少个端口
nmap ip
可以探测服务器开放了多少个端口如何查看本地到服务器间通不通
- ping ip ——-测试看本机 和 对应的ip的机器是否是通,有返回的字节数可以证明ip是通的
- telnet ip port —- 可以测试查看端口是否开启
linux查看日志
linux查看文件数量
统计当前目录下文件的个数(不包括子目录)
1 ls -l | grep "^-" | wc -l统计当前目录下文件的个数(包括子目录)
1 ls -lR | grep "^-" | wc -l查看某目录下文件夹(目录)的个数(包括子目录)
1 ls -lR | grep "^d" | wc -l
并发,多线程,多进程的区别
验证码怎么测试
为什么找测开
你做测开的优缺点
自我介绍
项目介绍,难点,怎么解决的
python异常了解吗
try except
python打开文件方法
open, with open as f:
python多线程,以及实现过程
使用threading模块
tcp三次握手、四次挥手
http请求方法,post、get区别(好像也记混了,脑子当时不知道在干啥)
在请求的url中携带数据;在请求体中携带数据
404状态码
资源没有找到,请求错误
selenium元素定位方位,xpath优缺点
selenium在使用元素定位方法时遇到错误,怎么解决(回答的是没有解决🤣)
linux查看内存、cpu命令
二面
自我介绍
实习内容
怎么写测试点测试用例
我们写用例的时候一般是先写测试点,然后再写测试用例,也可以这么理解,测试点就是精简版的测试用例。
编写用例四个基本方法:等价类、边界值、正交法、场景法。
编写测试用例的策略:先点后面,先局部再整体,最忌讳的是点和面混在一起,局部和整体不明。
一个任务做测试的时间是多久
如何提升测试速度
多线程
反问
初试
数据库:
终试
对测试行业的了解?
做测试应该要有一定的协调能力,因为测试人员经常要与开发接触处理一些问题,如果处理不好的话会引起一些冲突,这样的话工作上就会不好做。还有测试人员要有一定的耐心,有的时候做测试很枯燥乏味。除了耐心,测试人员不能放过每一个可能的错误。
以前实习的测试流程?
测试需要哪些技能?怎么去学习这些技能
比起其他人你的优势在哪?
初试
数据库ACID是什么,举例
Atom,原子性:直白点说就是一个事务中的所有操作(CRUD)就像是一个原子操作一样不可分割开来,要么全部成功,要么全部失败,不允许部分成功部分失败。
例,
这两个动作要么都成功,要么都失败,不存在只往篮子里放苹果而没拿梨,也不存在只从篮子里拿梨而没有放苹果。
原子性的侧重点在于多个动作必须同时成功或者同时失败。
Consistency,一致性:一致性和原子性的区别在于两者的侧重点不同,原子性关注的是状态,要么全部成功,要么全部失败,不存在部分成功的状态。而一致性关注的是数据的可见性,一个事务的中间状态的数据对外部不可见,只有最初状态和最终状态的数据对外可见。
事务的隔离级别就是在事务的四要素和性能上面做平衡,有时候为了提高性能,会适度的破坏一致性原则。
说回到主题一致性的理解上,我对一致性的理解是这样的,一致性关注的点是数据的操作结果是否与用户业务预期一致,这里有两点需要注意。
Isolation,隔离性:并发事务之间不会互相影响,就像串行执行一样,也就是说并发事务之间都是互相隔离的,你不影响我,我也不影响你。
隔离性侧重点是并发事务之间的影响,说到并发事务就要提到数据库的隔离级别,有的时候会通过调整数据库的隔离级别来适度的破坏一致性和隔离性,从而提高数据库处理性能。
ps. 画外音,隔离性是我们需要重点关注的,因为不同的隔离级别,可能对应的加锁过程不一样,而正是因为引入了各种各样的隔离级别,才让锁问题变得格外复杂。解决和分析死锁问题,重点就是要搞清楚数据库的隔离级别。那么隔离级别是个什么东西呢?我们会在后面出单独的文章来重点说明。
Durability,持久性:持久性就非常好理解了,事务提交后即持久化到磁盘不会丢失。
持久性侧重的是数据不丢失,这个跟网上讨论最多的 (“丢失更新”、“提交覆盖”、“Read-Modify-Write问题”)很容易混淆,看起来效果都是没有存入正确的数据,看起来好像数据丢失了一样。
实际上两者区别很大的,前者是说数据存到物理磁盘不会丢失,而后者则说的是并发事务中的相互影响导致最终的数据结果不同。
参考链接:一分钟弄清楚事务四要素:ACID | 凝雨 - Yun | 快乐编程每一天 - Happy Coding Every Day (ningyu1.github.io)
算法题求1-100内的素数
进程通信方式(4种)
测试的方法,框架,工具了解哪些
复试
项目介绍,细节要搞清楚
手撕
扫码支付设计测试用例
测试用例:
用户角度:
功能性测试:用户能否成功生成用于支付的二维码或二维码,二维码出现后屏幕能否变成增亮的模式,用户能否成功选取不同的付款方式,比如“花呗”、“账户余额”、“余额宝”、“银行账户”等。
扫码完成后,用户能否收到支付成功的界面,并且界面能正确显示用户支付的金额,包括付款信息、是否使用优惠、折扣等。
界面测试:打开支付宝后,能否正确显示界面,二维码的界面是否正确,支付的每个步骤界面是否正确。不会出现前端界面错误,或者打开不了界面。
易用性测试:在整个用户支付的过程中,操作步骤是否简易方便。
兼容性:测试扫码支付功能,在不同手机品牌,不同操作系统下是否兼容。
安全测试:二维码如果超过安全时间后能否自动更新为新的二维码。测试整个支付流程的安全机制能否成功实现。
压力测试:持续的扫码,测试扫码支付功能在强压的状态下,工作状态如何。
网络测试:测试在不同网络环境下,不同网络信号强度的情况下,整个支付流程是否出现卡顿,卡顿的点容易出现在哪里。
商家角度:
功能性测试:扫码枪能否成功扫到用户手机中的二维码,扫码成功后能否收到钱,并且成功生成收款的界面。支付宝后台、商家后台、用户手机能否成功传输支付结果信息。
易用性测试:在不同光线,屏幕不同亮度的情况下,能否成功完成扫码收款的功能。
hr面
一面
二面
介绍简历中的实习经历,你有什么收获
你为什么想要从事测试开发工程师
从技术角度来说,你觉得测试开发工程师需要掌握哪些技能?在这些技能中,你觉得你的掌握程度怎么样
你对自己的测试开发的职业规划是什么样的
首先快速熟悉业务,熟悉环境,了解自动化技术在部门业务的应用,然后主动研究,往技术上面考虑
是否了解自动化测试
对于一名测试工程师而言,连续的开发周期需要重复执行相同的测试用例组成的测试套件。如果每一次都手动执行此过程,可能会非常重复且耗时,很容易让人产生疲倦感。但是通过利用测试自动化工具,可以更轻松地编写测试套件,按需重手动执行,减轻人为干预并提高测试。
DDL和DML的区别是什么
如何测试一个台灯
如何测试一个柜子
(52条消息) 排序算法时间复杂度、空间复杂度、稳定性比较_潘建南的博客-CSDN博客_排序算法的时间复杂度
- 时间复杂度记忆-
- 冒泡、选择、直接 排序需要两个for循环,每次只关注一个元素,平均时间复杂度为O(n²))(一遍找元素O(n),一遍找位置O(n))
- 快速、归并、希尔、堆基于二分思想,log以2为底,平均时间复杂度为O(nlogn)(一遍找元素O(n),一遍找位置O(logn))
- 稳定性记忆-“快希选堆”(快牺牲稳定性)
- 排序算法的稳定性:排序前后相同元素的相对位置不变,则称排序算法是稳定的;否则排序算法是不稳定的。
解决一个回溯问题,实际上就是一个决策树的遍历过程。需要考虑三个问题
1、路径:就是已经做出的选择
2、选择列表:就是当前可以做出的选择
3、结束的条件:就是到达决策树底层,无法在做选择的条件。
算法框架:
1
2
3
4
5
6
7
8
9 result = []
def backtrack(路径, 选择列表):
if 满足结束条件:
result.add(路径)
return
for 选择 in 选择列表:
做选择
backtrack(路径, 选择列表)
撤销选择/回溯
预先训练的上下文语言模型(PrLMs)在下游自然语言理解任务中取得了强大的性能提高。然而,PrLMs仍然很容易被对抗性的替换词所愚弄,这是最具挑战性的文本对抗性攻击方法之一。本文提出了一个可以保护性能的框架,具有频率感知随机化的异常检测(ADFAR)。详细地,我们设计了一个辅助的异常检测分类器AD,并采用了一个多任务的学习程序,通过它,PrLMs能够识别对抗性的输入样本。然后,为了防御对抗性的替换词,对那些已识别的对抗性的输入样本应用了一个具有频率识别能力的随机化过程。实验结果表明,ADFAR在各种推理任务中的性能明显优于那些新提出的防御方法。值得注意的是,ADFAR并不会影响PrLMs的整体性能。
预先训练好的语言模型(PrLMs)被广泛采用为各种NLP系统的重要组成部分。然而,作为基于DNN的模型,PrLMs仍然很容易被文本对抗性样本所愚弄。PrLMs的这种脆弱性不断引起潜在的安全问题,因此研究防御技术来帮助PrLMs对抗文本对抗性样本是迫切必要的。
文本对抗性样本:词被替换为其他词,类似sql替换命令?
前人提出了不同类型的文本攻击方法,从字符级单词拼写错,单词级替代,短语级插入和删除,到句子级意译。
由于自然语言的离散性,通过拼写更正和语法纠错,可以很容易地发现和恢复的攻击方法。然而,基于对抗性替换词的攻击方法可以产生高质量和有效的对抗性样本,这仍然很难被现有的方法检测到。
因此,对抗性词替代对预训练语言模型的鲁棒性提出了更大、更深刻的挑战。因此,本文致力于克服对抗性的词替换所带来的挑战。
为此,作者提出了一个保护性能的框架,具有频率感知随机化的异常检测(ADFAR),以帮助预训练语言模型在不牺牲性能的情况下防御对抗性单词替换。
在推理中引入随机化可以有效地防御对抗性攻击。此外(Mozes等人,2020)表明,通常的对抗样本是用较少出现的同义词代替单词,而预训练语言模型对频繁出现的词更健壮。因此,我们提出了一个具有频率感知能力的随机化过程来帮助PrLMs抵御对抗性的单词替换。
AWS
对抗性词替代(AWS)是攻击预训练语言模型等高级神经模型的最有效的方法之一。
在AWS中,攻击者故意用其同义词替换某些词,以误导对目标模型的预测。同时,高质量的对抗性样本应保持语法正确性和语义一致性。为了制作高效和高质量的对抗性样本,攻击者应该首先确定要被干扰的脆弱token,然后选择合适的同义词来替换它们。
当前AWS模型采用启发式算法定位句子中脆弱的token。为了说明,对于给定的样本和目标模型,攻击者迭代地mask token并检查模型的输出。对最终输出日志具有显著影响的token被视为脆弱的。
防御aws
对于一般攻击方法,对抗性训练被广泛采用以减轻对抗性效应,但是表明该方法仍然容易受到AWS的攻击。这是因为AWS模型利用动态算法来攻击目标模型,而对抗性训练只涉及一个静态训练集。
由于AWS启发式攻击方法在攻击模型时迭代地替换每个单词,直到它成功地改变了模型的输出,因此使用静态策略来防御这种动态过程通常是不同的。
相反,动态策略,如随机化,可以更好地解决这个问题。人们还可以观察到,用它们更频繁的替代品替换单词可以更好地减轻对抗性的效果,并保持原始的性能。因此,设计了一种具有频率感知能力的随机化策略来干扰AWS策略。
图1显示了频率感知随机化的几个例子。
算法1中显示了频率感知随机化的建议方法,包括三个步骤。
该算法与与上述三个步骤基本一致,其中r是预定义的替代比率
在余弦相似度的选择上,又加上一个频率的选择
为了量化两个单词之间的语义相似性,我们使用来自(Mrkˇ si c等,2016)的嵌入来表示单词,这是专门为同义词识别而设计的。
两个词的语义相似度通过嵌入的余弦相似度来评估。为了确定一个单词的频率,我们使用了一个由频率单词库提供的频率字典。
将FAR过程应用于每个输入,仍然会降低正常样本的预测精度。为了克服这一问题,我们在PrLMs中添加了一个辅助异常检测头,并采用了多任务学习程序,使PrLMs能够对输入文本进行分类,同时区分敌对样本,而不引入额外的模型。在推断中,频率感知随机化只适用于被检测为对抗性的样本。这样非对抗性样本,很大程度上避免了精度的降低不会受到影响。
周等人。(2019)还详细阐述了使用扰动识别来阻止攻击的想法。然而,他们的方法在token级别检测异常,需要两个资源消耗的PrLM进行检测和校正,而我们的方法在句子级检测异常,不需要额外的模型。
在这一部分,我们阐述了训练和推理两个方面的ADFAR框架。
图2展示了训练中的ADFAR框架。
我们通过三个主要修改扩展了基线PrLMs:1)训练数据的构建,2)辅助异常检测器和3)训练目标,这将在本节中介绍。
如图2所示,我们结合了对抗性训练和数据增强的想法来构建我们的随机增强的对抗性训练数据。首先,我们使用了一个AWS模型。基于原始训练集生成对抗性样本。根据常见的对抗训练设置,我们将对抗样本与原始样本相结合,形成一个对抗训练集(蓝色)。
其次,为了让PrLMs更好地处理的随机化样本,我们将频率感知随机化(FAR)方法应用于对抗训练集,生成随机化对抗样本。最后,将对抗训练集和随机对抗训练集相结合,形成随机增强对抗训练集。
除了原始文本分类器之外,我们还在PrLMs上添加了一个辅助异常检测器(AD)来区分对抗性样本。对于输入句子,PrLMs通过自我注意每个token的上下文信息,并生成一系列上下文嵌入 ${h_0,\dots,h_m}$。对于文本分类任务,使用 $h_0\in R_h$作为聚合序列表示。原始文本类字符并利用$h_0$通过一个逻辑回归来预测$X$被标记为类$y^c$的概率:
$$
\begin{aligned} y _ { c } & = \operatorname { Prob } \left( \hat { y } _ { c } \mid x \right) \ & = \operatorname { softmax } \left( W _ { c } \left( d \operatorname { ropout } \left( h _ { 0 } \right) \right) + b _ { c } \right) , \end{aligned}
$$
对于异常检测器,$X$被标记为类$\hat{y}_d$的概率(如果$X$是攻击样本,$\hat{y_d}=1$;如果$X$是正常样本,$\hat{y_d}=0$)通过使用softmax的逻辑回归进行预测:
$$
\begin{aligned} y _ { d } & = \operatorname { Prob } \left( \hat { y } _ { d } \mid x \right) \ & = \operatorname { softmax } \left( W _ { d } \left( d r o p o u t \left( h _ { 0 } \right) \right) + b _ { d } \right) , \end{aligned}
$$
如图2所示,原始文本分类器在随机化增强的对抗训练集上训练,而异常检测器只在对抗训练集上训练。
我们采用了一个多任务学习框架,通过该框架训练PrLM对输入文本进行分类,同时区分对抗样本。我们以最小化交叉熵损失的形式设计了两个并行训练目标:
$$
\begin{aligned} \operatorname { loss } _ { c } & = - \left[ y _ { c } * \log \left( \hat { y } _ { c } \right) + \left( 1 - y _ { c } \right) * \log \left( 1 - \hat { y } _ { c } \right) \right] \ \operatorname { loss } _ { d } & = - \left[ y _ { d } * \log \left( \hat { y _ { d } } \right) + \left( 1 - y _ { d } \right) * \log \left( 1 - \hat { y _ { d } } \right) \right] \ \operatorname { Loss } & = \operatorname { loss } _ { c } + \operatorname { los } s _ { d } \end{aligned}
$$
本文的主要提出了一种辅助模型免受对抗文本影响的框架ADFAR,针对的对抗文本噪声主要是“词替换”。该框架可以拆分成两部分理解,FAR代表频率感知随机化方法,通过将被词替换的文本的词随机抽取一些替换回高频词,用对抗性的方法来打败对抗,可理解为一种数据增强的方法。而AD为则是一个异常检测器,通过逻辑回归区分对抗性样本,如若低于阈值,则该样本存在对抗性,需被FAR处理后分类。其他则可进行直接分类。
Deep Contrastive Learning for Unsupervised Textual Representations
句嵌入是许多自然语言处理系统的重要组成部分。与词嵌入一样,句嵌入通常是在大型文本语料库上学习的,然后转移到各种下游任务,如聚类和检索。与单词嵌入不同,学习句子嵌入的最高性能解决方案需要标记数据,这将它们的有用性限制在标记数据丰富的语言和领域。在本文中,我们提出了DeCLUTR:无监督文本表示的深度对比学习。受深度度量学习(DML)最新进展的启发,我们精心设计了一个不需要标记训练数据的学习通用句子嵌入的自监督目标。当用于扩展基于transformer的语言模型的预训练时,我们的方法缩小了通用句子编码器的无监督和有监督预训练之间的性能差距。重要的是,我们的实验表明,学习嵌入的质量与可训练参数的数量和未标记的训练数据的数量有关。我们的代码和预先训练的模型是公开可用的,可以很容易地适应新的领域或用于嵌入看不见的文本(训练集以外的数据)。
由于许多自然语言处理(NLP)任务可用的标记训练数据数量有限,迁移学习已变得普遍(Ruder等人,2019)。一段时间以来,NLP中的迁移学习仅限于预训练的词嵌入(Mikolov et al., 2013;Pennington et al., 2014)。最近的研究表明,使用预训练的句子嵌入有很强的迁移任务表现。这些固定长度的向量,通常被称为“通用”句子嵌入,通常在大型语料库中学习,然后转移到各种下游任务,如聚类(如主题建模)和检索(如语义搜索)。
事实上,句子嵌已经成为一个焦点领域,许多方法是有监督的(Conneau等人,2017年)、半监督的(Subramanian等人,2018;Pang等人,2018;Cer等人,2018;Reimers和Gurevych等人,2019年)和无监督的(Le和Mikolov,2014;Jernite等人,2017;Kiros等人,2015;Hill等人,2016;Logeswaran和Lee,2018)。然而,性能最高的解决方案需要带标签的数据,这限制了它们对带标签数据丰富的语言和领域的有用性。因此,缩小无监督和有监督通用语句嵌入方法之间的性能差距是一个重要的目标。
基于Transformer的预训练语言模型已成为从未标记语料库中学习文本表示的主要方法(Radford等人,2018年;Devlin等人,2019年;Dai等人,2019年;Yang等人,2019年;Liu等人,2019年;Clark等人,2020年)。这一成功主要是由屏蔽语言建模(MLM)推动的。这种自我监督的token级目标要求模型从输入序列中预测一些随机屏蔽的token的身份。除了MLM,这些模型中的一些有通过自监督学习句子级嵌入的机制。在BERT (Devlin等人,2019)中,一个特殊的分类标记被预先添加到每个输入序列中,并且它的表示被用于二进制分类任务中,以预测在训练语料库中一个文本片段是否跟随另一个文本片段,表示为下一句预测(NSP)。然而,最近的工作对NSP的有效性提出了质疑(Conneau和Lample,2019;Y ou等人,1904年;Joshi等人,2020年)。在Roberta(Liu等人,2019年)中,作者证明了在预训练期间移除NSP会导致下游句子水平任务(包括语义文本相似性和自然语言推理)的表现不变,甚至略有提高。
在 ALBERT (Lan et al., 2020) 中,作者假设 NSP 将主题预测和连贯性预测混为一谈,并提出了一个句子顺序预测目标 (SOP),表明它可以更好地模拟句间连贯性。在初步评估中,我们发现这两个目标都没有产生良好的通用句子嵌入(参见附录 A)。因此,我们提出了一个简单但有效的自我监督的句子级目标,其灵感来自度量学习的最新进展。
度量学习是一种表示学习,旨在学习一个嵌入空间,其中相似数据的向量表示被紧密映射在一起,反之亦然(Lowe,1995;Mika 等,1999;Xing 等,2002)。在计算机视觉 (CV) 中,深度度量学习 (DML) 已广泛用于学习视觉表征(Wohlhart 和 Lepetit,2015;Wen 等,2016;Zhang 和 Saligrama,2016;Bucher 等,2016;Leal- Taix´ 等,2016;Tao 等,2016;Yuan 等,2020;He 等,2018;Grabner 等,2018;Yelamarthi 等,2018;Y u 等, 2018)。
一般来说,DML的处理方法如下:精心设计一个“借口”任务(通常是自我监督的,例如着色或修复),并用于训练深层神经网络以生成有用的特征表示。
这里,“有用”指的是一种易于适应其他下游任务的表示,这些任务在训练时是未知的。下游任务(例如对象识别)然后被用于评估所学习特征的质量(独立于产生它们的模型),通常通过使用这些特征作为输入在任务上训练线性分类器。到目前为止,最成功的方法是设计一个借口任务,使用基于配对的对比损失函数进行学习。****对于给定的锚数据点,对比损失试图使锚和一些正数据点(相似的)之间的距离小于锚和一些负数据点(不相似的数据点)之间的距离(Hadsell等人,2006年)。
性能最好的方法通过随机增强相同的图像(例如,使用裁剪、翻转和颜色扭曲)来生成锚正向对;锚负向对是随机选择的、不同图像的增强视图(Bachman等人,2019年;Tian等人,2020年;He等人,2020年;Chen等人,2020年)。事实上,Kong 等人,2020 年证明 MLM 和 NSP 目标也是对比学习的实例。受这种方法的启发,我们提出了一个自监督的对比目标,可用于预训练句子编码器。我们的目标是通过训练一个编码器来学习通用句子的嵌入,使同一文档中随机抽取的文本片段的嵌入距离最小。通过使用SentEval (Conneau and Kiela, 2018)来扩展基于转换器的语言模型的前训练,并获得最先进的结果,我们证明了我们的目标的有效性。SentEval是一个由28个任务组成的基准任务,旨在评估通用句子嵌入。
我们的主要贡献是:
以前关于通用句子嵌入的工作可以根据他们在预训练步骤中是否使用标记数据来大致分组,我们简单地将其分别称为监督或半监督和非监督。
监督或半监督
性能最高的通用句子编码器在人类标记的自然语言推理(NLI)数据集Stanford NLI(SNLI)(Bowman等人,2015年)和MultiNLI(Williams等人,2018年)上进行了预训练。
自然语言推理的任务是将一对句子(表示“假设”和“前提”)归入三种关系中的一种:蕴涵、矛盾或中性。NLI在训练通用句子编码器方面的有效性通过有监督的InferSent方法得到了证明(Conneau等人,2017年)。通用句子编码器(USE)(Cer等人,2018年)是半监督的,增加了一个无监督的、类似跳过思想的任务(Kiros等人。2015年,见第2节),在SNLI语料库上进行监督训练。最近出版的句子转换器(Reimers和Gurevych,2019年)方法使用标记的NLI数据集对预先训练的、基于转换器的语言模型进行微调,比如Bert(Devlin等人,2019年)。
Unsupervised
Skip-Think(Kiros等人,2015)和FastSent(Hill等人,2016)是流行的无监督技术,它们通过使用句子的编码来预测相邻句子中的单词来学习句子嵌入。然而,除了计算成本高之外,这种生成性目标迫使模型重构句子的表面形式,这可能捕获与句子含义无关的信息。quickthings(Logeswaran和Lee,2018)用简单的区别性目标解决了这些缺点;给定一个句子及其上下文(相邻句子),它通过训练一个分类器来区分上下文句子和非上下文句子来学习句子表示。
无监督方法的统一主题是,它们利用了“分布假设”,即一个词(以及引申为一个句子)的意义由它出现的词的上下文来表征。
我们的整体方法与句子Transformer最相似——我们扩展了基于Transformer的语言模型的预处理,以产生有用的句子嵌入——但我们提出的目标是自监督的。消除对标签数据的依赖使我们能够利用网络上大量的未标签文本,而不局限于标签数据丰富的语言或领域(例如英语维基百科)。
我们的目标与 QuickThoughts 最为相似; 一些区别包括:我们将采样放宽到最大段落长度(而不是自然句子)的文本段,我们对每个锚点(而不是严格的一个)采样一个或多个正段,并且我们允许这些段相邻、重叠或 包含(而不是严格相邻;参见图 1,B)。
图1:自监督对比目标概述。
(A)对于$minibatch=N$的$d$的文档,我们为每个文档采样$A$个
anchor
。简单起见,我们举例说明$A=P=1$的情况,并表示anchor-positive
为$\boldsymbol { s } _ { i } , \boldsymbol { s } _ { j }$。每个span
都通过相同的编码器$f(\cdot)$和池化器$g(\cdot)$来产生对应的嵌入$\boldsymbol{e}_i=g(f(\boldsymbol{s_i})),\boldsymbol{e}_j=g(f(\boldsymbol{s_j}))$。编码器和pooler经过训练,通过对比预测任务最小化嵌入之间的距离,其中minibatch中的其他嵌入被视为负数(为了简单起见,这里省略了)。(B)正样本可以和
Anchor
重叠,相邻或包含(C)锚的长度和正数是从beta分布中随机抽样的,分别向较长的和较短的跨度倾斜。
我们的方法通过对比损失来学习文本表示,通过最大化从同一文档中附近采样的文本片段(在论文的其余部分称为“跨度”)之间的一致性来学习文本表示。如图1所示,该方法包括以下组件:
数据加载步骤从大小为$N$的小批次的每个文档中随机抽样成对的 anchor-positive
span。设 $A$是每个文档采样的anchor span
个数。 我们表示一个anchor span
和它对应的 $p\in {1…P}$ positive span
作为$\boldsymbol{s}i$和$\boldsymbol{s}{i+pAN}$。此程序旨在最大限度地抽样语义相似的anchor-positive
对(参见第3.2节)。
编码器 $f(\cdot )$将输入跨度中的每个token映射到嵌入。虽然我们的方法对编码器的选择没有限制,但我们选择$f( \cdot )$为基于Transformer的语言模型,因为这代表了文本编码器的最高水平。
池化器$g( \cdot )$将编码 span
,$f(\boldsymbol{s}i)$和 $f(\boldsymbol{s}{i+pAN})$映射到固定长度嵌入$\boldsymbol{e}_i=g(f(\boldsymbol{s}_i))$及其对应的平均positive
嵌入:
$$
\boldsymbol { e } _ { i + A N } = \frac { 1 } { P } \sum _ { p = 1 } ^ { P } g \left( f \left( \boldsymbol { s } _ { i + p A N } \right) \right)
$$
与Reimers和Gurevych 2019类似,我们发现选择$g(·)$作为token级嵌入的平均值(在论文的其余部分称为“mean pooling”)表现良好(见附录,表4)。我们将每个锚点嵌入与多个正嵌入的平均值配对。这一策略是由Saunshi等人在2019年提出的,他们证明了与使用每个锚的单一积极例子相比,理论和经验上的改进。
为对比预测任务定义的对比损失函数。给定一组嵌入区间${\boldsymbol{e_k}}$,其中包含正样本$\boldsymbol{e}i$和$\boldsymbol{e}{i+AN}$,对比预测任务的目标是识别给定$\boldsymbol{e}i$的$\boldsymbol{e}{i+AN}$ :
$$
\ell ( i , j ) = - \log \frac { \exp \left( \operatorname { sim } \left( \boldsymbol { e } _ { i } , \boldsymbol { e } _ { j } \right) / \tau \right) } { \sum _ { k = 1 } ^ { 2 A N } \mathbb { 1 } _ { [ i \neq k ] } \cdot \exp \left( \operatorname { sim } \left( \boldsymbol { e } _ { i } , \boldsymbol { e } _ { k } \right) / \tau \right) }
$$
其中,$\operatorname { sim } ( \boldsymbol { u } , \boldsymbol { v } ) = \boldsymbol { u } ^ { T } \boldsymbol { v } / | \boldsymbol { u } | _ { 2 } | \boldsymbol { v } | _ { 2 }$代表向量u和v余弦相似度,$\mathbb { 1 } _ { [ i \neq k ] } \in { 0,1 }$表示一个指示函数,如果$ i \neq k$则为1,$\tau > 0$ 表示温度超参数。
在训练期间,我们从训练集中随机抽取$ N $个文档的小批量样本,并在来自 $ N $ 个文档的锚正对$\boldsymbol{e}i,\boldsymbol{e}{i+AN}$上定义预测任务,从而产生$2AN$数据点。
正如 (Sohn, 2016) 中提出的,我们将minibatch中的其他$2(AN-1)$个实例视为反例。损失函数采用以下形式:
$$
\mathcal { L } _ { \text {contrastive } } = \sum _ { i = 1 } ^ { A N } \ell ( i , i + A N ) + \ell ( i + A N , i )
$$
这是之前作品中使用的InfoNCE损失(Sohn, 2016;Wu et al., 2018;Oord et al., 2018),并在(Chen et al., 2020)中表示归一化温度尺度交叉熵损失或“NT-Xent”。
要通过一个训练好的模型来embed文本,我们只需要在模型中传递一批token化的文本。因此,我们的方法在测试时的计算成本是编码器$f( \cdot )$和池化器 $g(\cdot )$的成本,当在使用平均池化时可以忽略不计。
我们从选择最小和最大的span长度开始;在本文中,$\ell _ { \min } = 32$,$\ell _ { \max } = 512$,这是许多预训练的Transformer的最大输入尺寸。接下来,文档$d$被标记化以产生$n$个token $\boldsymbol { x } ^ { d } =(x_1,x_2,\dots,x_n)$。为了从$\boldsymbol{x}^d$中随机抽样anchor span
$\boldsymbol{s}i$,我们首先从$\beta$分布中抽样其长度$\ell{anchor}$,然后随机抽样其起始位置$s_i^{start}$。
$$
\begin{aligned} \ell _ { \text {anchor } } & = \left\lfloor p _ { \text {anchor } } \times \left( \ell _ { \max } - \ell _ { \min } \right) + \ell _ { \min } \right\rfloor \ s _ { i } ^ { \text {start } } & \sim \left{ 0 , \ldots , n - \ell _ { \text {anchor } } \right} \ s _ { i } ^ { \text {end } } & = s _ { i } ^ { \text {start } } + \ell _ { \text {anchor } } \ \quad s _ { i } & = \boldsymbol { x } _ { s _ { i } ^ { d \text { start } } : s _ { i } ^ { \text {end } } } \end{aligned}
$$
然后,我们对$p \in { 1 \ldots P }$按照类似的过程采样对应的positive spans
$\boldsymbol { s } _ { i + p A N }$:
$$
\begin{aligned} \ell _ { \text {positive } } & = \left\lfloor p _ { \text {positive } } \times \left( \ell _ { \max } - \ell _ { \min } \right) + \ell _ { \min } \right\rfloor \ s _ { i + p A N } ^ { \text {start } } & \sim \left{ s _ { i } ^ { \text {start } } - \ell _ { \text {positive } } , \ldots , s _ { i } ^ { \text {end } } \right} \ s _ { i + p A N } ^ { \text {end } } & = s _ { i + p A N } ^ { \text {start } } + \ell _ { \text {positive } } \ \boldsymbol { s } _ { i + p A N } & = \boldsymbol { x } _ { s _ { i + p A N } ^ { s \text { start } } } { : s _ { i + p A N } ^ { \text {end } } } \end{aligned}
$$
其中$p _ { \text {anchor } } \sim \operatorname { Beta } ( \alpha = 4 , \beta = 2 )$,这使得锚定采样向更大跨度倾斜,以及
$p _ { \text {positive } } \sim \operatorname { Beta } ( \alpha = 2 , \beta = 4 )$这使得正样本偏向较短的跨度(图1.c)。在实际中,我们限定来自同一文档的anchor span
的采样,以便它们至少相隔$2* \ell_{max}$个token。在附录B中,我们展示了通过我们的方法抽样的文本的示例。我们在设计抽样程序时注意到几个经过深思熟虑的决定:
anchor span
的采样长度比positive span
更长,可以提供下游任务的性能(我们没有发现性能对特定的α和β选择敏感)。这样做的理由有两个。首先,它使该模型能够学习全局到局部视图预测(Hjelm等人,2019年;Bachman等人,2019年;Chen等人,2020年)(在图1,B中称为“包含视图”)。第二,当$P>1$时,它通过减少重复语篇的数量来鼓励positive span
的多样性。anchor
附件的positive
采样利用了分布式假设,并增加了采样的有效(既语义相似性) anchor-positive
对的机会。anchor
进行采样,每个anchor-positive
将与简单负样本(从Minibatch中其他文档采样的anchor
和positives
)和hard负样本(从同一文档中采用的anchor
和positive
)。总之,采样程序产生三种类型的正样本:
anchor
部分重叠的正样本anchor
相邻的正样本anchor
包含的正样本(图1,B)以及两种类型的负样本:
anchor
不同的文档中采样ancho
相同的文档中采样因此,我们随机生成的训练集和对比损失隐含地定义了一系列预测任务,可用于训练模型,独立于任何特定的编码器架构。
我们使用我们的目标函数来扩展基于Transformer语言模型的预训练模型,因为这代表NLP中最先进的编码器。我们按照(Devlin et al., 2019)中所述在minibatch中的每个anchor span
上采用MLM目标函数,并在反向传播之前对来自$MLM$和对比损失函数的损失求和。
$$
\mathcal { L } = \mathcal { L } _ { \text {contrastive } } + \mathcal { L } _ { \mathrm { MLM } }
$$
这类似于现有的预训练策略,其中 MLM 损失与句子级损失配对,例如 NSP(Devlin 等人,2019)或 SOP(Lan 等人,2020 年)。为了使计算要求可行,我们不会从头开始训练,而是继续训练一个已经用 MLM 目标进行预训练的模型。
具体来说,我们在实验中同时使用 RoBERTa-base (Liu et al., 2019) 和 DistilRoBERTa (Sanh et al., 2019)(RoBERTa-base 的蒸馏版本)。在本文的其余部分,我们将我们的方法称为 DeCLUTR-small(扩展 DistilRoBERTa 预训练时)和 DeCLUTR-base(扩展 RoBERTa-base 预训练时)。
在 5.1 小节中,我们将模型的性能与相关基线进行了比较。在剩下的部分中,我们探索哪些组件有助于学习嵌入的质量。
下游任务的性能
加粗的是最好性能。
我们消除了采样过程的几个组成部分,包括每个文档 $A$ 采样的锚点数量、每个锚点 $P$ 采样的正样本数量以及这些正样本的采样策略(图 2)。
每个文档采样的锚跨度数 (a)、每个锚点采样的正跨度数 (b) 和采样策略 (c) 的影响。从 SentEval 的验证集中报告平均下游任务分数。表格通过超参数网格进行计算,并绘制为分布图。
网格由
anchor
的数量$A={1,2}$,正样本的数量$P={1,2,4}$,温度超参数:$\tau = \left{ 5 \times 10 ^ { - 3 } , 1 \times 10 ^ { - 2 } , 5 \times 10 ^ { - 2 } \right}$和学习率$\alpha = \left{ 5 \times 10 ^ { - 5 } , 1 \times 10 ^ { - 4 } \right}$的数量来排列。P = 4被省略,因为这些实验不适合图形处理器内存。
我们注意到当$A=2$时,与$A=1$相比,模型在两倍的span数和两部的有效批量($2AN$,其中$N$是小批次中的文档数)上训练。为了控制这一点,所有$A=1$的实验都针对两个epoch($A=2$时epochs的两倍)和两倍的小批量(2N)进行训练。(数据量保持一样)因此,两组实验都在相同跨度数和相同的有效批次大小($4N$)上进行训练,唯一的区别就是每个文档的anchor
样本数量($A$)。
我们发现,对每个文档的多个锚点进行采样对学习嵌入的质量有很大的积极影响。我们假设这是因为当A > 1时,对比目标的难度增加了。回想一下,minibatch是由随机文档组成的,从文档中取样的每个锚-正对与minibatch中的所有其他锚-正对进行对比。当$A>1$时,anchor-positive
对将与来自同一文档的其他anchor-positive
进行对比,增加了对比难度,从而导致更好的表征。
我们还发现,一个正样本采样策略,允许positive
邻接和被包含,优于允许只采用二者之一的策略,这表明视图获取的信息是互补的。最后,我们注意到每个anchor
(P > 1)取样多个positive
对性能的影响很小。
这与(Sanshi等人,2019年)相反,他发现当给定的anchor
具有多个positive
平均时,理论和经验上都有所改善。
为了确定培训目标、训练集大小和模型容量的重要性,我们训练了两个大小的模型,训练集的10%到100%(1个完整的epoch)(图3)。
用MLM目标和对比目标对模型进行预处理,比单独用任何一个目标进行训练都提高了性能。随着训练集规模的增加,将MLM纳入对比目标会带来单调的改善。我们假设,包括MLM损失作为一种正则化形式,防止预训练模型(其本身是用MLM损失训练的)的权重偏离太大,这种现象被称为“灾难性遗忘”(McCloskey和Cohen,1989;拉特克利夫,1990年)。
这些结果表明,通过我们的方法学习到的嵌入质量根据模型容量和训练集大小来衡量;因为训练方法是完全自我监督的,所以缩放训练集只需要收集更多未标记的文本。
本文提出了一个学习通用句子嵌入的自监督目标。我们的目标不需要标记的训练数据,适用于任何文本编码器。我们通过评估SentEval基准上的学习嵌入来证明我们目标的有效性,该基准包含总共28个任务,旨在评估句子表示的可迁移性和语言属性。当用于扩展基于Transformer的语言模型的预处理时,我们的自我监督目标缩小了与现有方法的性能差距,现有方法需要人工标记的训练数据。实验表明,通过增加模型和训练集的大小,可以进一步提高学习嵌入的质量。总之,这些结果证明了用精心设计的学习通用句子嵌入的自我监督目标代替手工标记数据的有效性和可行性。我们公开发布我们的模型和代码,希望它能扩展到新的领域和非英语语言。