当前位置: 首页 > 面试题库 >

替换Tensorflow v2的占位符

章高爽
2023-03-14
问题内容

对于我的项目,我需要将有向图转换为图的张量流实现,就好像它是神经网络一样。在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
2.0一起使用的示例代码。它依赖于可
通过以下方式访问的兼容性APItensorflow.compat.v1,并且需要禁用v2行为。我不知道它的行为是否符合您的预期。如果没有,请向我们提供更多有关您要实现的目标的说明。

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

尽管以上代码段有效,但仍与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()

这里要注意什么?

  • 从更改placeholderkeras.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)


 类似资料:
  • 我一直在尝试通过FieldMailMerge和VariableReplace示例,但似乎无法运行本地测试用例。我基本上试图从一个docx模板文档开始,并让它从一个模板创建x个docx文档,替换变量。 在下面的代码中,试图替换单个变量,但失败了。模板文件中的${}值作为处理的一部分被移除,因此我认为它正在查找它们,而不是出于某种原因替换它们。我明白这可能是由于格式问题,正如示例代码的注释中所解释的那

  • 问题内容: 我的字符串看起来像这样:“您可以在[开始日期+ 30]之前使用促销。” 我需要将占位符替换为实际日期- 这是销售的开始日期加上30天(或其他任何数字)。也可以单独显示而无需添加数字。同样,占位符内的所有多余空格都应被忽略,并且不要使替换失败。 用Java做到这一点的最佳方法是什么?我正在考虑用于查找占位符的正则表达式,但不确定如何执行解析部分。如果只是[开始日期],我将使用该方法,但由

  • 问题内容: 使用pysqlite我正在制定一个程序来处理一些数据。对多个表和列中的相似字段执行相同类型的操作,因此我认为我可以参数化sql语句,如下所示: 我得到的错误不是很有帮助(),但我明白了:Pysqlite不赞赏以这种方式使用占位符。 谁能指出正在发生的事情以及执行上述操作的正确方法? 问题答案: 您根本不能将占位符用于列或表名。我对此没有权威的引用-我只是从尝试过和失败中“知道”这一点。

  • 我的问题的背景是,我试图本地化一些HTML文件,但我不想为每种语言拥有完整的HTML副本,我只想“以Android的方式”做到这一点,并在我的HTML中使用本地化字符串资源。 假设我在一个字符串中有一些HTML,在将HTML发送到WebView之前,应该用字符串资源替换占位符--我如何做到这一点? 和这些字符串资源: 现在,举一个简单的例子,我可以使用string.replace(),但是如果我想

  • 问题内容: 根据文档,我正在这样做 但是Postgres在说 我看不到我与演示代码有很大不同。我正在使用pq。 问题答案: 确切的语法取决于数据库。 用