tflite toco将冻结的PB张量流模型转换为tflite模型错误

时间:2018-09-12 03:37:20

标签: tensorflow tensorflow-lite

在pb模型中,我有一个PRelu层。因为tflite没有PRelu OP,所以我将PRelu转换为Relu就像这样:

 pos = relu(x)
 neg = - alphas * relu(-x)
 return pos + neg

转换为tflite模型时,PRelu将由relu和负OP代替。但是在转换时,两个负数op之间的负数relu op被toco丢弃。转换后的模型如下所示:

pos = relu(x)
neg = -alphas * (-x)
return pos + neg

有什么问题吗?

2 个答案:

答案 0 :(得分:2)

Tensorflow Lite将激活功能与op本身融合在一起,因此Relu ops将被从图中删除。来自documentation的引用(还提到了tf.nn.relu):

  

请注意,其中许多操作没有TensorFlow Lite等效项,并且如果无法消除或融合它们,则相应的模型将无法转换。


让我们看看它的含义。上面使用TensorBoard可视化的TensorFlow中的PReLU代码如下(原始图):

conv --> relu ---------------------\
     \-> neg -> relu -> mul -> neg --> add

但是,由于TfLite将Relu的操作与先前的操作(在docs中有更多的操作)融合在一起,因此 TRY 会进行如下操作(请注意[A+B]AB操作的融合层):

[conv+relu] -----------------------------\
            \-> [neg+relu] -> mul -> neg --> add

但是,由于neg操作(一元减)没有设计上的激活功能,因此TF-Lite中发生的实际情况如下所示(这是我自己在版本上测试的1.9.0):

[conv+relu] ----------------------\
            \-> neg -> mul -> neg --> add

所以,这没有任何意义!


以下是我的个人解决方法(考虑到您已经拥有训练有素的*.pb模型,并且不希望仅因为体系结构已更改而重新训练新模型):

def tflite_tolerant_prelu(_x, alpha, name_scope):
    with tf.name_scope(name_scope):
        alpha = tf.constant(alpha, name='alpha')
        return tf.maximum(_x, 0) + alpha * tf.minimum(_x, 0)

def replace_prelu(graph, prelu_block_name, tensor_before, tensor_after):
    alpha = graph.get_tensor_by_name(os.path.join(prelu_block_name, 'alpha:0'))
    with tf.Session() as sess:
        alpha_val = alpha.eval()
    new_prelu = tflite_tolerant_prelu(tensor_before,
            alpha_val, prelu_block_name + '_new')
    tf.contrib.graph_editor.swap_inputs(tensor_after.op, [new_prelu])

before = mtcnn_graph.get_tensor_by_name('pnet/conv1/BiasAdd:0')
after = mtcnn_graph.get_tensor_by_name('pnet/pool1:0')
replace_prelu(mtcnn_graph, 'pnet/PReLU1', before, after)

此代码用于将MTCNN从TensorFlow传输到TensorFlow Lite。看起来有点丑陋(绝对需要使它看起来更整洁),但是它功能齐全,可以完成工作。请注意,我使用了图形编辑器工具tensorflow.contrib.graph_editor来以离线模式修改图形。

答案 1 :(得分:1)

要简单地解决此问题,请将PRelu更改为 Max(x,0)+ alphas * Min(0,x)