153 lines
4.9 KiB
Python
153 lines
4.9 KiB
Python
|
# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
|
||
|
#
|
||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
# you may not use this file except in compliance with the License.
|
||
|
# You may obtain a copy of the License at
|
||
|
#
|
||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||
|
#
|
||
|
# Unless required by applicable law or agreed to in writing, software
|
||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
# See the License for the specific language governing permissions and
|
||
|
# limitations under the License.
|
||
|
# ==============================================================================
|
||
|
"""Python dataset sparse tensor utility functitons."""
|
||
|
from __future__ import absolute_import
|
||
|
from __future__ import division
|
||
|
from __future__ import print_function
|
||
|
|
||
|
from tensorflow.python.data.util import nest
|
||
|
from tensorflow.python.framework import dtypes
|
||
|
from tensorflow.python.framework import ops
|
||
|
from tensorflow.python.framework import sparse_tensor
|
||
|
from tensorflow.python.framework import tensor_shape
|
||
|
from tensorflow.python.ops import sparse_ops
|
||
|
|
||
|
|
||
|
def any_sparse(classes):
|
||
|
"""Checks for sparse tensor.
|
||
|
|
||
|
Args:
|
||
|
classes: a structure of objects that identify the dataset item classes
|
||
|
|
||
|
Returns:
|
||
|
`True` if `classes` contains a sparse tensor type and `False` otherwise.
|
||
|
"""
|
||
|
return any([c is sparse_tensor.SparseTensor for c in nest.flatten(classes)])
|
||
|
|
||
|
|
||
|
def as_dense_shapes(shapes, classes):
|
||
|
"""Converts sparse tensor shapes to their physical shapes.
|
||
|
|
||
|
Args:
|
||
|
shapes: a structure of shapes to convert.
|
||
|
classes: a structure of objects that identify the dataset item classes
|
||
|
|
||
|
Returns:
|
||
|
a structure matching the nested structure of `shapes`, containing
|
||
|
`tensor_shape.unknown_shape()` at positions where `classes` contains
|
||
|
`tf.SparseTensor` and matching contents of `shapes` otherwise
|
||
|
"""
|
||
|
ret = nest.pack_sequence_as(shapes, [
|
||
|
tensor_shape.unknown_shape() if c is sparse_tensor.SparseTensor else shape
|
||
|
for shape, c in zip(nest.flatten(shapes), nest.flatten(classes))
|
||
|
])
|
||
|
return ret
|
||
|
|
||
|
|
||
|
def as_dense_types(types, classes):
|
||
|
"""Converts sparse tensor types to `dtypes.variant`.
|
||
|
|
||
|
Args:
|
||
|
types: a structure of types to convert.
|
||
|
classes: a structure of objects that identify the dataset item classes
|
||
|
|
||
|
Returns:
|
||
|
a structure matching the nested structure of `types`, containing
|
||
|
`dtypes.variant` at positions where `classes` contains `tf.SparseTensor` and
|
||
|
matching contents of `types` otherwise
|
||
|
"""
|
||
|
ret = nest.pack_sequence_as(types, [
|
||
|
dtypes.variant if c is sparse_tensor.SparseTensor else ty
|
||
|
for ty, c in zip(nest.flatten(types), nest.flatten(classes))
|
||
|
])
|
||
|
return ret
|
||
|
|
||
|
|
||
|
def deserialize_sparse_tensors(tensors, types, shapes, classes):
|
||
|
"""Deserializes sparse tensors.
|
||
|
|
||
|
Args:
|
||
|
tensors: a structure of tensors to deserialize.
|
||
|
types: a structure that holds information about types of `tensors`
|
||
|
shapes: a structure that holds information about shapes of `tensors`
|
||
|
classes: a structure of objects that identify the dataset item classes
|
||
|
|
||
|
Returns:
|
||
|
`tensors` with any serialized sparse tensors replaced by their deserialized
|
||
|
version.
|
||
|
"""
|
||
|
ret = nest.pack_sequence_as(types, [
|
||
|
sparse_ops.deserialize_sparse(tensor, dtype=ty, rank=shape.ndims)
|
||
|
if c is sparse_tensor.SparseTensor else tensor
|
||
|
for (tensor, ty, shape, c) in zip(
|
||
|
nest.flatten(tensors), nest.flatten(types), nest.flatten(shapes),
|
||
|
nest.flatten(classes))
|
||
|
])
|
||
|
return ret
|
||
|
|
||
|
|
||
|
def get_classes(tensors):
|
||
|
"""Gets classes for a structure of tensors.
|
||
|
|
||
|
Args:
|
||
|
tensors: the tensor structure to get classes for.
|
||
|
|
||
|
Returns:
|
||
|
a structure matching the nested structure of `tensors`, containing
|
||
|
`tf.SparseTensor` at positions where `tensors` contains a sparse tensor and
|
||
|
`tf.Tensor` otherwise
|
||
|
"""
|
||
|
return nest.pack_sequence_as(tensors, [
|
||
|
sparse_tensor.SparseTensor
|
||
|
if isinstance(tensor, sparse_tensor.SparseTensor) else ops.Tensor
|
||
|
for tensor in nest.flatten(tensors)
|
||
|
])
|
||
|
|
||
|
|
||
|
def serialize_many_sparse_tensors(tensors):
|
||
|
"""Serializes many sparse tensors into a batch.
|
||
|
|
||
|
Args:
|
||
|
tensors: a tensor structure to serialize.
|
||
|
|
||
|
Returns:
|
||
|
`tensors` with any sparse tensors replaced by the serialized batch.
|
||
|
"""
|
||
|
|
||
|
ret = nest.pack_sequence_as(tensors, [
|
||
|
sparse_ops.serialize_many_sparse(tensor, out_type=dtypes.variant)
|
||
|
if sparse_tensor.is_sparse(tensor) else tensor
|
||
|
for tensor in nest.flatten(tensors)
|
||
|
])
|
||
|
return ret
|
||
|
|
||
|
|
||
|
def serialize_sparse_tensors(tensors):
|
||
|
"""Serializes sparse tensors.
|
||
|
|
||
|
Args:
|
||
|
tensors: a tensor structure to serialize.
|
||
|
|
||
|
Returns:
|
||
|
`tensors` with any sparse tensors replaced by their serialized version.
|
||
|
"""
|
||
|
|
||
|
ret = nest.pack_sequence_as(tensors, [
|
||
|
sparse_ops.serialize_sparse(tensor, out_type=dtypes.variant)
|
||
|
if isinstance(tensor, sparse_tensor.SparseTensor) else tensor
|
||
|
for tensor in nest.flatten(tensors)
|
||
|
])
|
||
|
return ret
|