1 /* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
2
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15
16 #include "tensorflow/core/framework/common_shape_fns.h"
17 #include "tensorflow/core/framework/op.h"
18 #include "tensorflow/core/framework/shape_inference.h"
19 #include "tensorflow/core/lib/core/errors.h"
20 #include "tensorflow/core/util/example_proto_helper.h"
21
22 namespace tensorflow {
23
24 using shape_inference::DimensionHandle;
25 using shape_inference::InferenceContext;
26 using shape_inference::ShapeHandle;
27
28 namespace {
29
30 // Adds output shapes for dense tensors in Parse*Example ops.
31 template <typename TensorShapeType> // TensorShape or PartialTensorShape
AddDenseOutputShapes(const std::vector<TensorShapeType> & dense_shapes,const ShapeHandle & prefix,InferenceContext * c,int * output_idx)32 Status AddDenseOutputShapes(const std::vector<TensorShapeType>& dense_shapes,
33 const ShapeHandle& prefix, InferenceContext* c,
34 int* output_idx) {
35 for (const auto& dense_shape : dense_shapes) {
36 ShapeHandle s;
37 TF_RETURN_IF_ERROR(c->MakeShapeFromPartialTensorShape(dense_shape, &s));
38 TF_RETURN_IF_ERROR(c->Concatenate(prefix, s, &s));
39 c->set_output((*output_idx)++, s);
40 }
41 return Status::OK();
42 }
43
44 // Adds output shapes for sparse tensors in Parse*Example ops.
AddSparseOutputShapes(int num_sparse,const ShapeHandle input_shape,int64 rank_delta,InferenceContext * c,int * output_idx)45 void AddSparseOutputShapes(int num_sparse, const ShapeHandle input_shape,
46 int64 rank_delta, InferenceContext* c,
47 int* output_idx) {
48 // Rank of SparseTensor is rank of input tensor plus rank_delta.
49 shape_inference::DimensionOrConstant rank(c->UnknownDim());
50 if (c->RankKnown(input_shape)) {
51 rank = c->Rank(input_shape) + rank_delta;
52 }
53 for (int i = 0; i < num_sparse; ++i) { // sparse_indices
54 c->set_output((*output_idx)++, c->Matrix(c->UnknownDim(), rank));
55 }
56 for (int i = 0; i < num_sparse; ++i) { // sparse_values
57 c->set_output((*output_idx)++, c->Vector(c->UnknownDim()));
58 }
59 for (int i = 0; i < num_sparse; ++i) { // sparse_dense_shapes
60 c->set_output((*output_idx)++, c->Vector(rank));
61 }
62 }
63
64 // Adds output shapes for ragged tensors in Parse*Example ops.
AddRaggedOutputShapes(int num_ragged,bool ragged_rank_2,const DimensionHandle & num_examples,InferenceContext * c,int * output_idx)65 Status AddRaggedOutputShapes(int num_ragged, bool ragged_rank_2,
66 const DimensionHandle& num_examples,
67 InferenceContext* c, int* output_idx) {
68 DimensionHandle num_splits;
69 TF_RETURN_IF_ERROR(c->Add(num_examples, 1, &num_splits));
70 // Values
71 for (int i = 0; i < num_ragged; ++i) {
72 c->set_output((*output_idx)++, c->Vector(c->UnknownDim()));
73 }
74 // Outer row_splits.
75 for (int i = 0; i < num_ragged; ++i) {
76 c->set_output((*output_idx)++, c->Vector(num_splits));
77 }
78 // Inner row_splits (for ParseSequenceExample feature_list features)
79 if (ragged_rank_2) {
80 for (int i = 0; i < num_ragged; ++i) {
81 c->set_output((*output_idx)++, c->Vector(c->UnknownDim()));
82 }
83 }
84 return Status::OK();
85 }
86
87 // Adds output shapes for dense_lengths tensors in Parse*Example ops.
AddDenseLengthsShapes(int num_dense,const ShapeHandle & shape,InferenceContext * c,int * output_idx)88 void AddDenseLengthsShapes(int num_dense, const ShapeHandle& shape,
89 InferenceContext* c, int* output_idx) {
90 for (int i = 0; i < num_dense; ++i) {
91 c->set_output((*output_idx)++, shape);
92 }
93 }
94
95 } // namespace
96
97 REGISTER_OP("DecodeRaw")
98 .Input("bytes: string")
99 .Output("output: out_type")
100 .Attr(
101 "out_type: "
102 "{half,float,double,int32,uint16,uint8,int16,int8,int64,complex64,"
103 "complex128,bool}")
104 .Attr("little_endian: bool = true")
__anonf8f6e66e0202(InferenceContext* c) 105 .SetShapeFn([](InferenceContext* c) {
106 // Note: last dimension is data dependent.
107 ShapeHandle out;
108 TF_RETURN_IF_ERROR(c->Concatenate(
109 c->input(0), c->Vector(InferenceContext::kUnknownDim), &out));
110 c->set_output(0, out);
111 return Status::OK();
112 });
113
114 REGISTER_OP("DecodePaddedRaw")
115 .Input("input_bytes: string")
116 .Input("fixed_length: int32")
117 .Output("output: out_type")
118 .Attr("out_type: {half,float,double,int32,uint16,uint8,int16,int8,int64}")
119 .Attr("little_endian: bool = true")
__anonf8f6e66e0302(InferenceContext* c) 120 .SetShapeFn([](InferenceContext* c) {
121 DimensionHandle fixed_length;
122 TF_RETURN_IF_ERROR(c->MakeDimForScalarInput(1, &fixed_length));
123
124 DataType out_type;
125 TF_RETURN_IF_ERROR(c->GetAttr("out_type", &out_type));
126
127 int32 data_type_size = DataTypeSize(out_type);
128
129 DimensionHandle width;
130 TF_RETURN_IF_ERROR(c->Divide(fixed_length, data_type_size, true, &width));
131
132 ShapeHandle out;
133 TF_RETURN_IF_ERROR(c->Concatenate(c->input(0), c->Vector(width), &out));
134
135 c->set_output(0, out);
136 return Status::OK();
137 });
138
139 REGISTER_OP("DecodeCompressed")
140 .Input("bytes: string")
141 .Output("output: string")
142 .Attr("compression_type: string = ''")
143 .SetShapeFn(shape_inference::UnchangedShape);
144
145 REGISTER_OP("ParseExample")
146 .Input("serialized: string")
147 .Input("names: string")
148 .Input("sparse_keys: Nsparse * string")
149 .Input("dense_keys: Ndense * string")
150 .Input("dense_defaults: Tdense")
151 .Output("sparse_indices: Nsparse * int64")
152 .Output("sparse_values: sparse_types")
153 .Output("sparse_shapes: Nsparse * int64")
154 .Output("dense_values: Tdense")
155 .Attr("Nsparse: int >= 0") // Inferred from sparse_keys
156 .Attr("Ndense: int >= 0") // Inferred from dense_keys
157 .Attr("sparse_types: list({float,int64,string}) >= 0")
158 .Attr("Tdense: list({float,int64,string}) >= 0")
159 .Attr("dense_shapes: list(shape) >= 0")
__anonf8f6e66e0402(InferenceContext* c) 160 .SetShapeFn([](InferenceContext* c) {
161 ParseExampleAttrs attrs;
162 TF_RETURN_IF_ERROR(attrs.Init(c, /*op_version=*/1));
163
164 ShapeHandle input;
165 TF_RETURN_IF_ERROR(c->WithRank(c->input(0), 1, &input));
166 ShapeHandle names;
167 TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 1, &names));
168
169 int output_idx = 0;
170 AddSparseOutputShapes(attrs.num_sparse, input, 1, c, &output_idx);
171 TF_RETURN_IF_ERROR(
172 AddDenseOutputShapes(attrs.dense_shapes, input, c, &output_idx));
173 return Status::OK();
174 });
175
176 // Differences between ParseExample and ParseExampleV2:
177 // * Supports ragged features.
178 // * `serialized` may be a vector or a scalar. (With v1, `serialized` could
179 // only be a vector).
180 // * Each set of keys is passed with a vector instead of a list of scalars.
181 // * No Ndense attribute (not needed).
182 // * num_sparse (formerly Nsparse) is no longer inferred; you must specify it
183 // explicitly.
184 REGISTER_OP("ParseExampleV2")
185 .Input("serialized: string")
186 .Input("names: string")
187 .Input("sparse_keys: string")
188 .Input("dense_keys: string")
189 .Input("ragged_keys: string")
190 .Input("dense_defaults: Tdense")
191 .Output("sparse_indices: num_sparse * int64")
192 .Output("sparse_values: sparse_types")
193 .Output("sparse_shapes: num_sparse * int64")
194 .Output("dense_values: Tdense")
195 .Output("ragged_values: ragged_value_types")
196 .Output("ragged_row_splits: ragged_split_types")
197 .Attr("Tdense: list({float,int64,string}) >= 0") // Inferred
198 .Attr("num_sparse: int >= 0")
199 .Attr("sparse_types: list({float,int64,string}) >= 0")
200 .Attr("ragged_value_types: list({float,int64,string}) >= 0")
201 .Attr("ragged_split_types: list({int32,int64}) >= 0")
202 .Attr("dense_shapes: list(shape) >= 0")
203
__anonf8f6e66e0502(InferenceContext* c) 204 .SetShapeFn([](InferenceContext* c) {
205 ParseExampleAttrs attrs;
206 TF_RETURN_IF_ERROR(attrs.Init(c, /*op_version=*/2));
207
208 ShapeHandle input;
209 TF_RETURN_IF_ERROR(c->WithRankAtMost(c->input(0), 1, &input));
210 ShapeHandle names;
211 TF_RETURN_IF_ERROR(c->WithRankAtMost(c->input(1), 1, &names));
212 DimensionHandle num_examples = c->UnknownDim();
213 if (c->RankKnown(input) && c->Rank(input) == 1) {
214 num_examples = c->Dim(input, 0);
215 }
216
217 int output_idx = 0;
218 AddSparseOutputShapes(attrs.num_sparse, input, 1, c, &output_idx);
219 TF_RETURN_IF_ERROR(
220 AddDenseOutputShapes(attrs.dense_shapes, input, c, &output_idx));
221 TF_RETURN_IF_ERROR(AddRaggedOutputShapes(attrs.num_ragged, false,
222 num_examples, c, &output_idx));
223
224 return Status::OK();
225 });
226
227 REGISTER_OP("ParseSingleExample")
228 .Input("serialized: string")
229 .Input("dense_defaults: Tdense")
230 .Output("sparse_indices: num_sparse * int64")
231 .Output("sparse_values: sparse_types")
232 .Output("sparse_shapes: num_sparse * int64")
233 .Output("dense_values: Tdense")
234 .Attr("num_sparse: int >= 0")
235 .Attr("sparse_keys: list(string) >= 0")
236 .Attr("dense_keys: list(string) >= 0")
237 .Attr("sparse_types: list({float,int64,string}) >= 0")
238 .Attr("Tdense: list({float,int64,string}) >= 0")
239 .Attr("dense_shapes: list(shape) >= 0")
__anonf8f6e66e0602(InferenceContext* c) 240 .SetShapeFn([](InferenceContext* c) {
241 ParseSingleExampleAttrs attrs;
242 TF_RETURN_IF_ERROR(attrs.Init(c));
243
244 ShapeHandle input;
245 TF_RETURN_IF_ERROR(c->WithRank(c->input(0), 0, &input));
246
247 int output_idx = 0;
248 AddSparseOutputShapes(attrs.sparse_keys.size(), input, 1, c, &output_idx);
249 TF_RETURN_IF_ERROR(
250 AddDenseOutputShapes(attrs.dense_shapes, input, c, &output_idx));
251 return Status::OK();
252 });
253
254 REGISTER_OP("ParseSequenceExample")
255 .Input("serialized: string")
256 .Input("debug_name: string")
257 .Input("context_dense_defaults: Tcontext_dense")
258 .Output("context_sparse_indices: Ncontext_sparse * int64")
259 .Output("context_sparse_values: context_sparse_types")
260 .Output("context_sparse_shapes: Ncontext_sparse * int64")
261 .Output("context_dense_values: Tcontext_dense")
262 .Output("feature_list_sparse_indices: Nfeature_list_sparse * int64")
263 .Output("feature_list_sparse_values: feature_list_sparse_types")
264 .Output("feature_list_sparse_shapes: Nfeature_list_sparse * int64")
265 .Output("feature_list_dense_values: feature_list_dense_types")
266 .Output("feature_list_dense_lengths: Nfeature_list_dense * int64")
267 .Attr("feature_list_dense_missing_assumed_empty: list(string) >= 0")
268 .Attr("context_sparse_keys: list(string) >= 0")
269 .Attr("context_dense_keys: list(string) >= 0")
270 .Attr("feature_list_sparse_keys: list(string) >= 0")
271 .Attr("feature_list_dense_keys: list(string) >= 0")
272 .Attr("Ncontext_sparse: int >= 0 = 0")
273 .Attr("Ncontext_dense: int >= 0 = 0")
274 .Attr("Nfeature_list_sparse: int >= 0 = 0")
275 .Attr("Nfeature_list_dense: int >= 0 = 0")
276 .Attr("context_sparse_types: list({float,int64,string}) >= 0 = []")
277 .Attr("Tcontext_dense: list({float,int64,string}) >= 0 = []")
278 .Attr("feature_list_dense_types: list({float,int64,string}) >= 0 = []")
279 .Attr("context_dense_shapes: list(shape) >= 0 = []")
280 .Attr("feature_list_sparse_types: list({float,int64,string}) >= 0 = []")
281 .Attr("feature_list_dense_shapes: list(shape) >= 0 = []")
__anonf8f6e66e0702(InferenceContext* c) 282 .SetShapeFn([](InferenceContext* c) {
283 ParseSequenceExampleAttrs attrs;
284 TF_RETURN_IF_ERROR(attrs.Init(c));
285
286 // Verify that the input is a vector, and carry the shape if known.
287 ShapeHandle input;
288 TF_RETURN_IF_ERROR(c->WithRank(c->input(0), 1, &input));
289 ShapeHandle names;
290 TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 1, &names));
291 DimensionHandle num_examples = c->Dim(input, 0);
292 ShapeHandle feature_list_dense_prefix =
293 c->Matrix(num_examples, c->UnknownDim());
294
295 int output_idx = 0;
296 AddSparseOutputShapes(attrs.num_context_sparse, input, 1, c, &output_idx);
297 TF_RETURN_IF_ERROR(AddDenseOutputShapes(attrs.context_dense_shapes, input,
298 c, &output_idx));
299 AddSparseOutputShapes(attrs.num_feature_list_sparse, input, 2, c,
300 &output_idx);
301 TF_RETURN_IF_ERROR(AddDenseOutputShapes(attrs.feature_list_dense_shapes,
302 feature_list_dense_prefix, c,
303 &output_idx));
304 AddDenseLengthsShapes(attrs.num_feature_list_dense, input, c,
305 &output_idx);
306
307 return Status::OK();
308 });
309
310 // Differences between ParseSequenceExample and ParseSequenceExampleV2:
311 // * Supports ragged features.
312 // * `serialized` may be a vector or a scalar. (With v1, `serialized` could
313 // only be a vector).
314 // * Each set of keys is passed with a vector instead of an attr list.
315 // * feature_list_dense_missing_assumed_empty is passed with as a boolean
316 // vector (aligned 1:1 w/ feature_list_dense_kyes) rather than an attrib
317 // containing a list of strings.
318 // * No Ncontext_dense attribute (not needed).
319 REGISTER_OP("ParseSequenceExampleV2")
320 .Input("serialized: string")
321 .Input("debug_name: string")
322 // Inputs: context features
323 .Input("context_sparse_keys: string")
324 .Input("context_dense_keys: string")
325 .Input("context_ragged_keys: string")
326 // Inputs: feature lists
327 .Input("feature_list_sparse_keys: string")
328 .Input("feature_list_dense_keys: string")
329 .Input("feature_list_ragged_keys: string")
330 .Input("feature_list_dense_missing_assumed_empty: bool")
331 .Input("context_dense_defaults: Tcontext_dense")
332 // Outputs: context features
333 .Output("context_sparse_indices: Ncontext_sparse * int64")
334 .Output("context_sparse_values: context_sparse_types")
335 .Output("context_sparse_shapes: Ncontext_sparse * int64")
336 .Output("context_dense_values: Tcontext_dense")
337 .Output("context_ragged_values: context_ragged_value_types")
338 .Output("context_ragged_row_splits: context_ragged_split_types")
339 // Outputs: feature lists
340 .Output("feature_list_sparse_indices: Nfeature_list_sparse * int64")
341 .Output("feature_list_sparse_values: feature_list_sparse_types")
342 .Output("feature_list_sparse_shapes: Nfeature_list_sparse * int64")
343 .Output("feature_list_dense_values: feature_list_dense_types")
344 .Output("feature_list_dense_lengths: Nfeature_list_dense * int64")
345 .Output("feature_list_ragged_values: feature_list_ragged_value_types")
346 .Output("feature_list_ragged_outer_splits: feature_list_ragged_split_types")
347 .Output("feature_list_ragged_inner_splits: feature_list_ragged_split_types")
348 // Attribs: context features
349 .Attr("Ncontext_sparse: int >= 0 = 0")
350 .Attr("Tcontext_dense: list({float,int64,string}) >= 0 = []") // inferred
351 .Attr("context_sparse_types: list({float,int64,string}) >= 0 = []")
352 .Attr("context_ragged_value_types: list({float,int64,string}) >= 0 = []")
353 .Attr("context_ragged_split_types: list({int32,int64}) >= 0 = []")
354 .Attr("context_dense_shapes: list(shape) >= 0 = []")
355 // Attribs: feature lists
356 .Attr("Nfeature_list_sparse: int >= 0 = 0")
357 .Attr("Nfeature_list_dense: int >= 0 = 0")
358 .Attr("feature_list_dense_types: list({float,int64,string}) >= 0 = []")
359 .Attr("feature_list_sparse_types: list({float,int64,string}) >= 0 = []")
360 .Attr(
361 "feature_list_ragged_value_types: list({float,int64,string}) >= 0 = []")
362 .Attr("feature_list_ragged_split_types: list({int32,int64}) >= 0 = []")
363 .Attr("feature_list_dense_shapes: list(shape) >= 0 = []")
__anonf8f6e66e0802(InferenceContext* c) 364 .SetShapeFn([](InferenceContext* c) {
365 ParseSequenceExampleAttrs attrs;
366 TF_RETURN_IF_ERROR(attrs.Init(c, /*op_version=*/2));
367 ShapeHandle input;
368 TF_RETURN_IF_ERROR(c->WithRankAtMost(c->input(0), 1, &input));
369 ShapeHandle names;
370 TF_RETURN_IF_ERROR(c->WithRankAtMost(c->input(1), 1, &names));
371 ShapeHandle feature_list_dense_prefix;
372 TF_RETURN_IF_ERROR(c->Concatenate(input, c->UnknownShapeOfRank(1),
373 &feature_list_dense_prefix));
374 DimensionHandle num_examples = c->UnknownDim();
375 if (c->RankKnown(input) && c->Rank(input) == 1) {
376 num_examples = c->Dim(input, 0);
377 }
378
379 int output_idx = 0;
380 // Context outputs.
381 AddSparseOutputShapes(attrs.num_context_sparse, input, 1, c, &output_idx);
382 TF_RETURN_IF_ERROR(AddDenseOutputShapes(attrs.context_dense_shapes, input,
383 c, &output_idx));
384 TF_RETURN_IF_ERROR(AddRaggedOutputShapes(attrs.num_context_ragged, false,
385 num_examples, c, &output_idx));
386 // FeatureList outputs.
387 AddSparseOutputShapes(attrs.num_feature_list_sparse, input, 2, c,
388 &output_idx);
389 TF_RETURN_IF_ERROR(AddDenseOutputShapes(attrs.feature_list_dense_shapes,
390 feature_list_dense_prefix, c,
391 &output_idx));
392 AddDenseLengthsShapes(attrs.num_feature_list_dense, input, c,
393 &output_idx);
394 TF_RETURN_IF_ERROR(AddRaggedOutputShapes(
395 attrs.num_feature_list_ragged, true, num_examples, c, &output_idx));
396 return Status::OK();
397 });
398
399 REGISTER_OP("ParseSingleSequenceExample")
400 .Input("serialized: string")
401 .Input("feature_list_dense_missing_assumed_empty: string")
402 .Input("context_sparse_keys: Ncontext_sparse * string")
403 .Input("context_dense_keys: Ncontext_dense * string")
404 .Input("feature_list_sparse_keys: Nfeature_list_sparse * string")
405 .Input("feature_list_dense_keys: Nfeature_list_dense * string")
406 .Input("context_dense_defaults: Tcontext_dense")
407 .Input("debug_name: string")
408 .Output("context_sparse_indices: Ncontext_sparse * int64")
409 .Output("context_sparse_values: context_sparse_types")
410 .Output("context_sparse_shapes: Ncontext_sparse * int64")
411 .Output("context_dense_values: Tcontext_dense")
412 .Output("feature_list_sparse_indices: Nfeature_list_sparse * int64")
413 .Output("feature_list_sparse_values: feature_list_sparse_types")
414 .Output("feature_list_sparse_shapes: Nfeature_list_sparse * int64")
415 .Output("feature_list_dense_values: feature_list_dense_types")
416 // Infer from context_sparse_keys
417 .Attr("Ncontext_sparse: int >= 0 = 0")
418 // Infer from context_dense_keys
419 .Attr("Ncontext_dense: int >= 0 = 0")
420 // Infer from feature_list_sparse_keys
421 .Attr("Nfeature_list_sparse: int >= 0 = 0")
422 // Infer from feature_list_dense_keys
423 .Attr("Nfeature_list_dense: int >= 0 = 0")
424 .Attr("context_sparse_types: list({float,int64,string}) >= 0 = []")
425 .Attr("Tcontext_dense: list({float,int64,string}) >= 0 = []")
426 .Attr("feature_list_dense_types: list({float,int64,string}) >= 0 = []")
427 .Attr("context_dense_shapes: list(shape) >= 0 = []")
428 .Attr("feature_list_sparse_types: list({float,int64,string}) >= 0 = []")
429 .Attr("feature_list_dense_shapes: list(shape) >= 0 = []")
__anonf8f6e66e0902(InferenceContext* c) 430 .SetShapeFn([](InferenceContext* c) {
431 ShapeHandle unused;
432 ParseSingleSequenceExampleAttrs attrs;
433 TF_RETURN_IF_ERROR(attrs.Init(c));
434
435 ShapeHandle input;
436 TF_RETURN_IF_ERROR(c->WithRank(c->input(0), 0, &input));
437
438 // feature_list_dense_missing_assumed_empty
439 TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 1, &unused));
440
441 int output_idx = 0;
442 AddSparseOutputShapes(attrs.num_context_sparse, input, 1, c, &output_idx);
443 TF_RETURN_IF_ERROR(AddDenseOutputShapes(attrs.context_dense_shapes, input,
444 c, &output_idx));
445 AddSparseOutputShapes(attrs.num_feature_list_sparse, input, 2, c,
446 &output_idx);
447 TF_RETURN_IF_ERROR(AddDenseOutputShapes(attrs.feature_list_dense_shapes,
448 c->UnknownShapeOfRank(1), c,
449 &output_idx));
450 return Status::OK();
451 });
452
453 REGISTER_OP("ParseTensor")
454 .Input("serialized: string")
455 .Output("output: out_type")
456 .Attr("out_type: type")
457 .SetShapeFn(shape_inference::UnknownShape);
458
459 REGISTER_OP("SerializeTensor")
460 .Input("tensor: T")
461 .Output("serialized: string")
462 .Attr("T: type")
463 .SetShapeFn(shape_inference::ScalarShape);
464
465 REGISTER_OP("DecodeJSONExample")
466 .Input("json_examples: string")
467 .Output("binary_examples: string")
468 .SetShapeFn(shape_inference::UnchangedShape);
469
470 REGISTER_OP("DecodeCSV")
471 .Input("records: string")
472 .Input("record_defaults: OUT_TYPE")
473 .Output("output: OUT_TYPE")
474 .Attr("OUT_TYPE: list({float,double,int32,int64,string})")
475 .Attr("field_delim: string = ','")
476 .Attr("use_quote_delim: bool = true")
477 .Attr("na_value: string = ''")
478 .Attr("select_cols: list(int) = []")
__anonf8f6e66e0a02(InferenceContext* c) 479 .SetShapeFn([](InferenceContext* c) {
480 // Validate the record_defaults inputs.
481 for (int i = 1; i < c->num_inputs(); ++i) {
482 ShapeHandle v;
483 TF_RETURN_IF_ERROR(c->WithRankAtMost(c->input(i), 1, &v));
484 if (c->Rank(c->input(i)) == 1 && c->Value(c->Dim(v, 0)) > 1) {
485 return errors::InvalidArgument(
486 "Shape of a default must be a length-0 or length-1 vector, or a "
487 "scalar.");
488 }
489 }
490
491 // Propagate shape of the records input.
492 for (int i = 0; i < c->num_outputs(); ++i) c->set_output(i, c->input(0));
493 return Status::OK();
494 });
495
496 REGISTER_OP("StringToNumber")
497 .Input("string_tensor: string")
498 .Output("output: out_type")
499 .Attr("out_type: {float, double, int32, int64} = DT_FLOAT")
500 .SetShapeFn(shape_inference::UnchangedShape);
501
502 } // namespace tensorflow
503