1.7 模块地图与版本脉络 本节摘要:TensorFlow 的子模块各自承包计算图调度中的一段:tf.data 管数据上料,tf.keras 管建模训练,tf.distribute 管多设备分派,tf.function 管图编译,tf.summary 管观测。本节把这张地图画全,并沿 1.x 到 2.x 的版本脉络解释每个模块为何长成今天的形状。学完本节,你遇到任何需求都能立刻定位"该去哪个模块找",也读懂旧代码里版本错位的历史原因。 学习目标 阅读完本节,你应当能够: 说出 tf 的八个子模块各自承包哪条调度线; 对照 1.x 与 2.x 的 API 变迁表,判断一段旧代码需要怎么改写; 根据"数据规模、模型来源、部署目标"三个维度快速定位本教程后文对应的章节。
本节摘要:TensorFlow 的子模块各自承包计算图调度中的一段:tf.data 管数据上料,tf.keras 管建模训练,tf.distribute 管多设备分派,tf.function 管图编译,tf.summary 管观测。本节把这张地图画全,并沿 1.x 到 2.x 的版本脉络解释每个模块为何长成今天的形状。学完本节,你遇到任何需求都能立刻定位"该去哪个模块找",也读懂旧代码里版本错位的历史原因。
阅读完本节,你应当能够:
排程室视角下,一次完整的训练要经过五段:数据进来、模型算前向、梯度回传、参数更新、过程被观测。TensorFlow 的子模块就是按这五段分的工位:
| 子模块 | 承包的调度线 | 本教程章节 |
|---|---|---|
| tf.data | 数据上料:读、变换、批、预取 | 第 2 章 |
| tf.keras | 建模与训练:层、compile、fit | 第 3 章 |
| tf.nn 与各模型层 | 网络结构:卷积、循环、注意力 | 第 4 章 |
| tf.GradientTape 与 tf.function | 图编译与自动求导 | 1.5、第 5 章 |
| tf.distribute | 多设备分派与聚合 | 5.2 |
| tf.saved_model 与部署工具链 | 模型存档与上线 | 3.8、5.3 |
| tf.summary 与 TensorBoard | 过程观测 | 6.1 |
| tfds、tfhub 等扩展包 | 数据集与预训练模型仓库 | 6.2 |
import tensorflow as tf # 用一段代码把五个工位串起来,体会各模块在链路上的位置 dataset = tf.data.Dataset.from_tensor_slices(tf.range(8)).batch(4) # tf.data:上料 model = tf.keras.Sequential([tf.keras.layers.Dense(1)]) # tf.keras:建模 model.compile(optimizer="sgd", loss="mse") # 训练配置 x = tf.random.normal([8, 3]) y = tf.random.normal([8, 1]) model.fit(x, y, epochs=1, verbose=0) # fit 内部:tf.function 编译训练步,GradientTape 求导,优化器写变量 # 也可以直接喂数据集:model.fit(dataset, y, epochs=1) print("trained, weights:", model.trainable_weights[0].shape) # 输出:trained, weights: (3, 1)
这段代码不求实用,只求让你看见:五个工位在一行流水里各就各位。后面六章就是把每个工位放大细讲。

1.x(2017 前后)的执行模型是纯图模式:先声明 placeholder 搭图,再开 tf.Session,用 feed_dict 喂数据。这个模型对静态图优化友好,但写法反直觉、调试必须进 Session。2.x(2019 起)做了三件结构性的事:默认 Eager 执行,写一行跑一行;tf.keras 升为官方高级 API,把建模训练收拢成 compile-fit 两条命令;Session 与 placeholder 退场,图模式改为按需 tf.function 编译。三者合起来的效果是:入门路径与生产路径统一了——同一份 Keras 代码,调试时是 Eager,fit 内部自动转图。
对照表帮你在旧代码面前不慌:
| 1.x 写法 | 2.x 对应 |
|---|---|
| tf.placeholder + feed_dict | 函数参数直接传张量 |
| tf.Session().run(fetch, feed) | 直接调用,或 tf.function |
| tf.layers / slim | tf.keras.layers |
| tf.train.GradientDescentOptimizer | tf.optimizers.SGD |
| estimator 与 experiment 封装 | Keras 直接训练或 tf.distribute |
# 一段典型的 1.x 风格代码骨架(仅供识别,2.x 已不可运行): # x = tf.placeholder(tf.float32, [None, 3]) # 占位符搭图 # y = tf.placeholder(tf.float32, [None, 1]) # pred = tf.layers.dense(x, 1) # 旧层 API # loss = tf.reduce_mean(tf.square(y - pred)) # opt = tf.train.GradientDescentOptimizer(0.1).minimize(loss) # with tf.Session() as sess: # 开会话执行 # sess.run(tf.global_variables_initializer()) # sess.run(opt, feed_dict={x: ..., y: ...}) # 等价的 2.x 写法,语义一致而篇幅减半: x = tf.random.normal([100, 3]) y = tf.random.normal([100, 1]) pred = tf.keras.layers.Dense(1)(x) loss = tf.reduce_mean(tf.square(y - pred)) print(float(loss)) # 输出示例:1.7320508(随机数据,数值不定)
迁移的心法只有一句:1.x 的"先搭图再开会话"翻译成 2.x 的"函数即图"——把搭图代码搬进函数体,加不加 @tf.function 决定它跑在哪种模式。
三个维度帮你把需求映射到章节。数据规模:单机内存装得下,用 2.2 节的内存上料;装不下或格式是记录流,用 2.3 节的 TFRecord。模型来源:从零训练走第 3、4 章;有预训练模型,走 6.2 节的 Hub 加载。部署目标:服务器 API 服务走 5.3 节 Serving 线,端侧走 Lite 线,浏览器走 tfjs 线。这张地图建议打印贴在手边——后面六章每翻开一节,先在地图上找到它的工位再往下读。
⚠️ 常见坑:混装 1.x 与 2.x 的写法是迁移期事故重灾区。识别标志有四个词:Session、placeholder、feed_dict、estimator,见到任何一个就要先问版本。
💡 关键直觉:子模块不是按"功能分类"随手切的,是按数据流五段切的。记住五段顺序——上料、前向、编译、求导、更新——模块名就再也不会记混。
第 1 章到站。第 2 章进入第一座车间——数据管道。