本文主要介紹如果使用huggingface的transformers 2.0 進行NLP的模型訓練
除了transformers,其它兼容tf2.0的bert項目還有:
我的博客裏有介紹使用方法 [深度學習] 自然語言處理--- 基於Keras Bert使用(上)
- keras-bert(Star:1.4k) 支持tf2,但它只支持bert一種預訓練模型
-
bert4keras (Star:692)支持tf2,bert/roberta/albert的預訓練權重進行finetune
- bert-for-tf2(Star:329)只給了tf2.0 pipeline示例
huggingface的transformers也發佈了transformers2.0,開始支持tf.2.0的各個預訓練模型,雖然沒有對pytorch支持的那麼全面但在我們的場景已經足夠適用了。
一 加載google原始預訓練Bert模型
1、先將原始google預訓練的模型文件轉換成pytorch格式
這個命令在安裝transformers時會回到環境變量中。
python convert_bert_original_tf_checkpoint_to_pytorch.py -h
python convert_bert_original_tf_checkpoint_to_pytorch.py \
--tf_checkpoint_path Models/chinese_L-12_H-768_A-12/bert_model.ckpt.index \
--bert_config_file Models/chinese_L-12_H-768_A-12/bert_config.json \
--pytorch_dump_path Models/chinese_L-12_H-768_A-12/pytorch_model.bin
output:
INFO:transformers.modeling_bert:Converting TensorFlow checkpoint from /home/work/Bert/Models/chinese_L-12_H-768_A-12/bert_model.ckpt.index
Save PyTorch model to Models/chinese_L-12_H-768_A-12/pytorch_model.bin
在開源代碼庫下面有好多有關轉換的py文件
2、加載轉換後的模型
import logging
logging.basicConfig(level=logging.INFO)
import tensorflow as tf
print("Tensorflow Version:", tf.__version__)
import torch
print("Pytorch Version:", torch.__version__)
from transformers import *
import os
pretrained_path = 'Models/chinese_L-12_H-768_A-12'
config_path = os.path.join(pretrained_path, 'bert_config.json')
vocab_path = os.path.join(pretrained_path, 'vocab.txt')
# 加載config
config = BertConfig.from_json_file(config_path)
# 加載torch原始模型
bert_model = BertModel.from_pretrained(pretrained_path, config=config)
# 加載tf原始模型
tfbert_model = TFBertModel.from_pretrained(pretrained_path,from_pt=True, config=config)
發現問題:如果加載爲TF2的模型,參數會變少 (請使用 pytorch版本加載轉換後的模型)
3、token編碼inputs
tokenizer = BertTokenizer.from_pretrained(vocab_path)
二 使用Bert模型
構建模型
class BertNerModel(TFBertPreTrainedModel):
def __init__(self, config, *inputs, **kwargs):
super(BERT_NER, self).__init__(config, *inputs, **kwargs)
self.bert_layer = TFBertMainLayer(config, name='bert')
self.bert_layer.trainable = False
self.concat_layer = tf.keras.layers.Concatenate(name='concat_bert')
def call(self, inputs):
outputs = self.bert_layer(inputs)
#將後n層的結果相連
tensor = self.concat_layer(list(outputs[2][-4:]))
這裏給出的是簡要的代碼,可以自行根據任務在bert_layer
之後加入RNN
等
自定義模型的寫法可以參考官方源碼裏的TFBertForSequenceClassification
, 繼承TFBertPreTrainedModel
self.bert_layer(inputs)
的返回值爲tuple
類型:
- 最後1層隱藏層的輸出值,
shape=(batch_size, max_length, hidden_dimention)
[CLS]
對應的輸出值,shape=(batch_size, hidden_dimention)
- 只有設置了
config.output_hidden_states = True
,纔有該值,所有隱藏層的輸出值,返回值類型是list
每個list
裏的值的shape
是(batch_size, max_length, hidden_dimention)
`
模型的初始化
bert_ner_model = BertNerModel.from_pretrained("bert-base-chinese", output_hidden_states=True)
因爲是模型繼承的TFBertPreTrainedModel
因此這裏初始化使用的父類的方式。第一個參數是要加載預訓練好的模型參數
注意事項
- 通過設置:
self.bert.trainable = False
, 模型可以更快收斂,減少訓練時間 - 預測的時候,輸出的數據一定要與
max_length
一致,否則效果完全不可用,猜測可能是我們只給了, 沒有給input_mask
,有看到transformers的源碼,如果不給attention_mask
,默認全是1的 - 通過設置
output_hidden_states=True
, 可以得到隱藏層的結果