1c8b59c046895fa5b6d79f73e0b5817330fcfbfc1A. Unique TensorFlower/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
29c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath Kudlur
39c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath KudlurLicensed under the Apache License, Version 2.0 (the "License");
49c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath Kudluryou may not use this file except in compliance with the License.
59c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath KudlurYou may obtain a copy of the License at
69c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath Kudlur
79c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath Kudlur    http://www.apache.org/licenses/LICENSE-2.0
89c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath Kudlur
99c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath KudlurUnless required by applicable law or agreed to in writing, software
109c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath Kudlurdistributed under the License is distributed on an "AS IS" BASIS,
119c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath KudlurWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
129c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath KudlurSee the License for the specific language governing permissions and
139c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath Kudlurlimitations under the License.
149c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath Kudlur==============================================================================*/
159c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath Kudlur
16f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur// See docs in ../ops/parsing_ops.cc.
17f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
185cae4a52edf9fe4951c51ee2352ca041e4ab9363Derek Murray#include <numeric>
19f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan#include <unordered_set>
20b481783fe0e00a86f6feb20a8dcad5fc4fc936a4Josh Levenberg#include <vector>
213381ef8e0137d2a2ca4bf104bf76318427829667A. Unique TensorFlower
22f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur#include "tensorflow/core/example/example.pb.h"
233883578ebff0e8f901386d6f2b5870de517de4a1A. Unique TensorFlower#include "tensorflow/core/example/feature.pb_text.h"
24cf93b043a88607db17b84b5b5d3f0064473cf5ceA. Unique TensorFlower#include "tensorflow/core/framework/common_shape_fns.h"
25f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur#include "tensorflow/core/framework/numeric_op.h"
26f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur#include "tensorflow/core/framework/register_types.h"
27db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower#include "tensorflow/core/lib/gtl/array_slice.h"
283381ef8e0137d2a2ca4bf104bf76318427829667A. Unique TensorFlower#include "tensorflow/core/platform/logging.h"
29f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur#include "tensorflow/core/platform/protobuf.h"
30db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower#include "tensorflow/core/util/example_proto_fast_parsing.h"
313381ef8e0137d2a2ca4bf104bf76318427829667A. Unique TensorFlower#include "tensorflow/core/util/example_proto_helper.h"
32f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur#include "tensorflow/core/util/sparse/sparse_tensor.h"
3397c5c72fa069e57a4c6fab0467a03a52c465bcd9A. Unique TensorFlower#include "tensorflow/core/util/work_sharder.h"
34f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
35f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlurnamespace tensorflow {
36f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
3796f3023b6a8b154c3840776c5feff3e028860a36Derek Murrayclass ParseExampleOp : public OpKernel {
38f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur public:
3996f3023b6a8b154c3840776c5feff3e028860a36Derek Murray  explicit ParseExampleOp(OpKernelConstruction* ctx) : OpKernel(ctx) {
40943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    OP_REQUIRES_OK(ctx, attrs_.Init(ctx));
41f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  }
42f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
43f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  void Compute(OpKernelContext* ctx) override {
44f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    const Tensor* names;
45f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    const Tensor* serialized;
46f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    OpInputList dense_keys;
47f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    OpInputList sparse_keys;
48f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    OpInputList dense_defaults;
49f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
503381ef8e0137d2a2ca4bf104bf76318427829667A. Unique TensorFlower    // Grab the input list arguments.
51f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    OP_REQUIRES_OK(ctx, ctx->input("names", &names));
52f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    OP_REQUIRES_OK(ctx, ctx->input("serialized", &serialized));
53f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    OP_REQUIRES_OK(ctx, ctx->input_list("dense_keys", &dense_keys));
54f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    OP_REQUIRES_OK(ctx, ctx->input_list("sparse_keys", &sparse_keys));
55f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    OP_REQUIRES_OK(ctx, ctx->input_list("dense_defaults", &dense_defaults));
56f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
57943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    std::vector<string> dense_keys_t(attrs_.num_dense);
58943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    std::vector<string> sparse_keys_t(attrs_.num_sparse);
593381ef8e0137d2a2ca4bf104bf76318427829667A. Unique TensorFlower
603381ef8e0137d2a2ca4bf104bf76318427829667A. Unique TensorFlower    // Check that the input list sizes match the attribute declared sizes.
61943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    CHECK_EQ(dense_keys.size(), attrs_.num_dense);
62943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    CHECK_EQ(sparse_keys.size(), attrs_.num_sparse);
633381ef8e0137d2a2ca4bf104bf76318427829667A. Unique TensorFlower
643381ef8e0137d2a2ca4bf104bf76318427829667A. Unique TensorFlower    // Copy from OpInputList to std::vector<string>.
65943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    for (int di = 0; di < attrs_.num_dense; ++di) {
66f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur      dense_keys_t[di] = dense_keys[di].scalar<string>()();
67f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    }
68943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    for (int di = 0; di < attrs_.num_sparse; ++di) {
69f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur      sparse_keys_t[di] = sparse_keys[di].scalar<string>()();
70f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    }
71f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
72db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower    if (names->NumElements() > 0) {
73f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur      OP_REQUIRES(
74f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur          ctx, TensorShapeUtils::IsVector(names->shape()),
75f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur          errors::InvalidArgument("Expected names to be a vector, got shape: ",
76d552be23658b3bdd1b7dedd34f25631773e81dffGeoffrey Irving                                  names->shape().DebugString()));
77f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur      OP_REQUIRES(
78f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur          ctx, names->NumElements() == serialized->NumElements(),
79f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur          errors::InvalidArgument(
80f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur              "Expected len(names) == len(serialized), but got: ",
81f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur              names->NumElements(), " vs. ", serialized->NumElements()));
82f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    }
83f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
84f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    OP_REQUIRES(ctx, TensorShapeUtils::IsVector(serialized->shape()),
85f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur                errors::InvalidArgument(
86f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur                    "Expected serialized to be a vector, got shape: ",
87d552be23658b3bdd1b7dedd34f25631773e81dffGeoffrey Irving                    serialized->shape().DebugString()));
88943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    OP_REQUIRES(ctx, dense_defaults.size() == attrs_.num_dense,
89f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur                errors::InvalidArgument(
90f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur                    "Expected len(dense_defaults) == len(dense_keys) but got: ",
91943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower                    dense_defaults.size(), " vs. ", attrs_.num_dense));
92f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
93943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    for (int d = 0; d < static_cast<int>(attrs_.num_dense); ++d) {
94f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur      const Tensor& def_value = dense_defaults[d];
95780bc6b4d98665125c43685b20eeba6ad2804c0cEugene Brevdo      if (attrs_.variable_length[d]) {
96780bc6b4d98665125c43685b20eeba6ad2804c0cEugene Brevdo        OP_REQUIRES(ctx, def_value.NumElements() == 1,
97780bc6b4d98665125c43685b20eeba6ad2804c0cEugene Brevdo                    errors::InvalidArgument(
98780bc6b4d98665125c43685b20eeba6ad2804c0cEugene Brevdo                        "dense_shape[", d, "] is a variable length shape: ",
99780bc6b4d98665125c43685b20eeba6ad2804c0cEugene Brevdo                        attrs_.dense_shapes[d].DebugString(),
100780bc6b4d98665125c43685b20eeba6ad2804c0cEugene Brevdo                        ", therefore "
101780bc6b4d98665125c43685b20eeba6ad2804c0cEugene Brevdo                        "def_value[",
102780bc6b4d98665125c43685b20eeba6ad2804c0cEugene Brevdo                        d,
103780bc6b4d98665125c43685b20eeba6ad2804c0cEugene Brevdo                        "] must contain a single element ("
104780bc6b4d98665125c43685b20eeba6ad2804c0cEugene Brevdo                        "the padding element).  But its shape is: ",
105780bc6b4d98665125c43685b20eeba6ad2804c0cEugene Brevdo                        def_value.shape().DebugString()));
106780bc6b4d98665125c43685b20eeba6ad2804c0cEugene Brevdo      } else if (def_value.NumElements() > 0) {
107a32dcc0c832929428067e93b1c05b0ef69096c0aEugene Brevdo        OP_REQUIRES(ctx,
108a32dcc0c832929428067e93b1c05b0ef69096c0aEugene Brevdo                    attrs_.dense_shapes[d].IsCompatibleWith(def_value.shape()),
109943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower                    errors::InvalidArgument(
110a32dcc0c832929428067e93b1c05b0ef69096c0aEugene Brevdo                        "def_value[", d,
111a32dcc0c832929428067e93b1c05b0ef69096c0aEugene Brevdo                        "].shape() == ", def_value.shape().DebugString(),
112a32dcc0c832929428067e93b1c05b0ef69096c0aEugene Brevdo                        " is not compatible with dense_shapes_[", d,
113a32dcc0c832929428067e93b1c05b0ef69096c0aEugene Brevdo                        "] == ", attrs_.dense_shapes[d].DebugString()));
114f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur      }
115780bc6b4d98665125c43685b20eeba6ad2804c0cEugene Brevdo      OP_REQUIRES(ctx, def_value.dtype() == attrs_.dense_types[d],
116780bc6b4d98665125c43685b20eeba6ad2804c0cEugene Brevdo                  errors::InvalidArgument(
117780bc6b4d98665125c43685b20eeba6ad2804c0cEugene Brevdo                      "dense_defaults[", d, "].dtype() == ",
118780bc6b4d98665125c43685b20eeba6ad2804c0cEugene Brevdo                      DataTypeString(def_value.dtype()), " != dense_types_[", d,
119780bc6b4d98665125c43685b20eeba6ad2804c0cEugene Brevdo                      "] == ", DataTypeString(attrs_.dense_types[d])));
120f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    }
121f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
122db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower    example::Result result;
123db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower
124db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower    example::FastParseExampleConfig config;
125db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower    for (int d = 0; d < attrs_.num_dense; ++d) {
126db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower      config.dense.push_back({dense_keys_t[d], attrs_.dense_types[d],
127a32dcc0c832929428067e93b1c05b0ef69096c0aEugene Brevdo                              attrs_.dense_shapes[d], dense_defaults[d],
128780bc6b4d98665125c43685b20eeba6ad2804c0cEugene Brevdo                              attrs_.variable_length[d],
129a32dcc0c832929428067e93b1c05b0ef69096c0aEugene Brevdo                              attrs_.elements_per_stride[d]});
130db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower    }
131db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower    for (int d = 0; d < attrs_.num_sparse; ++d) {
132db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower      config.sparse.push_back({sparse_keys_t[d], attrs_.sparse_types[d]});
133db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower    }
134db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower
135db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower    auto serialized_t = serialized->flat<string>();
136db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower    auto names_t = names->flat<string>();
137db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower    gtl::ArraySlice<string> slice(serialized_t.data(), serialized_t.size());
138db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower    gtl::ArraySlice<string> names_slice(names_t.data(), names_t.size());
139f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
140db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower    OP_REQUIRES_OK(
141db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower        ctx,
142db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower        FastParseExample(
143db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower            config, slice, names_slice,
144db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower            ctx->device()->tensorflow_cpu_worker_threads()->workers, &result));
145f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
146db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower    OpOutputList dense_values;
147f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    OpOutputList sparse_indices;
148f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    OpOutputList sparse_values;
149f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    OpOutputList sparse_shapes;
150db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower    OP_REQUIRES_OK(ctx, ctx->output_list("dense_values", &dense_values));
151f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    OP_REQUIRES_OK(ctx, ctx->output_list("sparse_indices", &sparse_indices));
152f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    OP_REQUIRES_OK(ctx, ctx->output_list("sparse_values", &sparse_values));
153f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    OP_REQUIRES_OK(ctx, ctx->output_list("sparse_shapes", &sparse_shapes));
154943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    for (int d = 0; d < attrs_.num_dense; ++d) {
155db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower      dense_values.set(d, result.dense_values[d]);
156f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    }
157943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    for (int d = 0; d < attrs_.num_sparse; ++d) {
158db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower      sparse_indices.set(d, result.sparse_indices[d]);
159db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower      sparse_values.set(d, result.sparse_values[d]);
160db7bdab6e586e02051556d9f36a7887500378cf9A. Unique TensorFlower      sparse_shapes.set(d, result.sparse_shapes[d]);
161f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    }
162f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  }
163f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
164f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur protected:
16596f3023b6a8b154c3840776c5feff3e028860a36Derek Murray  ParseExampleAttrs attrs_;
166f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur};
167f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
168f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath KudlurREGISTER_KERNEL_BUILDER(Name("ParseExample").Device(DEVICE_CPU),
16996f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                        ParseExampleOp);
17096f3023b6a8b154c3840776c5feff3e028860a36Derek Murray
17196f3023b6a8b154c3840776c5feff3e028860a36Derek Murrayclass ParseSingleExampleOp : public OpKernel {
17296f3023b6a8b154c3840776c5feff3e028860a36Derek Murray public:
17396f3023b6a8b154c3840776c5feff3e028860a36Derek Murray  explicit ParseSingleExampleOp(OpKernelConstruction* ctx) : OpKernel(ctx) {
17496f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    OP_REQUIRES_OK(ctx, attrs_.Init(ctx));
17596f3023b6a8b154c3840776c5feff3e028860a36Derek Murray  }
17696f3023b6a8b154c3840776c5feff3e028860a36Derek Murray
17796f3023b6a8b154c3840776c5feff3e028860a36Derek Murray  void Compute(OpKernelContext* ctx) override {
17896f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    const Tensor* serialized;
17996f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    OpInputList dense_defaults;
18096f3023b6a8b154c3840776c5feff3e028860a36Derek Murray
18196f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    // Grab the input list arguments.
18296f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    OP_REQUIRES_OK(ctx, ctx->input("serialized", &serialized));
18396f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    OP_REQUIRES_OK(ctx, ctx->input_list("dense_defaults", &dense_defaults));
18496f3023b6a8b154c3840776c5feff3e028860a36Derek Murray
18596f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    OP_REQUIRES(ctx, TensorShapeUtils::IsScalar(serialized->shape()),
18696f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                errors::InvalidArgument(
18796f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                    "Expected serialized to be a scalar, got shape: ",
18896f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                    serialized->shape().DebugString()));
18996f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    OP_REQUIRES(ctx, dense_defaults.size() == attrs_.dense_keys.size(),
19096f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                errors::InvalidArgument(
19196f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                    "Expected len(dense_defaults) == len(dense_keys) but got: ",
19296f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                    dense_defaults.size(), " vs. ", attrs_.dense_keys.size()));
19396f3023b6a8b154c3840776c5feff3e028860a36Derek Murray
19496f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    for (size_t d = 0; d < attrs_.dense_keys.size(); ++d) {
19596f3023b6a8b154c3840776c5feff3e028860a36Derek Murray      const Tensor& def_value = dense_defaults[d];
19696f3023b6a8b154c3840776c5feff3e028860a36Derek Murray      if (attrs_.variable_length[d]) {
19796f3023b6a8b154c3840776c5feff3e028860a36Derek Murray        OP_REQUIRES(ctx, def_value.NumElements() == 1,
19896f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                    errors::InvalidArgument(
19996f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                        "dense_shape[", d, "] is a variable length shape: ",
20096f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                        attrs_.dense_shapes[d].DebugString(),
20196f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                        ", therefore "
20296f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                        "def_value[",
20396f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                        d,
20496f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                        "] must contain a single element ("
20596f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                        "the padding element).  But its shape is: ",
20696f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                        def_value.shape().DebugString()));
20796f3023b6a8b154c3840776c5feff3e028860a36Derek Murray      } else if (def_value.NumElements() > 0) {
20896f3023b6a8b154c3840776c5feff3e028860a36Derek Murray        OP_REQUIRES(ctx,
20996f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                    attrs_.dense_shapes[d].IsCompatibleWith(def_value.shape()),
21096f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                    errors::InvalidArgument(
21196f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                        "def_value[", d,
21296f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                        "].shape() == ", def_value.shape().DebugString(),
21396f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                        " is not compatible with dense_shapes_[", d,
21496f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                        "] == ", attrs_.dense_shapes[d].DebugString()));
21596f3023b6a8b154c3840776c5feff3e028860a36Derek Murray      }
21696f3023b6a8b154c3840776c5feff3e028860a36Derek Murray      OP_REQUIRES(ctx, def_value.dtype() == attrs_.dense_types[d],
21796f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                  errors::InvalidArgument(
21896f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                      "dense_defaults[", d, "].dtype() == ",
21996f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                      DataTypeString(def_value.dtype()), " != dense_types_[", d,
22096f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                      "] == ", DataTypeString(attrs_.dense_types[d])));
22196f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    }
22296f3023b6a8b154c3840776c5feff3e028860a36Derek Murray
22396f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    example::Result result;
22496f3023b6a8b154c3840776c5feff3e028860a36Derek Murray
22596f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    // TODO(mrry): Build the configuration once and cache it.
22696f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    example::FastParseExampleConfig config;
22796f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    for (int d = 0; d < attrs_.dense_keys.size(); ++d) {
22896f3023b6a8b154c3840776c5feff3e028860a36Derek Murray      config.dense.push_back({attrs_.dense_keys[d], attrs_.dense_types[d],
22996f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                              attrs_.dense_shapes[d], dense_defaults[d],
23096f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                              attrs_.variable_length[d],
23196f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                              attrs_.elements_per_stride[d]});
23296f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    }
23396f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    for (int d = 0; d < attrs_.sparse_keys.size(); ++d) {
23496f3023b6a8b154c3840776c5feff3e028860a36Derek Murray      config.sparse.push_back({attrs_.sparse_keys[d], attrs_.sparse_types[d]});
23596f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    }
23696f3023b6a8b154c3840776c5feff3e028860a36Derek Murray
23796f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    const string& serialized_proto = serialized->scalar<string>()();
23896f3023b6a8b154c3840776c5feff3e028860a36Derek Murray
23996f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    OP_REQUIRES_OK(ctx,
24096f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                   FastParseSingleExample(config, serialized_proto, &result));
24196f3023b6a8b154c3840776c5feff3e028860a36Derek Murray
24296f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    OpOutputList dense_values;
24396f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    OpOutputList sparse_indices;
24496f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    OpOutputList sparse_values;
24596f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    OpOutputList sparse_shapes;
24696f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    OP_REQUIRES_OK(ctx, ctx->output_list("dense_values", &dense_values));
24796f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    OP_REQUIRES_OK(ctx, ctx->output_list("sparse_indices", &sparse_indices));
24896f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    OP_REQUIRES_OK(ctx, ctx->output_list("sparse_values", &sparse_values));
24996f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    OP_REQUIRES_OK(ctx, ctx->output_list("sparse_shapes", &sparse_shapes));
25096f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    for (int d = 0; d < attrs_.dense_keys.size(); ++d) {
25196f3023b6a8b154c3840776c5feff3e028860a36Derek Murray      dense_values.set(d, result.dense_values[d]);
25296f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    }
25396f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    for (int d = 0; d < attrs_.sparse_keys.size(); ++d) {
25496f3023b6a8b154c3840776c5feff3e028860a36Derek Murray      sparse_indices.set(d, result.sparse_indices[d]);
25596f3023b6a8b154c3840776c5feff3e028860a36Derek Murray      sparse_values.set(d, result.sparse_values[d]);
25696f3023b6a8b154c3840776c5feff3e028860a36Derek Murray      sparse_shapes.set(d, result.sparse_shapes[d]);
25796f3023b6a8b154c3840776c5feff3e028860a36Derek Murray    }
25896f3023b6a8b154c3840776c5feff3e028860a36Derek Murray  }
25996f3023b6a8b154c3840776c5feff3e028860a36Derek Murray
26096f3023b6a8b154c3840776c5feff3e028860a36Derek Murray protected:
26196f3023b6a8b154c3840776c5feff3e028860a36Derek Murray  ParseSingleExampleAttrs attrs_;
26296f3023b6a8b154c3840776c5feff3e028860a36Derek Murray};
26396f3023b6a8b154c3840776c5feff3e028860a36Derek Murray
26496f3023b6a8b154c3840776c5feff3e028860a36Derek MurrayREGISTER_KERNEL_BUILDER(Name("ParseSingleExample").Device(DEVICE_CPU),
26596f3023b6a8b154c3840776c5feff3e028860a36Derek Murray                        ParseSingleExampleOp);
266f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
267943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlowerclass SingleSequenceExampleParserOp : public OpKernel {
268943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower public:
269943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower  explicit SingleSequenceExampleParserOp(OpKernelConstruction* ctx)
270943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower      : OpKernel(ctx) {
271943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    OP_REQUIRES_OK(ctx, attrs_.Init(ctx));
272f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan  }
273f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
274f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan  void Compute(OpKernelContext* ctx) override {
275f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    const Tensor* debug_name;
276f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    const Tensor* serialized;
277f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    OpInputList context_dense_keys;
278f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    OpInputList context_sparse_keys;
279f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    OpInputList context_dense_defaults;
280f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    OpInputList feature_list_dense_keys;
2811c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower    OpInputList feature_list_sparse_keys;
282f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    const Tensor* feature_list_dense_missing_assumed_empty;
283f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
284f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    OP_REQUIRES_OK(ctx, ctx->input("debug_name", &debug_name));
285f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    OP_REQUIRES_OK(ctx, ctx->input("serialized", &serialized));
286f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    OP_REQUIRES_OK(ctx, ctx->input("feature_list_dense_missing_assumed_empty",
287f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                                   &feature_list_dense_missing_assumed_empty));
288f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    OP_REQUIRES_OK(ctx,
289f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                   ctx->input_list("context_dense_keys", &context_dense_keys));
290f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    OP_REQUIRES_OK(ctx, ctx->input_list("feature_list_dense_keys",
291f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                                        &feature_list_dense_keys));
292f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    OP_REQUIRES_OK(
293f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        ctx, ctx->input_list("context_sparse_keys", &context_sparse_keys));
2941c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower    OP_REQUIRES_OK(ctx, ctx->input_list("feature_list_sparse_keys",
2951c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower                                        &feature_list_sparse_keys));
296f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    OP_REQUIRES_OK(ctx, ctx->input_list("context_dense_defaults",
297f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                                        &context_dense_defaults));
298f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
299943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    std::vector<string> context_dense_keys_t(attrs_.num_context_dense);
300943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    std::vector<string> context_sparse_keys_t(attrs_.num_context_sparse);
301943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    std::vector<string> feature_list_dense_keys_t(
302943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower        attrs_.num_feature_list_dense);
303943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    std::vector<string> feature_list_sparse_keys_t(
304943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower        attrs_.num_feature_list_sparse);
305f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    std::unordered_set<string> feature_list_dense_missing_assumed_empty_set;
306943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    CHECK_EQ(context_dense_keys.size(), attrs_.num_context_dense);
307943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    CHECK_EQ(context_sparse_keys.size(), attrs_.num_context_sparse);
308943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    CHECK_EQ(feature_list_dense_keys.size(), attrs_.num_feature_list_dense);
309943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    CHECK_EQ(feature_list_sparse_keys.size(), attrs_.num_feature_list_sparse);
310943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    for (int di = 0; di < attrs_.num_context_dense; ++di) {
311f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      OP_REQUIRES(ctx,
312f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                  TensorShapeUtils::IsScalar(context_dense_keys[di].shape()),
313f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                  errors::InvalidArgument(
314f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                      "Expected context_dense_keys[", di,
315cc741b48e8bba90670fe9db3811d50f283ea8b1bA. Unique TensorFlower                      "] to be a scalar, got shape: ",
316d552be23658b3bdd1b7dedd34f25631773e81dffGeoffrey Irving                      context_dense_keys[di].shape().DebugString()));
317f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      context_dense_keys_t[di] = context_dense_keys[di].scalar<string>()();
318f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    }
319943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    for (int di = 0; di < attrs_.num_context_sparse; ++di) {
320f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      OP_REQUIRES(ctx,
321f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                  TensorShapeUtils::IsScalar(context_sparse_keys[di].shape()),
322f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                  errors::InvalidArgument(
323f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                      "Expected context_sparse_keys[", di,
324cc741b48e8bba90670fe9db3811d50f283ea8b1bA. Unique TensorFlower                      "] to be a scalar, got shape: ",
325d552be23658b3bdd1b7dedd34f25631773e81dffGeoffrey Irving                      context_sparse_keys[di].shape().DebugString()));
326f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      context_sparse_keys_t[di] = context_sparse_keys[di].scalar<string>()();
327f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    }
328943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    for (int di = 0; di < attrs_.num_feature_list_dense; ++di) {
329f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      OP_REQUIRES(
330f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan          ctx, TensorShapeUtils::IsScalar(feature_list_dense_keys[di].shape()),
331f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan          errors::InvalidArgument(
332f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan              "Expected feature_list_dense_keys[", di,
333cc741b48e8bba90670fe9db3811d50f283ea8b1bA. Unique TensorFlower              "] to be a scalar, got shape: ",
334d552be23658b3bdd1b7dedd34f25631773e81dffGeoffrey Irving              feature_list_dense_keys[di].shape().DebugString()));
335f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      feature_list_dense_keys_t[di] =
336f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan          feature_list_dense_keys[di].scalar<string>()();
337f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    }
338943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    for (int di = 0; di < attrs_.num_feature_list_sparse; ++di) {
3391c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower      OP_REQUIRES(
3401c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower          ctx, TensorShapeUtils::IsScalar(feature_list_sparse_keys[di].shape()),
3411c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower          errors::InvalidArgument(
3421c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower              "Expected feature_list_sparse_keys[", di,
343cc741b48e8bba90670fe9db3811d50f283ea8b1bA. Unique TensorFlower              "] to be a scalar, got shape: ",
344d552be23658b3bdd1b7dedd34f25631773e81dffGeoffrey Irving              feature_list_sparse_keys[di].shape().DebugString()));
3451c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower      feature_list_sparse_keys_t[di] =
3461c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower          feature_list_sparse_keys[di].scalar<string>()();
3471c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower    }
348d552be23658b3bdd1b7dedd34f25631773e81dffGeoffrey Irving    OP_REQUIRES(
349982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen        ctx,
350982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen        TensorShapeUtils::IsVector(
351982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen            feature_list_dense_missing_assumed_empty->shape()),
352d552be23658b3bdd1b7dedd34f25631773e81dffGeoffrey Irving        errors::InvalidArgument(
353d552be23658b3bdd1b7dedd34f25631773e81dffGeoffrey Irving            "Expected feature_list_dense_missing_assumed_empty ",
354d552be23658b3bdd1b7dedd34f25631773e81dffGeoffrey Irving            "to be a vector, got shape: ",
355d552be23658b3bdd1b7dedd34f25631773e81dffGeoffrey Irving            feature_list_dense_missing_assumed_empty->shape().DebugString()));
356f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    auto feature_list_dense_missing_assumped_empty_t =
357f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        feature_list_dense_missing_assumed_empty->vec<string>();
358f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    for (int de = 0;
359f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan         de < feature_list_dense_missing_assumed_empty->NumElements(); ++de) {
360f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      feature_list_dense_missing_assumed_empty_set.insert(
361f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan          feature_list_dense_missing_assumped_empty_t(de));
362f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    }
363f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
364f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    bool has_debug_name = (debug_name->NumElements() > 0);
365f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    if (has_debug_name) {
366f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      OP_REQUIRES(ctx, TensorShapeUtils::IsScalar(debug_name->shape()),
367f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                  errors::InvalidArgument(
368f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                      "Expected debug_name to be a scalar, got shape: ",
369d552be23658b3bdd1b7dedd34f25631773e81dffGeoffrey Irving                      debug_name->shape().DebugString()));
370f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    }
371f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    auto debug_name_t = debug_name->scalar<string>();
372f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
373f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    OP_REQUIRES(ctx, TensorShapeUtils::IsScalar(serialized->shape()),
374f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                errors::InvalidArgument(
375f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                    "Expected serialized to be a scalar, got shape: ",
376d552be23658b3bdd1b7dedd34f25631773e81dffGeoffrey Irving                    serialized->shape().DebugString()));
377f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
378943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    OP_REQUIRES(ctx, context_dense_defaults.size() == attrs_.num_context_dense,
379f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                errors::InvalidArgument("Expected len(context_dense_defaults) "
380f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                                        "== len(context_dense_keys) but got: ",
381f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                                        context_dense_defaults.size(), " vs. ",
382943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower                                        attrs_.num_context_dense));
383f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
384943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    std::vector<bool> required(attrs_.num_context_dense);
385943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    for (int d = 0; d < attrs_.num_context_dense; ++d) {
386f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      const Tensor& def_value = context_dense_defaults[d];
387f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      required[d] = (def_value.NumElements() == 0);  // No default provided.
388f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
389f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      if (def_value.NumElements() > 0) {
390982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen        OP_REQUIRES(ctx, def_value.shape() == attrs_.context_dense_shapes[d],
391982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen                    errors::InvalidArgument(
392982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen                        "def_value[", d,
393982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen                        "].shape() == ", def_value.shape().DebugString(),
394982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen                        " != context_dense_shapes_[", d,
395982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen                        "] == ", attrs_.context_dense_shapes[d].DebugString()));
396f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        OP_REQUIRES(
397943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower            ctx, def_value.dtype() == attrs_.context_dense_types[d],
398f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan            errors::InvalidArgument(
399f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                "context_dense_defaults[", d, "].dtype() == ",
400f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                DataTypeString(def_value.dtype()), " != context_dense_types_[",
401943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower                d, "] == ", DataTypeString(attrs_.context_dense_types[d])));
402f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      }
403f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    }
404f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
405f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    auto serialized_t = serialized->scalar<string>();
406f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
407f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    OpOutputList context_sparse_indices;
408f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    OpOutputList context_sparse_values;
409f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    OpOutputList context_sparse_shapes;
410f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    OpOutputList context_dense_values;
4111c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower    OpOutputList feature_list_sparse_indices;
4121c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower    OpOutputList feature_list_sparse_values;
4131c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower    OpOutputList feature_list_sparse_shapes;
414f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    OpOutputList feature_list_dense_values;
415f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
416f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    OP_REQUIRES_OK(ctx, ctx->output_list("context_sparse_indices",
417f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                                         &context_sparse_indices));
418f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    OP_REQUIRES_OK(
419f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        ctx, ctx->output_list("context_sparse_values", &context_sparse_values));
420f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    OP_REQUIRES_OK(
421f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        ctx, ctx->output_list("context_sparse_shapes", &context_sparse_shapes));
422f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    OP_REQUIRES_OK(
423f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        ctx, ctx->output_list("context_dense_values", &context_dense_values));
4241c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower    OP_REQUIRES_OK(ctx, ctx->output_list("context_sparse_indices",
4251c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower                                         &context_sparse_indices));
4261c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower    OP_REQUIRES_OK(ctx, ctx->output_list("feature_list_sparse_indices",
4271c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower                                         &feature_list_sparse_indices));
4281c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower    OP_REQUIRES_OK(ctx, ctx->output_list("feature_list_sparse_values",
4291c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower                                         &feature_list_sparse_values));
4301c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower    OP_REQUIRES_OK(ctx, ctx->output_list("feature_list_sparse_shapes",
4311c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower                                         &feature_list_sparse_shapes));
432f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    OP_REQUIRES_OK(ctx, ctx->output_list("feature_list_dense_values",
433f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                                         &feature_list_dense_values));
434f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
435f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    SequenceExample ex;
436f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    OP_REQUIRES(
437f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        ctx, ParseProtoUnlimited(&ex, serialized_t()),
438f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        errors::InvalidArgument("Could not parse example input, value: '",
439f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                                serialized_t(), "'"));
440f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
441f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    const string& name = (has_debug_name) ? debug_name_t() : "<unknown>";
442f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    const Features& context = ex.context();
443f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    const auto& context_dict = context.feature();
444f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
445f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    // Context Dense -----------------------------------------------------------
446f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
447f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    // Preallocate context_dense_values, since we know their sizes
448943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    for (int d = 0; d < attrs_.num_context_dense; ++d) {
449f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      TensorShape out_shape;
450943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower      for (const int dim : attrs_.context_dense_shapes[d].dim_sizes())
451f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        out_shape.AddDim(dim);
452f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      Tensor* out = nullptr;
453bc225bfaa534acc25047fe844f19edc333b7a76aPeter Hawkins      OP_REQUIRES_OK(ctx, context_dense_values.allocate(d, out_shape, &out));
454f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    }
455f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
456943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    for (int d = 0; d < attrs_.num_context_dense; ++d) {
457f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      const string& key = context_dense_keys_t[d];
458943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower      const DataType& dtype = attrs_.context_dense_types[d];
459943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower      const TensorShape& shape = attrs_.context_dense_shapes[d];
460f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
461f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      const auto& feature_found = context_dict.find(key);
462f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      OP_REQUIRES(
463f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan          ctx, (feature_found != context_dict.end()) || !required[d],
464f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan          errors::InvalidArgument("Name: ", name, ", Context feature '", key,
465f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                                  "' is required but could not be found."));
466f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      if (feature_found != context_dict.end()) {
467f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        const Feature& f = feature_found->second;
468f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        bool types_match;
469f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        OP_REQUIRES_OK(ctx, CheckTypesMatch(f, dtype, &types_match));
470f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        OP_REQUIRES(
471f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan            ctx, types_match,
472f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan            errors::InvalidArgument("Name: ", name, ", Context feature: ", key,
473f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                                    ".  Data types don't match. ",
474f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                                    "Expected type: ", DataTypeString(dtype),
4753883578ebff0e8f901386d6f2b5870de517de4a1A. Unique TensorFlower                                    "  Feature is: ", ProtoDebugString(f)));
476f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
477f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        OP_REQUIRES_OK(ctx, FeatureDenseCopy(0, name, key, dtype, shape, f,
478f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                                             context_dense_values[d]));
479f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      } else {
480f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        RowDenseCopy(0, dtype, context_dense_defaults[d],
481f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                     context_dense_values[d]);
482f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      }
483f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    }
484f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
485f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    // Context Sparse ----------------------------------------------------------
486943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    for (int d = 0; d < attrs_.num_context_sparse; ++d) {
487f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      const string& key = context_sparse_keys_t[d];
488943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower      const DataType& dtype = attrs_.context_sparse_types[d];
489f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
490f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      const auto& feature_found = context_dict.find(key);
491f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      bool feature_has_data =  // Found key & data type is set
492f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan          (feature_found != context_dict.end() &&
493f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan           (feature_found->second.kind_case() != Feature::KIND_NOT_SET));
494f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
495f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      if (feature_has_data) {
496f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        const Feature& f = feature_found->second;
497f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        bool types_match;
498f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        OP_REQUIRES_OK(ctx, CheckTypesMatch(f, dtype, &types_match));
499f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        OP_REQUIRES(
500f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan            ctx, types_match,
501f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan            errors::InvalidArgument("Name: ", name, ", Context feature: ", key,
502f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                                    ".  Data types don't match. ",
503f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                                    "Expected type: ", DataTypeString(dtype),
5043883578ebff0e8f901386d6f2b5870de517de4a1A. Unique TensorFlower                                    "  Feature is: ", ProtoDebugString(f)));
505f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
506f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        Tensor feature_values = FeatureSparseCopy(0, key, dtype, f);
507f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        const int64 num_elements = feature_values.NumElements();
508f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        TensorShape indices_shape({num_elements, 1});
509f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        Tensor* sp_indices_d = nullptr;
510f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        Tensor* sp_shape_d = nullptr;
511bc225bfaa534acc25047fe844f19edc333b7a76aPeter Hawkins        OP_REQUIRES_OK(ctx, context_sparse_indices.allocate(d, indices_shape,
512bc225bfaa534acc25047fe844f19edc333b7a76aPeter Hawkins                                                            &sp_indices_d));
513f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        context_sparse_values.set(d, feature_values);
514bc225bfaa534acc25047fe844f19edc333b7a76aPeter Hawkins        OP_REQUIRES_OK(ctx, context_sparse_shapes.allocate(d, TensorShape({1}),
515bc225bfaa534acc25047fe844f19edc333b7a76aPeter Hawkins                                                           &sp_shape_d));
516f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        auto shape_t = sp_shape_d->vec<int64>();
517f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        shape_t(0) = num_elements;
518f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        auto indices_t = sp_indices_d->matrix<int64>();
519f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        std::iota(indices_t.data(), indices_t.data() + num_elements, 0);
520f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      } else {
521f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        TensorShape indices_shape({0, 1});
522f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        TensorShape values_shape({0});
523f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        Tensor* sp_indices_d = nullptr;
524f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        Tensor* sp_values_d = nullptr;
525f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        Tensor* sp_shape_d = nullptr;
526bc225bfaa534acc25047fe844f19edc333b7a76aPeter Hawkins        OP_REQUIRES_OK(ctx, context_sparse_indices.allocate(d, indices_shape,
527bc225bfaa534acc25047fe844f19edc333b7a76aPeter Hawkins                                                            &sp_indices_d));
528bc225bfaa534acc25047fe844f19edc333b7a76aPeter Hawkins        OP_REQUIRES_OK(
529bc225bfaa534acc25047fe844f19edc333b7a76aPeter Hawkins            ctx, context_sparse_values.allocate(d, values_shape, &sp_values_d));
530bc225bfaa534acc25047fe844f19edc333b7a76aPeter Hawkins        OP_REQUIRES_OK(ctx, context_sparse_shapes.allocate(d, TensorShape({1}),
531bc225bfaa534acc25047fe844f19edc333b7a76aPeter Hawkins                                                           &sp_shape_d));
532f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        auto shape_t = sp_shape_d->vec<int64>();
533f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        shape_t(0) = 0;
534f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      }
535f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    }
536f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
537f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    // Feature List Dense ------------------------------------------------------
538f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
539f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    // Preallocate context_dense_values, since we can infer their
540f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    // sizes
541f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    const FeatureLists& feature_lists = ex.feature_lists();
542f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    const auto& feature_list_dict = feature_lists.feature_list();
543f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    FeatureList empty_feature_list;  // Placeholder for missing FLs
544f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
545943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    for (int d = 0; d < attrs_.num_feature_list_dense; ++d) {
546f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      const string& key = feature_list_dense_keys_t[d];
547943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower      const DataType& dtype = attrs_.feature_list_dense_types[d];
548943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower      const TensorShape& shape = attrs_.feature_list_dense_shapes[d];
549f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
550f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      const auto& feature_list_found = feature_list_dict.find(key);
551f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      bool feature_list_missing =
552f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan          (feature_list_found == feature_list_dict.end());
553f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      bool feature_list_allowed_missing =
554f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan          (feature_list_dense_missing_assumed_empty_set.count(key) > 0);
555f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
556f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      OP_REQUIRES(
557f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan          ctx, !feature_list_missing || feature_list_allowed_missing,
558f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan          errors::InvalidArgument("Name: ", name, ", Feature list '", key,
559f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                                  "' is required but could not be found.  "
560f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                                  "Did you mean to include it in "
561f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                                  "feature_list_dense_missing_assumed_empty or "
562f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                                  "feature_list_dense_defaults?"));
563f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
564f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      TensorShape out_shape;
565f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      const FeatureList& fl = (feature_list_missing)
566f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                                  ? empty_feature_list
567f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                                  : feature_list_found->second;
568f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      out_shape.AddDim(fl.feature_size());
569943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower      for (const int dim : attrs_.feature_list_dense_shapes[d].dim_sizes()) {
570f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        out_shape.AddDim(dim);
571f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      }
572f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      Tensor* out = nullptr;
573bc225bfaa534acc25047fe844f19edc333b7a76aPeter Hawkins      OP_REQUIRES_OK(ctx,
574bc225bfaa534acc25047fe844f19edc333b7a76aPeter Hawkins                     feature_list_dense_values.allocate(d, out_shape, &out));
575f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
576f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      for (int64 t = 0; t < fl.feature_size(); ++t) {
577f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        const Feature& f = fl.feature(t);
578f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        bool types_match;
579f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        OP_REQUIRES_OK(ctx, CheckTypesMatch(f, dtype, &types_match));
580982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen        OP_REQUIRES(ctx, types_match,
581982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen                    errors::InvalidArgument(
582982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen                        "Name: ", name, ", Feature list: ", key, ", Index: ", t,
583982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen                        ".  Data types don't match. ",
584982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen                        "Expected type: ", DataTypeString(dtype),
585982549ea3423df4270ff154e5c764beb43d472daRasmus Munk Larsen                        "  Feature is: ", ProtoDebugString(f)));
586f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan        OP_REQUIRES_OK(ctx, FeatureDenseCopy(t, name, key, dtype, shape, f,
587f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                                             feature_list_dense_values[d]));
588f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan      }
589f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan    }
5901c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower
5911c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower    // Feature List Sparse -----------------------------------------------------
592943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower    for (int d = 0; d < attrs_.num_feature_list_sparse; ++d) {
5931c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower      const string& key = feature_list_sparse_keys_t[d];
594943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower      const DataType& dtype = attrs_.feature_list_sparse_types[d];
5951c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower
5961c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower      const auto& feature_list_found = feature_list_dict.find(key);
5971c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower      bool feature_list_has_data =  // Found key
5981c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower          (feature_list_found != feature_list_dict.end());
5991c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower
6001c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower      std::vector<Tensor> sparse_values_tmp;
6011c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower      int64 feature_list_size = 0;
6021c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower      if (feature_list_has_data) {
6031c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower        const FeatureList& fl = feature_list_found->second;
6041c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower        feature_list_size = fl.feature_size();
6051c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower        for (int64 t = 0; t < feature_list_size; ++t) {
6061c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower          const Feature& f = fl.feature(t);
6071c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower          bool types_match;
6081c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower          OP_REQUIRES_OK(ctx, CheckTypesMatch(f, dtype, &types_match));
609a245f73c7d9dea4aeb5c524e290f05ef6d5efdabA. Unique TensorFlower          OP_REQUIRES(
610a245f73c7d9dea4aeb5c524e290f05ef6d5efdabA. Unique TensorFlower              ctx, f.kind_case() == Feature::KIND_NOT_SET || types_match,
611a245f73c7d9dea4aeb5c524e290f05ef6d5efdabA. Unique TensorFlower              errors::InvalidArgument("Name: ", name, ", Feature List: ", key,
612a245f73c7d9dea4aeb5c524e290f05ef6d5efdabA. Unique TensorFlower                                      ", Index: ", t,
613a245f73c7d9dea4aeb5c524e290f05ef6d5efdabA. Unique TensorFlower                                      ".  Data types don't match. ",
614a245f73c7d9dea4aeb5c524e290f05ef6d5efdabA. Unique TensorFlower                                      "Expected type: ", DataTypeString(dtype),
615a245f73c7d9dea4aeb5c524e290f05ef6d5efdabA. Unique TensorFlower                                      "  Feature is: ", ProtoDebugString(f)));
6161c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower          sparse_values_tmp.push_back(FeatureSparseCopy(t, key, dtype, f));
6171c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower        }
6181c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower      } else {
6191c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower        sparse_values_tmp.push_back(Tensor(dtype, TensorShape({0})));
6201c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower      }
6211c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower
6221c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower      int64 total_num_features = 0;
6231c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower      int64 max_num_features = 0;
6241c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower      for (int t = 0; t < feature_list_size; ++t) {
6251c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower        const Tensor& v = sparse_values_tmp[t];
6261c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower        const int64 num_elements = v.shape().num_elements();
6271c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower        total_num_features += num_elements;
6281c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower        max_num_features = std::max(max_num_features, num_elements);
6291c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower      }
6301c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower
6311c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower      TensorShape indices_shape({total_num_features, 2});
6321c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower      TensorShape values_shape({total_num_features});
6331c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower      Tensor* sp_indices_d = nullptr;
6341c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower      Tensor* sp_values_d = nullptr;
6351c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower      Tensor* sp_shape_d = nullptr;
636bc225bfaa534acc25047fe844f19edc333b7a76aPeter Hawkins      OP_REQUIRES_OK(ctx, feature_list_sparse_indices.allocate(d, indices_shape,
637bc225bfaa534acc25047fe844f19edc333b7a76aPeter Hawkins                                                               &sp_indices_d));
638bc225bfaa534acc25047fe844f19edc333b7a76aPeter Hawkins      OP_REQUIRES_OK(ctx, feature_list_sparse_values.allocate(d, values_shape,
639bc225bfaa534acc25047fe844f19edc333b7a76aPeter Hawkins                                                              &sp_values_d));
640bc225bfaa534acc25047fe844f19edc333b7a76aPeter Hawkins      OP_REQUIRES_OK(ctx, feature_list_sparse_shapes.allocate(
641bc225bfaa534acc25047fe844f19edc333b7a76aPeter Hawkins                              d, TensorShape({2}), &sp_shape_d));
6421c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower      auto shape_t = sp_shape_d->vec<int64>();
6431c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower      shape_t(0) = feature_list_size;
6441c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower      shape_t(1) = max_num_features;
6451c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower
6461c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower      int64 offset = 0;
6471c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower
6481c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower      for (int t = 0; t < feature_list_size; ++t) {
6491c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower        const int64 num_elements = CopyIntoSparseTensor(
6501c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower            sparse_values_tmp[t], t, offset, sp_indices_d, sp_values_d);
6511c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower        offset += num_elements;
6521c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower      }
6531c579361cd1e088dd5e05a394b1561a73e3667baA. Unique TensorFlower    }
654f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan  }
655f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
656f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan protected:
657943745c4e145962f1614282ba5f70e9dd70fc9edA. Unique TensorFlower  ParseSingleSequenceExampleAttrs attrs_;
658f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan};
659f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
660f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay VasudevanREGISTER_KERNEL_BUILDER(Name("ParseSingleSequenceExample").Device(DEVICE_CPU),
661f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan                        SingleSequenceExampleParserOp);
662f9d3e9d03c69bfac77a2fe1ad80f7c5aa517e0f0Vijay Vasudevan
663f2ae2dbcf37cd4ca40de8a7a149d88f3d4435d27A. Unique TensorFlower#ifndef IS_MOBILE_PLATFORM
664f2ae2dbcf37cd4ca40de8a7a149d88f3d4435d27A. Unique TensorFlower// when using lite protos on mobile, decoding JSON is not available.
665f2ae2dbcf37cd4ca40de8a7a149d88f3d4435d27A. Unique TensorFlower
6663ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murrayclass DecodeJSONExampleOp : public OpKernel {
6673ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray public:
6683ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray  explicit DecodeJSONExampleOp(OpKernelConstruction* ctx) : OpKernel(ctx) {
6693ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray    resolver_.reset(protobuf::util::NewTypeResolverForDescriptorPool(
6703ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray        "type.googleapis.com", protobuf::DescriptorPool::generated_pool()));
6713ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray  }
6723ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray
6733ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray  void Compute(OpKernelContext* ctx) {
6743ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray    const Tensor* json_examples;
6753ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray    OP_REQUIRES_OK(ctx, ctx->input("json_examples", &json_examples));
6763ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray    Tensor* binary_examples;
6773ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray    OP_REQUIRES_OK(
6783ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray        ctx, ctx->allocate_output("binary_examples", json_examples->shape(),
6793ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray                                  &binary_examples));
6803ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray
6813ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray    for (int i = 0; i < json_examples->NumElements(); ++i) {
6823ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray      const string& json_example = json_examples->flat<string>()(i);
6833ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray      auto status = protobuf::util::JsonToBinaryString(
6843ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray          resolver_.get(), "type.googleapis.com/tensorflow.Example",
6853ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray          json_example, &binary_examples->flat<string>()(i));
6863ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray      OP_REQUIRES(ctx, status.ok(),
6873ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray                  errors::InvalidArgument("Error while parsing JSON: ",
6883ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray                                          string(status.error_message())));
6893ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray    }
6903ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray  }
6913ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray
6923ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray private:
6933ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray  std::unique_ptr<protobuf::util::TypeResolver> resolver_;
6943ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray};
6953ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray
6963ea040538b318b8e2d76f626fa34df801e1af1d0Derek MurrayREGISTER_KERNEL_BUILDER(Name("DecodeJSONExample").Device(DEVICE_CPU),
6973ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray                        DecodeJSONExampleOp);
698f2ae2dbcf37cd4ca40de8a7a149d88f3d4435d27A. Unique TensorFlower#endif
6993ea040538b318b8e2d76f626fa34df801e1af1d0Derek Murray
700f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur}  // namespace tensorflow
701