CNC锁机机床解锁数控系统解密加工中心解锁
- 失了字符在词汇中的语义表达
- 丢失了词边界信息
有人说不要担心我们有Bert!可以直接用预训练语言模型去提取通用的包含上下文的文本信息,但使用Bert还是几个问题
- infer速度在部分场景不满足要求,因此部分场景使用词汇增强是为了在保证推理延时的前提下,去逼近bert的性能
- Bert在部分垂直领域的表现一般,因此需要领域内的词汇信息加持
- Bert的信息提取更加全局,NER的识别需要局部信息,因此依旧会存在边界识别错误的问题
词汇增强的方法主要分为两种
- Embedding增强:包括softword, Ex-softword, 以及去年的新贵SoftLexicon,它们对模型结构无任何要求只通过引入带有词汇/分词信息的Embedding达到词汇增强的目的,更灵活且SoftLexicon的效果拔群
- 特殊模型结构类:Lattice-LSTM出发的各种改良,例如用CNN替换LSTM结构的LR-CNN,改造transformer positional encoding的FLAT等等。
Embedding增强
Softword
最简单引入词边界信息的方案,就是直接引入分词B/M/E/S的标签。这里我直接用了jieba,当然如果有用目标数据集训练的Segmentator更好,对句子进行分词,根据分词结果对字符分别标注是一个单词的开始(B),中间(M),结束(E)还是单个字符(S),如下
然后在模型输入侧,把分词的label encoding进行向量表达,用相加或者拼接的方式,加入到已有的token embedding上。
这种方式最简单粗暴,但问题就是其一B/M/E/S基本只引入了词边界信息,对于词本身语义信息的表达有限,其二单一分词器的会因为自身的准确率以及粒度问题引入噪音。在MSRA/People Daily的数据集上,softword对tag级别的预测基本没啥增益,但是对entity级别的预测有1个多点左右的提升,对于样本更小的people daily数据集提升更大。
Ex-softword
既然softword有单一分词器的问题,那如果不考虑分词,直接把该字符在上下文中所有能匹配上词汇信息都加入进来会不会更好呢? 如下所示每个字符会遍历词表,拿到所有包含这个字且满足前后文本的所有分词tag。整个遍历是O(NK)的复杂度其中N是句子长度,K是最长词搜索长度我取了10,Exsoftword的结果如下
Ex-softword通过引入更多的分词信息,来模糊单一分词器可能的分词错误问题,不过它并没有对引入的信息相关性/重要性进行区分,虽然引入更多信息,但同时引入了更多噪音,效果相较softword并没啥提升。
Softlexicon
softlexicon是在Ex-softword的基础上把只使用B/M/E/S的分词tag,变成直接使用所有匹配上的单词。每个字符都得到该字符作为B/M/E/S所能匹配上的所有单词,这样在引入词边界信息的同时也引入词汇本身信息。
default = {'B' : set(), 'M' : set(), 'E' : set(), 'S' :set()}
soft_lexicon = [deepcopy(default) for i in range(len(sentence))]
for i in range(len(sentence)):
for j in range(i, min(i+MaxWordLen, len(sentence))):
word = sentence[i:(j + 1)]
if word in Vocab2IDX:
if j-i==0:
soft_lexicon[i]['S'].add(word)
elif j-i==1:
soft_lexicon[i]['B'].add(word)
soft_lexicon[i+1]['E'].add(word)
else:
soft_lexicon[i]['B'].add(word)
soft_lexicon[j]['E'].add(word)
for k in range(i+1, j):
soft_lexicon[k]['M'].add(word)
for key, val in soft_lexicon[i].items():
if not val:
soft_lexicon[i][key].add(NONE_TOKEN)
以上build_softlexicon会得到以下输出
作者尝试了对匹配上的单词取对应预训练Embedding然后对B/M/E/S分别算average embedding再concat在一起,但是效果并不好。这种做法和以上Ex-softword相同,没有对词汇的重要性进行区分会引入较多噪音。于是作者是直接在训练集+验证集上统计了匹配上的word count z(w)
作为该词的embeding权重,在代码里我默认使用了预训练glove的词频,毕竟实际标注数据往往较少,直接在训练集上统计词频OOV问题会比较严重。
v(S)Z=4Z∑w∈Sz(w)e(w)=∑w∈B∪M∪E∪Sz(w)(1)(2)
在效果上softLexicon还是比较厉害的,相较bilstm_crf有近6个点的提升【这里MSRA的样本split和paper有差异,bilstm_crf就低了3个点左右,不过相对提升和paper中近似】。在paper的样本划分中,MSRA数据集上softlexicon的效果只比bert差1个多点,在Weibo/OneNote上要差的多些,毕竟词频统计在测试集上的适配程度是训练集越大好的,不过和以下Lattice增强的各种模型相比表现是不相上下的!
对比我们马上要聊的Lattice家族,SoftLexicon可以说是简单粗暴又好使!且因为只比bilstm多了一层O(NK)的词表匹配,infer speed比bert要快一倍多,比lattice快5倍,可以说是十分优秀了!
Lattice Family
词汇增强的另一种实现方式就是借助特殊的模型结构引入词信息,这一块没有代码复现更多只是了解下模型,毕竟结构的限制
2)创建项目,代码编写
1、在项目依赖中添加SQL模块的JPA依赖、MySql依赖以及Web模块中的Web依赖,如下图所示:
引入这三个依赖器创建项目,在项目pom.xml文件会出现以下依赖:
2、编写数据库表对应的实体类,并使用JPA相关注解配置映射关系
package com.hardy.springbootdatacache.entity; import org.springframework.data.annotation.Id; import javax.persistence.*; /** * @Author: HardyYao * @Date: 2021/6/19 */ @Entity(name = "t_comment") // 设置ORM实体类,并指定映射的表名 public class Comment { @Id // 映射对应的主键id @GeneratedValue(strategy = GenerationType.IDENTITY) // 设置主键自增策略 private Integer id; private String content; private String author; @Column(name = "a_id") // 指定映射的表字段名 private Integer aId; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public Integer getaId() { return aId; } public void setaId(Integer aId) { this.aId = aId; }
报错原因分析
报错的原因首先是因为 IDEA 强大的报警机制,@Autowired 为 Spring 的注解,含义是将某类动态的注入到当前类中,如下图所示:
@Autowired 默认是根据 type 进行注入,并且注入时要求(注入)对象不能为 NULL,默认值如下图所示:
而 IDEA 报错的原因是:@Autowired 为 Spring 的注解,而注入的 Mapper 对象使用的又是 @Mapper 的注解,然而 @Mapper 又为 MyBaits 的注解,IDEA 能很好的兼容并识别 Spring 的注解,但不能很好的识别 MyBatis 的注解,因此在使用 @Autowired 注解时,IDEA 并不能检测到 @Mapper 注解的对象不为 NULL,因此就会报错。
这就是为什么使用 Spring 的注解 @Repository/@Component... 不报错,而使用 @Mapper 注解却会报错的根本原因,如下图所示:
解决方案1:关闭报警机制
关闭 IDEA 注入报警机制,可以避免报错,实现步骤如下。
1.打开 IDEA,找到参数设置选项 “Preferences...” ,如下图所示:
2.依次选择 “Editor” -> “Inspections” -> “Spring” -> “Spring Core” -> “Code” -> “Autowiring for bean class” 将 “Error” 级别修改成 “Waring” 级别,如下图所示:
设置完成之后点击确认,查看之前报错的 Mapper 类,此时展示效果如下:
数控车床解密SYNTEC解锁CNC锁机机床解锁数控系统解密加工中心解锁数控车床解密SYNTEC解锁