目录

前言

一、BERT的主要亮点

1. 双向Transformers

2.句子级别的应用

3.能够解决的任务

二、BERT代码解读

1. 数据预处理

1.1 InputExample类

1.2 InputFeatures类

1.3 DataProcessor   重点

1.4 convert_single_example

1.5 file_based_convert_examples_to_features

1.6 file_based_input_fn_builder

1.7 _truncate_seq_pair

2. 模型部分

2.1 model_fn_builder

2.2 create_model   重点

3. main主函数

4. 总结

三、Entity-Relation-Extraction-master实战


BERT代码:参加另一篇文章《命名实体识别NER & 如何使用BERT实现》

前言

BERT模型是谷歌2018年10月底公布的,它的提出主要是针对word2vec等模型的不足,在之前的预训练模型(包括word2vec,ELMo等)都会生成词向量,这种类别的预训练模型属于domain transfer。而近一两年提出的ULMFiT,GPT,BERT等都属于模型迁移,说白了BERT 模型是将预训练模型和下游任务模型结合在一起的,核心目的就是:是把下游具体NLP任务的活逐渐移到预训练产生词向量上。

基于google公布的一个源代码:https://github.com/google-research/bert

将bert写成了service 的方式:https://github.com/hanxiao/bert-as-service

论文:https://arxiv.org/abs/1810.04805

一篇中文博客:https://www.cnblogs.com/rucwxb/p/10277217.html

一、BERT的主要亮点

1. 双向Transformers

BERT真真意义上同时考虑了上下文:

正如论文中所讲,目前的主要限制是当前模型不能同时考虑上下文,像上图的GPT只是一个从左到右,ELMo虽然有考虑从左到右和从右到左,但是是两个分开的网络,只有BERT是真真意义上的同时考虑了上下文。

2.句子级别的应用

通过使用segment同时考虑了句子级别的预测。

3.能够解决的任务

google已经预预训练好了模型,我们要做的就是根据不同的任务,按照bert的输入要求(后面会看到)输入我们的数据,然后获取输出,在输出层加一层(通常情况下)全连接层就OK啦,整个训练过程就是基于预训练模型的微调,下述图片是其可以完成的几大类任务:

a、b都是sentence级别的:文本分类,关系抽取等;

c、d是tokens级别的:如命名实体识别,知识问答等。

二、BERT代码解读

BERT的代码主要分为两个部分:

1. 预训练部分:其入口是在run_pretraining.py。

2. Fine-tune部分:Fine-tune的入口针对不同的任务分别在run_classifier.py和run_squad.py。其中

  • run_classifier.py:适用的任务为分类任务,如CoLA、MRPC、MultiNLI等。而
  • run_squad.py:适用的是阅读理解任务,如squad2.0和squad1.1。

在使用的时候,一般是需要下面三个脚本的,我们也不必修改,直接拿过来使用就ok

  • modeling.py:模型定义
  • optimization.py:优化器
  • tokenization.py

其中tokenization是对原始句子内容的解析,分为BasicTokenizer和WordpieceTokenizer两个,一般来说BasicTokenizer主要是进行unicode转换、标点符号分割、中文字符分割、去除重音符号等操作,最后返回的是关于词的数组(中文是字的数组),WordpieceTokenizer的目的是将合成词分解成类似词根一样的词片。例如将"unwanted"分解成["un", "##want", "##ed"],这么做的目的是防止因为词的过于生僻没有被收录进词典最后只能以[UNK]代替的局面,因为英语当中这样的合成词非常多,词典不可能全部收录。FullTokenizer的作用就很显而易见了,对一个文本段进行以上两种解析,最后返回词(字)的数组,同时还提供token到id的索引以及id到token的索引。这里的token可以理解为文本段处理过后的最小单元。上述来源https://www.jianshu.com/p/22e462f01d8c,更多该脚本的内容可以看该链接,下面主要用到FullTokenizer这个类。

真正需要修改是:

run_classifier.py
            run_squad.py
分别是解决分类、阅读理解任务,其实套路差不多,我们具体来看一下run_classifier.py

首先BERT主要分为两个部分。一个是训练语言模型(language model)的预训练(run_pretraining.py)部分。另一个是训练具体任务(task)的fine-tune部分,预训练部分巨大的运算资源,但是其已经公布了BERT的预训练模型。

这里需要中文,直接下载就行,总得来说,我们要做的就是自己的数据集上进行fine-tune。

1. 数据预处理

run_classifier.py中的类如下:

1.1 InputExample类

主要定义了一些数据预处理后要生成的字段名,如下:

  • guid就是一个id号,一般将数据处理成train、dev、test数据集,那么这里定义方式就可以是相应的数据集+行号(句子)
  • text_a 就是当前的句子,text_b是另一个句子,因为有的任务需要两个两个句子,如果任务中没有的话,可以将text_b设为None
  • label就是标签

1.2 InputFeatures类

主要是定义了bert的输入格式,形象化点就是特征,即上面的格式使我们需要将原始数据处理成的格式,但并不是bert使用的最终格式,且还会通过一些代码将InputExample转化为InputFeatures,这才是bert最终使用的数据格式,当然啦这里根据自己的需要还可以自定义一些字段作为中间辅助字段,但bert最基本的输入字段就需要input_ids,input_mask和segment_ids这三个字段,label_id是计算loss时候用到的:

  • input_ids,segment_ids:分别对应单词id和句子(上下句标示),input_ids、segment_ids分别代表token、segment。
  • Input_mask:记录的是填充信息,具体看下面

1.3 DataProcessor   重点

这是一个数据预处理的基类,里面定义了一些基本方法。

XnliProcessor、MnliProcessor、MrpcProcessor、ColaProcessor四个类是对DataProcessor的具体实现,这里之所以列举了四个是尽可能多的给用户呈现出各种demo,具体到实际使用的时候我们只需要参考其写法,定义一个自己的数据预处理类即可,其中一般包括如下几个方法:

get_train_examples,get_dev_examples,get_test_examples,get_labels,_create_examples

其中前三个都通过调用_create_examples返回一个InputExample类数据结构,get_labels就是返回类别,所以重点就是以下两个函数:

这里的tokenization的convert_to_unicode就是将文本转化为utf-8编码。

上述就是数据预处理过程,也是需要我们自己根据自己的数据定义的,其实呢,这并不是Bert使用的最终样子,其还得经过一系列过程才能变成其能处理的数据格式该过程是通过接下来的四个方法完成的

convert_single_example:返回一个InputFeatures类
            file_based_convert_examples_to_features
            file_based_input_fn_builder
            truncate_seq_pair
只不过一般情况下我们不需要修改,它都是一个固定的流程。

1.4 convert_single_example

bert的输入:

代码中的input_ids、segment_ids分别代表token、segment,同时其还在句子的开头结尾加上了[CLS]和SEP]标示 :

  • input_ids:记录的是使用FullTokenizer类convert_tokens_to_ids方法将tokens转化成单个字的id;
  • segment_ids:就是句子级别(上下句)的标签,大概形式:

(a) For sequence pairs:
      tokens:   [CLS] is this jack ##son ##ville ? [SEP]  no it is not . [SEP]
      type_ids:    0     0  0     0       0         0      0    0      1  1  1  1   1    1
(b) For single sequences:
     tokens:     [CLS] the dog is hairy . [SEP]
     type_ids:      0     0     0   0    0    0    0

当没有text_b的时候,就都是0啦

  • input_mask:其就是和最大长度有关,假设我们定义句子的最大长度是120,当前句子长度是100,那么input_mask前100个元素都是1,其余20个就是0。

最后返回的就是一个InputFeatures类:

1.5 file_based_convert_examples_to_features

很简单啦,因为在训练的时候为了读写快速方便,便将数据制作成TFrecords 数据格式,该函数主要就是将上述返回的InputFeatures类数据,保存成一个TFrecords数据格式,关于TFrecords数据格式的制作可以参考:https://blog.csdn.net/weixin_42001089/article/details/90236241

1.6 file_based_input_fn_builder

对应的就是从TFrecords 解析读取数据

1.7 _truncate_seq_pair

就是来限制text_a和text_b总长度的,当超过的话,会轮番pop掉tokens

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------

至此整个数据的预处理才算处理好,其实最后最关键的就是得到了那个TFrecords文件。

2. 模型部分

  • create_model
  • model_fn_builder

整个模型过程采用了tf.contrib.tpu.TPUEstimator这一高级封装的API

model_fn_builder是壳,create_model是核心,其内部定义了loss,预测概率以及预测结果等等。

2.1 model_fn_builder

其首先调用create_model得到total_loss、 per_example_loss、logits、 probabilities等:

然后针对不同的状态返回不同的结果(output_spec):

  • 如果是train,则返回loss、train_op等;
  • 如果是dev,则返回一些评价指标如accuracy;
  • 如果是test,则返回预测结果

所以我们如果想看一下别的指标什么的,可以在这里改 ,需要注意的是指标的定义这里因为使用了estimator API使得其必须返回一个operation,至于怎么定义f1可以看:

https://www.cnblogs.com/jiangxinyang/p/10341392.html

2.2 create_model  重点

这里可以说整个Bert使用的最关键的地方,我们使用Bert大多数情况无非进行在定义自己的下游工作进行fine-tune,就是在这里定义的。

把这段代码贴出来吧

def create_model(bert_config, is_training, input_ids, input_mask, segment_ids,labels, num_labels, use_one_hot_embeddings):"""Creates a classification model."""model = modeling.BertModel(config=bert_config,is_training=is_training,input_ids=input_ids,input_mask=input_mask,token_type_ids=segment_ids,use_one_hot_embeddings=use_one_hot_embeddings)# In the demo, we are doing a simple classification task on the entire# segment.## If you want to use the token-level output, use model.get_sequence_output()# instead.output_layer = model.get_pooled_output()hidden_size = output_layer.shape[-1].valueoutput_weights = tf.get_variable("output_weights", [num_labels, hidden_size],initializer=tf.truncated_normal_initializer(stddev=0.02))output_bias = tf.get_variable("output_bias", [num_labels], initializer=tf.zeros_initializer())with tf.variable_scope("loss"):if is_training:# I.e., 0.1 dropoutoutput_layer = tf.nn.dropout(output_layer, keep_prob=0.9)logits = tf.matmul(output_layer, output_weights, transpose_b=True)logits = tf.nn.bias_add(logits, output_bias)probabilities = tf.nn.softmax(logits, axis=-1)log_probs = tf.nn.log_softmax(logits, axis=-1)one_hot_labels = tf.one_hot(labels, depth=num_labels, dtype=tf.float32)per_example_loss = -tf.reduce_sum(one_hot_labels * log_probs, axis=-1)loss = tf.reduce_mean(per_example_loss)return (loss, per_example_loss, logits, probabilities)

首先调用modeling.BertModel得到bert模型:

(1)bert模型的输入:input_ids,input_mask,segment_ids

model = modeling.BertModel(config=bert_config,is_training=is_training,input_ids=input_ids,input_mask=input_mask,token_type_ids=segment_ids,use_one_hot_embeddings=use_one_hot_embeddings
  • config:是bert的配置文件,在开头下载的中文模型中里面有,直接加载即可

  • use_one_hot_embeddings:是根据是不是用GPU而定的,其他字段上述都说过啦

(2)bert模型的输出:其有两种情况   

model.get_sequence_output():第一种输出结果是[batch_size, seq_length, embedding_size]

model.get_pooled_output():第二种输出结果是[batch_size, embedding_size]

第二种结果是第一种结果在第二个维度上面进行了池化,要是形象点比喻的话,第一种结果得到是tokens级别的结果,第二种是句子级别的,其实就是一个池化。

(3)我们定义部分

这部分就是需要我们根据自己的任务自己具体定义啦,假设是一个简单的分类,那么就是定义一个全连接层将其转化为[batch_size, num_classes]。

output_weights和output_bias就是对应全连接成的权值,后面就是loss,使用了tf.nn.log_softmax应该是一个多分类,多标签的话可以使用tf.nn.sigmoid。

总的来说,使用bert进行自己任务的时候,可以千变万化,变的就是这里这个下游。

3. main主函数

最后就是主函数,主要就是通过人为定义的一些配置值(FLAGS)将上面的流程整个组合起来

这里大体说一下流程:

processors = {"cola": ColaProcessor,"mnli": MnliProcessor,"mrpc": MrpcProcessor,"xnli": XnliProcessor,}

这里就是定义数据预处理器的,记得把自己定义的预处理包含进来,名字嘛,随便起起啦,到时候通过外部参数字段task_name来指定用哪个(说白了就是处理哪个数据)。

数据预处理完了,就使用tf.contrib.tpu.TPUEstimator定义模型

最后就是根据不同模式(train/dev/test,这也是运行时可以指定的)运行estimator.train,estimator.evaluate,estimator.predict。

4. 总结

(1)总体来说,在进行具体工作时,复制 BERT 的 run_classifier.py,修改核心内容作为自己的run函数,需要改的核心就是:

1) 继承DataProcessor,定义一个自己的数据预处理类

2) 在create_model中,定义自己的具体下游工作

剩下的就是一些零零碎碎的小地方啦,也很简单

(2)关于bert上游的具体模型定义这里没有,实在感兴趣可以看modeling.py脚本,优化器部分是optimization.py

(3)这里没有从头训练bert模型,因为耗时耗力,没有资源一般来说很难,关于预训练的部分是run_pretraining.py

三、Entity-Relation-Extraction-master实战

https://github.com/yuanxiaosc/Entity-Relation-Extraction

基于 TensorFlow 的实体及关系抽取,2019语言与智能技术竞赛信息抽取(实体与关系抽取)任务解决方案。

实体关系抽取本模型过程:

该代码以管道式的方式处理实体及关系抽取任务,首先使用一个多标签分类模型判断句子的关系种类, 然后把句子和可能的关系种类输入序列标注模型中,序列标注模型标注出句子中的实体,最终结合预 测的关系和实体输出实体-关系列表:(实体1,关系,实体2)

  • 1. 先进行关系抽取:得到一句话中有几种关系
  • 2. 根据预测出来的关系类,如当前句子预测出3个关系,那么就重复该句话分成3个样本
  • 3. 再进行实体识别:根据序列标注找出实体
  • 4. 生成实体—关系三元组结果

模型过程总结:

BERT:代码解读、实体关系抽取实战相关推荐

  1. 基于Bert的实体关系抽取模型

    关注微信公众号:NLP分享汇.[喜欢的扫波关注,每天都在更新自己之前的积累] 文章链接:https://mp.weixin.qq.com/s/OebxnvwjQiVbBZZFL2Un3A 前言 信息抽 ...

  2. 零基础入门--中文实体关系抽取(BiLSTM+attention,含代码)

    前面写过一片实体抽取的入门,实体关系抽取就是在实体抽取的基础上,找出两个实体之间的关系. 本文使用的是BiLSTM+attention模型,代码在这里,不定期对代码进行修改添加优化. 数据处理 其实数 ...

  3. 超级超级详细的实体关系抽取数据预处理代码详解

    超级超级详细的实体关系抽取数据预处理代码详解 由于本人是代码小白,在学习代码过程中会出现很多的问题,所以需要一直记录自己出现的问题以及解决办法. 废话不多说,直接上代码!!! 一.data_proce ...

  4. nlp中的实体关系抽取方法总结

    点击上方,选择星标或置顶,每天给你送干货! 阅读大概需要35分钟 跟随小博主,每天进步一丢丢 来自:知乎 地址:https://zhuanlan.zhihu.com/p/77868938 作者:Jay ...

  5. 阿里云医疗实体关系抽取大赛

    1.本项目是基于阿里云比赛开放的医疗数据集去做的实体关系抽取.下面会从数据的详情,模型的选取,模型的训练,模型的验证和模型的预测去讲述. 2.数据准备阶段 1.数据来源是阿里云医疗大赛,选取的是其中一 ...

  6. 知识图谱-LSTM+CRF人物关系抽取实战

    文章目录 一.引言 二.实践简介 1.数据来源 2.预测类别(7个) 3.框架 4.模型结构 5.项目流程 三.数据标注 四.实战 1.数据预处理 1.1 词典映射 1.2 从训练文件中获取句子和标签 ...

  7. 知识图谱从哪儿来?实体关系抽取的现状和未来

    12月17日晚,2019年清华特奖获得者之一,清华大学自然语言处理实验室大四本科生高天宇,在智源论坛Live第1期,以<实体关系抽取的现状和未来>为主题,与150位观众进行了在线交流.本文 ...

  8. 【每周NLP论文推荐】 掌握实体关系抽取必读的文章

    欢迎来到<每周NLP论文推荐>.在这个专栏里,还是本着有三AI一贯的原则,专注于让大家能够系统性完成学习,所以我们推荐的文章也必定是同一主题的. 实体关系抽取作为信息抽取领域的重要研究课题 ...

  9. 技术动态 | 知识图谱从哪里来:实体关系抽取的现状与未来

    本文作者为:韩旭.高天宇.刘知远.转载自刘知远老师的知乎专栏,文章链接:https://zhuanlan.zhihu.com/p/91762831 最近几年深度学习引发的人工智能浪潮席卷全球,在互联网 ...

最新文章

  1. Keras【Deep Learning With Python】手写数字识别
  2. POJ1149 PIGS(最大流)
  3. Sharding-JDBC(一)简介
  4. windows mobile设置插移动卡没反应_ETC不用时,能不能把卡拔下来
  5. 【学习小记】一般图最大匹配——带花树算法
  6. mysql 命令 _mysql 命令
  7. Xlua中的util脚本中的async_to_sync方法 记录
  8. 安卓教程:提取APK程序里图片资源的方法
  9. java使用DES加密方式,实现对数据的加密解密
  10. VirtualBox虚拟机如何选中“启用嵌套 VT-x/AMD-V”
  11. 1104报表背景知识
  12. PHP之AJAX、POST传值【顶、踩】
  13. 非模式生物KEGG富集分析: clusterProfiler
  14. 计算机nie,聂眉宁-西南石油大学 - 计算机科学学院
  15. 袁老走好,谢谢您!我辈也当自强。
  16. 关于把Excel转换成word的经验
  17. WiFi技术概述:WiFi那些事
  18. WHAT、HOW、WHY
  19. Python软件的下载安装教程
  20. Mac下常用工具软件

热门文章

  1. Java 多态中成员变量与成员属性的特点【复习】
  2. Android --- 百度地图 SDK v3.6.0 以上版本找不到 PoiOverlay 类
  3. 使用element ui 组件的时候,如果使用两个或多个按钮在同一个单元格内,按钮会竖着排列,但是不能够对齐怎么解决?
  4. Failure while trying to resolve exception [org.springframework.http.converter.HttpMessageNotWritabl
  5. 计算机的磁盘地址格式,如何查看电脑硬盘是GPT分区还是MBR分区
  6. 数据中心水环热泵余热回收系统分析与应用
  7. 数据中心能效指标有哪些?怎么计算?
  8. 动力专业节假日保障预案
  9. 为什么vs会输出一个框作为结果_检测与分类专辑 | 对精准目标检测的含不确定性的边界框回归...
  10. Computer:现代计算机操作系统的四大基本特性(并发/共享/虚拟/异步)