在TensorFlow中重新训练冻结的*.pb模型
如何导入冻结的protobuf以使其能够重新训练 我在网上找到的所有方法都需要检查点。有没有办法读取protobuf,从而将内核和偏差常量转换为变量在TensorFlow中重新训练冻结的*.pb模型,tensorflow,Tensorflow,如何导入冻结的protobuf以使其能够重新训练 我在网上找到的所有方法都需要检查点。有没有办法读取protobuf,从而将内核和偏差常量转换为变量 编辑1: 这与以下问题类似: 我看了DeepSpeech,这是在对那个问题的回答中推荐的。他们似乎需要从冻结的模型中初始化。我找不到原因 编辑2:我尝试创建一个新的GraphDef对象,用变量替换内核和偏差: probable_variables=[…]#Conv2D和MatMul的内核和偏差 新的_图形_def=tf.GraphDef() 使
编辑1: 这与以下问题类似: 我看了DeepSpeech,这是在对那个问题的回答中推荐的。他们似乎需要从冻结的模型中初始化。我找不到原因
编辑2:我尝试创建一个新的GraphDef对象,用变量替换内核和偏差:
probable_variables=[…]#Conv2D和MatMul的内核和偏差
新的_图形_def=tf.GraphDef()
使用tf.Session(graph=graph)作为sess:
对于sess.graph_def.node中的n:
如果n.name在或然变量中:
#创建变量op
nn=新建图定义节点添加()
nn.name=n.name
nn.op='VariableV2'
nn.attr['dtype'].CopyFrom(attr_value_pb2.AttrValue(type=dtype))
nn.attr['shape'].CopyFrom(attr_value_pb2.AttrValue(shape=shape))
其他:
nn=新建_model.node.add()
nn.CopyFrom(n)
不确定我是否走对了路。不知道如何在nodededef
对象中设置trainable=True
。您提供的代码片段实际上方向正确:)
步骤1:获取以前可训练变量的名称 最棘手的部分是获取以前可训练变量的名称。希望该模型是使用一些高级框架创建的,比如or——它们将变量很好地包装在
conv2d\u 1/kernel
、densite\u 1/bias
、batch\u normalization/gamma
等内容中
如果您不确定,最有用的方法是可视化图形
#读取图形定义
将tf.gfile.gfile('freezed.pb','rb')作为f:
graph_def=tf.GraphDef()
graph_def.ParseFromString(f.read())
#现在在内存中构建图形并将其可视化
将tf.Graph()作为\u default()作为图形:
tf.import_graph_def(graph_def,name=“prefix”)
writer=tf.summary.FileWriter('out',graph)
writer.close()
。。。带张力板:
$ tensorboard --logdir out/
你自己看看这个图是什么样子,名字是什么
步骤2:用变量替换常量(有趣的部分:D) 你所需要的只是一个叫做的魔法图书馆。现在,假设您已将以前可培训的OP的名称(以前是变量,但现在是常量)存储在
可能变量中(如编辑2中)
注意:记住ops
、张量
和变量之间的区别。Ops是图形的元素,张量是包含Ops结果的缓冲区,变量围绕张量,有3个Ops:assign
(在初始化变量时调用)、read
(由其他Ops调用,例如conv2d
)和(保存值)
注2:graph\u编辑器只能在会话之外运行——不能在线修改任何图形
将numpy导入为np
将tensorflow.contrib.graph_编辑器作为ge导入
#将graphdef加载到内存中,如步骤1所示
图=加载图('freezed.pb')
#为每个常量创建一个变量,注意命名
const_var_name_pairs=[]
对于可能的_变量中的名称:
var_shape=graph.get_tensor_by_name({}:0).format(name)).get_shape()
var_name='{}_a'。格式(名称)
var=tf.get\u变量(name=var\u name,shape=var\u shape,dtype='float32')
const_var_name_pairs.append((name,var_name))
#从现在起,我们将与GraphDef合作
name_to_op=dict([(n.name,n)表示图中的n.as_-graph_-def().node])
#魔术:现在我们交换const的输出并创建变量
对于常量名称,常量变量名称对中的变量名称:
const_op=name_to_op[const_name]
var_reader_op=name_to_op[var_name+'/read']
ge.swap_输出(ge.sgv(const_op)、ge.sgv(var_reader_op))
#现在我们可以安全地创建会话并复制值
sess=tf.Session(graph=graph)
对于常量名称,常量变量名称对中的变量名称:
ts=graph.get\u tensor\u by\u name(“{}:0.”格式(const\u name))
var=tf.get\u变量(var\u名称)
变负荷(ts.eval(sess))
#全部完成!现在,您可以通过可视化来确保一切都是正确的
#并计算一些输入的输出。
PS:此代码未经测试;然而,我最近一直在使用graph\u editor
并经常执行网络手术,所以我认为它应该基本正确:)我已经用测试过的代码验证了@FalconUA的解决方案。需要稍微修改(特别是,我使用get_variable
中的initializer
选项来正确初始化变量)。给你
假设您的冻结模型存储在冻结图.pb
中:
probable_variables=[…]#Conv2D和MatMul的内核和偏差
tf_-graph=load_-pb('freezed_-graph.pb'))
const_var_name_pairs=[]
使用tf_graph.as_default()作为g:
对于可能的_变量中的名称:
tensor=g.get_tensor_by_name(“{}:0.”格式(名称))
使用tf.Session()作为sess:
张量数组=sess.run(张量)
var_shape=tensor.get_shape()
#为每个变量指定一个图中不存在的名称
var_name='{}{u_var'.格式(名称)
#创建由原始常量值初始化的TensorFlow变量。
var=tf.get\u变量(name=var\u name,dtype='float32',shape=var\u shape,\
初始值设定项=tf.常数初始值设定项(张量作为numpy数组))
#我们希望为以后跟踪变量名称。
const_var_name_pairs.append((name,var_name))
#在这一点上,我们向图中添加了一组tf.变量,但它们是
def protobuf_to_checkpoint_conversion(pb_model, ckpt_dir):
graph = tf.Graph()
with graph.as_default():
od_graph_def = tf.GraphDef()
with tf.gfile.GFile(pb_model, 'rb') as fid:
serialized_graph = fid.read()
od_graph_def.ParseFromString(serialized_graph)
tf.import_graph_def(od_graph_def,name='')
image_tensor = graph.get_tensor_by_name('image_tensor:0')
dummy = np.random.random((1, 512, 512, 3))
with graph.as_default():
config = tf.ConfigProto()
with tf.Session(graph=graph, config=config) as sess:
constant_ops = [op for op in graph.get_operations() if op.type == "Const"]
vars_dict = {}
ass = []
for constant_op in constant_ops:
name = constant_op.name
const = constant_op.outputs[0]
shape = const.shape
var = tf.get_variable(name, shape, dtype=const.dtype, initializer=tf.zeros_initializer())
vars_dict[name] = var
print('INFO:Initializing variables')
init = tf.global_variables_initializer()
sess.run(init)
print('INFO: Loading vars')
for constant_op in tqdm(constant_ops):
name = constant_op.name
if 'FeatureExtractor' in name or 'BoxPredictor' in name:
const = constant_op.outputs[0]
shape = const.shape
var = vars_dict[name]
var.load(sess.run(const, feed_dict={image_tensor:dummy}), sess)
saver = tf.train.Saver(var_list=vars_dict)
ckpt_path = os.path.join(ckpt_dir, 'model.ckpt')
saver.save(sess, ckpt_path)
graph = tf.Graph()
with graph.as_default():
od_graph_def = tf.GraphDef()
with tf.gfile.GFile(pb_model, 'rb') as fid:
serialized_graph = fid.read()
od_graph_def.ParseFromString(serialized_graph)
tf.import_graph_def(od_graph_def,name='')
image_tensor = graph.get_tensor_by_name('image_tensor:0')
dummy = np.random.random((1, 512, 512, 3))
with graph.as_default():
config = tf.ConfigProto()
with tf.Session(graph=graph, config=config) as sess:
constant_ops = [op for op in graph.get_operations() if op.type == "Const"]
vars_dict = {}
ass = []
for constant_op in constant_ops:
name = constant_op.name
const = constant_op.outputs[0]
shape = const.shape
var = tf.get_variable(name, shape, dtype=const.dtype, initializer=tf.zeros_initializer())
vars_dict[name] = var
print('INFO:Initializing variables')
init = tf.global_variables_initializer()
sess.run(init)
print('INFO: Loading vars')
for constant_op in tqdm(constant_ops):
name = constant_op.name
if 'FeatureExtractor' in name or 'BoxPredictor' in name:
const = constant_op.outputs[0]
shape = const.shape
var = vars_dict[name]
var.load(sess.run(const, feed_dict={image_tensor:dummy}), sess)
saver = tf.train.Saver(var_list=vars_dict)
ckpt_path = os.path.join(ckpt_dir, 'model.ckpt')
saver.save(sess, ckpt_path)