guithub链接:https://github.com/CyberZHG/keras-bert/blob/master/README.zh-CN.md
1.keras Bert是什么: Bert的非官方实现,可以加载预训练好的bert模型进行特征提取和预测
2. keras Bert安装:pip install keras-bert
3. keras Bert使用:
3.1使用官方模型
特征提取中使用官方的预训练模型chinese_L-12_H-768_A-12 可得到和官方工具相同的结果
在预测是可以填补缺失词并预测是否是上下文
3.2分词
Tokenizer类用于分词,包括归一化和英文部分的最大贪心匹配,在CJK字符集内的中文会以单字分割`
from keras_bert import Tokenizer
token_dict = {
'[CLS]': 0,
'[SEP]': 1,
'un': 2,
'##aff': 3,
'##able': 4,
'[UNK]': 5,
}
tokenizer = Tokenizer(token_dict)
print(tokenizer.tokenize('unaffable'))
结果:['[CLS]', 'un', '##aff', '##able', '[SEP]']
# %%
indices, segments = tokenizer.encode(first='unaffable', second='钢', max_len=10)
结果:indices:[0, 2, 3, 4, 1, 5, 1, 0, 0, 0]
segment:[0, 0, 0, 0, 0, 1, 1, 0, 0, 0]
3.3训练和使用
from tensorflow import keras
from keras_bert import get_base_dict, get_model, compile_model, gen_batch_inputs
# 随便的输入样例:
sentence_pairs = [
[['all', 'work', 'and', 'no', 'play'], ['makes', 'jack', 'a', 'dull', 'boy']],
[['from', 'the', 'day', 'forth'], ['my', 'arm', 'changed']],
[['and', 'a', 'voice', 'echoed'], ['power', 'give', 'me', 'more', 'power']],
]
# 构建自定义词典
token_dict = get_base_dict() # 初始化特殊符号,如`[CLS]`
for pairs in sentence_pairs:
for token in pairs[0] + pairs[1]:
if token not in token_dict:
token_dict[token] = len(token_dict)
token_list = list(token_dict.keys()) # Used for selecting a random word
#构建模型
model = get_model(
token_num=len(token_dict),
head_num=5,
transformer_num=12,
embed_dim=25,
feed_forward_dim=100,
seq_len=20,
pos_num=20,
dropout_rate=0.05,
)
compile_model(model)
model.summary()
#训练模型
def _generator():
while True:
yield gen_batch_inputs(
sentence_pairs,
token_dict,
token_list,
seq_len=20,
mask_rate=0.3,
swap_sentence_rate=1.0,
)
model.fit_generator(
generator=_generator(),
steps_per_epoch=1000,
epochs=100,
validation_data=_generator(),
validation_steps=100,
callbacks=[
keras.callbacks.EarlyStopping(monitor='val_loss', patience=5)
],
)
# 使用训练好的模型
inputs, output_layer = get_model(
token_num=len(token_dict),
head_num=5,
transformer_num=12,
embed_dim=25,
feed_forward_dim=100,
seq_len=20,
pos_num=20,
dropout_rate=0.05,
training=False, # 当`training`是`False`,返回值是输入和输出
trainable=False, # 模型是否可训练,默认值和`training`相同
output_layer_num=4, # 最后几层的输出将合并在一起作为最终的输出,只有当`training`是`False`有效
)
3.4关于traning和trainable
training=True:完整的bert模型会被返回
training=False: 返回输出层和合并最后几层的输出
trainable=True: 加载的层可训练
trainable=False: 加载的层不可训练
3.5使用WarmUp
提供optimizer和decay,比如Adamwarmup
3.6关于输入
在training为True的情况下,输入包含三项:token下标、segment下标、被masked的词的模版。
当training为False时输入只包含前两项。
位置下标由于是固定的,会在模型内部生成,不需要手动再输入一遍。被masked的词的模版在输入被masked的词是值为1,否则为0。
3.7下载预训练模型
3.8提取特征
如果不需要微调,使用extract_embeddings即可
#提取句子中每个词的全部特征
from keras_bert imort extract_embeddings
model_path=''
texts = ['all work and no play', 'makes jack a dull boy~']
embeddings = extract_embeddings(model_path,texts)
#返回的结果是一个list,长度和输入文本的个数相同,每个元素都是numpy的数组,默认会根据输出的长度进行裁剪
#如果输入是成对的句子,想使用最后4层特征,且提取NSP位输出和max-pooling的结果,则可以用
from keras_bert import extract_embeddings, POOL_NSP, POOL_MAX
model_path = 'xxx/yyy/uncased_L-12_H-768_A-12'
texts = [
('all work and no play', 'makes jack a dull boy'),
('makes jack a dull boy', 'all work and no play'),
]
embeddings = extract_embeddings(model_path, texts, output_layer_num=4, poolings=[POOL_NSP, POOL_MAX])
#输出结果中不再包含词的特征,NSP和max-pooling的输出会拼接在一起,每个numpy数组的大小为(768 x 4 x 2,)
#第二个参数接受的是一个generator,如果想读取文件并生成特征,可以用下面的方法:
import codecs
from keras_bert import extract_embeddings
model_path = 'xxx/yyy/uncased_L-12_H-768_A-12'
with codecs.open('xxx.txt', 'r', 'utf8') as reader:
texts = map(lambda x: x.strip(), reader)
embeddings = extract_embeddings(model_path, texts)
3.9模型存储与加载
from keras_bert import load_trained_model_from_checkpoint, get_custom_objects
model = load_trained_model_from_checkpoint('xxx', 'yyy')
model.save('save_path.h5')
model.load('save_path.h5', custom_objects=get_custom_objects())