bert tensorflow2 serving部署

使用tensorflow2 加载预训练的bert模型进行部署

1 模型准备

1.1 下载预训练的bert模型

本次使用的模型是谷歌提供的预训练模型
bert-case-chinese

1.2 安装transform

安装transform 包,用于加载bert模型

2 模型训练及保存

模型训练:(完整代码见最后)
1)将模型修改为计算图格式,使用tf.function(model.call)

# model initialization
model = TFBertForSequenceClassification.from_pretrained(model_path, num_labels=num_classes)
# 修改为计算图函数
callback=tf.function(model.call)

2)通过调用get_concrete_function设置模型输入参数

#设置模型的输入参数
concrete_function =callback.get_concrete_function([tf.TensorSpec([None, 50], tf.int32, name="input_ids"),
                                tf.TensorSpec([None, 50], tf.int32, name="attention_mask"),
                                                   tf.TensorSpec([None, 50], tf.int32, name="token_type_ids")])
  1. 模型保存,并设置signatures
#模型保存,并设置signatures                                                  
 tf.saved_model.save(model, './tfsevingmodel/', signatures=concrete_function)

print(model.summary())
  1. 查看模型保存情况
 python D:\pythonapp\anacondas\envs\torchenv\Lib\site-packages\tensorflow\python\tools\saved_model_cli.py show --dir tfsevingmodel --all 

输出如下所示

signature_def['serving_default']:
  The given SavedModel SignatureDef contains the following input(s):
    inputs['attention_mask'] tensor_info:
        dtype: DT_INT32
        shape: (-1, 50)
        name: serving_default_attention_mask:0
    inputs['input_ids'] tensor_info:
        dtype: DT_INT32
        shape: (-1, 50)
        name: serving_default_input_ids:0
    inputs['token_type_ids'] tensor_info:
        dtype: DT_INT32
        shape: (-1, 50)
        name: serving_default_token_type_ids:0
  The given SavedModel SignatureDef contains the following output(s):
    outputs['logits'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 10)
        name: StatefulPartitionedCall:0
  Method name is: tensorflow/serving/predict

3 模型部署服务

1 docker 拉取tfserving 镜像。
docker pull tensorflow/serving

2 将上面保存的模型放到某个目录下
我是在windows下训练的模型,将保存在model路径下的模型 放在了/opt/tfserving下。

3 . 构建模型和tserving 的链接,启动服务。

docker run -p 8501:8501 --mount type=bind,source=/opt/tfserving/model/,target=/models/model -e MODEL_NAME=model -t tensorflow/serving
1
4 模型提供的服务请求默认为 http://localhost:8501/v1/models/model:predict

4 模型部署 http请求推理

1 curl 请求

curl -H "Content-Type: application/json" -X POST -d "{\"signature_name\": \"serving_default\",\"instances\":[{\"input_ids\": [1,1159,1100,914,7218,2564,704,1068,3333,4178,7305,4324,3227,5011,6381,3315,3017,5384,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"attention_mask\": [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"token_type_ids\": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}] }"   http://192.168.10.100:8501/v1/models/model:predict

返回结过如下
{
“predictions”: [[-2.01432037, -1.96287441, -2.01508093, -0.15862219, 10.0372896, -0.712031305, -1.18103349, -1.21998453, -0.111421183, -1.34767079]
]
}

2 http 请求推理


tokenizer = BertTokenizer.from_pretrained(model_path )
headers = {"content-type": "application/json"}
def predict(text):
    input_dict = tokenizer(text, return_tensors='tf',max_length=max_length,padding  ='max_length')
    input_ids = input_dict["input_ids"].numpy().tolist()[0]
    attention_mask = input_dict["attention_mask"].numpy().tolist()[0]
    token_type_ids = input_data["token_type_ids"].numpy().tolist()[0]

    features = [{'input_ids': input_ids, 'attention_mask': attention_mask,'token_type_ids':token_type_ids}]

    data = json.dumps({ "signature_name": "serving_default", "instances": features})

    json_response = requests.post('http://192.168.10.100:8501/v1/models/model:predict', data=data, headers=headers)

    predictions = json.loads(json_response.text)['predictions']
    return predictions
text = "上海2010上半年四六级考试报名4月8日前完成"
predictions=predict(text)
label_to_index=tf.math.argmax(predictions[0]).numpy()
index_to_label=new_label[label_to_index]
index_to_label
输出 : '教育'

5 完整代码

5.1 模型训练保存


import logging
logging.basicConfig(level=logging.ERROR)
# from transformers import TFBertPreTrainedModel,TFBertMainLayer,BertTokenizer
from transformers import TFBertForSequenceClassification,BertTokenizer
import tensorflow as tf
import pandas as pd
from sklearn.model_selection import train_test_split

def convert_example_to_feature(review):
  
  # combine step for tokenization, WordPiece vector mapping, adding special tokens as well as truncating reviews longer than the max length
	return tokenizer.encode_plus(review, 
	            add_special_tokens = True, # add [CLS], [SEP]
	            max_length = max_length, # max length of the text that can go to BERT
	            pad_to_max_length = True, # add [PAD] tokens
	            return_attention_mask = True, # add attention mask to not focus on pad tokens
		    truncation=True
	          )
# map to the expected input to TFBertForSequenceClassification, see here 
def map_example_to_dict(input_ids, attention_masks, token_type_ids, label):
    return {
      "input_ids": input_ids,
      "token_type_ids": token_type_ids,
      "attention_mask": attention_masks,
  }, label

def encode_examples(ds, limit=-1):
    # prepare list, so that we can build up final TensorFlow dataset from slices.
    input_ids_list = []
    token_type_ids_list = []
    attention_mask_list = []
    label_list = []
    if (limit > 0):
        ds = ds.take(limit)
  
    for index, row in ds.iterrows():
        review = row["text"]
        label = row["y"]
        bert_input = convert_example_to_feature(review)
  
        input_ids_list.append(bert_input['input_ids'])
        token_type_ids_list.append(bert_input['token_type_ids'])
        attention_mask_list.append(bert_input['attention_mask'])
        label_list.append([label])
    return tf.data.Dataset.from_tensor_slices((input_ids_list, attention_mask_list, token_type_ids_list, label_list)).map(map_example_to_dict)



def split_dataset(df):
    train_set, x = train_test_split(df, 
        stratify=df['label'],
        test_size=0.1, 
        random_state=42)
    val_set, test_set = train_test_split(x, 
        stratify=x['label'],
        test_size=0.5, 
        random_state=43)

    return train_set,val_set, test_set
 data_path = "data.txt" # 数据路径
model_path = "./bert-case-chinese/" #模型路径,建议预先下载(https://huggingface.co/bert-base-chinese#)

max_length = 50
batch_size = 30
learning_rate = 2e-5
number_of_epochs = 5
num_classes = 10 # 类别数

# read data
df_raw = pd.read_csv(data_path,sep="\t",header=None,names=["text","label"])
df_label = pd.DataFrame({"label":["财经","房产","股票","教育","科技","社会","时政","体育","游戏","娱乐"],"y":list(range(10))})
new_label=df_label.to_dict()['label']
df_raw = pd.merge(df_raw,df_label,on="label",how="left")
# split data
train_data,val_data, test_data = split_dataset(df_raw)

# tokenizer
tokenizer = BertTokenizer.from_pretrained(model_path)
# train dataset
ds_train_encoded = encode_examples(train_data).shuffle(10000).batch(batch_size)
# val dataset
ds_val_encoded = encode_examples(val_data).batch(batch_size)
# test dataset
ds_test_encoded = encode_examples(test_data).batch(batch_size)
# model initialization
model = TFBertForSequenceClassification.from_pretrained(model_path, num_labels=num_classes)
callback=tf.function(model.call)
model.load_weights("./ckpt/news.ckpt")
concrete_function =callback.get_concrete_function([tf.TensorSpec([None, 50], tf.int32, name="input_ids"),
                                tf.TensorSpec([None, 50], tf.int32, name="attention_mask"),
                                                   tf.TensorSpec([None, 50], tf.int32, name="token_type_ids")])
# tf.saved_model.save(model, './tfsevingmodel/', signatures=concrete_function)

print(model.summary())

5.2 模型部署

docker run -p 8501:8501   --mount type=bind,source=/opt/tfserving/model/,target=/models/model   -e MODEL_NAME=model -t tensorflow/serving

5.2 模型推理

from transformers import BertTokenizer
import tensorflow as tf
import pandas as pd
import json
import requests
model_path = "./bert-case-chinese/"
max_length=50
df_label = pd.DataFrame({"label":["财经","房产","股票","教育","科技","社会","时政","体育","游戏","娱乐"],"y":list(range(10))})
new_label=df_label.to_dict()['label']

tokenizer = BertTokenizer.from_pretrained(model_path )
headers = {"content-type": "application/json"}
def predict(text):
    input_dict = tokenizer(text, return_tensors='tf',max_length=max_length,padding  ='max_length')
    input_ids = input_dict["input_ids"].numpy().tolist()[0]
    attention_mask = input_dict["attention_mask"].numpy().tolist()[0]
    token_type_ids = input_dict["token_type_ids"].numpy().tolist()[0]

    features = [{'input_ids': input_ids, 'attention_mask': attention_mask,'token_type_ids':token_type_ids}]

    data = json.dumps({ "signature_name": "serving_default", "instances": features})

    json_response = requests.post('http://192.168.10.100:8501/v1/models/model:predict', data=data, headers=headers)

    predictions = json.loads(json_response.text)['predictions']
    return predictions
text = "上海2010上半年四六级考试报名4月8日前完成"
predictions=predict(text)
label_to_index=tf.math.argmax(predictions[0]).numpy()
index_to_label=new_label[label_to_index]
index_to_label
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
【资源介绍】 基于Bert预训练模型微调命名实体识别项目python源码+使用说明+模型(支持docker部署).zip 基于Bert(或Robert)预训练模型微调命名实体识别任务,并提供基于docker的Tensor Serving部署模型方案实现过程。 # 1. 数据 人名日报标注语料,具体格式见data目录中txt文件。 # 2. 类别 训练数据使用 BIO 标注方式,总共分为3种实体(person_name-人名、org_name-机构名、location-地名、other-其他) 对应的标签: person_name: B-PER I-PER org_name: B-ORG I-ORG location: B-LOC I-LOC other: O 以及 [CLS] [SEP] X 标签 可在 information.yaml 配置文件中查看。 训练 # 1. 环境 * python 3.6+ * tensorflow 1.9.0+ # 2. 项目结构 ``` bert_ner |________bert # 官方bert代码 |________chinese_L-12_H-768_A-12或roberta_zh_l12: |________checkpoint # 模型固化 |________data # 数据集 |________model # 模型固化PB格式,用于tensor serving部署 |________run_ner.py # 模型运行程序 |________information.yaml # 配置文件 |________infer.py # 预测程序 |________utils_.py # 预测阶段文本处理程序 ``` 运行 不建议使用命令行解析方式修改超参数,在调参过程中需要频繁修改超参数,在文件中修改既方便,也不会出错。 ``` python3 run_ner.py ``` 【备注】 该项目是个人毕设/课设/大作业项目,代码都经过本地调试测试,功能ok才上传,高分作品,可快速上手运行!欢迎下载使用,可用于小白学习、进阶。 该资源主要针对计算机、通信、人工智能、自动化等相关专业的学生、老师或从业者下载使用,亦可作为期末课程设计、课程大作业、毕业设计等。 项目整体具有较高的学习借鉴价值!基础能力强的可以在此基础上修改调整,以实现不同的功能。 欢迎下载使用,也欢迎交流学习!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值