• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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