检查点
短语“保存一个TensorFlow模型”通常意味着以下两件事之一:
- 检查点,或
- SavedModel。
检查点捕获所有参数的确切值(tf $变量
对象)被模型使用。检查点不包含模型定义的计算的任何描述,因此通常只有在使用保存的参数值的源代码可用时才有用。
的SavedModel
另一方面,格式除了参数值(检查点)之外,还包括模型定义的计算的序列化描述。这种格式的模型独立于创建模型的源代码。因此,它们适合通过TensorFlow服务、TensorFlow Lite、TensorFlow.js或其他编程语言(C、c++、Java、Go、Rust、c#等)进行部署。TensorFlow api)。
本指南涵盖了用于写入和读取检查点的api。
设置
图书馆(keras)图书馆(tensorflow)一个简单的线性模型create_model < -函数(大小){keras_model_custom(name =“linear_model”,函数(自我){自我$l1 < -layer_dense(单位=大小)函数(输入,掩码=零){自我$l1(输入)}})}模型< -create_model(5)
通过Keras API保存模型
各自的Keras指南解释了如何使用Keras API来保存和恢复完整的模型以及模型权重。
调用save_weights
有效地导致保存一个TensorFlow检查点:
模型% > %save_model_weights_tf(“weights_only”)
可以通过更低级的TensorFlow方法进行更多定制。
写作检查点
TensorFlow模型的持久状态存储在tf $变量
对象。这些可以直接构建,但通常是通过Keras层或模型等高级api创建的。
管理变量最简单的方法是将它们附加到Python对象上,然后引用这些对象。
的子类特遣部队训练美元检查站
,tf keras层美元美元层
,tf keras美元模型
自动跟踪分配给其属性的变量。下面的示例构建一个简单的线性模型,然后编写包含模型所有变量值的检查点。
手动检查点
设置
的所有特性特遣部队训练美元检查站
,定义玩具数据集和优化步骤:
图书馆(tfdatasets)toy_dataset < -函数() {输入< -矩阵(0:9,ncol =1)% > %特遣部队$投(特遣部队$float32)标签< -矩阵(0:49,ncol =5,byrow =真正的)% > %特遣部队$投(特遣部队$float32)tensor_slices_dataset(列表(x =输入,y =标签)% > %dataset_repeat(10)% > %dataset_batch(2)}train_step < -函数(模型,示例,优化器){与(特遣部队$GradientTape()%, %胶带,{输出< -模型(例子$x)损失< -特遣部队$reduce_mean(特遣部队$腹肌(输出-例子$y))})变量< -模型$trainable_variables梯度< -磁带$梯度(损失,变量)优化器$apply_gradients(purrr::转置(列表(变量梯度)))损失}
创建检查点对象
要手动创建检查点,您需要一个特遣部队训练美元检查站
对象。要检查点的对象被设置为对象上的属性。
一个特遣部队训练CheckpointManager美元
对于管理多个检查点也很有帮助。
训练和检查模型
下面的训练循环创建模型和优化器的实例,然后将它们聚集到特遣部队训练美元检查站
对象。它在每个批数据的循环中调用训练步骤,并定期将检查点写入磁盘。
图书馆(胶)图书馆(tfautograph)train_and_checkpoint < -亲笔签名(函数(模型,管理器,数据集){ckpt$恢复(经理$latest_checkpoint)如果(!is.null(经理$latest_checkpoint)) {特遣部队$打印(胶水(“恢复从$ latest_checkpoint}{经理\ n"))}其他的{特遣部队$打印(“从头开始初始化。\ n")}为(例子在数据集()){损失< -train_step(选择模型,示例)ckpt$一步$assign_add(1)如果(ckpt$一步% %10= =0){save_path < -经理$保存()特遣部队$打印(胶水("保存检查点的步骤{as.numeric(ckpt$step)}: {as.character(save_path)}"))特遣部队$打印(胶水(“损失:{轮(as.numeric(损失),2)}”))}}})train_and_checkpoint(模型、经理toy_dataset)
恢复并继续训练
在第一次培训之后,你可以通过新的模特和经理的培训,但pick - up training完全按照你离开的地方进行:
选择< -optimizer_adam(0.1)净< -create_model(5)ckpt < -特遣部队$火车$检查点(一步=特遣部队$变量(1),优化器=选择,网=净)经理< -特遣部队$火车$CheckpointManager(ckpt,”。/ tf_ckpts ',max_to_keep =3.)train_and_checkpoint(toy_dataset净、经理)
的特遣部队训练CheckpointManager美元
对象删除旧的检查点。上面它被配置为只保留三个最近的检查点。
这些路径,例如。/tf_ckpts/ckpt-10 '不是磁盘上的文件。相反,它们是索引文件和一个或多个包含变量值的数据文件的前缀。这些前缀被组合在一个检查点文件中(' ./tf_ckpts/checkpoint '),其中CheckpointManager
保存其状态。
list.files(”。/ tf_ckpts /”)#> [1] "checkpoint" "ckpt-18 - data-00000-of-00001"# > ckpt-18[3]”。在dex" "ckpt-19.data-00000-of-00001"# > ckpt-19[5]”。在dex" "ckpt-20.data-00000-of-00001"# >[7]“ckpt - 20.——指数”
TensorFlow通过遍历带命名边的有向图来匹配变量和检查点值,从加载的对象开始。边缘名称通常来自对象中的属性名称,例如“l1”Self $l1 <- layer_dense(units = size)
.特遣部队训练美元检查站
使用它的关键字参数名称,如在“step”中特遣部队训练CheckpointManager美元(步骤=…)
.
上面例子中的依赖图是这样的:
优化器用红色表示,常规变量用蓝色表示,优化器槽变量用橙色表示。其他节点,例如表示特遣部队训练美元检查站
,是黑色的。
槽变量是优化器状态的一部分,但是是为特定的变量创建的。例如米
上面的边对应的动量,亚当优化器跟踪每个变量。槽变量只保存在检查点,如果变量和优化器都保存,因此虚线边。
调用恢复()
在一个特遣部队训练美元检查站
对象对请求的恢复进行排队,一旦从Checkpoint对象中找到匹配的路径,就立即恢复变量值。例如,我们可以从上面定义的模型加载内核,方法是通过网络和层重构到内核的一条路径。
to_restore < -特遣部队$变量(特遣部队$0(列表(5 l)))as.numeric(to_restore)#所有零#> [1] 0 0 0 0 0fake_layer < -特遣部队$火车$检查点(偏见=to_restore)fake_net < -特遣部队$火车$检查点(l1 =fake_layer)new_root < -特遣部队$火车$检查点(网=fake_net)< -状态new_root$恢复(特遣部队$火车$latest_checkpoint(“tf_ckpts /。”))as.numeric(to_restore)#我们现在拿到修复后的价值#> [1] 0.0308778 1.0408185 1.9840808 2.9422886 3.9628119
这些新对象的依赖关系图是我们上面所写的较大检查点的一个小得多的子图。它只包括偏差和保存计数器特遣部队训练美元检查站
用于编号检查点。
恢复()
返回一个状态对象,该对象具有可选断言。所有我们在new中创建的对象检查点
都被修复了,所以呢status.assert_existing_objects_matched ()
传球。
状态$assert_existing_objects_matched()# > < tensorflow.python.training.tracking.util.CheckpointLoadStatus >
检查点中有许多对象没有匹配,包括层的内核和优化器的变量。美元地位assert_consumed ()
只有当检查点和程序完全匹配时才通过,并在这里抛出异常。
延迟修复
当输入形状可用时,TensorFlow中的层对象可能会将变量的创建延迟到第一次调用时。例如,密集层的内核形状取决于层的输入和输出形状,因此作为构造函数参数所需的输出形状不足以单独创建变量。因为调用Layer也会读取变量的值,所以必须在变量创建和第一次使用之间进行恢复。
为了支卡塔尔世界杯欧洲预选赛赛程表持这个习语,特遣部队训练美元检查站
恢复还没有匹配变量的队列。
delayed_restore < -特遣部队$变量(特遣部队$0(列表(1 l, 5 l)))as.numeric(delayed_restore)#不恢复;还是零#> [1] 0 0 0 0 0fake_layer$内核< -delayed_restoreas.numeric(delayed_restore)#恢复#> [1] 4.995093 4.982657 5.014721 5.007162 5.001130
手动检查检查点
特遣部队训练list_variables美元
列出检查点中的检查点键和变量的形状。检查点键是上图中显示的路径。
特遣部队$火车$list_variables(特遣部队$火车$latest_checkpoint(“tf_ckpts /。”))# > [[1]]# > [[1]] [[1]]# >[1]“_CHECKPOINTABLE_OBJECT_GRAPH”# ># > [[1]] [[2]]# >列表()# ># ># > [[2]]# > [[2]] [[1]]# > net/l1/bias/[1]”。一个TTRIBUTES/VARIABLE_VALUE"# ># > [[2]] [[2]]5 # > [1]# ># ># > [[3]]# > [[3]] [[1]]# >[1]“net/l1/bias/.OPTIMIZER_SLOT/optimizer/m/.ATTRIBUTES/VARIABLE_VALUE”# ># > [[3]] [[2]]5 # > [1]# ># ># > [[4]]# > [[4]] [[1]]# >[1]“net/l1/bias/.OPTIMIZER_SLOT/optimizer/v/.ATTRIBUTES/VARIABLE_VALUE”# ># > [[4]] [[2]]5 # > [1]# ># ># > [[5]]# > [[5]] [[1]]# > net/l1/kernel/[1]”。一个TTRIBUTES/VARIABLE_VALUE"# ># > [[5]] [[2]]#> [1] 15# ># ># > [[6]]# > [[6]] [[1]]# >[1]“net/l1/kernel/.OPTIMIZER_SLOT/optimizer/m/.ATTRIBUTES/VARIABLE_VALUE”# ># > [[6]] [[2]]#> [1] 15# ># ># > [[7]]# > [[7]] [[1]]# >[1]“net/l1/kernel/.OPTIMIZER_SLOT/optimizer/v/.ATTRIBUTES/VARIABLE_VALUE”# ># > [[7]] [[2]]#> [1] 15# ># ># > [[8]]# > [[8]] [[1]]# >[1]”优化器/ beta_1 /。属性/ VARIABLE_VALUE”# ># > [[8]] [[2]]# >列表()# ># ># > [[9]]# > [[9]] [[1]]# >[1]”优化器/ beta_2 /。属性/ VARIABLE_VALUE”# ># > [[9]] [[2]]# >列表()# ># ># > [[10]]# > [[10]] [[1]]# >[1]”优化器/衰减。一个TTRIBUTES/VARIABLE_VALUE"# ># > [[10]] [[2]]# >列表()# ># ># > [[11]]# > [[11]] [[1]]# >[1]”优化器/ iter /。一个TTRIBUTES/VARIABLE_VALUE"# ># > [[11]] [[2]]# >列表()# ># ># > [[12]]# > [[12]] [[1]]# >[1]”优化器/ learning_rate /。属性/ VARIABLE_VALUE”# ># > [[12]] [[2]]# >列表()# ># ># > [[13]]# > [[13]] [[1]]# >[1]“save_counter /。一个TTRIBUTES/VARIABLE_VALUE"# ># > [[13]] [[2]]# >列表()# ># ># > [[14]]# > [[14]] [[1]]/ # >[1]”一步。一个TTRIBUTES/VARIABLE_VALUE"# ># > [[14]] [[2]]# >列表()
列表和字典跟踪
就像直接的属性赋值一样Self $l1 <- layer_dense(units = size)
,将列表和字典分配给属性将跟踪它们的内容。
保存< -特遣部队$火车$检查点()保存$列出< -列表(特遣部队$变量(1))保存$上市$附加(特遣部队$变量(2))保存$映射< -dict(一个=保存$上市(0])网状::py_set_item(保存$映射,“两个”,保存$上市(1])#保存映射(“两个”)< -美元拯救美元上市[1]save_path < -保存$保存(”。/ tf_list_example ')恢复< -特遣部队$火车$检查点()v2 < -特遣部队$变量(0)0= =as.numeric(v2)#还没有恢复# > [1]恢复$映射< -dict(两个=v2)恢复$恢复(save_path)# > < tensorflow.python.training.tracking.util.CheckpointLoadStatus >2= =as.numeric(v2)# > [1]
您可能注意到了列表和字典的包装器对象。这些包装器是底层数据结构的检查指向版本。与基于属性的加载一样,这些包装器在将变量添加到容器中后立即恢复变量的值。
恢复$列出< -列表()打印(恢复$列出)# ListWrapper ([])# > ListWrapper ([])v1 < -特遣部队$变量(0.)恢复$上市$附加(v1)从上一个单元格中的restore()恢复v11.= =as.numeric(v1)# > [1]
同样的跟踪也自动应用于tf.keras的子类。模型,并可用于跟踪层列表。