Returns the converted value corresponding to SparseTensor y. For SparseTensors, instead of stacking the component tensors separately, resulting in component tensors with shapes (N, m, rank), (N, m), and (N, rank) respectively for indices, values, and dense_shape (where N is the loop
(self, y)
| 1138 | return op._id in self._pfor_op_ids |
| 1139 | |
| 1140 | def _convert_sparse(self, y): |
| 1141 | """Returns the converted value corresponding to SparseTensor y. |
| 1142 | |
| 1143 | For SparseTensors, instead of stacking the component tensors separately, |
| 1144 | resulting in component tensors with shapes (N, m, rank), (N, m), and (N, |
| 1145 | rank) respectively for indices, values, and dense_shape (where N is the loop |
| 1146 | length and m is the number of sparse tensor values per loop iter), we want |
| 1147 | to logically stack the SparseTensors, to create a SparseTensor whose |
| 1148 | components are size (N * m, rank + 1), (N * m, ), and (rank + 1,) |
| 1149 | respectively. |
| 1150 | |
| 1151 | Here, we try to get the conversion of each component tensor. |
| 1152 | If the tensors are stacked via a sparse conversion, return the resulting |
| 1153 | SparseTensor composed of the converted components. Otherwise, the component |
| 1154 | tensors are either unstacked or stacked naively. In the latter case, we |
| 1155 | unstack the component tensors to reform loop_len SparseTensor elements, |
| 1156 | then correctly batch them. |
| 1157 | |
| 1158 | The unstacked tensors must have the same rank. Each dimension of each |
| 1159 | SparseTensor will expand to be the largest among all SparseTensor elements |
| 1160 | for that dimension. For example, if there are N SparseTensors of rank 3 |
| 1161 | being stacked, with N dense shapes, where the i_th shape is (x_i, y_i, z_i), |
| 1162 | the new dense shape will be (N, max_i(x_i), max_i(y_i), max_i(z_i)). |
| 1163 | |
| 1164 | Args: |
| 1165 | y: A tf.SparseTensor. |
| 1166 | |
| 1167 | Returns: |
| 1168 | A tf.SparseTensor that is the converted value corresponding to y. |
| 1169 | """ |
| 1170 | outputs = [ |
| 1171 | self._convert_helper(t) for t in (y.indices, y.values, y.dense_shape) |
| 1172 | ] |
| 1173 | assert all(isinstance(o, WrappedTensor) for o in outputs) |
| 1174 | |
| 1175 | if all(w.is_sparse_stacked for w in outputs): |
| 1176 | return sparse_tensor.SparseTensor(*[w.t for w in outputs]) |
| 1177 | |
| 1178 | assert not any(w.is_sparse_stacked for w in outputs), ( |
| 1179 | "Error converting SparseTensor. All components should be logically " |
| 1180 | "stacked, or none.") |
| 1181 | |
| 1182 | # If component tensors were not sparsely stacked, they are either unstacked |
| 1183 | # or stacked without knowledge that they are components of sparse tensors. |
| 1184 | # In this case, we have to restack them. |
| 1185 | return self._restack_sparse_tensor_logically( |
| 1186 | *[self._unwrap_or_tile(w) for w in outputs]) |
| 1187 | |
| 1188 | def _restack_sparse_tensor_logically(self, indices, values, shape): |
| 1189 | sparse_tensor_rank = indices.get_shape().dims[-1].value |
no test coverage detected