- BERT中文预训练模型:
- BERT模型整体架构基于Transformer模型架构(只使用Transformer中的编码器), BERT中文预训练模型的Transformer编码器具有12层, 输出层中的线性层具有768个节点, 即输出张量最后一维的维度是768. 它使用的多头注意力机制结构中, 头的数量为12, 模型总参数量为110M. 同时, 它在中文简体和繁体上进行训练, 因此适合中文简体和繁体任务.
- BERT中文预训练模型作用:
- 在实际的文本任务处理中, 有些训练语料很难获得, 他们的总体数量和包含的词汇总数都非常少, 不适合用于训练带有Embedding层的模型, 但这些数据中却又蕴含这一些有价值的规律可以被模型挖掘, 在这种情况下,使用预训练模型对原始文本进行编码是非常不错的选择, 因为预训练模型来自大型语料, 能够使得当前文本具有意义, 虽然这些意义可能并不针对某个特定领域, 但是这种缺陷可以使用微调模型来进行弥补.
- 使用BERT中文预训练模型对两个句子进行编码:
import torch
import 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_len
segments_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_layers
encoded_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