替换 tensorflow v2 的占位符

     2023-02-16     43

关键词:

【中文标题】替换 tensorflow v2 的占位符【英文标题】:Replacing placeholder for tensorflow v2 【发布时间】:2020-03-18 01:07:30 【问题描述】:

对于我的项目,我需要将有向图转换为图的 tensorflow 实现,就好像它是一个神经网络一样。在 tensorflow 版本 1 中,我可以将所有输入定义为占位符,然后使用图的广度优先搜索为输出生成数据流图。然后我会使用 feed_dict 输入我的输入。然而,在 TensorFlow v2.0 中,他们决定完全取消占位符。

如何在不使用占位符的情况下为每个接受可变数量的输入并返回可变数量的输出的图创建一个 tf.function?

我想生成一个像这样适用于任意无环有向图的 tf.function,这样我就可以利用 tensorflow GPU 支持在生成图后连续运行数千次前馈。


编辑代码示例:

我的图表被定义为字典。每个键代表一个节点,并具有另一个字典的对应值,指定传入和传出链接的权重。


    "A": 
        "incoming": [("B", 2), ("C", -1)],
        "outgoing": [("D", 3)]
    

为简洁起见,我省略了 B、C 和 D 的条目。 以下是我将如何在 tensorflow v1.0 中构建我想要的代码,其中输入只是一个严格输入到图形的键值列表

def construct_graph(graph_dict, inputs, outputs):
    queue = inputs[:]
    make_dict = 
    for key, val in graph_dict.items():
        if key in inputs:
            make_dict[key] = tf.placeholder(tf.float32, name=key)
        else:
            make_dict[key] = None
    # Breadth-First search of graph starting from inputs
    while len(queue) != 0:
        cur = graph_dict[queue[0]]
        for outg in cur["outgoing"]:
            if make_dict[outg[0]]: # If discovered node, do add/multiply operation
                make_dict[outg[0]] = tf.add(make_dict[outg[0]], tf.multiply(outg[1], make_dict[queue[0]]))
            else: # If undiscovered node, input is just coming in multiplied and add outgoing to queue
                make_dict[outg[0]] = tf.multiply(make_dict[queue[0]], outg[1])
                for outgo in graph_dict[outg[0]]["outgoing"]:
                    queue.append(outgo[0])
        queue.pop(0)
    # Returns one data graph for each output
    return [make_dict[x] for x in outputs]

然后我可以多次运行输出,因为它们只是带有占位符的图表,我会为其提供 feed_dict。

显然,这不是 TensorFlow v2.0 的预期方式,因为他们似乎强烈反对在这个新版本中使用占位符。

关键是我只需要对图进行一次预处理,因为它返回一个独立于 graph_dict 定义的数据图。

【问题讨论】:

如果没有您尝试做的一些示例,很难找出解决方案。您能否举一个“接受可变数量的输入并返回可变数量的输出”的函数示例,您无法将其转换为 TF 2.0 tf.function @jdehesa 添加了代码示例。 @OmerEldar,inputsoutputs 中有什么? 如果您可以包含一个示例图,例如graph_dictinputsoutputs,将会很有帮助。 【参考方案1】:

让您的代码与 TF 2.0 一起工作

以下是可用于 TF 2.0 的示例代码。 它依赖于compatibility API 可以通过tensorflow.compat.v1 访问,并且需要disable v2 behaviors。 我不知道它的行为是否符合您的预期。 如果没有,请向我们提供更多关于您尝试实现的目标的说明。

import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()

@tf.function
def construct_graph(graph_dict, inputs, outputs):
    queue = inputs[:]
    make_dict = 
    for key, val in graph_dict.items():
        if key in inputs:
            make_dict[key] = tf.placeholder(tf.float32, name=key)
        else:
            make_dict[key] = None
    # Breadth-First search of graph starting from inputs
    while len(queue) != 0:
        cur = graph_dict[queue[0]]
        for outg in cur["outgoing"]:
            if make_dict[outg[0]]: # If discovered node, do add/multiply operation
                make_dict[outg[0]] = tf.add(make_dict[outg[0]], tf.multiply(outg[1], make_dict[queue[0]]))
            else: # If undiscovered node, input is just coming in multiplied and add outgoing to queue
                make_dict[outg[0]] = tf.multiply(make_dict[queue[0]], outg[1])
                for outgo in graph_dict[outg[0]]["outgoing"]:
                    queue.append(outgo[0])
        queue.pop(0)
    # Returns one data graph for each output
    return [make_dict[x] for x in outputs]

def main():
    graph_def = 
        "B": 
            "incoming": [],
            "outgoing": [("A", 1.0)]
        ,
        "C": 
            "incoming": [],
            "outgoing": [("A", 1.0)]
        ,
        "A": 
            "incoming": [("B", 2.0), ("C", -1.0)],
            "outgoing": [("D", 3.0)]
        ,
        "D": 
            "incoming": [("A", 2.0)],
            "outgoing": []
        
    
    outputs = construct_graph(graph_def, ["B", "C"], ["A"])
    print(outputs)

if __name__ == "__main__":
    main()
[<tf.Tensor 'PartitionedCall:0' shape=<unknown> dtype=float32>]

 将您的代码迁移到 TF 2.0

虽然上面的 sn-p 是有效的,但它仍然与 TF 1.0 相关联。 要将其迁移到 TF 2.0,您必须重构一些代码。

我建议您返回一个张量列表,而不是返回一个张量列表,这些张量是 TF 1.0 的可调用对象。 keras.layers.Model.

下面是一个工作示例:

import tensorflow as tf

def construct_graph(graph_dict, inputs, outputs):
    queue = inputs[:]
    make_dict = 
    for key, val in graph_dict.items():
        if key in inputs:
            # Use keras.Input instead of placeholders
            make_dict[key] = tf.keras.Input(name=key, shape=(), dtype=tf.dtypes.float32)
        else:
            make_dict[key] = None
    # Breadth-First search of graph starting from inputs
    while len(queue) != 0:
        cur = graph_dict[queue[0]]
        for outg in cur["outgoing"]:
            if make_dict[outg[0]] is not None: # If discovered node, do add/multiply operation
                make_dict[outg[0]] = tf.keras.layers.add([
                    make_dict[outg[0]],
                    tf.keras.layers.multiply(
                        [[outg[1]], make_dict[queue[0]]],
                    )],
                )
            else: # If undiscovered node, input is just coming in multiplied and add outgoing to queue
                make_dict[outg[0]] = tf.keras.layers.multiply(
                    [make_dict[queue[0]], [outg[1]]]
                )
                for outgo in graph_dict[outg[0]]["outgoing"]:
                    queue.append(outgo[0])
        queue.pop(0)
    # Returns one data graph for each output
    model_inputs = [make_dict[key] for key in inputs]
    model_outputs = [make_dict[key] for key in outputs]
    return [tf.keras.Model(inputs=model_inputs, outputs=o) for o in model_outputs]

def main():
    graph_def = 
        "B": 
            "incoming": [],
            "outgoing": [("A", 1.0)]
        ,
        "C": 
            "incoming": [],
            "outgoing": [("A", 1.0)]
        ,
        "A": 
            "incoming": [("B", 2.0), ("C", -1.0)],
            "outgoing": [("D", 3.0)]
        ,
        "D": 
            "incoming": [("A", 2.0)],
            "outgoing": []
        
    
    outputs = construct_graph(graph_def, ["B", "C"], ["A"])
    print("Builded models:", outputs)
    for o in outputs:
        o.summary(120)
        print("Output:", o((1.0, 1.0)))

if __name__ == "__main__":
    main()

这里要注意什么?

placeholder 更改为keras.Input,需要设置输入的形状。 使用keras.layers.[add|multiply] 进行计算。 这可能不是必需的,但请坚持使用一个界面。 但是,它需要将因子包装在列表中(以处理批处理) 构建 keras.Model 以返回 使用值元组(不再是字典)调用您的模型

这是代码的输出。

Builded models: [<tensorflow.python.keras.engine.training.Model object at 0x7fa0b49f0f50>]
Model: "model"
________________________________________________________________________________________________________________________
Layer (type)                           Output Shape               Param #       Connected to                            
========================================================================================================================
B (InputLayer)                         [(None,)]                  0                                                     
________________________________________________________________________________________________________________________
C (InputLayer)                         [(None,)]                  0                                                     
________________________________________________________________________________________________________________________
tf_op_layer_mul (TensorFlowOpLayer)    [(None,)]                  0             B[0][0]                                 
________________________________________________________________________________________________________________________
tf_op_layer_mul_1 (TensorFlowOpLayer)  [(None,)]                  0             C[0][0]                                 
________________________________________________________________________________________________________________________
add (Add)                              (None,)                    0             tf_op_layer_mul[0][0]                   
                                                                                tf_op_layer_mul_1[0][0]                 
========================================================================================================================
Total params: 0
Trainable params: 0
Non-trainable params: 0
________________________________________________________________________________________________________________________
Output: tf.Tensor([2.], shape=(1,), dtype=float32)

【讨论】:

您的迁移解决方案正是我想要的,我不知道 keras api 对模型构建有如此好的定义。很好的答案。 @Alexis 脚本现在给出了这个错误ValueError: A merge layer should be called on a list of inputs. @Hirak 这适用于 TF 2.0。从那时起,也许一些 API 发生了变化。就这一行错误,很难说是哪里出了问题,但我认为与迁移过程无关。 @AlexisBRENON 感谢您的回复,这是 ipynb 的链接,错误为 colab.research.google.com/drive/… @AlexisBRENON 仅供参考,如果其他人在执行此更正时遇到同样的错误:outg[1]K.constant([outg[1]]) 将修复错误。

TensorFlow 占位符依赖于其他占位符

】TensorFlow占位符依赖于其他占位符【英文标题】:Tesorflowplaceholderdependsonotherplaceholder【发布时间】:2017-10-1214:40:10【问题描述】:我有一个占位符,其形状取决于另一个占位符。在占位符初始化期间如何连接它们?nUsers=tf.placeho... 查看详情

TensorFlow 类占位符,以及其他定义输入张量的方法

】TensorFlow类占位符,以及其他定义输入张量的方法【英文标题】:TensorFlowclassPlaceholder,andotherwaystodefineinputtensor【发布时间】:2019-10-0521:11:38【问题描述】:尝试将TensorFlow程序从Python转换为C++,在最新的文档1.12和1.3中没有发现... 查看详情

Keras 输入层和 TensorFlow 占位符之间的区别

】Keras输入层和TensorFlow占位符之间的区别【英文标题】:DifferenceBetweenKerasInputLayerandTensorflowPlaceholders【发布时间】:2017-11-2504:07:12【问题描述】:我希望有人能解释Keras中的输入层和Tensorflow中的占位符之间的区别(如果有的话)... 查看详情

Tensorflow:在占位符中引入不同大小的矩阵

】Tensorflow:在占位符中引入不同大小的矩阵【英文标题】:Tensorflow:introducingamatrixofdifferentsizeinaplaceholder【发布时间】:2016-10-0208:06:33【问题描述】:我正在尝试使用矩阵乘法的张量流进行简单的操作,但我必须使用其列的可变... 查看详情

Tensorflow - 按批次索引对占位符进行分组

】Tensorflow-按批次索引对占位符进行分组【英文标题】:Tensorflow-Groupingplaceholdersbybatchindex【发布时间】:2018-05-1419:19:04【问题描述】:给定一个具有两个或多个不同维度的占位符的网络,例如x1=tf.placeholder(tf.int32,[None,seq_len])x2=tf.... 查看详情

TensorFlow 中 LSTM-RNN 参数的占位符

】TensorFlow中LSTM-RNN参数的占位符【英文标题】:PlaceholdersforLSTM-RNNparametersinTensorFlow【发布时间】:2016-10-0114:02:27【问题描述】:我想在基于LSTM的RNN中使用占位符来表示丢失率、隐藏单元数和层数。以下是我目前正在尝试的代码... 查看详情

尝试填充占位符时出现Tensorflow错误

】尝试填充占位符时出现Tensorflow错误【英文标题】:Tensorflowerrorwhiletryingtofillaplaceholder【发布时间】:2017-11-1211:06:31【问题描述】:我正在使用mnist数据进行练习,但由于此错误,我无法输入占位符:ValueError:Cannotfeedvalueofshape(20,... 查看详情

TensorFlow,“‘模块’对象没有属性‘占位符’”

】TensorFlow,“‘模块’对象没有属性‘占位符’”【英文标题】:TensorFlow,"\'module\'objecthasnoattribute\'placeholder\'"【发布时间】:2016-09-1921:50:49【问题描述】:我已经尝试使用tensorflow两天了,现在在python2.7和3.4中一遍又一... 查看详情

训练后用占位符交换 TensorFlow 数据集输入管道

】训练后用占位符交换TensorFlow数据集输入管道【英文标题】:SwapaTensorFlowDatasetinputpipelinewithaplaceholderaftertraining【发布时间】:2018-09-1318:27:40【问题描述】:我正在使用新的tf.data.DatasetAPI,但我似乎无法弄清楚如何执行推理。最... 查看详情

使用稀疏张量为 TensorFlow 中的 softmax 层提供占位符

】使用稀疏张量为TensorFlow中的softmax层提供占位符【英文标题】:UsingSparseTensorstofeedaplaceholderforasoftmaxlayerinTensorFlow【发布时间】:2016-02-2806:30:11【问题描述】:有没有人尝试过使用稀疏张量和TensorFlow进行文本分析并取得成功?... 查看详情

馈送占位符时的TensorFlow InvalidArgumentError

】馈送占位符时的TensorFlowInvalidArgumentError【英文标题】:TensorFlowInvalidArgumentErrorwhenfeedingaplaceholder【发布时间】:2018-02-0215:39:05【问题描述】:我有这个占位符:__y=tf.placeholder(tf.int32)然后我在下面的代码中使用它:self.session.run(t... 查看详情

java中属性中的动态占位符替换

】java中属性中的动态占位符替换【英文标题】:DynamicPlaceholdersubstitutioninpropertiesinjava【发布时间】:2011-01-1310:05:06【问题描述】:我想在java应用程序的属性中动态替换占位符。喜欢WelcomeMessage=WelcomeMr.firstNamelastName!!!这些firstName... 查看详情

使用 CNN 和 LSTM 在 Tensorflow 中占位符大小和类型的错误

】使用CNN和LSTM在Tensorflow中占位符大小和类型的错误【英文标题】:ErrorinPlaceholdersizeandtypeinTensorflowusingCNNandLSTM【发布时间】:2018-10-3102:25:12【问题描述】:我使用这段代码结合了CNN和LSTM:from__future__importabsolute_importfrom__future__imp... 查看详情

用 PHP 替换多个占位符?

】用PHP替换多个占位符?【英文标题】:ReplacemultipleplaceholderswithPHP?【发布时间】:2012-04-2318:21:13【问题描述】:我有一个发送站点电子邮件的功能(使用phpmailer),我想要做的基本上是让php用我提供的内容替换email.tpl文件中的... 查看详情

如何替换文本文件中的 $ 占位符?

】如何替换文本文件中的$占位符?【英文标题】:Howtoreplace$placeholdersinatextfile?如何替换文本文件中的$占位符?【发布时间】:2010-09-2918:19:21【问题描述】:我想将“模板”文件的输出通过管道传输到MySQL,该文件中散布着像$dbN... 查看详情

tensorflow入门----占位符常量和session

安装好TensorFlow之后,开一个python环境,就可以开始运行和使用TensorFlow了。先给一个实例,#先导入TensorFlowimporttensorflowastf#CreateTensorFlowobjectcalledhello_constanthello_constant=tf.constant(‘HelloWorld!‘)withtf.Session()assess:#R 查看详情

用动态数据替换占位符

】用动态数据替换占位符【英文标题】:replaceplaceholderwithdynamicdata【发布时间】:2018-04-2319:25:00【问题描述】:是否有使用XSL或java.text.MessageFormat实现以下目标的通用方法?【问题讨论】:【参考方案1】:如果您输入的XML如下:... 查看详情

java实现json参数占位符名称替换指定的多个变量值(代码片段)

前言Java实现占位符名称替换值占位符现在应该说是比较流行的动态赋值,本文主要介绍了Java占位符名称替换值,根据一串带着参数名占位符的url,替换掉对应参数名的值问题1如果有这样一个字符串Stringinfo="我... 查看详情