这是利用bert生成字向量的完整代码
import torch
import numpy as np
from pytorch_pretrained_bert import BertTokenizer, BertModel, BertForMaskedLM
# Load pre-trained model tokenizer (vocabulary)
# tokenizer = BertTokenizer.from_pretrained('F:\\Code\\Bert-Pre-Pytorch\\bert-base-chinese')
def pad_and_truncate(sequence, maxlen, dtype='int64', padding='post', truncating='post', value=0):
x = (np.ones(maxlen) * value).astype(dtype)
if truncating == 'pre':
trunc = sequence[-maxlen:]
else:
trunc = sequence[:maxlen]
trunc = np.asarray(trunc, dtype=dtype)
if padding == 'post':
x[:len(trunc)] = trunc
else:
x[-len(trunc):] = trunc
return x
class Tokenizer4Bert:
def __init__(self, max_seq_len, pretrained_bert_name):
self.tokenizer = BertTokenizer.from_pretrained(pretrained_bert_name)
self.max_seq_len = max_seq_len
def text_to_sequence(self, text, reverse=False, padding='post', truncating='post'):
sequence = self.tokenizer.convert_tokens_to_ids(self.tokenizer.tokenize(text))
if len(sequence) == 0:
sequence = [0]
if reverse:
sequence = sequence[::-1]
return pad_and_truncate(sequence, self.max_seq_len, padding=padding, truncating=truncating)
max_seq_len =18
pretrained_bert_name = "F:\\Code\\Bert-Pre-Pytorch\\bert-base-chinese"
tokenizer = Tokenizer4Bert(max_seq_len,pretrained_bert_name)
text = "[CLS] Who was Jim Henson are you ? [SEP] Jim Henson was a good puppeteer [SEP]"
wenben_one = "你在干什么呢?"
wenben_two = "我好想你呀"
# textone = "[CLS]"+ wenben+ [SEP] 我好想你呀 [SEP]"
textall = "[CLS]" + wenben_one + "[SEP]" + wenben_two + "[SEP]"
model = BertModel.from_pretrained('F:\\Code\\Bert-Pre-Pytorch\\bert-base-chinese')
wenbenALL_indices = tokenizer.text_to_sequence(textall)
# 将第一个转换成编号
wenben_one_indices = tokenizer.text_to_sequence(wenben_one)
wenben_one_len = np.sum(wenben_one_indices != 0)
# 将第二个转换成编号
wenben_two_indices = tokenizer.text_to_sequence(wenben_two)
wenben_two_len = np.sum(wenben_two_indices != 0)
# indexed_tokens = tokenizer.convert_tokens_to_ids(wenbenALL_indices)
# text_raw_indices = tokenizer.text_to_sequence(textone) # 词和 序号一一对应
# 通过这样的一番操作 就可以顺利的拿到 “句子位置编码” 也就是第几个句子 000000000000000 1111111111
# 而 句子编码 表示的句子中每一个字 是多少编号 比如 我爱你,你真可爱 逗号也要计算 0 1 2 3 4 5 6 7
bert_segments_ids = np.asarray([0] * (wenben_one_len + 2) + [1] * (wenben_two_len + 1))
bert_segments_ids = pad_and_truncate(bert_segments_ids, tokenizer.max_seq_len)
# 下面这个是死方法 别人自己直接表示出来的
# segments_ids = [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1]
segments_tensors = torch.tensor([bert_segments_ids])
tokens_tensor = torch.tensor([wenbenALL_indices])
# 主模型最后输出所有的标记表示和整体的序列表示,
# 分别用于针对每个标记的预测任务和针对整个序列的预测任务。
outputs, pooled_outputs = model(tokens_tensor, segments_tensors)
print()
print("这就是输入到LSTM里面去的东西 所谓的编码 batchSize * hiddenSize")
# print(pooled_outputs)
print(len(pooled_outputs))
print(pooled_outputs.size())# 这是cls
print(outputs) # output是list 这是一个装了seqlen
print(len(outputs)) #句子长度
print(outputs[0].size())
print(outputs[1].size())
# 标记编码:[101, 146, 112, 182, 6949, 102, 2508, 1315, 119, 102]
# 位置编码:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# 句子位置编码:[0, 0, 0, 0, 0, 0, 1, 1, 1, 1]
# 注意力掩码:[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
下面是文件路径 还有几点需要注意 请大家仔细观察 bert-base-chinese 这个文件夹里面的内容 词表的文件名字需要进行修改
这个bert-base-chinese文件里面 只需要有我红色方框 框住的几个文件即可 词表的名字必须改成 vocab.txt 否则这个在加载模型的时候 一定会报错 。提示找不到词表路径。