Freezes the subgraph of all nodes needed by `outputs`.
| 173 | |
| 174 | // Freezes the subgraph of all nodes needed by `outputs`. |
| 175 | Status FreezeGraphDef(const SavedModelBundle& saved_model_bundle, |
| 176 | const std::unordered_set<string>& outputs, |
| 177 | GraphDef* frozen_graph_def) { |
| 178 | GraphDef graph_def = saved_model_bundle.meta_graph_def.graph_def(); |
| 179 | // Copy versions and library as-is from original graph. |
| 180 | *frozen_graph_def->mutable_versions() = graph_def.versions(); |
| 181 | *frozen_graph_def->mutable_library() = graph_def.library(); |
| 182 | // If the graph is empty there is nothing left to do. |
| 183 | if (graph_def.node_size() == 0) { |
| 184 | return Status::OK(); |
| 185 | } |
| 186 | // name_to_node_map is needed to get the inputs from the NodeDef corresponding |
| 187 | // the a string node name. These inputs are used when doing our backwards |
| 188 | // traversal. |
| 189 | std::unordered_map<string, NodeDef*> name_to_node_map; |
| 190 | GetNodeNameToNodeDefMap(&graph_def, &name_to_node_map); |
| 191 | std::unordered_set<string> reachable_node_names; |
| 192 | std::unordered_set<string> variable_node_names; |
| 193 | GetReachableNodesAndVariables(&graph_def, outputs, name_to_node_map, |
| 194 | &reachable_node_names, &variable_node_names); |
| 195 | std::unordered_map<string, Tensor> variable_to_value_map; |
| 196 | TF_RETURN_IF_ERROR(GetVariableNameToTensorMap( |
| 197 | saved_model_bundle.session.get(), name_to_node_map, variable_node_names, |
| 198 | &variable_to_value_map)); |
| 199 | // We copy the nodes in the same order they were in the original graph_def. |
| 200 | for (const NodeDef& node : graph_def.node()) { |
| 201 | if (reachable_node_names.find(node.name()) == reachable_node_names.end()) { |
| 202 | continue; |
| 203 | } |
| 204 | if (variable_node_names.find(node.name()) != variable_node_names.end()) { |
| 205 | ConvertVariableToConstant(node, variable_to_value_map[node.name()], |
| 206 | frozen_graph_def->add_node()); |
| 207 | } else if (node.op() == "ReadVariableOp" && |
| 208 | variable_node_names.find(node.input(0)) != |
| 209 | variable_node_names.end()) { |
| 210 | // If the node is a ReadVariableOp, its input VarHandleOp will be |
| 211 | // converted to a Constant, so we will need to convert it to an Identity. |
| 212 | ConvertReadVariableOpToIdentity(node, frozen_graph_def->add_node()); |
| 213 | } else { |
| 214 | // If the node isn't a variable, just copy the node as-is. |
| 215 | *frozen_graph_def->add_node() = node; |
| 216 | } |
| 217 | } |
| 218 | return Status::OK(); |
| 219 | } |
| 220 | |
| 221 | } // namespace |
| 222 |
no test coverage detected