BERT以Transformer的Encoder为架构,已MLM为模型,在很多领域取得历史性的的突破。这里以Transformers上基于中文语料库上训练的预训练模型bert-base-chinese为模型,以BertForSequenceClassification为下游任务模型,在一个中文数据集上进行语句分类。具体包括如下内容:
 使用BERT的分词库Tokenizer
 可视化BERT注意力权重
 用BERT预训练模型微调下游任务
 训练模型

14.1 背景说明

本章用到预训练模型库Transformers,Transformers为自然语言理解(NLU)和自然语言生成(NLG)提供了最先进的通用架构(BERT、GPT、GPT-2、Transformer-XL、XLNET、XLM、T5等等),其中有超过32个100多种语言的预训练模型并同时支持TensorFlow 2.0和Pythorch1.0两大深度学习框架。可用pip安装Transformers。

1

pip install transformers

Transformers的官网:https://github.com/huggingface
这章使用BERT模型中汉语版本:BERT-Base, Chinese: 包括简体和繁体汉字,共12层,768个隐单元,12个Attention head,110M参数。中文 BERT 的字典大小约有 2.1 万个标识符(tokens),这些预训练模型可以从Transformers官网下载。
使用了可视化工具BertViz,它的安装步骤如下:
1.下载bertviz:
https://github.com/jessevig/bertviz
2.解压到jupyter notebook当前目录下
bertviz-master

14.1.1 查看中文BERT字典里的一些信息

1.导入需要的库
指定使用预训练模型bert-base-chinese。

1

2

3

4

5

6

7

8

import torch

from transformers import BertTokenizer

from IPython.display import clear_output

# 指定繁简中文 BERT-BASE预训练模型

PRETRAINED_MODEL_NAME = "bert-base-chinese"

# 获取预测模型所使用的tokenizer

tokenizer = BertTokenizer.from_pretrained(PRETRAINED_MODEL_NAME)

2. 查看tokenizer的信息

1

2

vocab = tokenizer.vocab

print("字典大小:", len(vocab))

运行结果:
字典大小: 21128
3.查看分词的一些信息

1

2

3

4

5

6

7

8

import random

random_tokens = random.sample(list(vocab), 5)

random_ids = [vocab[t] for t in random_tokens]

print("{0:20}{1:15}".format("token", "index"))

print("-" * 30)

for t, id in zip(random_tokens, random_ids):

print("{0:15}{1:10}".format(t, id))

运行结果:
token index
------------------------------
##san 10978
王 4374
##and 9369
蚀 6008
60 8183

BERT 使用当初 Google NMT 提出的 WordPiece Tokenization ,将本来的 words 拆成更小粒度的 wordpieces,有效处理不在字典里头的词汇 。中文的话大致上就像是 character-level tokenization,而有 ## 前缀的 tokens 即为 wordpieces。
除了一般的wordpieces以外,BERT还有5个特殊tokens:
 [CLS]:在做分类任务时其最后一层的表示.会被视为整个输入序列的表示;
 [SEP]:有两个句子的文本会被串接成一个输入序列,并在两句之间插入这个token作为分割;
 [UNK]:没出现在BERT字典里头的字会被这个token取代;
 [PAD]:zero padding掩码,将长度不一的输入序列补齐方便做batch运算;
 [MASK]:未知掩码,仅在预训练阶段会用到。

14.1.2 使用Tokenizer分割中文语句

让我们利用中文BERT的tokenizer将一个中文句子断词。

1

2

3

4

5

6

7

text = "[CLS] 他移开这[MASK]桌子,就看到他的手表了。"

tokens = tokenizer.tokenize(text)

ids = tokenizer.convert_tokens_to_ids(tokens)

print(text)

print(tokens[:10], '...')

print(ids[:10], '...')

运行结果:
[CLS] 他移开这[MASK]桌子,就看到他的手表了。
['[CLS]', '他', '移', '开', '这', '[MASK]', '桌', '子', ',', '就'] ...
[101, 800, 4919, 2458, 6821, 103, 3430, 2094, 8024, 2218] ...

14.2 可视化BERT注意力权重

现在马上让我们看看给定上面有 [MASK] 的句子,BERT会填入什么字。

14.2.1 BERT对MAKS字的预测

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

"""

导入已训练好的masked语言模型并对有[MASK]的句子做预测

"""

from transformers import BertForMaskedLM

# 除了tokens 以外我们还需要辨別句子的segment ids

tokens_tensor = torch.tensor([ids])  # (1, seq_len)

segments_tensors = torch.zeros_like(tokens_tensor)  # (1, seq_len)

maskedLM_model = BertForMaskedLM.from_pretrained(PRETRAINED_MODEL_NAME)

clear_output()

# 使用masked LM 估计[MASK]位置所代表的实际标识符(token)

maskedLM_model.eval()

with torch.no_grad():

outputs = maskedLM_model(tokens_tensor, segments_tensors)

predictions = outputs[0]

# (1, seq_len, num_hidden_units)

del maskedLM_model

# 将[MASK]位置的概率分布取前k个最有可能的标识符出来

masked_index = 5

k = 3

probs, indices = torch.topk(torch.softmax(predictions[0, masked_index], -1), k)

predicted_tokens = tokenizer.convert_ids_to_tokens(indices.tolist())

# 显示前k个最可能的字。一般取第一个作为预测值

print("輸入 tokens :", tokens[:10], '...')

print('-' * 50)

for i, (t, p) in enumerate(zip(predicted_tokens, probs), 1):

tokens[masked_index] = t

print("Top {} ({:2}%):{}".format(i, int(p.item() * 100), tokens[:10]), '...')

运行结果:
輸入 tokens : ['[CLS]', '他', '移', '开', '这', '[MASK]', '桌', '子', ',', '就'] ...
--------------------------------------------------
Top 1 (83%):['[CLS]', '他', '移', '开', '这', '张', '桌', '子', ',', '就'] ...
Top 2 ( 7%):['[CLS]', '他', '移', '开', '这', '个', '桌', '子', ',', '就'] ...
Top 3 ( 0%):['[CLS]', '他', '移', '开', '这', '间', '桌', '子', ',', '就'] ...

BERT透过关注这桌这两个字,从2万多个wordpieces的可能性中选出"张"作为这个情境下[MASK] token的预测值,效果还是不错的。

14.2.2 导入可视化需要的库

1.导入需要的库

1

2

from transformers import BertTokenizer, BertModel

from bertv_master.bertviz import head_view

2.创建可视化使用html配置函数

1

2

3

4

5

6

# 在 jupyter notebook 显示visualzation

def call_html():

import IPython

display(IPython.core.display.HTML('''<script src="/static/components/requirejs/require.js"></script><script>// <![CDATA[

requirejs.config({ paths: { base: '/static/base', "d3": "https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.8/d3.min", jquery: '//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min', }, });

// ]]></script>'''))

14.2.3 可视化

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

# 記得我们是使用中文 BERT

model_version = 'bert-base-chinese'

model = BertModel.from_pretrained(model_version, output_attentions=True)

tokenizer = BertTokenizer.from_pretrained(model_version)

# 情境 1 的句子

sentence_a = "老爸叫小宏去买酱油,"

sentence_b = "回来慢了就骂他。"

# 得到tokens后输入BERT模型获取注意力权重(attention)

inputs = tokenizer.encode_plus(sentence_a,sentence_b,return_tensors='pt', add_special_tokens=True)

token_type_ids = inputs['token_type_ids']

input_ids = inputs['input_ids']

attention = model(input_ids, token_type_ids=token_type_ids)[-1]

input_id_list = input_ids[0].tolist() # Batch index 0

tokens = tokenizer.convert_ids_to_tokens(input_id_list)

call_html()

# 用BertViz可视化

head_view(attention, tokens)

运行结果:

图14-1 某词对其它词注意力权重示意图
这是BERT第 10 层 Encoder block 其中一个 head 的注意力结果,从改图可以看出,左边的这个他对右边的“宏”字关注度较高。

格式图像发布于2020年9月3日作者feiguyun分类人工智能

发表评论

第14章 用BERT实现中文语句分类相关推荐

  1. 基于BERT做中文文本分类(情感分析)

    Bert: BERT是一种预训练语言表示的方法,这意味着我们在大型文本语料库(例如Wikipedia)上训练通用的"语言理解"模型,然后将该模型用于我们关心的下游NLP任务,BER ...

  2. 电商评论文本情感分类(中文文本分类)(第二部分-Bert)

    电商评论文本情感分类(中文文本分类) 第二部分-Bert部分 第一部分:textcnn部分 本项目包含: 1.中文文本处理 2.中文词云图绘制(在第一部分) 3.中文词嵌入 4.基于textcnn的中 ...

  3. 手把手教 | 使用Bert预训练模型文本分类(内附源码)

    作者:GjZero 标签:Bert, 中文分类, 句子向量 本文约1500字,建议阅读8分钟. 本文从实践入手,带领大家进行Bert的中文文本分类和作为句子向量进行使用的教程. Bert介绍 Bert ...

  4. BERT_中文情感分类操作及代码

    本实验,是用BERT进行中文情感分类,记录了详细操作及完整程序,代码链接,喜欢的话给个star哟(凑不要脸~) 本文参考奇点机智的文章,记录自己在运行BERT中的一些操作. BERT的代码同论文里描述 ...

  5. 读书笔记_代码大全_第14章_组织直线型代码_第15章_使用条件语句

    组织直线型代码 + 使用条件语句 希望我的读书笔试能带你翻过18页的书 http://www.cnblogs.com/jerry19880126/ <代码大全>第14章和第15章的内容比较 ...

  6. 《C Primer Plus》中文第六版 编程练习答案 第五章 运算符、表达式和语句

    C Primer Plus 第5章 运算符.表达式和语句 编程练习答案 ***先说一下关于 i++和 ++i 情况.*** 1.编写一个程序,把用分钟表示的时间转换成用小时和分钟表示的时间.使用#de ...

  7. 如何用Python和BERT做中文文本二元分类?| 程序员硬核评测

    点击上方↑↑↑蓝字关注我们~ 「2019 Python开发者日」全日程揭晓,请扫码咨询 ↑↑↑ 作者 | 王树义 来源 | 王树芝兰(ID:nkwangshuyi) 兴奋 去年, Google 的 B ...

  8. 【书评:Oracle查询优化改写】第14章 结尾章

    [书评:Oracle查询优化改写]第14章 结尾章 一.1  相关参考文章链接 前13章的链接参考相关连接: [书评:Oracle查询优化改写]第一章 http://blog.itpub.net/26 ...

  9. 【机器学习实战】第14章 利用SVD简化数据

    第14章 利用SVD简化数据 SVD 概述 奇异值分解(SVD, Singular Value Decomposition):提取信息的一种方法,可以把 SVD 看成是从噪声数据中抽取相关特征.从生物 ...

最新文章

  1. php数字截取2位小树,数据结构-PHP 二分搜索树的层序遍历(队列实现)
  2. 【组队学习】【25期】Datawhale组队学习内容介绍
  3. 以技术面试官的经验分享毕业生和初级程序员通过面试的技巧(Java后端方向)...
  4. 海康摄像头的二次开发(java)
  5. 求x0时,y=x^3-6x^2+15的极值
  6. eeglab教程系列(17)-DIPFIT对独立成分进行等价偶极子定位
  7. 与癌症作战的 12 家 AI 公司,八仙过海各显神通
  8. 在八十年代末,比尔·盖茨和史蒂夫·巴尔默
  9. qt爬取网页信息_豆瓣TOP250数据爬取
  10. Linux内核系统调用处理过程
  11. 为什么 IEnumerable 没有提供 ForEach ?
  12. Android SDK中tools详解
  13. matlab雷诺曲线,多重网格法求解雷诺方程的MATLAB编程 - 程序语言 - 小木虫 - 学术 科研 互动社区...
  14. UDP协议相关及报文格式
  15. react 路径跳转组件不跳转_Taro 小程序开发大型实战(二):多页面跳转和 Taro UI 组件库...
  16. weka mac安装
  17. python 相关系数(全)
  18. 聊聊故事点背后的故事
  19. 行列式的计算机应用结题报告,行列式计算开题报告(共10篇).doc
  20. python3精简笔记(三)——高级特性

热门文章

  1. DataGridView的使用
  2. 加拿大留学商科好还是计算机科学好,去加拿大读商科专业就是要选择这些才最好!...
  3. c语言位运算符读音,C语言六种位运算符
  4. python大学生信息管理系统_python学生信息管理系统
  5. IDEA上编写hadoop程序(Maven)【笔记自用】
  6. C++基类和派生类的构造函数(一)
  7. opencv画直线,矩形
  8. 不用任何比较判断找出两个数中较大的数
  9. 文巾解题 面试题 03.06. 动物收容所
  10. Flink从入门到精通100篇(二十一)-Apache Flink 与 Apache Hive 的集成