用bert

it2024-10-07  35

在使用keras_bert精调中文albert模型的过程中,发现采用开源的Tokenizer代码,会出现训练过程中张量形状不匹配的问题。 进一步探索,会发现Tokenizer会默认在句子的前后加上’CLS’和’SEP’标识,导致出来的id数目会比设置的maxlen多2个(bert模型自带的机制),因此导致后续定义模型时针对输入张量定义形状时,会出现问题:

class OurTokenizer(Tokenizer): def _tokenize(self, text): R = [] for c in text: if c in self._token_dict: R.append(c) elif self._is_space(c): R.append('[unused1]') # space类用未经训练的[unused1]表示 else: R.append('[UNK]') # 剩余的字符是[UNK] return R bert_params = params_from_pretrained_ckpt(model_dir) bert = BertModelLayer.from_params(bert_params, name="bert") hiddern_output = bert([x1_in, x2_in]) # [batch_size, max_seq_len, hidden_size] hiddern_output = Lambda(lambda x: x[:, 0], name='CLS-token')(hiddern_output) output = Dense(1, activation='sigmoid')(hiddern_output) model = keras.Model(inputs=[x1_in, x2_in], outputs=output) model.build(input_shape=[(None, maxlen), (None, maxlen)])

因此,要针对Tokenizer或者模型输入张量进行微调。 采用前者的方案如下:

class OurTokenizer(Tokenizer): def _tokenize(self, text): R = [] for c in text: if c in self._token_dict: R.append(c) elif self._is_space(c): R.append('[unused1]') # space类用未经训练的[unused1]表示 else: R.append('[UNK]') # 剩余的字符是[UNK] return R[:-2]

采用后者的方案如下:

model.build(input_shape=[(None, maxlen+2), (None, maxlen+2)])

微调后,代码就可以正常运行了,且针对中文文本的NLP任务结果会好于非针对中文的bert base版本。

最新回复(0)