输入类包括:['question_title', 'question_body', 'answer']
输出类包括:['question_asker_intent_understanding', 'question_body_critical', 'question_conversational',...]
对于输出类都是离散的指标,因此可以直接进行合并。
在使用transformer模型时,需要对文本进行分词和编码,我们需要先下载词库,然后使用预训练好的分词器进行分词生成编码后的句子。这些资源来自于hugging face库。
encode_plus生成的是ids、attention_mask和type_ids。
下一步构建我们的模型:
Model: "model"
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_1 (InputLayer) [(None, 384)] 0 []
input_3 (InputLayer) [(None, 384)] 0 []
input_5 (InputLayer) [(None, 384)] 0 []
input_2 (InputLayer) [(None, 384)] 0 []
input_4 (InputLayer) [(None, 384)] 0 []
input_6 (InputLayer) [(None, 384)] 0 []
tf_bert_model (TFBertModel) TFBaseModelOutputWi 109482240 ['input_1[0][0]',
thPoolingAndCrossAt 'input_3[0][0]',
tentions(last_hidde 'input_5[0][0]',
n_state=(None, 384, 'input_2[0][0]',
768), 'input_4[0][0]',
pooler_output=(Non 'input_6[0][0]']
e, 768),
past_key_values=No
ne, hidden_states=N
one, attentions=Non
e, cross_attentions
=None)
global_average_pooling1d (Glob (None, 768) 0 ['tf_bert_model[0][0]']
alAveragePooling1D)
global_average_pooling1d_1 (Gl (None, 768) 0 ['tf_bert_model[1][0]']
obalAveragePooling1D)
concatenate (Concatenate) (None, 1536) 0 ['global_average_pooling1d[0][0]'
, 'global_average_pooling1d_1[0][
0]']
dropout_37 (Dropout) (None, 1536) 0 ['concatenate[0][0]']
dense (Dense) (None, 30) 46110 ['dropout_37[0][0]']
==================================================================================================
Total params: 109,528,350
Trainable params: 109,528,350
Non-trainable params: 0
__________________________________________________________________________________________________
分开训练两个模型,然后进行合并,三层全连接层,经过bert,两层pooling层,再将QA。
这里使用三层全连接层的作用是值得考虑的,一般来说在cv领域全连接层是在特征图后面进行整合的,对于nlp我们的输入是384维的向量(也可以看成是句子的特征表示),384就是特征,我们做的其实就是特征整合的工作。
然后再输出到我们的bert模型中,我们在构建模型时,对输出的参数进行了调整。
config.output_hidden_states = False
所以,简单介绍一下transformers库:
transformers新版只需要定义三个类:
1.config 可以输入已有的config设置 如:
from transformers import TFBertModel
import tensorflow as tf
config = BertConfig.from_json_file(os.path.join(PATH, "config.json"))
model = TFBertModel.from_pretrained(PATH, config=config)
config包括:
"architectures": [
"BertForMaskedLM"
],
"attention_probs_dropout_prob": 0.1,
"hidden_act": "gelu",
"hidden_dropout_prob": 0.1,
"hidden_size": 768,
"initializer_range": 0.02,
"intermediate_size": 3072,
"max_position_embeddings": 512,
"num_attention_heads": 12,
"num_hidden_layers": 12,
"type_vocab_size": 2,
"vocab_size": 30522
- 通用参数
- vocab_size:词汇数,默认30522
- hidden_size:编码器内隐藏层神经元数量,默认768
- num_hidden_layers:编码器内隐藏层层数,默认12
- num_attention_heads:编码器内注意力头数,默认12
- 其他参数
- intermediate_size:编码器内全连接层的输入维度,默认3072
- hidden_act:编码器内激活函数,默认"gelu",还可为"relu"、"swish"或 "gelu_new"
- hidden_dropout_prob:词嵌入层或编码器的 dropout,默认为0.1
- attention_probs_dropout_prob:注意力机制的 dropout,默认为0.1
其中比较重要的
- output_attentions:是否返回中间每层的 attention 输出;
- output_hidden_states:是否返回中间每层的输出;
- return_dict:是否按键值对的形式(ModelOutput 类,也可以当作 tuple 用)返回输出,默认为真。
bert_model输出的有两种形式,包括last_hidden_state 顶层输出,还有顶层经过poolout的输出。
最后我们导入我们keras的五折优化,就可以开始model.fit啦 不过gpu3060 还是不太行只能1个batch一个batch的抓数据
第一个batch validation的结果为0.3905
一个在其他方面有意思的做法是将一些层赋予注意力代替dropout 我们需要将输出的state设为True 让模型输出每一层的输出,然后选取靠近上层的几层,简单进行相加,再初始化一个attention矩阵增加参数进行训练,效果没有提升。
值得注意的是损失函数的设置没有使用mse,binary cross entropy的效果更好。