Load all saved objects and wire their properties.
(self)
| 216 | raise ValueError("Can't convert node %s to tensor" % (type(obj))) |
| 217 | |
| 218 | def _load_all(self): |
| 219 | """Load all saved objects and wire their properties.""" |
| 220 | # Maps from node ids to recreated objects |
| 221 | nodes = {} |
| 222 | # Maps from node ids to setter functions (same signature as setattr) for |
| 223 | # setting dependencies. |
| 224 | node_setters = {} |
| 225 | |
| 226 | # Figure out which objects are slot variables. These objects are created |
| 227 | # with Optimizer.add_slot rather than _recreate_variable. |
| 228 | slot_variable_node_ids = set() |
| 229 | for proto in self._proto.nodes: |
| 230 | for slot_variable_proto in proto.slot_variables: |
| 231 | slot_variable_node_ids.add(slot_variable_proto.slot_variable_node_id) |
| 232 | |
| 233 | # Re-create everything except slot variables. |
| 234 | for node_id, proto in enumerate(self._proto.nodes): |
| 235 | if node_id in slot_variable_node_ids: |
| 236 | # Defer recreating slot variables so we can use the public Optimizer |
| 237 | # interface. |
| 238 | continue |
| 239 | node, setter = self._recreate(proto) |
| 240 | nodes[node_id] = node |
| 241 | node_setters[node_id] = setter |
| 242 | |
| 243 | # Now that we have created the variables being optimized, we have enough |
| 244 | # information to re-create slot variables for them. |
| 245 | for node_id, proto in enumerate(self._proto.nodes): |
| 246 | optimizer_object = nodes[node_id] |
| 247 | for slot_variable_proto in proto.slot_variables: |
| 248 | optimized_variable = nodes[ |
| 249 | slot_variable_proto.original_variable_node_id] |
| 250 | slot_variable = optimizer_object.add_slot( |
| 251 | var=optimized_variable, |
| 252 | slot_name=slot_variable_proto.slot_name) |
| 253 | nodes[slot_variable_proto.slot_variable_node_id] = slot_variable |
| 254 | node_setters[slot_variable_proto.slot_variable_node_id] = setattr |
| 255 | |
| 256 | self._nodes = [] |
| 257 | |
| 258 | # After creating the objects, construct the edges between the objects. |
| 259 | for node_id, object_proto in enumerate(self._proto.nodes): |
| 260 | obj = nodes[node_id] |
| 261 | setter = node_setters[node_id] |
| 262 | self._nodes.append(obj) |
| 263 | |
| 264 | for reference in object_proto.children: |
| 265 | setter(obj, reference.local_name, nodes[reference.node_id]) |
| 266 | # Note: if an object has an attribute `__call__` add a class method |
| 267 | # that allows `obj()` syntax to work. This is done per-instance to |
| 268 | # allow `callable` to be used to find out if an object is callable. |
| 269 | if reference.local_name == "__call__" and not callable(obj): |
| 270 | setattr(type(obj), "__call__", _call_attribute) |
| 271 | |
| 272 | def _restore_checkpoint(self): |
| 273 | """Load state from checkpoint into the deserialized objects.""" |