Hexo

凡事预则立,不预则废


  • Home

  • Tags

  • Archives

  • Navigation

  • Search

TensorFlow——计算图管理


整体总结

  • 在 TensorFlow 1.x 里,类型转换是把张量从一种数据类型转换为另一种数据类型的操作,可分为隐式类型转换和显式类型转换
  • 简单总结:
    • TensorFlow 会自动进行类型提升以确保操作数兼容
    • 如果类型不兼容,会抛出错误
    • 使用 tf.cast() 可以手动控制类型转换
    • 布尔类型可以参与数值运算(变成0或1),但建议做显示类型转换

显式类型转换(推荐使用)

  • 若要明确地把一个张量从一种数据类型转换为另一种数据类型,你可以使用 tf.cast 函数,下面是一个显式类型转换的示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import tensorflow.compat.v1 as tf
    tf.disable_v2_behavior()

    # 创建一个整数类型的张量
    a = tf.constant([1, 2, 3], dtype=tf.int32)

    # 显式地将其转换为浮点数类型
    b = tf.cast(a, dtype=tf.float32)

    with tf.Session() as sess:
    result = sess.run(b)
    print("Result:", result)
    print("Data type:", b.dtype)
    • 在这个例子中,借助 tf.cast 函数把 a 从 int32 类型显式转换为 float32 类型
  • 注:在实际使用中,建议尽量采用显式类型转换,这样能让代码的意图更加清晰,也便于调试和维护


隐式类型转换(不建议)

  • 在TensorFlow 1.x中,部分操作会自动进行隐式类型转换。不过,这种转换并非在所有情形下都会发生,并且不同类型之间的运算可能会引发错误。通常,当操作涉及不同数据类型的张量时,TensorFlow会尝试把它们转换为兼容的类型

  • 下面是一个简单的示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    import tensorflow.compat.v1 as tf
    tf.disable_v2_behavior()

    # 创建两个不同类型的张量
    a = tf.constant(2, dtype=tf.int32)
    b = tf.constant(3.0, dtype=tf.float32)

    # 进行加法操作,会发生隐式类型转换
    c = a + b

    with tf.Session() as sess:
    result = sess.run(c)
    print("Result:", result)
    print("Data type:", c.dtype)
    • 在这个例子中,a 是 int32 类型,b 是 float32 类型。在执行加法操作时,TensorFlow 会把 a 隐式转换为 float32 类型,然后再进行计算

隐式类型转换规则

  • 在 TensorFlow 中,不同类型(dtype)的张量或常量相加时,TensorFlow 会尝试自动进行类型转换(type casting),以便使两个操作数的类型兼容。如果类型无法安全地转换,就会抛出错误
  • 自动类型提升 :当两个不同类型的张量或常量相加时,TensorFlow 会根据操作数的类型选择一个更“宽”的类型来存储结果。这种行为类似于 NumPy 的类型提升规则:
    • int32 和 float32 相加,结果会被提升为 float32
    • float32 和 float64 相加,结果会被提升为 float64
  • 不兼容的类型引发错误 :如果两个类型的张量无法安全地转换,TensorFlow 会抛出 TypeError 或类似的错误:
    • string 和 int32 是完全不同的类型,无法直接相加
    • complex64 和 float32 可能需要显式转换
  • 布尔类型的操作(特殊) :布尔类型(bool)在 TensorFlow 中被视为数值类型(True 等价于 1,False 等价于 0),但需要使用显示类型转换
    1
    2
    3
    4
    5
    a = tf.constant(True, dtype=tf.bool)     # bool 类型
    b = tf.constant(2, dtype=tf.int32) # int32 类型
    a = tf.cast(a, dtype=tf.int32) # 如果没有这一行,下面做加法时可能会报类型错误
    result = a + b # 自动将 bool 提升为 int32
    print(result) # 输出: tf.Tensor(3, shape=(), dtype=int32)

TensorFlow——计算图管理


一句话说明

  • 在 TensorFlow 1.x 版本中,tf.Graph() 用于创建一个新的计算图,而会话(tf.Session())则用于执行计算图中的操作
  • 本文将分别给出明确创建图(tf.Graph())和不明确创建图创建会话的示例,并说明它们之间的区别

不明确创建图

  • 当不指定图时,TensorFlow 会使用一个全局默认的计算图。以下是一个简单的示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # 在TensorFlow 2.x中可以通过下面的代码替换 `import tensorflow as tf`,仍可在TensorFlow 2.x环境中使用TensorFlow 1.x
    import tensorflow.compat.v1 as tf
    tf.disable_v2_behavior()

    # 定义操作,使用默认计算图
    a = tf.constant(3.0)
    b = tf.constant(4.0)
    c = tf.add(a, b)

    # 创建会话并执行操作
    with tf.Session() as sess:
    result = sess.run(c)
    print("不使用 tf.Graph() 的结果:", result)
  • 在这个示例中,我们没有显式地创建计算图,TensorFlow 会使用默认的计算图来定义操作 a、b 和 c。然后创建一个会话并在该会话中运行操作 c,最终得到计算结果


明确创建图(使用tf.Graph())

  • 也可以使用 tf.Graph() 函数,创建一个新的独立计算图,并在这个图中定义操作。以下是示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    # 在TensorFlow 2.x中可以通过下面的代码替换 `import tensorflow as tf`,仍可在TensorFlow 2.x环境中使用TensorFlow 1.x
    import tensorflow.compat.v1 as tf
    tf.disable_v2_behavior()

    # 创建一个新的计算图
    graph = tf.Graph()

    # as_default() 只在 with 上下文中生效,退出后默认图会恢复为原来的全局默认图
    with graph.as_default():
    # 在新的计算图中定义操作
    a = tf.constant(5.0)
    b = tf.constant(6.0)
    c = tf.add(a, b)

    # 创建会话并指定使用新的计算图
    with tf.Session(graph=graph) as sess:
    result = sess.run(c)
    print("使用 tf.Graph() 的结果:", result)
  • 在这个示例中,我们做了以下操作:

    • 首先使用 tf.Graph() 创建了一个新的计算图 graph
    • 然后使用 graph.as_default() 上下文管理器,将这个新的计算图设置为默认图,并在其中定义操作 a、b 和 c
    • 最后创建一个会话,并通过 graph=graph 参数指定该会话使用我们创建的新计算图,在会话中运行操作 c 并得到结果

多图管理(TensorFlow 1.x)

  • TensorFlow 1.x中创建和管理多个计算图的示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    import tensorflow as tf

    # 创建第一个计算图
    graph1 = tf.Graph()
    with graph1.as_default():
    # 在图1中定义变量和操作
    a = tf.constant(5, name='a')
    b = tf.constant(3, name='b')
    c = tf.add(a, b, name='sum')

    # 在图1中初始化所有变量
    init1 = tf.global_variables_initializer()

    # 创建第二个计算图
    graph2 = tf.Graph()
    with graph2.as_default():
    # 在图2中定义不同的变量和操作
    x = tf.constant(10, name='x')
    y = tf.constant(4, name='y')
    z = tf.multiply(x, y, name='product')

    # 在图2中初始化所有变量
    init2 = tf.global_variables_initializer()

    # 创建会话执行图1
    with tf.Session(graph=graph1) as sess1:
    sess1.run(init1)
    result1 = sess1.run(c)
    print("图1的结果:", result1) # 输出: 图1的结果: 8

    # 创建会话执行图2
    with tf.Session(graph=graph2) as sess2:
    sess2.run(init2)
    result2 = sess2.run(z)
    print("图2的结果:", result2) # 输出: 图2的结果: 40

多图管理的必要性

  • 隔离性 :不同的图完全隔离,变量和操作不会相互干扰。这在以下场景特别有用:
    • 同时运行多个模型
    • 比较不同模型结构
    • 隔离训练和推理图
  • 资源管理 :每个图有自己的资源集合,可以独立释放,避免内存泄漏
  • 命名空间 :不同图中的操作可以有相同的名称而不会冲突
  • 并行执行 :可以在不同线程中同时运行不同的图(每个线程有自己的会话)
  • 调试 :当出现问题时,可以更容易地定位是哪个图出现了错误

多图管理的最佳实践

  • 使用with graph.as_default():上下文管理器来明确操作属于哪个图
  • 会话(Session)和图(Graph)是一一对应的,需要为每个图创建独立的会话,明确关闭不再需要的会话以释放资源
  • 一般情况可以不用明确创建多个图 ,仅维护一个默认的图即可,更好的做法是在单个图中使用不同的名称作用域(namescope)来组织操作
  • 多线程运行时需要维护不同的图,确保图不会被同时访问(注:不同图的变量命名也可以相同,也就是可以使用相同的代码来定义)
  • 在 TensorFlow 2.x 中,默认启用了即时执行(Eager Execution)模式,不再需要显式地创建计算图和会话

关于图的作用域示例

  • as_default() 只在 with 上下文中生效,退出后默认图会恢复为原来的全局默认图:

    1
    2
    3
    4
    with new_graph.as_default():
    op1 = tf.constant(1) # 属于 new_graph

    op2 = tf.constant(2) # 属于全局默认图(不是 new_graph)
  • 嵌套多个 as_default() 的示例(不建议使用)

    1
    2
    3
    4
    5
    6
    7
    8
    g1 = tf.Graph()
    g2 = tf.Graph()

    with g1.as_default():
    a = tf.constant(1) # 属于 g1

    with g2.as_default():
    b = tf.constant(2) # 属于 g2
  • 通过 tf.get_default_graph() 可以检查当前默认图:

    1
    2
    with new_graph.as_default():
    print(tf.get_default_graph() is new_graph) # 输出 True

新增变量及其初始化

  • 在已经创建session后,依然是可以加入新的变量的,但是需要进行初始化才可以使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    import tensorflow as tf

    var1 = tf.Variable(3, dtype=tf.float32)
    var2 = tf.Variable(5, dtype=tf.float32)
    add_op1 = tf.add(var1, var2)

    sess = tf.Session()

    init_op = tf.global_variables_initializer() # 初始化所有变量
    sess.run(init_op)

    result1 = sess.run(add_op1)
    print("两个变量的和:", result1)

    # 在Session后继续创建变量
    var3 = tf.Variable(7, dtype=tf.float32)
    add_op2 = tf.add(add_op1, var3)

    init_new_var = tf.variables_initializer([var3]) # 初始化新创建的变量
    sess.run(init_new_var)

    result2 = sess.run(add_op2)
    print("三个变量的和:", result2)

    sess.close() # 显式关闭会话

    # 两个变量的和: 8.0
    # 三个变量的和: 15.0
  • 注意:TensorFlow 1.x中,所有变量都需要初始化(因为变量定义操作不会分配内存,只有在初始化后才会分配内存),重复初始化变量会将变量重置为初始化值

1…316317318…352
San Ye

San Ye

Stay Hungry. Stay Foolish.

704 posts
53 tags
© 2026 San Ye
Powered by Hexo
|
Theme — NexT.Gemini v5.1.4