- BERT中文预训练模型:
- BERT模型整体架构基于Transformer模型架构(只使用Transformer中的编码器), BERT中文预训练模型的Transformer编码器具有12层, 输出层中的线性层具有768个节点, 即输出张量最后一维的维度是768. 它使用的多头注意力机制结构中, 头的数量为12, 模型总参数量为110M. 同时, 它在中文简体和繁体上进行训练, 因此适合中文简体和繁体任务.
- BERT中文预训练模型作用:
- 在实际的文本任务处理中, 有些训练语料很难获得, 他们的总体数量和包含的词汇总数都非常少, 不适合用于训练带有Embedding层的模型, 但这些数据中却又蕴含这一些有价值的规律可以被模型挖掘, 在这种情况下,使用预训练模型对原始文本进行编码是非常不错的选择, 因为预训练模型来自大型语料, 能够使得当前文本具有意义, 虽然这些意义可能并不针对某个特定领域, 但是这种缺陷可以使用微调模型来进行弥补.
- 使用BERT中文预训练模型对两个句子进行编码:
import torchimport torch.nn as nn# 使用torch.hub加载bert中文模型的字映射器tokenizer = torch.hub.load('huggingface/pytorch-transformers', 'tokenizer', 'bert-base-chinese')# 使用torch.hub加载bert中文模型model = torch.hub.load('huggingface/pytorch-transformers', 'model', 'bert-base-chinese')def get_bert_encode(text_1, text_2, mark=102, max_len=10):"""description: 使用bert中文模型对输入的文本对进行编码:param text_1: 代表输入的第一句话:param text_2: 代表输入的第二句话:param mark: 分隔标记, 是预训练模型tokenizer本身的标记符号, 当输入是两个文本时,得到的index_tokens会以102进行分隔:param max_len: 文本的允许最大长度, 也是文本的规范长度即大于该长度要被截断, 小于该长度要进行0补齐:return 输入文本的bert编码"""# 使用tokenizer的encode方法对输入的两句文本进行字映射.indexed_tokens = tokenizer.encode(text_1, text_2)# 准备对映射后的文本进行规范长度处理即大于该长度要被截断, 小于该长度要进行0补齐# 所以需要先找到分隔标记的索引位置k = indexed_tokens.index(mark)# 首先对第一句话进行长度规范因此将indexed_tokens截取到[:k]判断if len(indexed_tokens[:k]) >= max_len:# 如果大于max_len, 则进行截断indexed_tokens_1 = indexed_tokens[:max_len]else:# 否则使用[0]进行补齐, 补齐的0的个数就是max_len-len(indexed_tokens[:k])indexed_tokens_1 = indexed_tokens[:k] + (max_len-len(indexed_tokens[:k]))*[0]# 同理下面是对第二句话进行规范长度处理, 因此截取[k:]if len(indexed_tokens[k:]) >= max_len:# 如果大于max_len, 则进行截断indexed_tokens_2 = indexed_tokens[k:k+max_len]else:# 否则使用[0]进行补齐, 补齐的0的个数就是max_len-len(indexed_tokens[:k])indexed_tokens_2 = indexed_tokens[k:] + (max_len-len(indexed_tokens[k:]))*[0]# 最后将处理后的indexed_tokens_1和indexed_tokens_2再进行相加indexed_tokens = indexed_tokens_1 + indexed_tokens_2# 为了让模型在编码时能够更好的区分这两句话, 我们可以使用分隔ids,# 它是一个与indexed_tokens等长的向量, 0元素的位置代表是第一句话# 1元素的位置代表是第二句话, 长度都是max_lensegments_ids = [0]*max_len + [1]*max_len# 将segments_ids和indexed_tokens转换成模型需要的张量形式segments_tensor = torch.tensor([segments_ids])tokens_tensor = torch.tensor([indexed_tokens])# 模型不自动求解梯度with torch.no_grad():# 使用bert model进行编码, 传入参数tokens_tensor和segments_tensor得到encoded_layersencoded_layers, _ = model(tokens_tensor, token_type_ids=segments_tensor)return encoded_layers
- 代码位置: /data/doctor_online/bert_serve/bert_chinese_encode.py
- 输入参数:
text_1 = "人生该如何起头"text_2 = "改变要如何起手"
- 调用:
encoded_layers = get_bert_encode(text_1, text_2)print(encoded_layers)print(encoded_layers.shape)
- 输出效果:
tensor([[[ 1.0210, 0.0659, -0.3472, ..., 0.5131, -0.7699, 0.0202],[-0.1966, 0.2660, 0.3689, ..., -0.0650, -0.2853, -0.1777],[ 0.9295, -0.3890, -0.1026, ..., 1.3917, 0.4692, -0.0851],...,[ 1.4777, 0.7781, -0.4310, ..., 0.7403, 0.2006, -0.1198],[ 0.3867, -0.2031, -0.0721, ..., 1.0050, -0.2479, -0.3525],[ 0.0599, 0.2883, -0.4011, ..., -0.1875, -0.2546, 0.0453]]])torch.Size([1, 20, 768])
- 小节总结:
- 学习了BERT中文预训练模型的有关知识和作用.
- 使用BERT中文预训练模型对句子编码的函数: get_bert_encode
