技术标签: tensorflow 推荐系统 神经网络 知识图谱
1、找到当前模型中定义的variables,并在此定义一个saver用于保存模型参数
def saveVariables(self):
variables_dict = {
}
variables_dict[self.user_embedding.op.name] = self.user_embedding
variables_dict[self.item_embedding.op.name] = self.item_embedding
for v in self.reduce_dimension_layer.variables:
variables_dict[v.op.name] = v
self.saver = tf.train.Saver(variables_dict)
在模型的输入和输出的地方,尽量自行定义name,这样在之后的部署的时候会方便很多!
self.item_input = tf.placeholder("int32", [None, 1],name="gat_iteminput")
self.user_input = tf.placeholder("int32", [None, 1],name="gat_userinput")
...
self.prediction = tf.sigmoid(tf.reduce_sum(self.predict_vector, 1, keepdims=True),name="gat_predict")
2、在需要保存模型参数的地方调用save方法,一般建议在模型取到最高指标处保存模型
#此处的saver为上面模型中定义的saver
#sess即为session;weights_save_path为自定义的文件路径;global_step表示当前为第几次epoch
model.saver.save(sess, weights_save_path + '/weights', global_step=epoch)
3、最终会保存为如下图所示的文件
110、111、112、119、127是最近5次模型指标最高的5次记录,可以根据自己需要选择最高的记录,也可以在self.saver = tf.train.Saver(variables_dict)
这里指定好保存的次数,例如保留最多两次:self.saver = tf.train.Saver(variables_dict,max_to_keep=2)
此处训练中,我得到的最高指标epoch为127,所以我使用127的weights
因为tensorflow serving需要saved_model的格式,所以我们需要将ckpt的格式转成savedModel格式,转换的代码如下:
import tensorflow as tf
#两个参数都是文件夹的名称,一个是ckpt文件所在文件夹,一个是之后导出的文件夹
def restore_and_save(input_checkpoint, export_path):
checkpoint_file = tf.train.latest_checkpoint(input_checkpoint)
graph = tf.Graph()
with graph.as_default():
session_conf = tf.ConfigProto(allow_soft_placement=True, log_device_placement=False)
sess = tf.Session(config=session_conf)
with sess.as_default():
# 载入保存好的meta graph,恢复图中变量,通过SavedModelBuilder保存可部署的模型
saver = tf.train.import_meta_graph("{}.meta".format(checkpoint_file))
saver.restore(sess, checkpoint_file)
print("graph.get_name_scope()=",graph.get_name_scope())
# for node in graph.as_graph_def().node:
# print(node.name)
builder = tf.saved_model.builder.SavedModelBuilder(export_path)
# 建立签名映射,需要包括计算图中的placeholder(ChatInputs, SegInputs, Dropout)和
# 我们需要的结果(project/logits,crf_loss/transitions)
"""
build_tensor_info
建立一个基于提供的参数构造的TensorInfo protocol buffer,
输入:tensorflow graph中的tensor;
输出:基于提供的参数(tensor)构建的包含TensorInfo的protocol buffer
get_operation_by_name
通过name获取checkpoint中保存的变量,能够进行这一步的前提是在模型保存的时候给对应的变量赋予name
"""
user_inputs = tf.saved_model.utils.build_tensor_info(
graph.get_tensor_by_name("gat_userinput:0"))
item_inputs = tf.saved_model.utils.build_tensor_info(
graph.get_tensor_by_name("gat_iteminput:0"))
prediction = tf.saved_model.utils.build_tensor_info(
graph.get_tensor_by_name("gat_predict:0"))
print("user_inputs=",user_inputs)
print("item_inputs=",item_inputs)
print("prediction=",prediction)
sess.run(tf.global_variables_initializer())
sess.run(tf.local_variables_initializer())
"""
signature_constants
SavedModel保存和恢复操作的签名常量。
在序列标注的任务中,这里的method_name是"tensorflow/serving/predict"
"""
# 定义模型的输入输出,建立调用接口与tensor签名之间的映射
labeling_signature = (
tf.saved_model.signature_def_utils.build_signature_def(
inputs={
"user_inputs": user_inputs,
"item_inputs": item_inputs
},
outputs={
"prediction": prediction
},
method_name="tensorflow/serving/predict"
))
"""
tf.group
创建一个将多个操作分组的操作,返回一个可以执行所有输入的操作
"""
# legacy_init_op = tf.group(tf.tables_initializer(), name='legacy_init_op')
"""
add_meta_graph_and_variables
建立一个Saver来保存session中的变量,输出对应的原图的定义,这个函数假设保存的变量已经被初始化;
对于一个SavedModelBuilder,这个API必须被调用一次来保存meta graph;
对于后面添加的图结构,可以使用函数 add_meta_graph()来进行添加
"""
# 建立模型名称与模型签名之间的映射
builder.add_meta_graph_and_variables(
sess, [tf.saved_model.tag_constants.SERVING],
# 保存模型的方法名,与客户端的request.model_spec.signature_name对应
signature_def_map={
tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY:labeling_signature
})
builder.save()
print("Build Done")
# 模型格式转换
restore_and_save("ckpt","saved_model")
最后转换成功后的文件夹目录如下:
下面是一些查看节点和张量的代码:
import tensorflow as tf # from parser_predict import parse_args from tensorflow.python import pywrap_tensorflow from tensorflow.python.framework import graph_util import os def get_pretrain_path(): pretrain_path= "ckpt" print("get_pretrain_path="+str(pretrain_path)) return pretrain_path def get_ckpt_file(): return tf.train.get_checkpoint_state(os.path.dirname(get_pretrain_path() + '/checkpoint')) def get_tensors_name(): ckpt = get_ckpt_file() if ckpt and ckpt.model_checkpoint_path: reader = pywrap_tensorflow.NewCheckpointReader(ckpt.model_checkpoint_path) var_to_shape_map = reader.get_variable_to_shape_map() for key in var_to_shape_map: print('tensor_name: ', key) else: print('wrong path') def get_nodes_name(): ckpt = get_ckpt_file() print("ckpt.model_checkpoint_path="+str(ckpt.model_checkpoint_path)) if ckpt and ckpt.model_checkpoint_path: saver = tf.train.import_meta_graph(ckpt.model_checkpoint_path + '.meta', clear_devices=True) with tf.Session() as sess: saver.restore(sess, ckpt.model_checkpoint_path) graph_def = tf.get_default_graph().as_graph_def(add_shapes=True) node_list = [n.name for n in graph_def.node] for node in node_list: print('node_name: ', node) def get_operations_name(): ckpt = get_ckpt_file() if ckpt and ckpt.model_checkpoint_path: with tf.Session() as sess, open('../log/gat_operation_log', 'w', encoding='utf-8') as log: sess.run(tf.global_variables_initializer()) tf.train.import_meta_graph(ckpt.model_checkpoint_path + '.meta', clear_devices=True) for operation in tf.get_default_graph().get_operations(): log.write(operation.name + '\n') def freeze_graph( pb_file_path): ckpt = get_ckpt_file() if ckpt and ckpt.model_checkpoint_path: saver = tf.train.import_meta_graph(ckpt.model_checkpoint_path + '.meta', clear_devices=True) graph = tf.get_default_graph() input_graph_def = graph.as_graph_def() with tf.Session() as sess: # 恢复图并得到数据 print(sess.run(tf.global_variables_initializer())) print(sess.run(tf.local_variables_initializer())) saver.restore(sess, ckpt.model_checkpoint_path) # 模型持久化,将变量值固定 output_graph_def = graph_util.convert_variables_to_constants( sess=sess, input_graph_def=input_graph_def, output_node_names=['gat_predict']) # 注意是节点名称不是张量名称 # 保存模型 with tf.gfile.GFile(pb_file_path, 'wb') as f: # 序列化输出 f.write(output_graph_def.SerializeToString()) # 得到当前图的操作节点 nodes = output_graph_def.node print('%d ops in the final graph.' % len(nodes)) def load_freeze_graph(pb_file_path): with tf.Session() as sess: graph = load_pb(pb_file_path) # 定义输入的张量名称,对应网络结构的输入张量 input_user_id = graph.get_tensor_by_name('user_embedding') # 定义输出的张量名称 output_tensor_name = graph.get_tensor_by_name('item_embedding') # 测试读出来的模型是否正确 # 注意这里传入的是输出和输入节点的tensor的名字,不是操作节点的名字 out = sess.run(output_tensor_name, feed_dict={ input_user_id: [0]}) print('out:', out) def load_pb(pb_file_path): with tf.gfile.GFile(pb_file_path, "rb") as f: graph_def = tf.GraphDef() graph_def.ParseFromString(f.read()) with tf.Graph().as_default() as graph: tf.import_graph_def(graph_def, name='') return graph if __name__ == '__main__': # get_tensors_name() # get_nodes_name() #freeze_graph('gat.pb') #此处功能不正确,但是可以参考下 # get_operations_name() # load_freeze_graph('gat.pb')#此处功能不正确,但是可以参考下
4、安装好docker,并下载tensorflow serving的镜像
5、编写dockerfile
from:表示使用tensorflow/serving:latest的docker基础镜像
RUN:在镜像变成容器时,可以执行的命令(直接docker run进行/挂载也是一样的,这里为了方便);此处的命令意思为创建文件夹models,并在models下创建gat文件夹,并在gat文件夹下面创建1文件夹
ADD:有两个参数,前一个参数指的是当前机器上的文件夹名称,后一个参数指的是创建出来的容器的文件夹名称。此处的命令意思是将当前机器上的gat(相对路径)文件夹下的所有东西,都复制到docker创建出来的容器中的/models/gat/1/文件夹下
ENV:设置系统变量
from tensorflow/serving:latest
RUN mkdir -p /models/gat/1
ADD gat /models/gat/1/
ENV MODEL_NAME=gat
当前dockerfile文件名称为:GatDockerFile
6、构建镜像
#-f后面跟着dockerfile文件名称;-t后面跟着自定义的创建出来的镜像名称;冒号后面的1.0代表自定义的版本号;最后的那个点号一定要加上
docker build -f GatDockerFile -t gat:1.0 .
构建完成后,会出现下面的提示:
然后使用docker image ls可以看到已经成功构建了镜像:
7、创建容器实例:
#8508:指的是本机的端口号(此处可以更改为其他,只要本机上的这个端口号没有被占用就可以)
#8501:指的是容器中的端口号,因为tensorflow serving是通过8501提供服务的,所以此处最好不要修改
#--name:后面跟着的是自己创建的容器名称,自定义
#-d:指的是后台运行
#gat:1.0是刚才我们创建的镜像名称+版本号
docker run -p 8508:8501 --name gatContainer -d gat:1.0
输入命令后,如果出现一串很长的字符,并且没有报错,则代表创建成功,可以使用docker ps 查看
STATUS为Up… 说明已经启动成功
http://主机ip地址:8508/v1/models/gat
http://主机ip地址:8508/v1/models/gat/metadata
整体格式如下:
细节:
此处就是模型的名称:
此处是模型的输入和输出:
参数名是上面定义的,具体的数据格式如图所示了
可以使用postman进行测试:
http://主机IP地址:8508/v1/models/gat:predict
参考:
整套流程+多模型部署,强烈建议参考这篇:https://blog.csdn.net/tianyunzqs/article/details/103842894
文章浏览阅读1.3k次。1.下载微信小程序安装包下载链接: https://pan.baidu.com/s/1R7Av24IY9vk4i9-H97uTBA 密码: mb5j2.双击程序,点击运行:3.点击下一步:4.选择接受协议:5.选择目标文件夹,点击安装:6.等待系统安装成功:7.完成之后就可以运行了。_小程序需要window如何下载
文章浏览阅读1.9k次,点赞4次,收藏11次。websocket是什么?是一種網路傳輸協定,可在單個TCP連接上進行全雙工通訊,位於OSI模型的應用層。WebSocket協定在2011年由IETF標準化為RFC 6455,後由RFC 7936補充規範。Web IDL中的WebSocket API由W3C標準化。WebSocket使得客戶端和伺服器之間的資料交換變得更加簡單,允許伺服器端主動向客戶端推播資料。在WebSocket API中,瀏覽器和伺服器只需要完成一次交握,兩者之間就可以建立永續性的連接,並進行雙向資料傳輸 ..._uniapp使用webscock如何传token
文章浏览阅读149次。翻到很久以前整理的文档,慢慢把这些东东变成博客文章也不容易弄丢~~接受域是 Microsoft Exchange 为其接受传入邮件的任何 SMTP 域。接受域可以为权威域或中继域。接受域配置为 Exchange 组织和安装了边缘传输服务器的计算机上的全局设置。先决条件: 要创建的接受域的名称不能与已配置的远程域的名称相同。例如,如果已将 fabrikam.com 配置为..._exchange 2010 指向域控服务器
文章浏览阅读252次。N皇后问题Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 27849 Accepted Submission(s): 12359Problem Description在N*N的方格棋盘放置了N个皇后,使得它们不_hdu 2553 n皇后问题java
文章浏览阅读241次。我们在设计Redis架构时,我们会去想一个问题,生产环境如何设计一套高性能、高可用、可扩展的Redis架构?接下来我会带着大家从单机到集群,一步一步演进。01Redis单机版在网站最初时,用户量和并发量都比较小,我们采用SpringBoot + MyBatis + Redis架构,写个单体应用就行,此时Redis我们也采用单机版,系统很快就可以构建起来,并且维护成本低。存在问题:①如果Redis宕..._高性能 高可用面试题
文章浏览阅读2.8k次。环境准备rancherserver的部署部署nginx容器验证部署rancher容器验证k8s节点部署etcd、controller、worker总结证书证书分为服务器证书和CA证书;证书验证过程阿里云ssl证书介绍:nginx环境准备两台linux服务器Ubuntu16.04: rancherserver的部署..._etcd controller worker
文章浏览阅读514次。//重载+号运算符 使其两个矩阵相加//矩阵的输入输出都需要使用for循环 行和列的循环#include<iostream>using namespace std;class mix{public: friend mix operator+(mix&, mix&); void printin(); void printout();private: int arr[2][3];};//输入数据void mix::printin(){ cout <_用重载运算符实现矩阵相加
文章浏览阅读2.2k次。环境空间 ( environment ) 对于刚接触 R 语言的我来说,是比较陌生的。虽然不了解它的运行原理,但也不影响我使用 R 语言。环境空间是 R 语言中关于计算机方面的底层设计,主要用于R语言是环境加载器。通过环境空间,封装了加载器的运行过程,让使用者在不知道底层细节的情况下,可以任意加载使用到的第三方的 R 语言程序包。介绍在R语言中,不管是变量,对象,或者函数,都存在于 R 的环境空间中,R程序在运行时都自己的运行时空间。R 语言的环境 (environment) 是由内核定义的一个数据结构_r environment
文章浏览阅读1.2w次,点赞3次,收藏5次。关于底层知识的学习,汇编当然是绕不过,当你需要调优一小段代码时,你需要看的汇编语言。通过学习汇编语言,你能更清楚明白的了解整个计算机的计算过程,指令相关知识,对学习计算机帮助甚大。目录:第1章 基础知识1.1 机器语言1.2 汇编语言的产生1.3 汇编语言的组成1.4 存储器1.5 指令和数据1.6 存储单元1.7 CPU对存储器的读写1.8 地址总线1.9 数据总线1.10 控制总线1.11 内存地址空间(概述)1.12 主板1.1..._汇编阅读书籍
文章浏览阅读601次。视频太长又不想删减里面的内容,大家一般通常会通过加速的方式,让时间变短,可是在视频数量很多的情况下,该如何快速处理呢?下面随小编一起来试试。所需工具一台电脑视频素材操作步骤在浏览器中搜索【视频剪辑高手】并安装到电脑上,此款软件绿色安全,可以放心使用进入软件,在“剪辑视频”这个版块之中,单击“添加视频”按钮在所弹出的对话框之中,选中这些视频素材,并点打开,即可导入全部视频接着在“设置新视频选项”中,勾选“播放倍速”,先将数值调整为0.5,再去剪辑(数值大于1为慢速,小于1为快速进入“浏览”窗口_如何快进视频缩短时间
文章浏览阅读365次。一、k3s介绍二、k3s部署三、rancher部署四、集群导入rancher_rancher+k3s+云校
文章浏览阅读1.6k次。如何在图形中设置坐标轴刻度matlab(zz)2010-11-01 10:49:18| 分类:默认分类 | 标签:|举报|字号大中小订阅 [转载]Matlab中Tick(坐标轴刻度)的设置及风格x=1:8;subplot(2,2,1)plot(x)%tick style 0(auto)subplot(2,2,2)plot(_evalin字体