From c38f1ac2bd8f0664831a476243d3d4534a566668 Mon Sep 17 00:00:00 2001 From: Peter Hawkins Date: Fri, 5 May 2017 06:00:35 -0800 Subject: [PATCH 01/27] [TF:XLA] Update LLVM revision to SVN revision r302214. Change: 155192906 --- tensorflow/workspace.bzl | 8 ++++---- third_party/llvm/llvm.BUILD | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/tensorflow/workspace.bzl b/tensorflow/workspace.bzl index 50e329f8c09..14fce6cf404 100644 --- a/tensorflow/workspace.bzl +++ b/tensorflow/workspace.bzl @@ -479,11 +479,11 @@ def tf_workspace(path_prefix="", tf_repo_name=""): temp_workaround_http_archive( name = "llvm", urls = [ - "http://bazel-mirror.storage.googleapis.com/github.com/llvm-mirror/llvm/archive/8a1f075c93565dd665a10ac38490f644b2c02037.tar.gz", - "https://github.com/llvm-mirror/llvm/archive/8a1f075c93565dd665a10ac38490f644b2c02037.tar.gz", + "http://bazel-mirror.storage.googleapis.com/github.com/llvm-mirror/llvm/archive/13790c8735a78a029dec92d80f5633418d9ffdd6.tar.gz", + "https://github.com/llvm-mirror/llvm/archive/13790c8735a78a029dec92d80f5633418d9ffdd6.tar.gz", ], - sha256 = "d9ebd0b49544f3b20ee2a412aac18ed8899b8eef376343a6ba8e179563cbfd86", - strip_prefix = "llvm-8a1f075c93565dd665a10ac38490f644b2c02037", + sha256 = "da4fc7147f1e2706977822934d1b245dcb6248930f8089129362ada14f6119dd", + strip_prefix = "llvm-13790c8735a78a029dec92d80f5633418d9ffdd6", build_file = str(Label("//third_party/llvm:llvm.BUILD")), repository = tf_repo_name, ) diff --git a/third_party/llvm/llvm.BUILD b/third_party/llvm/llvm.BUILD index d5ab3262835..386c41910b9 100644 --- a/third_party/llvm/llvm.BUILD +++ b/third_party/llvm/llvm.BUILD @@ -366,6 +366,7 @@ llvm_target_list = [ ("-gen-asm-matcher", "lib/Target/ARM/ARMGenAsmMatcher.inc"), ("-gen-dag-isel", "lib/Target/ARM/ARMGenDAGISel.inc"), ("-gen-fast-isel", "lib/Target/ARM/ARMGenFastISel.inc"), + ("-gen-global-isel", "lib/Target/ARM/ARMGenGlobalISel.inc"), ("-gen-callingconv", "lib/Target/ARM/ARMGenCallingConv.inc"), ("-gen-subtarget", "lib/Target/ARM/ARMGenSubtargetInfo.inc"), ("-gen-disassembler", "lib/Target/ARM/ARMGenDisassemblerTables.inc"), @@ -1116,6 +1117,7 @@ cc_library( ]), deps = [ ":analysis", + ":bit_reader", ":bit_writer", ":config", ":core", From 88cb0291b759397481a1f2df6fe4bb591984dcad Mon Sep 17 00:00:00 2001 From: Mark Daoust Date: Fri, 5 May 2017 06:48:03 -0800 Subject: [PATCH 02/27] Added missing 's' on and in `bijectors` guide, fixing the links. fixed link to `kl_divergence` in `distributions` guide. Change: 155196210 --- .../python/contrib.distributions.bijector.md | 33 ------------------- .../python/contrib.distributions.bijectors.md | 33 +++++++++++++++++++ .../python/contrib.distributions.md | 2 +- .../docs_src/api_guides/python/index.md | 2 +- 4 files changed, 35 insertions(+), 35 deletions(-) delete mode 100644 tensorflow/docs_src/api_guides/python/contrib.distributions.bijector.md create mode 100644 tensorflow/docs_src/api_guides/python/contrib.distributions.bijectors.md diff --git a/tensorflow/docs_src/api_guides/python/contrib.distributions.bijector.md b/tensorflow/docs_src/api_guides/python/contrib.distributions.bijector.md deleted file mode 100644 index 16a47bfd8b1..00000000000 --- a/tensorflow/docs_src/api_guides/python/contrib.distributions.bijector.md +++ /dev/null @@ -1,33 +0,0 @@ -# Random variable transformations (contrib) -[TOC] - -Bijector Ops. - -An API for invertible, differentiable transformations of random variables. - -## Background - -Differentiable, bijective transformations of continuous random variables alter -the calculations made in the cumulative/probability distribution functions and -sample function. This module provides a standard interface for making these -manipulations. - -For more details and examples, see the `Bijector` docstring. - -To apply a `Bijector`, use `distributions.TransformedDistribution`. - -## Bijectors - -* @{tf.contrib.distributions.bijector.Affine} -* @{tf.contrib.distributions.bijector.AffineLinearOperator} -* @{tf.contrib.distributions.bijector.Bijector} -* @{tf.contrib.distributions.bijector.Chain} -* @{tf.contrib.distributions.bijector.CholeskyOuterProduct} -* @{tf.contrib.distributions.bijector.Exp} -* @{tf.contrib.distributions.bijector.Identity} -* @{tf.contrib.distributions.bijector.Inline} -* @{tf.contrib.distributions.bijector.Invert} -* @{tf.contrib.distributions.bijector.PowerTransform} -* @{tf.contrib.distributions.bijector.SigmoidCentered} -* @{tf.contrib.distributions.bijector.SoftmaxCentered} -* @{tf.contrib.distributions.bijector.Softplus} diff --git a/tensorflow/docs_src/api_guides/python/contrib.distributions.bijectors.md b/tensorflow/docs_src/api_guides/python/contrib.distributions.bijectors.md new file mode 100644 index 00000000000..0ce187b329b --- /dev/null +++ b/tensorflow/docs_src/api_guides/python/contrib.distributions.bijectors.md @@ -0,0 +1,33 @@ +# Random variable transformations (contrib) +[TOC] + +Bijector Ops. + +An API for invertible, differentiable transformations of random variables. + +## Background + +Differentiable, bijective transformations of continuous random variables alter +the calculations made in the cumulative/probability distribution functions and +sample function. This module provides a standard interface for making these +manipulations. + +For more details and examples, see the `Bijector` docstring. + +To apply a `Bijector`, use `distributions.TransformedDistribution`. + +## Bijectors + +* @{tf.contrib.distributions.bijectors.Affine} +* @{tf.contrib.distributions.bijectors.AffineLinearOperator} +* @{tf.contrib.distributions.bijectors.Bijector} +* @{tf.contrib.distributions.bijectors.Chain} +* @{tf.contrib.distributions.bijectors.CholeskyOuterProduct} +* @{tf.contrib.distributions.bijectors.Exp} +* @{tf.contrib.distributions.bijectors.Identity} +* @{tf.contrib.distributions.bijectors.Inline} +* @{tf.contrib.distributions.bijectors.Invert} +* @{tf.contrib.distributions.bijectors.PowerTransform} +* @{tf.contrib.distributions.bijectors.SigmoidCentered} +* @{tf.contrib.distributions.bijectors.SoftmaxCentered} +* @{tf.contrib.distributions.bijectors.Softplus} diff --git a/tensorflow/docs_src/api_guides/python/contrib.distributions.md b/tensorflow/docs_src/api_guides/python/contrib.distributions.md index 2b43e1281d7..7a3d509b751 100644 --- a/tensorflow/docs_src/api_guides/python/contrib.distributions.md +++ b/tensorflow/docs_src/api_guides/python/contrib.distributions.md @@ -76,7 +76,7 @@ representing the posterior or posterior predictive. ## Kullback-Leibler Divergence -* @{tf.contrib.distributions.kl} +* @{tf.contrib.distributions.kl_divergence} * @{tf.contrib.distributions.RegisterKL} ## Utilities diff --git a/tensorflow/docs_src/api_guides/python/index.md b/tensorflow/docs_src/api_guides/python/index.md index 177f19bc80d..19d50926d88 100644 --- a/tensorflow/docs_src/api_guides/python/index.md +++ b/tensorflow/docs_src/api_guides/python/index.md @@ -40,7 +40,7 @@ * [Losses (contrib)](contrib.losses.md) * [Metrics (contrib)](contrib.metrics.md) * [Optimization (contrib)](contrib.opt.md) -* [Random variable transformations (contrib)](contrib.distributions.bijector.md) +* [Random variable transformations (contrib)](contrib.distributions.bijectors.md) * [RNN and Cells (contrib)](contrib.rnn.md) * [Seq2seq Library (contrib)](contrib.seq2seq.md) * [Staging (contrib)](contrib.staging.md) From 6044cbdf9c7354aeca70f289abadc46daaee9f58 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Fri, 5 May 2017 08:07:48 -0800 Subject: [PATCH 03/27] Automated rollback of change 155096835 Change: 155203119 --- tensorflow/core/kernels/crop_and_resize_op.cc | 545 ++++++++++-------- tensorflow/core/kernels/crop_and_resize_op.h | 8 +- .../core/kernels/crop_and_resize_op_gpu.cu.cc | 2 +- .../core/kernels/crop_and_resize_op_test.cc | 6 +- 4 files changed, 320 insertions(+), 241 deletions(-) diff --git a/tensorflow/core/kernels/crop_and_resize_op.cc b/tensorflow/core/kernels/crop_and_resize_op.cc index 746fe63e2a0..6a748d34623 100644 --- a/tensorflow/core/kernels/crop_and_resize_op.cc +++ b/tensorflow/core/kernels/crop_and_resize_op.cc @@ -19,6 +19,9 @@ limitations under the License. #include "tensorflow/core/kernels/crop_and_resize_op.h" +#include +#include + #include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor" #include "tensorflow/core/framework/op_kernel.h" #include "tensorflow/core/framework/register_types.h" @@ -26,10 +29,13 @@ limitations under the License. #include "tensorflow/core/framework/tensor_shape.h" #include "tensorflow/core/framework/types.h" #include "tensorflow/core/kernels/bounds_check.h" +#include "tensorflow/core/lib/core/errors.h" #include "tensorflow/core/lib/core/status.h" #include "tensorflow/core/platform/logging.h" +#include "tensorflow/core/platform/types.h" #if GOOGLE_CUDA +#include "tensorflow/core/common_runtime/gpu/gpu_event_mgr.h" #include "tensorflow/core/platform/stream_executor.h" #endif // GOOGLE_CUDA @@ -37,41 +43,67 @@ namespace tensorflow { typedef Eigen::ThreadPoolDevice CPUDevice; typedef Eigen::GpuDevice GPUDevice; +using Callback = std::function; -static inline void ParseAndCheckBoxSizes(OpKernelContext* context, - const Tensor& boxes, - const Tensor& box_ind, - int* num_boxes) { - if (boxes.NumElements() == 0 && box_ind.NumElements() == 0) { +namespace { + +static inline Status ParseAndCheckBoxSizes(const Tensor& boxes, + const Tensor& box_index, + int* num_boxes) { + if (boxes.NumElements() == 0 && box_index.NumElements() == 0) { *num_boxes = 0; - return; + return Status::OK(); } // The shape of 'boxes' is [num_boxes, 4]. - OP_REQUIRES(context, boxes.dims() == 2, - errors::InvalidArgument("boxes must be 2-D", - boxes.shape().DebugString())); + if (boxes.dims() != 2) { + return errors::InvalidArgument("boxes must be 2-D", + boxes.shape().DebugString()); + } *num_boxes = boxes.dim_size(0); - OP_REQUIRES(context, boxes.dim_size(1) == 4, - errors::InvalidArgument("boxes must have 4 columns")); - - // The shape of 'box_ind' is [num_boxes]. - OP_REQUIRES(context, box_ind.dims() == 1, - errors::InvalidArgument("box_ind must be 1-D", - box_ind.shape().DebugString())); - OP_REQUIRES(context, box_ind.dim_size(0) == *num_boxes, - errors::InvalidArgument("box_ind has incompatible shape")); + if (boxes.dim_size(1) != 4) { + return errors::InvalidArgument("boxes must have 4 columns"); + } + // The shape of 'box_index' is [num_boxes]. + if (box_index.dims() != 1) { + return errors::InvalidArgument("box_index must be 1-D", + box_index.shape().DebugString()); + } + if (box_index.dim_size(0) != *num_boxes) { + return errors::InvalidArgument("box_index has incompatible shape"); + } + return Status::OK(); } -// Verifies that all values in box_ind are in [0, batch). +// Conditionally calls the compute callback if all values in box_index are in +// [0, batch_size) then calls done. template -inline void CheckValidBoxInd( - OpKernelContext* context, - typename TTypes::ConstTensor box_ind_data, int batch); +inline void RunIfBoxIndexIsValid( + OpKernelContext* context, typename TTypes::ConstTensor box_index, + int batch_size, Callback compute, Callback done); + +// Specialization of CheckValidBoxIndex for a CPUDevice. +template <> +inline void RunIfBoxIndexIsValid( + OpKernelContext* context, typename TTypes::ConstTensor box_index, + int batch_size, Callback compute, Callback done) { + const int num_boxes = box_index.dimension(0); + for (int b = 0; b < num_boxes; ++b) { + OP_REQUIRES_ASYNC( + context, FastBoundsCheck(box_index(b), batch_size), + errors::OutOfRange("box_index has values outside [0, batch_size)"), + done); + } + compute(); + done(); +} + +} // namespace template -class CropAndResizeOp : public OpKernel { +class CropAndResizeOp : public AsyncOpKernel { public: - explicit CropAndResizeOp(OpKernelConstruction* context) : OpKernel(context) { + explicit CropAndResizeOp(OpKernelConstruction* context) + : AsyncOpKernel(context) { string method; OP_REQUIRES_OK(context, context->GetAttr("method", &method)); OP_REQUIRES(context, method == "bilinear", @@ -80,69 +112,77 @@ class CropAndResizeOp : public OpKernel { &extrapolation_value_)); } - void Compute(OpKernelContext* context) override { - // The shape of 'image' is [batch, image_height, image_width, channels]. + void ComputeAsync(OpKernelContext* context, DoneCallback done) override { + // The shape of 'image' is [batch_size, image_height, image_width, + // channels]. const Tensor& image = context->input(0); - OP_REQUIRES(context, image.dims() == 4, - errors::InvalidArgument("input image must be 4-D", - image.shape().DebugString())); - - const int batch = image.dim_size(0); - const int image_height = image.dim_size(1); - const int image_width = image.dim_size(2); - const int depth = image.dim_size(3); - OP_REQUIRES(context, image_height > 0 && image_width > 0, - errors::InvalidArgument("image dimensions must be positive")); - // The shape of 'boxes' is [num_boxes, 4]. const Tensor& boxes = context->input(1); - - // The shape of 'box_ind' is [num_boxes]. - const Tensor& box_ind = context->input(2); - - int num_boxes = 0; - ParseAndCheckBoxSizes(context, boxes, box_ind, &num_boxes); - + // The shape of 'box_index' is [num_boxes]. + const Tensor& box_index = context->input(2); // The shape of 'crop_size' is [2]. const Tensor& crop_size = context->input(3); - OP_REQUIRES(context, crop_size.dims() == 1, - errors::InvalidArgument("crop_size must be 1-D", - crop_size.shape().DebugString())); - OP_REQUIRES(context, crop_size.dim_size(0) == 2, - errors::InvalidArgument("crop_size must have two elements", - crop_size.shape().DebugString())); + // Validate inputs dimensions. + OP_REQUIRES_ASYNC(context, image.dims() == 4, + errors::InvalidArgument("input image must be 4-D", + image.shape().DebugString()), + done); + const int batch_size = image.dim_size(0); + const int image_height = image.dim_size(1); + const int image_width = image.dim_size(2); + const int depth = image.dim_size(3); + OP_REQUIRES_ASYNC( + context, image_height > 0 && image_width > 0, + errors::InvalidArgument("image dimensions must be positive"), done); + int num_boxes = 0; + OP_REQUIRES_OK_ASYNC( + context, ParseAndCheckBoxSizes(boxes, box_index, &num_boxes), done); + OP_REQUIRES_ASYNC(context, crop_size.dims() == 1, + errors::InvalidArgument("crop_size must be 1-D", + crop_size.shape().DebugString()), + done); + OP_REQUIRES_ASYNC( + context, crop_size.dim_size(0) == 2, + errors::InvalidArgument("crop_size must have two elements", + crop_size.shape().DebugString()), + done); + + // Copy and validate crop sizes. auto crop_size_vec = crop_size.vec(); const int crop_height = internal::SubtleMustCopy(crop_size_vec(0)); const int crop_width = internal::SubtleMustCopy(crop_size_vec(1)); - OP_REQUIRES(context, crop_height > 0 && crop_width > 0, - errors::InvalidArgument("crop dimensions must be positive")); + OP_REQUIRES_ASYNC( + context, crop_height > 0 && crop_width > 0, + errors::InvalidArgument("crop dimensions must be positive"), done); // Allocate output tensor. Tensor* output = nullptr; - OP_REQUIRES_OK( + OP_REQUIRES_OK_ASYNC( context, context->allocate_output( 0, TensorShape({num_boxes, crop_height, crop_width, depth}), - &output)); + &output), + done); - typename TTypes::ConstTensor image_data = image.tensor(); - typename TTypes::ConstTensor boxes_data = - boxes.tensor(); - typename TTypes::ConstTensor box_ind_data = - box_ind.tensor(); - typename TTypes::Tensor crops_data = output->tensor(); + auto compute_callback = [this, context, output]() { + const Tensor& image = context->input(0); + const Tensor& boxes = context->input(1); + const Tensor& box_index = context->input(2); + const bool status = functor::CropAndResize()( + context->eigen_device(), image.tensor(), + boxes.tensor(), box_index.tensor(), + extrapolation_value_, output->tensor()); + if (!status) { + context->SetStatus( + errors::Internal("Failed launch CropAndResizeKernel.")); + } + }; - CheckValidBoxInd(context, box_ind_data, batch); - - bool status = functor::CropAndResize()( - context->eigen_device(), image_data, boxes_data, box_ind_data, - extrapolation_value_, crops_data); - if (!status) { - context->SetStatus( - errors::Internal("Failed launch CropAndResizeKernel.")); - } + RunIfBoxIndexIsValid(context, box_index.tensor(), + batch_size, std::move(compute_callback), + std::move(done)); } private: @@ -155,10 +195,10 @@ template struct CropAndResize { bool operator()(const CPUDevice& d, typename TTypes::ConstTensor image, typename TTypes::ConstTensor boxes, - typename TTypes::ConstTensor box_ind, + typename TTypes::ConstTensor box_index, float extrapolation_value, typename TTypes::Tensor crops) { - const int batch = image.dimension(0); + const int batch_size = image.dimension(0); const int image_height = image.dimension(1); const int image_width = image.dimension(2); @@ -173,8 +213,8 @@ struct CropAndResize { const float y2 = boxes(b, 2); const float x2 = boxes(b, 3); - const int32 b_in = box_ind(b); - if (b_in < 0 || b_in >= batch) { + const int32 b_in = box_index(b); + if (!FastBoundsCheck(b_in, batch_size)) { continue; } @@ -235,89 +275,94 @@ struct CropAndResize { return true; } }; + } // namespace functor template -class CropAndResizeGradImageOp : public OpKernel { +class CropAndResizeGradImageOp : public AsyncOpKernel { public: explicit CropAndResizeGradImageOp(OpKernelConstruction* context) - : OpKernel(context) { + : AsyncOpKernel(context) { string method; OP_REQUIRES_OK(context, context->GetAttr("method", &method)); OP_REQUIRES(context, method == "bilinear", errors::InvalidArgument("method must be 'bilinear'", method)); } - void Compute(OpKernelContext* context) override { + void ComputeAsync(OpKernelContext* context, DoneCallback done) override { // The shape of 'grads' is [num_boxes, crop_height, crop_width, depth]. const Tensor& grads = context->input(0); - - OP_REQUIRES(context, grads.dims() == 4, - errors::InvalidArgument("grads image must be 4-D", - grads.shape().DebugString())); - const int crop_height = grads.dim_size(1); - const int crop_width = grads.dim_size(2); - OP_REQUIRES(context, crop_height > 0 && crop_width > 0, - errors::InvalidArgument("grads dimensions must be positive")); - // The shape of 'boxes' is [num_boxes, 4]. const Tensor& boxes = context->input(1); - - // The shape of 'box_ind' is [num_boxes]. - const Tensor& box_ind = context->input(2); - - int num_boxes = 0; - ParseAndCheckBoxSizes(context, boxes, box_ind, &num_boxes); - - OP_REQUIRES( - context, grads.dim_size(0) == num_boxes, - errors::InvalidArgument("boxes and grads have incompatible shape")); - + // The shape of 'box_index' is [num_boxes]. + const Tensor& box_index = context->input(2); // The shape of 'image_size' is [4]. const Tensor& image_size = context->input(3); - OP_REQUIRES(context, image_size.dims() == 1, - errors::InvalidArgument("image_size must be 1-D", - image_size.shape().DebugString())); - OP_REQUIRES(context, image_size.dim_size(0) == 4, - errors::InvalidArgument("image_size must have 4 elements", - image_size.shape().DebugString())); + // Validate input shapes. + OP_REQUIRES_ASYNC(context, grads.dims() == 4, + errors::InvalidArgument("grads image must be 4-D", + grads.shape().DebugString()), + done); + const int crop_height = grads.dim_size(1); + const int crop_width = grads.dim_size(2); + OP_REQUIRES_ASYNC( + context, crop_height > 0 && crop_width > 0, + errors::InvalidArgument("grads dimensions must be positive"), done); + int num_boxes = 0; + OP_REQUIRES_OK_ASYNC( + context, ParseAndCheckBoxSizes(boxes, box_index, &num_boxes), done); + OP_REQUIRES_ASYNC( + context, grads.dim_size(0) == num_boxes, + errors::InvalidArgument("boxes and grads have incompatible shape"), + done); + + OP_REQUIRES_ASYNC(context, image_size.dims() == 1, + errors::InvalidArgument("image_size must be 1-D", + image_size.shape().DebugString()), + done); + OP_REQUIRES_ASYNC(context, image_size.dim_size(0) == 4, + errors::InvalidArgument("image_size must have 4 elements", + image_size.shape().DebugString()), + done); auto image_size_vec = image_size.vec(); - const int batch = internal::SubtleMustCopy(image_size_vec(0)); + const int batch_size = internal::SubtleMustCopy(image_size_vec(0)); const int image_height = internal::SubtleMustCopy(image_size_vec(1)); const int image_width = internal::SubtleMustCopy(image_size_vec(2)); const int depth = internal::SubtleMustCopy(image_size_vec(3)); - - OP_REQUIRES(context, image_height > 0 && image_width > 0, - errors::InvalidArgument("image dimensions must be positive")); - OP_REQUIRES( + OP_REQUIRES_ASYNC( + context, image_height > 0 && image_width > 0, + errors::InvalidArgument("image dimensions must be positive"), done); + OP_REQUIRES_ASYNC( context, grads.dim_size(3) == depth, - errors::InvalidArgument("image_size and grads are incompatible")); + errors::InvalidArgument("image_size and grads are incompatible"), done); // Allocate output tensor. Tensor* output = nullptr; - OP_REQUIRES_OK( - context, context->allocate_output( - 0, TensorShape({batch, image_height, image_width, depth}), - &output)); + OP_REQUIRES_OK_ASYNC( + context, + context->allocate_output( + 0, TensorShape({batch_size, image_height, image_width, depth}), + &output), + done); - typename TTypes::ConstTensor grads_data = - grads.tensor(); - typename TTypes::ConstTensor boxes_data = - boxes.tensor(); - typename TTypes::ConstTensor box_ind_data = - box_ind.tensor(); - typename TTypes::Tensor output_data = output->tensor(); + auto compute_callback = [context, output]() { + const Tensor& grads = context->input(0); + const Tensor& boxes = context->input(1); + const Tensor& box_index = context->input(2); + const bool status = functor::CropAndResizeBackpropImage()( + context->eigen_device(), grads.tensor(), + boxes.tensor(), box_index.tensor(), + output->tensor()); + if (!status) { + context->SetStatus(errors::Internal( + "Failed launch CropAndResizeBackpropImage kernel.")); + } + }; - CheckValidBoxInd(context, box_ind_data, batch); - - bool status = functor::CropAndResizeBackpropImage()( - context->eigen_device(), grads_data, boxes_data, box_ind_data, - output_data); - if (!status) { - context->SetStatus( - errors::Internal("Failed launch CropAndResizeBackpropImageKernel.")); - } + RunIfBoxIndexIsValid(context, box_index.tensor(), + batch_size, std::move(compute_callback), + std::move(done)); } }; @@ -328,9 +373,9 @@ struct CropAndResizeBackpropImage { bool operator()(const CPUDevice& d, typename TTypes::ConstTensor grads, typename TTypes::ConstTensor boxes, - typename TTypes::ConstTensor box_ind, + typename TTypes::ConstTensor box_index, typename TTypes::Tensor grads_image) { - const int batch = grads_image.dimension(0); + const int batch_size = grads_image.dimension(0); const int image_height = grads_image.dimension(1); const int image_width = grads_image.dimension(2); @@ -347,8 +392,8 @@ struct CropAndResizeBackpropImage { const float y2 = boxes(b, 2); const float x2 = boxes(b, 3); - const int32 b_in = box_ind(b); - if (b_in < 0 || b_in >= batch) { + const int32 b_in = box_index(b); + if (!FastBoundsCheck(b_in, batch_size)) { continue; } @@ -399,83 +444,90 @@ struct CropAndResizeBackpropImage { return true; } }; + } // namespace functor template -class CropAndResizeGradBoxesOp : public OpKernel { +class CropAndResizeGradBoxesOp : public AsyncOpKernel { public: explicit CropAndResizeGradBoxesOp(OpKernelConstruction* context) - : OpKernel(context) { + : AsyncOpKernel(context) { string method; OP_REQUIRES_OK(context, context->GetAttr("method", &method)); OP_REQUIRES(context, method == "bilinear", errors::InvalidArgument("method must be 'bilinear'", method)); } - void Compute(OpKernelContext* context) override { + void ComputeAsync(OpKernelContext* context, DoneCallback done) override { // The shape of 'grads' is [num_boxes, crop_height, crop_width, depth]. const Tensor& grads = context->input(0); + // The shape of 'boxes' is [num_boxes, 4]. + const Tensor& boxes = context->input(2); + // The shape of 'box_index' is [num_boxes]. + const Tensor& box_index = context->input(3); + // The shape of 'image' is [batch_size, image_height, image_width, depth]. + const Tensor& image = context->input(1); - OP_REQUIRES(context, grads.dims() == 4, - errors::InvalidArgument("grads image must be 4-D", - grads.shape().DebugString())); - + // Validate input shapes. + OP_REQUIRES_ASYNC(context, grads.dims() == 4, + errors::InvalidArgument("grads image must be 4-D", + grads.shape().DebugString()), + done); const int crop_height = grads.dim_size(1); const int crop_width = grads.dim_size(2); const int depth = grads.dim_size(3); - OP_REQUIRES(context, crop_height > 0 && crop_width > 0, - errors::InvalidArgument("grads dimensions must be positive")); + OP_REQUIRES_ASYNC( + context, crop_height > 0 && crop_width > 0, + errors::InvalidArgument("grads dimensions must be positive"), done); - // The shape of 'image' is [batch, image_height, image_width, depth]. - const Tensor& image = context->input(1); - OP_REQUIRES(context, image.dims() == 4, - errors::InvalidArgument("input image must be 4-D", - image.shape().DebugString())); - - const int batch = image.dim_size(0); + OP_REQUIRES_ASYNC(context, image.dims() == 4, + errors::InvalidArgument("input image must be 4-D", + image.shape().DebugString()), + done); + const int batch_size = image.dim_size(0); const int image_height = image.dim_size(1); const int image_width = image.dim_size(2); - OP_REQUIRES(context, image_height > 0 && image_width > 0, - errors::InvalidArgument("image dimensions must be positive")); - OP_REQUIRES(context, image.dim_size(3) == depth, - errors::InvalidArgument("image, grads depth differ")); - - // The shape of 'boxes' is [num_boxes, 4]. - const Tensor& boxes = context->input(2); - - // The shape of 'box_ind' is [num_boxes]. - const Tensor& box_ind = context->input(3); + OP_REQUIRES_ASYNC( + context, image_height > 0 && image_width > 0, + errors::InvalidArgument("image dimensions must be positive"), done); + OP_REQUIRES_ASYNC(context, image.dim_size(3) == depth, + errors::InvalidArgument("image, grads depth differ"), + done); int num_boxes = 0; - ParseAndCheckBoxSizes(context, boxes, box_ind, &num_boxes); + OP_REQUIRES_OK_ASYNC( + context, ParseAndCheckBoxSizes(boxes, box_index, &num_boxes), done); - OP_REQUIRES( + OP_REQUIRES_ASYNC( context, grads.dim_size(0) == num_boxes, - errors::InvalidArgument("boxes and grads have incompatible shape")); + errors::InvalidArgument("boxes and grads have incompatible shape"), + done); // Allocate output tensor. Tensor* output = nullptr; - OP_REQUIRES_OK(context, context->allocate_output( - 0, TensorShape({num_boxes, 4}), &output)); + OP_REQUIRES_OK_ASYNC( + context, + context->allocate_output(0, TensorShape({num_boxes, 4}), &output), + done); - typename TTypes::ConstTensor grads_data = - grads.tensor(); - typename TTypes::ConstTensor image_data = image.tensor(); - typename TTypes::ConstTensor boxes_data = - boxes.tensor(); - typename TTypes::ConstTensor box_ind_data = - box_ind.tensor(); - typename TTypes::Tensor output_data = output->tensor(); + auto compute_callback = [context, output]() { + const Tensor& grads = context->input(0); + const Tensor& image = context->input(1); + const Tensor& boxes = context->input(2); + const Tensor& box_index = context->input(3); + const bool status = functor::CropAndResizeBackpropBoxes()( + context->eigen_device(), grads.tensor(), + image.tensor(), boxes.tensor(), + box_index.tensor(), output->tensor()); + if (!status) { + context->SetStatus(errors::Internal( + "Failed launch CropAndResizeBackpropBoxes kernel.")); + } + }; - CheckValidBoxInd(context, box_ind_data, batch); - - bool status = functor::CropAndResizeBackpropBoxes()( - context->eigen_device(), grads_data, image_data, boxes_data, - box_ind_data, output_data); - if (!status) { - context->SetStatus( - errors::Internal("Failed launch CropAndResizeBackpropBoxesKernel.")); - } + RunIfBoxIndexIsValid(context, box_index.tensor(), + batch_size, std::move(compute_callback), + std::move(done)); } }; @@ -487,9 +539,9 @@ struct CropAndResizeBackpropBoxes { typename TTypes::ConstTensor grads, typename TTypes::ConstTensor image, typename TTypes::ConstTensor boxes, - typename TTypes::ConstTensor box_ind, + typename TTypes::ConstTensor box_index, typename TTypes::Tensor grads_boxes) { - const int batch = image.dimension(0); + const int batch_size = image.dimension(0); const int image_height = image.dimension(1); const int image_width = image.dimension(2); @@ -506,8 +558,8 @@ struct CropAndResizeBackpropBoxes { const float y2 = boxes(b, 2); const float x2 = boxes(b, 3); - const int32 b_in = box_ind(b); - if (b_in < 0 || b_in >= batch) { + const int32 b_in = box_index(b); + if (!FastBoundsCheck(b_in, batch_size)) { continue; } @@ -589,30 +641,19 @@ struct CropAndResizeBackpropBoxes { return true; } }; + } // namespace functor -// Specialization of CheckValidBoxInd for a CPUDevice. -template <> -inline void CheckValidBoxInd( - OpKernelContext* context, typename TTypes::ConstTensor box_ind, - int batch) { - const int num_boxes = box_ind.dimension(0); - for (int b = 0; b < num_boxes; ++b) { - OP_REQUIRES(context, box_ind(b) >= 0 && box_ind(b) < batch, - errors::OutOfRange("box_ind has values outside [0, batch)")); - } -} - -#define REGISTER_KERNEL(T) \ - REGISTER_KERNEL_BUILDER(Name("CropAndResize") \ - .Device(DEVICE_CPU) \ - .TypeConstraint("T") \ - .HostMemory("crop_size"), \ - CropAndResizeOp); \ - \ - REGISTER_KERNEL_BUILDER(Name("CropAndResizeGradBoxes") \ - .Device(DEVICE_CPU) \ - .TypeConstraint("T"), \ +#define REGISTER_KERNEL(T) \ + REGISTER_KERNEL_BUILDER(Name("CropAndResize") \ + .Device(DEVICE_CPU) \ + .TypeConstraint("T") \ + .HostMemory("crop_size"), \ + CropAndResizeOp); \ + \ + REGISTER_KERNEL_BUILDER(Name("CropAndResizeGradBoxes") \ + .Device(DEVICE_CPU) \ + .TypeConstraint("T"), \ CropAndResizeGradBoxesOp); TF_CALL_REAL_NUMBER_TYPES(REGISTER_KERNEL); @@ -634,50 +675,86 @@ TF_CALL_double(REGISTER_KERNEL); #if GOOGLE_CUDA -// Forward declaration of the CheckValidBoxIndHelper specialization for GPU. +// Forward declaration of the CheckValidBoxIndexHelper specialization for GPU. namespace functor { template <> -void CheckValidBoxIndHelper::operator()( - const GPUDevice& d, typename TTypes::ConstTensor box_ind, - int batch, typename TTypes::Tensor isvalid); -extern template struct CheckValidBoxIndHelper; +void CheckValidBoxIndexHelper::operator()( + const GPUDevice& d, typename TTypes::ConstTensor box_index, + int batch_size, typename TTypes::Tensor isvalid); +extern template struct CheckValidBoxIndexHelper; } // namespace functor -// Specialization of CheckValidBoxInd for a GPUDevice. +namespace { + +// Specialization of CheckValidBoxIndex for a GPUDevice. template <> -inline void CheckValidBoxInd( - OpKernelContext* context, typename TTypes::ConstTensor box_ind, - int batch) { - const int num_boxes = box_ind.dimension(0); +inline void RunIfBoxIndexIsValid( + OpKernelContext* context, typename TTypes::ConstTensor box_index, + int batch_size, Callback compute, Callback done) { + const int num_boxes = box_index.dimension(0); if (num_boxes == 0) { + compute(); + done(); return; } - Tensor isvalid_tensor; - OP_REQUIRES_OK(context, - context->allocate_temp(DataTypeToEnum::value, - TensorShape({}), &isvalid_tensor)); - typename TTypes::Tensor isvalid = isvalid_tensor.tensor(); + Tensor isvalid_dev_tensor; + OP_REQUIRES_OK_ASYNC( + context, + context->allocate_temp(DataTypeToEnum::value, TensorShape({}), + &isvalid_dev_tensor), + done); + typename TTypes::Tensor isvalid_dev = + isvalid_dev_tensor.tensor(); - functor::CheckValidBoxIndHelper()( - context->eigen_device(), box_ind, batch, isvalid); + // Run the actual box check on the device. + functor::CheckValidBoxIndexHelper()( + context->eigen_device(), box_index, batch_size, isvalid_dev); + // Copy the result back to the host. auto* stream = context->op_device_context()->stream(); - OP_REQUIRES(context, stream, errors::Internal("No GPU stream available.")); + OP_REQUIRES_ASYNC(context, stream, + errors::Internal("No GPU stream available."), done); + Tensor isvalid_host_tensor; + // Use pinned host memory on the host to avoid unnecessary + // synchronization. + AllocatorAttributes alloc_attr; + alloc_attr.set_on_host(true); + alloc_attr.set_gpu_compatible(true); + OP_REQUIRES_OK_ASYNC( + context, + context->allocate_temp(DataTypeToEnum::value, TensorShape({}), + &isvalid_host_tensor, alloc_attr), + done); + perftools::gputools::DeviceMemoryBase wrapped(isvalid_dev.data(), + sizeof(bool)); + const bool status = + stream + ->ThenMemcpy( + isvalid_host_tensor.scalar().data() /* destination */, + wrapped /* source */, sizeof(bool)) + .ok(); + OP_REQUIRES_ASYNC( + context, status, + errors::Internal("Failed to launch copy of isvalid from device to host."), + done); - bool isvalid_host = false; - perftools::gputools::DeviceMemoryBase isvalid_gpu(isvalid.data(), - sizeof(bool)); - stream->ThenMemcpy(&isvalid_host, isvalid_gpu, sizeof(bool)); - stream->BlockHostUntilDone(); + auto wrapped_callback = [context, isvalid_host_tensor, compute, done]() { + const bool isvalid = isvalid_host_tensor.scalar()(); + OP_REQUIRES_ASYNC( + context, isvalid, + errors::OutOfRange("box_index has values outside [0, batch_size)"), + done); + compute(); + done(); + }; - OP_REQUIRES(context, stream->ok(), - errors::Internal("cudaMemcpy from device to host failed")); - - OP_REQUIRES(context, isvalid_host, - errors::OutOfRange("box_ind has values outside [0, batch)")); + context->device()->tensorflow_gpu_device_info()->event_mgr->ThenExecute( + stream, wrapped_callback); } +} // namespace + #define REGISTER_KERNEL(T) \ REGISTER_KERNEL_BUILDER(Name("CropAndResize") \ .Device(DEVICE_GPU) \ diff --git a/tensorflow/core/kernels/crop_and_resize_op.h b/tensorflow/core/kernels/crop_and_resize_op.h index 22df1bdd56b..460dbad22b4 100644 --- a/tensorflow/core/kernels/crop_and_resize_op.h +++ b/tensorflow/core/kernels/crop_and_resize_op.h @@ -53,12 +53,12 @@ struct CropAndResizeBackpropBoxes { }; template -struct CheckValidBoxIndHelper { - // Checks if all values in box_ind are in [0, batch). +struct CheckValidBoxIndexHelper { + // Checks if all values in box_index are in [0, batch). void operator()(const Device& d, - typename TTypes::ConstTensor box_ind, int batch, + typename TTypes::ConstTensor box_index, int batch, typename TTypes::Tensor isvalid) { - isvalid.device(d) = ((box_ind >= 0) && (box_ind < batch)).all(); + isvalid.device(d) = ((box_index >= 0) && (box_index < batch)).all(); } }; diff --git a/tensorflow/core/kernels/crop_and_resize_op_gpu.cu.cc b/tensorflow/core/kernels/crop_and_resize_op_gpu.cu.cc index 254475db465..c1235fda892 100644 --- a/tensorflow/core/kernels/crop_and_resize_op_gpu.cu.cc +++ b/tensorflow/core/kernels/crop_and_resize_op_gpu.cu.cc @@ -440,7 +440,7 @@ TF_CALL_GPU_NUMBER_TYPES(DEFINE_GPU_SPECS); #undef DEFINE_GPU_SPECS -template struct CheckValidBoxIndHelper; +template struct CheckValidBoxIndexHelper; } // namespace functor } // namespace tensorflow diff --git a/tensorflow/core/kernels/crop_and_resize_op_test.cc b/tensorflow/core/kernels/crop_and_resize_op_test.cc index 3a7f180598e..d6139dae966 100644 --- a/tensorflow/core/kernels/crop_and_resize_op_test.cc +++ b/tensorflow/core/kernels/crop_and_resize_op_test.cc @@ -251,7 +251,7 @@ TEST_F(CropAndResizeOpTest, TestInvalidBoxIndexShape) { Status s = RunOpKernel(); ASSERT_FALSE(s.ok()); EXPECT_TRUE( - StringPiece(s.ToString()).contains("box_ind has incompatible shape")) + StringPiece(s.ToString()).contains("box_index has incompatible shape")) << s; } @@ -264,8 +264,10 @@ TEST_F(CropAndResizeOpTest, TestInvalidBoxIndex) { Status s = RunOpKernel(); ASSERT_FALSE(s.ok()); EXPECT_TRUE(StringPiece(s.ToString()) - .contains("box_ind has values outside [0, batch)")) + .contains("box_index has values outside [0, batch_size)")) << s; } +// TODO(zhengxq, rmlarsen): Add a benchmark. + } // namespace tensorflow From 1b75a7bcb1648e9b065fbb2f50a6d708fbbb2aa8 Mon Sep 17 00:00:00 2001 From: Sukriti Ramesh Date: Fri, 5 May 2017 08:51:38 -0800 Subject: [PATCH 04/27] Update load functionality in SavedModel loader to use the Session graph and not the default graph. Change: 155207584 --- tensorflow/python/saved_model/loader_impl.py | 73 ++++++++++--------- .../python/saved_model/saved_model_test.py | 21 ++++++ 2 files changed, 58 insertions(+), 36 deletions(-) diff --git a/tensorflow/python/saved_model/loader_impl.py b/tensorflow/python/saved_model/loader_impl.py index a9d999dad3a..32526521749 100644 --- a/tensorflow/python/saved_model/loader_impl.py +++ b/tensorflow/python/saved_model/loader_impl.py @@ -195,46 +195,47 @@ def load(sess, tags, export_dir, **saver_kwargs): Raises: RuntimeError: MetaGraphDef associated with the tags cannot be found. """ - # Build the SavedModel protocol buffer and find the requested meta graph def. - saved_model = _parse_saved_model(export_dir) - found_match = False - for meta_graph_def in saved_model.meta_graphs: - if set(meta_graph_def.meta_info_def.tags) == set(tags): - meta_graph_def_to_load = meta_graph_def - found_match = True - break + with sess.graph.as_default(): + # Build the SavedModel protocol buffer and find requested meta graph def. + saved_model = _parse_saved_model(export_dir) + found_match = False + for meta_graph_def in saved_model.meta_graphs: + if set(meta_graph_def.meta_info_def.tags) == set(tags): + meta_graph_def_to_load = meta_graph_def + found_match = True + break - if not found_match: - raise RuntimeError("MetaGraphDef associated with tags " + str(tags).strip( - "[]") + " could not be found in SavedModel") + if not found_match: + raise RuntimeError("MetaGraphDef associated with tags " + str(tags).strip( + "[]") + " could not be found in SavedModel") - # Build a saver by importing the meta graph def to load. - saver = tf_saver.import_meta_graph(meta_graph_def_to_load, **saver_kwargs) + # Build a saver by importing the meta graph def to load. + saver = tf_saver.import_meta_graph(meta_graph_def_to_load, **saver_kwargs) - if saver: - # Build the checkpoint path where the variables are located. - variables_path = os.path.join( - compat.as_bytes(export_dir), - compat.as_bytes(constants.VARIABLES_DIRECTORY), - compat.as_bytes(constants.VARIABLES_FILENAME)) + if saver: + # Build the checkpoint path where the variables are located. + variables_path = os.path.join( + compat.as_bytes(export_dir), + compat.as_bytes(constants.VARIABLES_DIRECTORY), + compat.as_bytes(constants.VARIABLES_FILENAME)) - # Restore the variables using the built saver in the provided session. - saver.restore(sess, variables_path) - else: - tf_logging.info("The specified SavedModel has no variables; no " - "checkpoints were restored.") + # Restore the variables using the built saver in the provided session. + saver.restore(sess, variables_path) + else: + tf_logging.info("The specified SavedModel has no variables; no " + "checkpoints were restored.") - # Get asset tensors, if any. - asset_tensors_dictionary = _get_asset_tensors(export_dir, - meta_graph_def_to_load) + # Get asset tensors, if any. + asset_tensors_dictionary = _get_asset_tensors(export_dir, + meta_graph_def_to_load) - main_op_tensor = _get_main_op_tensor(meta_graph_def_to_load) - if main_op_tensor is not None: - sess.run(fetches=[main_op_tensor], feed_dict=asset_tensors_dictionary) - else: - legacy_init_op_tensor = _get_legacy_init_op_tensor(meta_graph_def_to_load) - if legacy_init_op_tensor is not None: - sess.run(fetches=[legacy_init_op_tensor], - feed_dict=asset_tensors_dictionary) + main_op_tensor = _get_main_op_tensor(meta_graph_def_to_load) + if main_op_tensor is not None: + sess.run(fetches=[main_op_tensor], feed_dict=asset_tensors_dictionary) + else: + legacy_init_op_tensor = _get_legacy_init_op_tensor(meta_graph_def_to_load) + if legacy_init_op_tensor is not None: + sess.run( + fetches=[legacy_init_op_tensor], feed_dict=asset_tensors_dictionary) - return meta_graph_def_to_load + return meta_graph_def_to_load diff --git a/tensorflow/python/saved_model/saved_model_test.py b/tensorflow/python/saved_model/saved_model_test.py index a81f7441752..fcd6bc39547 100644 --- a/tensorflow/python/saved_model/saved_model_test.py +++ b/tensorflow/python/saved_model/saved_model_test.py @@ -151,6 +151,27 @@ class SavedModelTest(test.TestCase): constants.SAVED_MODEL_FILENAME_PBTXT): loader.load(sess, ["foo"], export_dir) + def testVerifySessionGraphUsage(self): + export_dir = os.path.join(test.get_temp_dir(), + "test_verify_session_graph_usage") + builder = saved_model_builder.SavedModelBuilder(export_dir) + + with self.test_session(graph=ops.Graph()) as sess: + self._init_and_validate_variable(sess, "v", 42) + builder.add_meta_graph_and_variables(sess, [tag_constants.TRAINING]) + + # Save the SavedModel to disk. + builder.save() + + # Build a session and supply it to the load operation. + sess = session.Session(graph=ops.Graph()) + loader.load(sess, [tag_constants.TRAINING], export_dir) + + # Check the variable within the scope of the session and its graph. + with sess: + self.assertEqual( + 42, ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES)[0].eval()) + def testSequence(self): export_dir = os.path.join(test.get_temp_dir(), "test_sequence") builder = saved_model_builder.SavedModelBuilder(export_dir) From dd63839973e407b4e1501d2dd146e54ee30e445b Mon Sep 17 00:00:00 2001 From: Benoit Steiner Date: Fri, 5 May 2017 08:58:08 -0800 Subject: [PATCH 05/27] Open sourced the analytical cost model Change: 155208347 --- tensorflow/core/grappler/costs/BUILD | 37 +++++ .../costs/analytical_cost_estimator.cc | 128 ++++++++++++++++++ .../costs/analytical_cost_estimator.h | 63 +++++++++ .../core/grappler/costs/virtual_placer.cc | 57 ++++++++ .../core/grappler/costs/virtual_placer.h | 45 ++++++ 5 files changed, 330 insertions(+) create mode 100644 tensorflow/core/grappler/costs/analytical_cost_estimator.cc create mode 100644 tensorflow/core/grappler/costs/analytical_cost_estimator.h create mode 100644 tensorflow/core/grappler/costs/virtual_placer.cc create mode 100644 tensorflow/core/grappler/costs/virtual_placer.h diff --git a/tensorflow/core/grappler/costs/BUILD b/tensorflow/core/grappler/costs/BUILD index 372092f42a9..8e7209d0d47 100644 --- a/tensorflow/core/grappler/costs/BUILD +++ b/tensorflow/core/grappler/costs/BUILD @@ -135,6 +135,22 @@ cc_library( ], ) +cc_library( + name = "virtual_placer", + srcs = ["virtual_placer.cc"], + hdrs = ["virtual_placer.h"], + visibility = ["//visibility:public"], + deps = [ + ":op_performance_data_cc", + ":utils", + "//tensorflow/core:framework", + "//tensorflow/core:framework_lite", + "//tensorflow/core:protos_all_cc", + "//tensorflow/core/grappler:devices", + "//tensorflow/core/grappler/clusters:cluster", + ], +) + cc_library( name = "virtual_scheduler", srcs = ["virtual_scheduler.cc"], @@ -194,3 +210,24 @@ cc_test( "//tensorflow/core:test_main", ], ) + +cc_library( + name = "analytical_cost_estimator", + srcs = ["analytical_cost_estimator.cc"], + hdrs = ["analytical_cost_estimator.h"], + visibility = ["//visibility:public"], + deps = [ + ":cost_estimator", + ":graph_properties", + ":op_level_cost_estimator", + ":op_performance_data_cc", + ":utils", + ":virtual_placer", + ":virtual_scheduler", + "//tensorflow/core:core_cpu", + "//tensorflow/core:core_cpu_internal", + "//tensorflow/core:lib", + "//tensorflow/core:protos_all_cc", + "//tensorflow/core/grappler:grappler_item", + ], +) diff --git a/tensorflow/core/grappler/costs/analytical_cost_estimator.cc b/tensorflow/core/grappler/costs/analytical_cost_estimator.cc new file mode 100644 index 00000000000..29d55ca5916 --- /dev/null +++ b/tensorflow/core/grappler/costs/analytical_cost_estimator.cc @@ -0,0 +1,128 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/core/grappler/costs/analytical_cost_estimator.h" + +#include +#include + +#include "tensorflow/core/framework/attr_value.pb.h" +#include "tensorflow/core/graph/types.h" +#include "tensorflow/core/grappler/costs/graph_properties.h" +#include "tensorflow/core/grappler/costs/op_performance_data.pb.h" +#include "tensorflow/core/grappler/costs/utils.h" +#include "tensorflow/core/grappler/costs/virtual_placer.h" +#include "tensorflow/core/grappler/costs/virtual_scheduler.h" +#include "tensorflow/core/grappler/grappler_item.h" +#include "tensorflow/core/public/session.h" + +namespace tensorflow { +namespace grappler { + +AnalyticalCostEstimator::AnalyticalCostEstimator(Cluster* cluster, + bool use_static_shapes) + : cluster_(cluster), use_static_shapes_(use_static_shapes) {} + +Status AnalyticalCostEstimator::Initialize(const GrapplerItem& item) { + item_ = item; + return Status::OK(); +} + +Status AnalyticalCostEstimator::PredictCosts(const GraphDef& optimized_graph, + CostGraphDef* cost_graph, + Costs* costs) const { + GrapplerItem item = item_; + item.graph = optimized_graph; + GraphProperties properties(item); + Status status; + if (use_static_shapes_) { + status = properties.InferStatically(); + } else { + status = properties.InferDynamically(cluster_); + } + + if (!status.ok()) { + costs->execution_time = Costs::Duration::max(); + return status; + } + + std::unordered_map name_to_cost; + if (cost_graph) { + for (auto& node : *cost_graph->mutable_node()) { + name_to_cost[node.name()] = &node; + } + } + std::vector inaccurate_nodes; + VirtualScheduler scheduler(optimized_graph, item_.fetch); + VirtualPlacer placer(cluster_); + Costs node_costs; + do { + const NodeDef* node = scheduler.GetCurrNode(); + std::vector inputs = + properties.GetInputProperties(node->name()); + + OpInfo::DeviceProperties device = placer.get_device(*node); + OpInfo op_info; + op_info.set_op(node->op()); + *op_info.mutable_attr() = node->attr(); + for (auto& input : inputs) { + op_info.add_inputs()->Swap(&input); + } + op_info.mutable_device()->Swap(&device); + + node_costs = node_estimator_.PredictCosts(op_info); + if (node_costs.inaccurate) { + inaccurate_nodes.push_back(node->name()); + } + if (cost_graph) { + auto it = name_to_cost.find(node->name()); + CostGraphDef::Node* cost_node; + if (it != name_to_cost.end()) { + cost_node = it->second; + } else { + cost_node = cost_graph->add_node(); + cost_node->set_name(node->name()); + } + string device_name = properties.GetDeviceName(node->name()); + cost_node->set_device(device_name); + cost_node->set_compute_cost( + node_costs.execution_time.asMicroSeconds().count()); + cost_node->set_compute_time( + node_costs.compute_time.asMicroSeconds().count()); + cost_node->set_memory_time( + node_costs.memory_time.asMicroSeconds().count()); + std::vector outputs = + properties.GetOutputProperties(node->name()); + for (const auto& output : outputs) { + auto output_info = cost_node->add_output_info(); + output_info->set_dtype(output.dtype()); + auto shape = output_info->mutable_shape(); + *shape = output.shape(); + } + } + } while (scheduler.MarkCurrNodeExecuted(node_costs)); + + *costs = scheduler.Summary(); + VLOG(1) << inaccurate_nodes.size() << " out of " + << optimized_graph.node_size() + << " nodes have inaccurate time estimation"; + for (const auto& node : inaccurate_nodes) { + VLOG(2) << "Node with inaccurate time estimation: " << node; + } + return Status::OK(); +} + +} // end namespace grappler +} // end namespace tensorflow diff --git a/tensorflow/core/grappler/costs/analytical_cost_estimator.h b/tensorflow/core/grappler/costs/analytical_cost_estimator.h new file mode 100644 index 00000000000..03e7faa4ff5 --- /dev/null +++ b/tensorflow/core/grappler/costs/analytical_cost_estimator.h @@ -0,0 +1,63 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_CORE_GRAPPLER_COSTS_ANALYTICAL_COST_ESTIMATOR_H_ +#define TENSORFLOW_CORE_GRAPPLER_COSTS_ANALYTICAL_COST_ESTIMATOR_H_ + +#include "tensorflow/core/grappler/costs/cost_estimator.h" +#include "tensorflow/core/grappler/costs/op_level_cost_estimator.h" +#include "tensorflow/core/grappler/grappler_item.h" +#include "tensorflow/core/lib/core/status.h" + +namespace tensorflow { +class CostGraphDef; +class GraphDef; +} // namespace tensorflow + +namespace tensorflow { +namespace grappler { + +class Cluster; +struct GrapplerItem; + +// Estimate the cost of running a Grappler item based on the theoretical +// performance of the hardware that will run the model. +class AnalyticalCostEstimator : public CostEstimator { + public: + // Does not take ownership of cluster. + explicit AnalyticalCostEstimator(Cluster* cluster, bool use_static_shapes); + ~AnalyticalCostEstimator() override {} + + // Initalizes the estimator for the specified grappler item. + // This implementation always returns OK. + Status Initialize(const GrapplerItem& item) override; + + // Predict the performance of each node of the optimized graph and annotate + // the CostGraphDef with the corresponding estimates. Also returns the + // expected latency for the whole graph. + Status PredictCosts(const GraphDef& optimized_graph, CostGraphDef* cost_graph, + Costs* overall_latency) const override; + + private: + Cluster* cluster_; // Not owned. + GrapplerItem item_; + OpLevelCostEstimator node_estimator_; + bool use_static_shapes_; +}; + +} // end namespace grappler +} // end namespace tensorflow + +#endif // TENSORFLOW_CORE_GRAPPLER_COSTS_ANALYTICAL_COST_ESTIMATOR_H_ diff --git a/tensorflow/core/grappler/costs/virtual_placer.cc b/tensorflow/core/grappler/costs/virtual_placer.cc new file mode 100644 index 00000000000..adc640aaa41 --- /dev/null +++ b/tensorflow/core/grappler/costs/virtual_placer.cc @@ -0,0 +1,57 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/core/grappler/costs/virtual_placer.h" +#include "tensorflow/core/framework/node_def.pb.h" +#include "tensorflow/core/grappler/clusters/cluster.h" +#include "tensorflow/core/grappler/costs/utils.h" +#include "tensorflow/core/grappler/devices.h" +#include "tensorflow/core/util/device_name_utils.h" + +namespace tensorflow { +namespace grappler { + +VirtualPlacer::VirtualPlacer(Cluster* cluster) : has_gpu_(false) { + devices_["CPU"] = GetLocalCPUInfo(); + if (GetNumAvailableGPUs() > 0) { + has_gpu_ = true; + devices_["GPU"] = GetLocalGPUInfo(0); + } + unknown_device_.set_type("UNKNOWN"); +} + +const OpInfo::DeviceProperties& VirtualPlacer::get_device( + const NodeDef& node) const { + string device_type; + DeviceNameUtils::ParsedName parsed; + if (!node.device().empty() && + DeviceNameUtils::ParseFullName(node.device(), &parsed)) { + device_type = parsed.type; + } else { + if (has_gpu_) { + device_type = "GPU"; + } else { + device_type = "CPU"; + } + } + auto it = devices_.find(device_type); + if (it == devices_.end()) { + return unknown_device_; + } + return it->second; +} + +} // end namespace grappler +} // end namespace tensorflow diff --git a/tensorflow/core/grappler/costs/virtual_placer.h b/tensorflow/core/grappler/costs/virtual_placer.h new file mode 100644 index 00000000000..812e94bf59d --- /dev/null +++ b/tensorflow/core/grappler/costs/virtual_placer.h @@ -0,0 +1,45 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_CORE_GRAPPLER_COSTS_VIRTUAL_PLACER_H_ +#define TENSORFLOW_CORE_GRAPPLER_COSTS_VIRTUAL_PLACER_H_ + +#include +#include "tensorflow/core/grappler/costs/op_performance_data.pb.h" +#include "tensorflow/core/platform/types.h" + +namespace tensorflow { +class NodeDef; + +namespace grappler { +class Cluster; + +// The virtual placer emulates the behavior of the TF placer. +class VirtualPlacer { + public: + VirtualPlacer(Cluster* cluster); + + const OpInfo::DeviceProperties& get_device(const NodeDef& node) const; + + private: + std::unordered_map devices_; + bool has_gpu_; + OpInfo::DeviceProperties unknown_device_; +}; + +} // namespace grappler +} // end namespace tensorflow + +#endif // TENSORFLOW_CORE_GRAPPLER_COSTS_VIRTUAL_PLACER_H_ From b329dd821e29e64c93b1b9bf38e61871c6cb53da Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Fri, 5 May 2017 09:04:16 -0800 Subject: [PATCH 06/27] Add `categorical_column_with_identity`. Change: 155209179 --- .../python/feature_column/feature_column.py | 102 +++++++++ .../feature_column/feature_column_test.py | 194 ++++++++++++++++++ 2 files changed, 296 insertions(+) diff --git a/tensorflow/python/feature_column/feature_column.py b/tensorflow/python/feature_column/feature_column.py index ffdf8868e21..f8855f259e2 100644 --- a/tensorflow/python/feature_column/feature_column.py +++ b/tensorflow/python/feature_column/feature_column.py @@ -129,6 +129,7 @@ from tensorflow.python.framework import ops from tensorflow.python.framework import sparse_tensor as sparse_tensor_lib from tensorflow.python.framework import tensor_shape from tensorflow.python.ops import array_ops +from tensorflow.python.ops import check_ops from tensorflow.python.ops import embedding_ops from tensorflow.python.ops import init_ops from tensorflow.python.ops import math_ops @@ -656,6 +657,44 @@ def categorical_column_with_vocabulary_list( default_value=default_value) +def categorical_column_with_identity(key, num_buckets, default_value=None): + """A `_CategoricalColumn` that returns identity values. + + Use this when your inputs are integers in the range `[0, num_buckets)`. Values + outside this range will result in `default_value` if specified, otherwise it + will fail. + + Inputs can be either `Tensor` or `SparseTensor`. + ``` + + Args: + key: A unique string identifying the input feature. It is used as the + column name and the dictionary key for feature parsing configs, feature + `Tensor` objects, and feature columns. + num_buckets: Range of inputs and outputs is `[0, num_buckets)`. + default_value: If `None`, this column's graph operations will fail for + out-of-range inputs. Otherwise, this value must be in the range + `[0, num_buckets)`, and will replace inputs in that range. + + Returns: + A `_CategoricalColumn` that returns identity values. + + Raises: + ValueError: if `num_buckets` is less than one. + ValueError: if `default_value` is not in range `[0, num_buckets)`. + """ + if num_buckets < 1: + raise ValueError( + 'num_buckets {} < 1, column_name {}'.format(num_buckets, key)) + if (default_value is not None) and ( + (default_value < 0) or (default_value >= num_buckets)): + raise ValueError( + 'default_value {} not in range [0, {}), column_name {}'.format( + default_value, num_buckets, key)) + return _IdentityCategoricalColumn( + key=key, num_buckets=num_buckets, default_value=default_value) + + class _FeatureColumn(object): """Represents a feature column abstraction. @@ -1384,6 +1423,69 @@ class _VocabularyListCategoricalColumn( return _CategoricalColumn.IdWeightPair(inputs.get(self), None) +class _IdentityCategoricalColumn( + _CategoricalColumn, + collections.namedtuple('_IdentityCategoricalColumn', ( + 'key', 'num_buckets', 'default_value' + ))): + + """See `categorical_column_with_identity`.""" + + @property + def name(self): + return self.key + + @property + def _parse_example_config(self): + return {self.key: parsing_ops.VarLenFeature(dtypes.int64)} + + def _transform_feature(self, inputs): + input_tensor = _to_sparse_input(inputs.get(self.key)) + + if not input_tensor.dtype.is_integer: + raise ValueError( + 'Invalid input, not integer. key: {} dtype: {}'.format( + self.key, input_tensor.dtype)) + + values = math_ops.to_int64(input_tensor.values, name='values') + num_buckets = math_ops.to_int64(self.num_buckets, name='num_buckets') + zero = math_ops.to_int64(0, name='zero') + if self.default_value is None: + # Fail if values are out-of-range. + assert_less = check_ops.assert_less( + values, num_buckets, data=(values, num_buckets), + name='assert_less_than_num_buckets') + assert_greater = check_ops.assert_greater_equal( + values, zero, data=(values,), + name='assert_greater_or_equal_0') + with ops.control_dependencies((assert_less, assert_greater)): + values = array_ops.identity(values) + else: + # Assign default for out-of-range values. + values = array_ops.where( + math_ops.logical_or( + values < zero, values >= num_buckets, name='out_of_range'), + array_ops.fill( + dims=array_ops.shape(values), + value=math_ops.to_int64(self.default_value), + name='default_values'), + values) + + return sparse_tensor_lib.SparseTensor( + indices=input_tensor.indices, + values=values, + dense_shape=input_tensor.dense_shape) + + @property + def _num_buckets(self): + """Returns number of buckets in this sparse feature.""" + return self.num_buckets + + def _get_sparse_tensors( + self, inputs, weight_collections=None, trainable=None): + return _CategoricalColumn.IdWeightPair(inputs.get(self), None) + + # TODO(zakaria): Move this to embedding_ops and make it public. def _safe_embedding_lookup_sparse(embedding_weights, sparse_ids, diff --git a/tensorflow/python/feature_column/feature_column_test.py b/tensorflow/python/feature_column/feature_column_test.py index 59aa39411f5..52018118316 100644 --- a/tensorflow/python/feature_column/feature_column_test.py +++ b/tensorflow/python/feature_column/feature_column_test.py @@ -31,6 +31,7 @@ from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors from tensorflow.python.framework import ops from tensorflow.python.framework import sparse_tensor +from tensorflow.python.ops import array_ops from tensorflow.python.ops import lookup_ops from tensorflow.python.ops import parsing_ops from tensorflow.python.ops import variable_scope @@ -1828,5 +1829,198 @@ class VocabularyListCategoricalColumnTest(test.TestCase): self.assertAllClose(((3.,), (1.,)), predictions.eval()) +class IdentityCategoricalColumnTest(test.TestCase): + + def test_constructor(self): + column = fc.categorical_column_with_identity(key='aaa', num_buckets=3) + self.assertEqual('aaa', column.name) + # pylint: disable=protected-access + self.assertEqual(3, column._num_buckets) + self.assertEqual({ + 'aaa': parsing_ops.VarLenFeature(dtypes.int64) + }, column._parse_example_config) + # pylint: enable=protected-access + + def test_deep_copy(self): + """Tests deepcopy of categorical_column_with_hash_bucket.""" + original = fc.categorical_column_with_identity(key='aaa', num_buckets=3) + for column in (original, copy.deepcopy(original)): + self.assertEqual('aaa', column.name) + # pylint: disable=protected-access + self.assertEqual(3, column._num_buckets) + self.assertEqual({ + 'aaa': parsing_ops.VarLenFeature(dtypes.int64) + }, column._parse_example_config) + # pylint: enable=protected-access + + def test_invalid_num_buckets_zero(self): + with self.assertRaisesRegexp(ValueError, 'num_buckets 0 < 1'): + fc.categorical_column_with_identity(key='aaa', num_buckets=0) + + def test_invalid_num_buckets_negative(self): + with self.assertRaisesRegexp(ValueError, 'num_buckets -1 < 1'): + fc.categorical_column_with_identity(key='aaa', num_buckets=-1) + + def test_invalid_default_value_too_small(self): + with self.assertRaisesRegexp(ValueError, 'default_value -1 not in range'): + fc.categorical_column_with_identity( + key='aaa', num_buckets=3, default_value=-1) + + def test_invalid_default_value_too_big(self): + with self.assertRaisesRegexp(ValueError, 'default_value 3 not in range'): + fc.categorical_column_with_identity( + key='aaa', num_buckets=3, default_value=3) + + def test_invalid_input_dtype(self): + column = fc.categorical_column_with_identity(key='aaa', num_buckets=3) + inputs = sparse_tensor.SparseTensorValue( + indices=((0, 0), (1, 0), (1, 1)), + values=('omar', 'stringer', 'marlo'), + dense_shape=(2, 2)) + with self.assertRaisesRegexp(ValueError, 'Invalid input, not integer'): + # pylint: disable=protected-access + column._get_sparse_tensors(fc._LazyBuilder({'aaa': inputs})) + # pylint: enable=protected-access + + def test_get_sparse_tensors(self): + column = fc.categorical_column_with_identity(key='aaa', num_buckets=3) + inputs = sparse_tensor.SparseTensorValue( + indices=((0, 0), (1, 0), (1, 1)), + values=(0, 1, 0), + dense_shape=(2, 2)) + # pylint: disable=protected-access + id_weight_pair = column._get_sparse_tensors( + fc._LazyBuilder({'aaa': inputs})) + # pylint: enable=protected-access + self.assertIsNone(id_weight_pair.weight_tensor) + with _initialized_session(): + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=inputs.indices, + values=np.array((0, 1, 0), dtype=np.int64), + dense_shape=inputs.dense_shape), + id_weight_pair.id_tensor.eval()) + + def test_get_sparse_tensors_dense_input(self): + column = fc.categorical_column_with_identity(key='aaa', num_buckets=3) + # pylint: disable=protected-access + id_weight_pair = column._get_sparse_tensors(fc._LazyBuilder({ + 'aaa': ((0, -1), (1, 0)) + })) + # pylint: enable=protected-access + self.assertIsNone(id_weight_pair.weight_tensor) + with _initialized_session(): + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=((0, 0), (1, 0), (1, 1)), + values=np.array((0, 1, 0), dtype=np.int64), + dense_shape=(2, 2)), + id_weight_pair.id_tensor.eval()) + + def test_get_sparse_tensors_with_inputs_too_small(self): + column = fc.categorical_column_with_identity(key='aaa', num_buckets=3) + inputs = sparse_tensor.SparseTensorValue( + indices=((0, 0), (1, 0), (1, 1)), + values=(1, -1, 0), + dense_shape=(2, 2)) + # pylint: disable=protected-access + id_weight_pair = column._get_sparse_tensors( + fc._LazyBuilder({'aaa': inputs})) + # pylint: enable=protected-access + self.assertIsNone(id_weight_pair.weight_tensor) + with _initialized_session(): + with self.assertRaisesRegexp( + errors.OpError, 'assert_greater_or_equal_0'): + id_weight_pair.id_tensor.eval() + + def test_get_sparse_tensors_with_inputs_too_big(self): + column = fc.categorical_column_with_identity(key='aaa', num_buckets=3) + inputs = sparse_tensor.SparseTensorValue( + indices=((0, 0), (1, 0), (1, 1)), + values=(1, 99, 0), + dense_shape=(2, 2)) + # pylint: disable=protected-access + id_weight_pair = column._get_sparse_tensors( + fc._LazyBuilder({'aaa': inputs})) + # pylint: enable=protected-access + self.assertIsNone(id_weight_pair.weight_tensor) + with _initialized_session(): + with self.assertRaisesRegexp( + errors.OpError, 'assert_less_than_num_buckets'): + id_weight_pair.id_tensor.eval() + + def test_get_sparse_tensors_with_default_value(self): + column = fc.categorical_column_with_identity( + key='aaa', num_buckets=4, default_value=3) + inputs = sparse_tensor.SparseTensorValue( + indices=((0, 0), (1, 0), (1, 1)), + values=(1, -1, 99), + dense_shape=(2, 2)) + # pylint: disable=protected-access + id_weight_pair = column._get_sparse_tensors( + fc._LazyBuilder({'aaa': inputs})) + # pylint: enable=protected-access + self.assertIsNone(id_weight_pair.weight_tensor) + with _initialized_session(): + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=inputs.indices, + values=np.array((1, 3, 3), dtype=np.int64), + dense_shape=inputs.dense_shape), + id_weight_pair.id_tensor.eval()) + + def test_get_sparse_tensors_with_default_value_and_placeholder_inputs(self): + column = fc.categorical_column_with_identity( + key='aaa', num_buckets=4, default_value=3) + input_indices = array_ops.placeholder(dtype=dtypes.int64) + input_values = array_ops.placeholder(dtype=dtypes.int32) + input_shape = array_ops.placeholder(dtype=dtypes.int64) + inputs = sparse_tensor.SparseTensorValue( + indices=input_indices, + values=input_values, + dense_shape=input_shape) + # pylint: disable=protected-access + id_weight_pair = column._get_sparse_tensors( + fc._LazyBuilder({'aaa': inputs})) + # pylint: enable=protected-access + self.assertIsNone(id_weight_pair.weight_tensor) + with _initialized_session(): + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=np.array(((0, 0), (1, 0), (1, 1)), dtype=np.int64), + values=np.array((1, 3, 3), dtype=np.int64), + dense_shape=np.array((2, 2), dtype=np.int64)), + id_weight_pair.id_tensor.eval(feed_dict={ + input_indices: ((0, 0), (1, 0), (1, 1)), + input_values: (1, -1, 99), + input_shape: (2, 2), + })) + + def test_make_linear_model(self): + column = fc.categorical_column_with_identity(key='aaa', num_buckets=3) + self.assertEqual(3, column._num_buckets) + with ops.Graph().as_default(): + predictions = fc.make_linear_model({ + column.name: sparse_tensor.SparseTensorValue( + indices=((0, 0), (1, 0), (1, 1)), + values=(0, 2, 1), + dense_shape=(2, 2)) + }, (column,)) + bias = get_linear_model_bias() + weight_var = get_linear_model_column_var(column) + with _initialized_session(): + self.assertAllClose((0.,), bias.eval()) + self.assertAllClose(((0.,), (0.,), (0.,)), weight_var.eval()) + self.assertAllClose(((0.,), (0.,)), predictions.eval()) + weight_var.assign(((1.,), (2.,), (3.,))).eval() + # weight_var[0] = 1 + # weight_var[2] + weight_var[1] = 3+2 = 5 + self.assertAllClose(((1.,), (5.,)), predictions.eval()) + + if __name__ == '__main__': test.main() From 692fad20f913ffa2cb874a87578ecabb03cc4557 Mon Sep 17 00:00:00 2001 From: Dan Ringwalt Date: Fri, 5 May 2017 09:09:05 -0800 Subject: [PATCH 07/27] Merge changes from github. Change: 155209832 --- ISSUE_TEMPLATE.md | 51 +- README.md | 15 +- RELEASE.md | 1 + configure | 70 +- tensorflow/BUILD | 1 + tensorflow/contrib/batching/BUILD | 1 + .../factorization/python/ops/gmm_ops.py | 2 +- .../python/kernel_tests/grid_rnn_test.py | 627 +++++++++++------- .../grid_rnn/python/ops/grid_rnn_cell.py | 497 +++++++++----- .../python/kernel_tests/image_ops_test.py | 25 + .../contrib/image/python/ops/image_ops.py | 40 +- .../camera/CameraExampleViewController.mm | 4 +- .../keras/python/keras/initializers_test.py | 2 +- .../contrib/layers/python/layers/encoders.py | 2 +- .../layers/python/layers/initializers.py | 5 +- tensorflow/contrib/learn/__init__.py | 1 + .../learn/estimators/dnn_linear_combined.py | 12 +- .../learn/estimators/dynamic_rnn_estimator.py | 351 ---------- .../estimators/dynamic_rnn_estimator_test.py | 50 -- .../learn/python/learn/estimators/kmeans.py | 5 +- .../estimators/state_saving_rnn_estimator.py | 178 ----- .../state_saving_rnn_estimator_test.py | 50 -- tensorflow/contrib/rnn/__init__.py | 2 + tensorflow/contrib/signal/BUILD | 46 ++ tensorflow/contrib/signal/__init__.py | 27 + tensorflow/contrib/signal/python/__init__.py | 19 + .../python/kernel_tests/shape_ops_test.py | 68 ++ .../contrib/signal/python/ops/__init__.py | 19 + .../contrib/signal/python/ops/shape_ops.py | 87 +++ tensorflow/contrib/slim/README.md | 2 +- .../contrib/slim/python/slim/data/README.md | 14 +- .../slim/python/slim/nets/resnet_v2.py | 2 + .../python/framework/fake_summary_writer.py | 3 + tensorflow/contrib/verbs/README.md | 42 +- .../contrib/verbs/grpc_verbs_service.cc | 4 + tensorflow/contrib/verbs/rdma.cc | 15 +- tensorflow/contrib/verbs/rdma.h | 2 + tensorflow/contrib/verbs/rdma_mgr.cc | 4 + tensorflow/contrib/verbs/verbs_service.proto | 2 + .../core/distributed_runtime/rpc/grpc_call.h | 1 + .../rpc/grpc_tensor_coding.cc | 22 +- tensorflow/core/kernels/cwise_op_atan2.cc | 23 + .../core/kernels/cwise_op_gpu_atan2.cu.cc | 26 + tensorflow/core/kernels/cwise_ops.h | 16 + tensorflow/core/kernels/linalg_ops_common.cc | 32 +- tensorflow/core/kernels/linalg_ops_common.h | 3 - tensorflow/core/ops/math_ops.cc | 15 + .../docs_src/community/documentation.md | 22 +- tensorflow/docs_src/get_started/input_fn.md | 2 +- tensorflow/docs_src/install/install_linux.md | 22 +- tensorflow/docs_src/install/install_mac.md | 4 +- .../docs_src/install/install_sources.md | 4 +- .../docs_src/install/install_windows.md | 21 +- .../examples/image_retraining/retrain.py | 9 +- tensorflow/python/estimator/estimator_test.py | 5 + tensorflow/python/framework/ops.py | 10 +- .../python/kernel_tests/cwise_ops_test.py | 27 + .../kernel_tests/tensor_priority_test.py | 86 +++ tensorflow/python/layers/convolutional.py | 278 +++++++- .../python/layers/convolutional_test.py | 169 +++++ tensorflow/python/layers/layers.py | 2 + tensorflow/python/layers/utils.py | 26 + tensorflow/python/layers/utils_test.py | 7 + tensorflow/python/ops/array_ops.py | 5 +- tensorflow/python/ops/ctc_ops.py | 7 +- tensorflow/python/ops/init_ops.py | 23 +- tensorflow/python/ops/logging_ops.py | 2 +- tensorflow/python/ops/math_grad.py | 10 + tensorflow/python/ops/math_ops.py | 12 +- tensorflow/python/ops/nn_impl.py | 5 +- tensorflow/python/ops/nn_ops.py | 107 +-- tensorflow/python/ops/parsing_ops.py | 2 +- tensorflow/python/ops/random_ops.py | 2 +- .../python/summary/writer/writer_cache.py | 4 + .../python/tools/import_pb_to_tensorboard.py | 50 ++ .../python/training/checkpoint_utils.py | 16 +- tensorflow/python/training/input.py | 6 - .../python/training/monitored_session.py | 4 +- tensorflow/python/training/saver.py | 4 +- .../stream_executor/cuda/cuda_gpu_executor.cc | 8 - .../stream_executor/cuda/cuda_gpu_executor.h | 11 - .../tensorboard/backend/application_test.py | 13 + .../event_accumulator_test.py | 12 +- .../tensorboard/dist/tf-tensorboard.html | 2 +- tensorflow/tensorflow.bzl | 2 +- .../tools/api/golden/tensorflow.layers.pbtxt | 4 + .../tools/api/golden/tensorflow.nn.pbtxt | 2 +- tensorflow/tools/api/golden/tensorflow.pbtxt | 4 + tensorflow/tools/ci_build/update_version.sh | 5 +- tensorflow/tools/common/public_api.py | 2 +- tensorflow/tools/compatibility/tf_upgrade.py | 4 + tensorflow/tools/docker/Dockerfile.devel | 3 +- tensorflow/tools/docker/Dockerfile.devel-gpu | 3 +- .../tools/docs/doc_generator_visitor.py | 2 +- tensorflow/tools/docs/pretty_docs.py | 2 +- tensorflow/tools/graph_transforms/README.md | 15 +- tensorflow/tools/pip_package/BUILD | 2 + tensorflow/tools/pip_package/setup.py | 2 +- .../tools/quantization/quantize_graph.py | 3 +- tensorflow/tools/tfprof/README.md | 4 +- .../crosstool_wrapper_driver_is_not_gcc.tpl | 2 +- 101 files changed, 2169 insertions(+), 1377 deletions(-) create mode 100644 tensorflow/contrib/signal/BUILD create mode 100644 tensorflow/contrib/signal/__init__.py create mode 100644 tensorflow/contrib/signal/python/__init__.py create mode 100644 tensorflow/contrib/signal/python/kernel_tests/shape_ops_test.py create mode 100644 tensorflow/contrib/signal/python/ops/__init__.py create mode 100644 tensorflow/contrib/signal/python/ops/shape_ops.py create mode 100644 tensorflow/core/kernels/cwise_op_atan2.cc create mode 100644 tensorflow/core/kernels/cwise_op_gpu_atan2.cu.cc create mode 100644 tensorflow/python/kernel_tests/tensor_priority_test.py create mode 100644 tensorflow/python/tools/import_pb_to_tensorboard.py diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md index d0979e87f73..6f4c048ce83 100644 --- a/ISSUE_TEMPLATE.md +++ b/ISSUE_TEMPLATE.md @@ -1,33 +1,36 @@ -Please go to Stack Overflow for help and support. http://stackoverflow.com/questions/tagged/tensorflow +Please go to Stack Overflow for help and support: + +http://stackoverflow.com/questions/tagged/tensorflow + If you open a GitHub issue, here is our policy: -1. It must be a bug or feature request. +1. It must be a bug or a feature request. 2. The form below must be filled out. -**Here's why we have that policy**: TensorFlow developers respond to issues. We want to focus on work that benefits the whole community, e.g. fixing bugs and adding features. Support only helps individuals. GitHub also notifies thousands of people when issues are filed. We want them to see you communicating an interesting problem, rather than being redirected to Stack Overflow. +**Here's why we have that policy**: TensorFlow developers respond to issues. We want to focus on work that benefits the whole community, e.g., fixing bugs and adding features. Support only helps individuals. GitHub also notifies thousands of people when issues are filed. We want them to see you communicating an interesting problem, rather than being redirected to Stack Overflow. ------------------------ +### System information +- **Have I written custom code (as opposed to using a stock example script provided in TensorFlow)**: +- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**: +- **TensorFlow installed from (source or binary)**: +- **TensorFlow version (use command below)**: +- **Bazel version (if compiling from source)**: +- **CUDA/cuDNN version**: +- **GPU model and memory**: +- **Exact command to reproduce**: + +You can collect some of this information using our environment capture script: + +https://github.com/tensorflow/tensorflow/tree/master/tools/tf_env_collect.sh + +You can obtain the TensorFlow version with + +python -c "import tensorflow as tf; print(tf.GIT_VERSION, tf.VERSION)" + +### Describe the problem Describe the problem clearly here. Be sure to convey here why it's a bug in TensorFlow or a feature request. -### System Information -- *Have I written custom code (as opposed to using a stock example script provided in TensorFlow)?*: -- *OS Platform and Distribution (i.e. Linux Ubuntu 16.0)*: -- *TensorFlow installed from (source or binary)?*: -- *TensorFlow version* (use command below): -- *Bazel version (if compiling from source)*: -- *CUDA/cuDNN version*: -- *GPU Model and Memory*: -- *Exact command to reproduce*: - -You can collect some of this information using our environment capture script https://github.com/tensorflow/tensorflow/blob/master/tools/ -You can collect the TensorFlow version with -```sh -python -c "import tensorflow as tf; print (tf.GIT_VERSION, tf.VERSION)" -``` - - -### Describe the problem clearly - -### Source Code / Logs -Include any logs or source code that would be helpful to diagnose the problem. If including tracebacks, please include the full-traceback. Large logs and files should be attached. Try to reproducible test-case code the bare-minimum necessary to generate the problem +### Source code / logs +Include any logs or source code that would be helpful to diagnose the problem. If including tracebacks, please include the full traceback. Large logs and files should be attached. Try to provide a reproducible test case that is the bare minimum necessary to generate the problem. diff --git a/README.md b/README.md index 951e7c3b9f6..2878dab2601 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ guidelines](CONTRIBUTING.md).** **We use [GitHub issues](https://github.com/tensorflow/tensorflow/issues) for tracking requests and bugs, but please see -[Community](tensorflow/docs_src/about/index.md#community) for general questions +[Community](https://www.tensorflow.org/community/) for general questions and discussion.** ## Installation @@ -34,13 +34,12 @@ and discussion.** People who are a little more adventurous can also try our nightly binaries: - -* Linux CPU-only: [Python 2](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-cpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON2,label=cpu-slave/lastSuccessfulBuild/artifact/pip_test/whl/tensorflow-1.1.0rc2-cp27-none-linux_x86_64.whl) ([build history](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-cpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON2,label=cpu-slave)) / [Python 3.4](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-cpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON3,label=cpu-slave/lastSuccessfulBuild/artifact/pip_test/whl/tensorflow-1.1.0rc2-cp34-cp34m-linux_x86_64.whl) ([build history](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-cpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON3,label=cpu-slave/)) / [Python 3.5](https://ci.tensorflow.org/view/Nightly/job/nightly-python35-linux-cpu/lastSuccessfulBuild/artifact/pip_test/whl/tensorflow-1.1.0rc2-cp35-cp35m-linux_x86_64.whl) ([build history](https://ci.tensorflow.org/view/Nightly/job/nightly-python35-linux-cpu/)) -* Linux GPU: [Python 2](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-linux-gpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON2,label=gpu-linux/lastSuccessfulBuild/artifact/pip_test/whl/tensorflow_gpu-1.1.0rc2-cp27-none-linux_x86_64.whl) ([build history](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-linux-gpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON2,label=gpu-linux/)) / [Python 3.4](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-linux-gpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON3,label=gpu-linux/lastSuccessfulBuild/artifact/pip_test/whl/tensorflow_gpu-1.1.0rc2-cp34-cp34m-linux_x86_64.whl) ([build history](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-linux-gpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON3,label=gpu-linux/)) / [Python 3.5](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-linux-gpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON3.5,label=gpu-linux/lastSuccessfulBuild/artifact/pip_test/whl/tensorflow_gpu-1.1.0rc2-cp35-cp35m-linux_x86_64.whl) ([build history](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-linux-gpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON3.5,label=gpu-linux/)) -* Mac CPU-only: [Python 2](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-cpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON2,label=mac-slave/lastSuccessfulBuild/artifact/pip_test/whl/tensorflow-1.1.0rc2-py2-none-any.whl) ([build history](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-cpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON2,label=mac-slave/)) / [Python 3](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-cpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON3,label=mac-slave/lastSuccessfulBuild/artifact/pip_test/whl/tensorflow-1.1.0rc2-py3-none-any.whl) ([build history](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-cpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON3,label=mac-slave/)) -* Mac GPU: [Python 2](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-mac-gpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON2,label=gpu-mac/lastSuccessfulBuild/artifact/pip_test/whl/tensorflow_gpu-1.1.0rc2-py2-none-any.whl) ([build history](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-mac-gpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON2,label=gpu-mac/)) / [Python 3](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-mac-gpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON3,label=gpu-mac/lastSuccessfulBuild/artifact/pip_test/whl/tensorflow_gpu-1.1.0rc2-py3-none-any.whl) ([build history](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-mac-gpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON3,label=gpu-mac/)) -* Windows CPU-only: [Python 3.5 64-bit](https://ci.tensorflow.org/view/Nightly/job/nightly-win/DEVICE=cpu,OS=windows/lastSuccessfulBuild/artifact/cmake_build/tf_python/dist/tensorflow-1.1.0rc2-cp35-cp35m-win_amd64.whl) ([build history](https://ci.tensorflow.org/view/Nightly/job/nightly-win/DEVICE=cpu,OS=windows/)) -* Windows GPU: [Python 3.5 64-bit](https://ci.tensorflow.org/view/Nightly/job/nightly-win/DEVICE=gpu,OS=windows/lastSuccessfulBuild/artifact/cmake_build/tf_python/dist/tensorflow_gpu-1.1.0rc2-cp35-cp35m-win_amd64.whl) ([build history](https://ci.tensorflow.org/view/Nightly/job/nightly-win/DEVICE=gpu,OS=windows/)) +* Linux CPU-only: [Python 2](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-cpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON2,label=cpu-slave/lastSuccessfulBuild/artifact/pip_test/whl/tensorflow-1.1.0-cp27-none-linux_x86_64.whl) ([build history](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-cpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON2,label=cpu-slave)) / [Python 3.4](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-cpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON3,label=cpu-slave/lastSuccessfulBuild/artifact/pip_test/whl/tensorflow-1.1.0-cp34-cp34m-linux_x86_64.whl) ([build history](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-cpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON3,label=cpu-slave/)) / [Python 3.5](https://ci.tensorflow.org/view/Nightly/job/nightly-python35-linux-cpu/lastSuccessfulBuild/artifact/pip_test/whl/tensorflow-1.1.0-cp35-cp35m-linux_x86_64.whl) ([build history](https://ci.tensorflow.org/view/Nightly/job/nightly-python35-linux-cpu/)) +* Linux GPU: [Python 2](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-linux-gpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON2,label=gpu-linux/lastSuccessfulBuild/artifact/pip_test/whl/tensorflow_gpu-1.1.0-cp27-none-linux_x86_64.whl) ([build history](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-linux-gpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON2,label=gpu-linux/)) / [Python 3.4](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-linux-gpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON3,label=gpu-linux/lastSuccessfulBuild/artifact/pip_test/whl/tensorflow_gpu-1.1.0-cp34-cp34m-linux_x86_64.whl) ([build history](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-linux-gpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON3,label=gpu-linux/)) / [Python 3.5](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-linux-gpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON3.5,label=gpu-linux/lastSuccessfulBuild/artifact/pip_test/whl/tensorflow_gpu-1.1.0-cp35-cp35m-linux_x86_64.whl) ([build history](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-linux-gpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON3.5,label=gpu-linux/)) +* Mac CPU-only: [Python 2](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-cpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON2,label=mac-slave/lastSuccessfulBuild/artifact/pip_test/whl/tensorflow-1.1.0-py2-none-any.whl) ([build history](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-cpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON2,label=mac-slave/)) / [Python 3](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-cpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON3,label=mac-slave/lastSuccessfulBuild/artifact/pip_test/whl/tensorflow-1.1.0-py3-none-any.whl) ([build history](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-cpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON3,label=mac-slave/)) +* Mac GPU: [Python 2](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-mac-gpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON2,label=gpu-mac/lastSuccessfulBuild/artifact/pip_test/whl/tensorflow_gpu-1.1.0-py2-none-any.whl) ([build history](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-mac-gpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON2,label=gpu-mac/)) / [Python 3](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-mac-gpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON3,label=gpu-mac/lastSuccessfulBuild/artifact/pip_test/whl/tensorflow_gpu-1.1.0-py3-none-any.whl) ([build history](https://ci.tensorflow.org/view/Nightly/job/nightly-matrix-mac-gpu/TF_BUILD_IS_OPT=OPT,TF_BUILD_IS_PIP=PIP,TF_BUILD_PYTHON_VERSION=PYTHON3,label=gpu-mac/)) +* Windows CPU-only: [Python 3.5 64-bit](https://ci.tensorflow.org/view/Nightly/job/nightly-win/DEVICE=cpu,OS=windows/lastSuccessfulBuild/artifact/cmake_build/tf_python/dist/tensorflow-1.1.0-cp35-cp35m-win_amd64.whl) ([build history](https://ci.tensorflow.org/view/Nightly/job/nightly-win/DEVICE=cpu,OS=windows/)) +* Windows GPU: [Python 3.5 64-bit](https://ci.tensorflow.org/view/Nightly/job/nightly-win/DEVICE=gpu,OS=windows/lastSuccessfulBuild/artifact/cmake_build/tf_python/dist/tensorflow_gpu-1.1.0-cp35-cp35m-win_amd64.whl) ([build history](https://ci.tensorflow.org/view/Nightly/job/nightly-win/DEVICE=gpu,OS=windows/)) * Android: [demo APK](https://ci.tensorflow.org/view/Nightly/job/nightly-android/lastSuccessfulBuild/artifact/out/tensorflow_demo.apk), [native libs](http://ci.tensorflow.org/view/Nightly/job/nightly-android/lastSuccessfulBuild/artifact/out/native/) ([build history](https://ci.tensorflow.org/view/Nightly/job/nightly-android/)) diff --git a/RELEASE.md b/RELEASE.md index fe6d052640a..f078d336abb 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,6 +1,7 @@ # Changes since the last release ## Major Features and Improvements +* Added `tf.layers.conv3d_transpose` layer for spatio temporal deconvolution. * Added `tf.Session.make_callable()`, which provides a lower overhead means of running a similar step multiple times. * Added ibverbs-based RDMA support to contrib (courtesy @junshi15 from Yahoo). * `RNNCell` objects now subclass `tf.layers._Layer`. The strictness described diff --git a/configure b/configure index d7dde98292a..7f68a8f5d47 100755 --- a/configure +++ b/configure @@ -35,12 +35,9 @@ function is_windows() { fi } -function sed_hyphen_i() { - if is_macos; then - sed -i '' "$@" - else - sed -i "$@" - fi +function sed_in_place() { + sed -e $1 $2 > "$2.bak" + mv "$2.bak" $2 } function write_to_bazelrc() { @@ -170,7 +167,7 @@ function setup_python { rm -f .tf_configure.bazelrc touch .tf_configure.bazelrc touch .bazelrc -sed_hyphen_i "/tf_configure/d" .bazelrc +sed_in_place "/tf_configure/d" .bazelrc echo "import %workspace%/.tf_configure.bazelrc" >> .bazelrc # Delete any leftover BUILD files from the Makefile build, which would interfere @@ -409,31 +406,6 @@ done export TF_CUDA_CLANG write_action_env_to_bazelrc "TF_CUDA_CLANG" "$TF_CUDA_CLANG" -# Set up which gcc nvcc should use as the host compiler -# No need to set this on Windows -while [[ "$TF_CUDA_CLANG" != "1" ]] && ! is_windows && true; do - fromuser="" - if [ -z "$GCC_HOST_COMPILER_PATH" ]; then - default_gcc_host_compiler_path=$(which gcc || true) - read -p "Please specify which gcc should be used by nvcc as the host compiler. [Default is $default_gcc_host_compiler_path]: " GCC_HOST_COMPILER_PATH - fromuser="1" - if [ -z "$GCC_HOST_COMPILER_PATH" ]; then - GCC_HOST_COMPILER_PATH="$default_gcc_host_compiler_path" - fi - fi - if [ -e "$GCC_HOST_COMPILER_PATH" ]; then - export GCC_HOST_COMPILER_PATH - write_action_env_to_bazelrc "GCC_HOST_COMPILER_PATH" "$GCC_HOST_COMPILER_PATH" - break - fi - echo "Invalid gcc path. ${GCC_HOST_COMPILER_PATH} cannot be found" 1>&2 - if [ -z "$fromuser" ]; then - exit 1 - fi - GCC_HOST_COMPILER_PATH="" - # Retry -done - # Set up which clang we should use as the cuda / host compiler. while [[ "$TF_CUDA_CLANG" == "1" ]] && true; do fromuser="" @@ -474,6 +446,11 @@ while true; do else default_cuda_path="$(cygpath -m "$CUDA_PATH")" fi + elif is_linux; then + # If the default doesn't exist, try an alternative default. + if [ ! -d $default_cuda_path ] && [ -d /opt/cuda ]; then + default_cuda_path=/opt/cuda + fi fi read -p "Please specify the location where CUDA $TF_CUDA_VERSION toolkit is installed. Refer to README.md for more details. [Default is $default_cuda_path]: " CUDA_TOOLKIT_PATH fromuser="1" @@ -513,6 +490,35 @@ while true; do CUDA_TOOLKIT_PATH="" done +# Set up which gcc nvcc should use as the host compiler +# No need to set this on Windows +while [[ "$TF_CUDA_CLANG" != "1" ]] && ! is_windows && true; do + fromuser="" + if [ -z "$GCC_HOST_COMPILER_PATH" ]; then + default_gcc_host_compiler_path=$(which gcc || true) + cuda_bin_symlink="$CUDA_TOOLKIT_PATH/bin/gcc" + if [ -L "$cuda_bin_symlink" ]; then + default_gcc_host_compiler_path=$(readlink $cuda_bin_symlink) + fi + read -p "Please specify which gcc should be used by nvcc as the host compiler. [Default is $default_gcc_host_compiler_path]: " GCC_HOST_COMPILER_PATH + fromuser="1" + if [ -z "$GCC_HOST_COMPILER_PATH" ]; then + GCC_HOST_COMPILER_PATH="$default_gcc_host_compiler_path" + fi + fi + if [ -e "$GCC_HOST_COMPILER_PATH" ]; then + export GCC_HOST_COMPILER_PATH + write_action_env_to_bazelrc "GCC_HOST_COMPILER_PATH" "$GCC_HOST_COMPILER_PATH" + break + fi + echo "Invalid gcc path. ${GCC_HOST_COMPILER_PATH} cannot be found" 1>&2 + if [ -z "$fromuser" ]; then + exit 1 + fi + GCC_HOST_COMPILER_PATH="" + # Retry +done + # Find out where the cuDNN library is installed while true; do # Configure the cuDNN version to use. diff --git a/tensorflow/BUILD b/tensorflow/BUILD index a2f7a9fb639..a36a57314d6 100644 --- a/tensorflow/BUILD +++ b/tensorflow/BUILD @@ -255,6 +255,7 @@ filegroup( "//tensorflow/contrib/seq2seq:all_files", "//tensorflow/contrib/session_bundle:all_files", "//tensorflow/contrib/session_bundle/example:all_files", + "//tensorflow/contrib/signal:all_files", "//tensorflow/contrib/slim:all_files", "//tensorflow/contrib/slim/python/slim/data:all_files", "//tensorflow/contrib/slim/python/slim/nets:all_files", diff --git a/tensorflow/contrib/batching/BUILD b/tensorflow/contrib/batching/BUILD index 1f1e2db69b0..b441906cd4d 100644 --- a/tensorflow/contrib/batching/BUILD +++ b/tensorflow/contrib/batching/BUILD @@ -181,6 +181,7 @@ py_test( size = "small", srcs = ["python/ops/batch_ops_test.py"], srcs_version = "PY2AND3", + tags = ["nomac"], deps = [ ":batch_py", "//tensorflow/python:framework_test_lib", diff --git a/tensorflow/contrib/factorization/python/ops/gmm_ops.py b/tensorflow/contrib/factorization/python/ops/gmm_ops.py index 42544ff884f..b092eab3166 100644 --- a/tensorflow/contrib/factorization/python/ops/gmm_ops.py +++ b/tensorflow/contrib/factorization/python/ops/gmm_ops.py @@ -85,7 +85,7 @@ def _init_clusters_random(data, num_clusters, random_seed): maxval=math_ops.cast(num_data, dtypes.int64), seed=random_seed, dtype=dtypes.int64) - indices = math_ops.cast(indices, dtypes.int32) % num_data + indices %= math_ops.cast(num_data, dtypes.int64) clusters_init = embedding_lookup(data, indices, partition_strategy='div') return clusters_init diff --git a/tensorflow/contrib/grid_rnn/python/kernel_tests/grid_rnn_test.py b/tensorflow/contrib/grid_rnn/python/kernel_tests/grid_rnn_test.py index 758e0bcc07c..280271a42dc 100644 --- a/tensorflow/contrib/grid_rnn/python/kernel_tests/grid_rnn_test.py +++ b/tensorflow/contrib/grid_rnn/python/kernel_tests/grid_rnn_test.py @@ -34,180 +34,228 @@ from tensorflow.python.platform import test class GridRNNCellTest(test.TestCase): def testGrid2BasicLSTMCell(self): - with self.test_session() as sess: + with self.test_session(use_gpu=False) as sess: with variable_scope.variable_scope( 'root', initializer=init_ops.constant_initializer(0.2)) as root_scope: x = array_ops.zeros([1, 3]) - m = array_ops.zeros([1, 8]) + m = ((array_ops.zeros([1, 2]), array_ops.zeros([1, 2])), + (array_ops.zeros([1, 2]), array_ops.zeros([1, 2]))) cell = grid_rnn_cell.Grid2BasicLSTMCell(2) - self.assertEqual(cell.state_size, 8) + self.assertEqual(cell.state_size, ((2, 2), (2, 2))) g, s = cell(x, m) - self.assertEqual(g.get_shape(), (1, 2)) - self.assertEqual(s.get_shape(), (1, 8)) + self.assertEqual(g[0].get_shape(), (1, 2)) + self.assertEqual(s[0].c.get_shape(), (1, 2)) + self.assertEqual(s[0].h.get_shape(), (1, 2)) + self.assertEqual(s[1].c.get_shape(), (1, 2)) + self.assertEqual(s[1].h.get_shape(), (1, 2)) sess.run([variables.global_variables_initializer()]) - res = sess.run([g, s], { - x: np.array([[1., 1., 1.]]), - m: np.array([[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]]) + res_g, res_s = sess.run([g, s], { + x: + np.array([[1., 1., 1.]]), + m: ((np.array([[0.1, 0.2]]), np.array([[0.3, 0.4]])), + (np.array([[0.5, 0.6]]), np.array([[0.7, 0.8]]))) }) - self.assertEqual(res[0].shape, (1, 2)) - self.assertEqual(res[1].shape, (1, 8)) - self.assertAllClose(res[0], [[0.36617181, 0.36617181]]) - self.assertAllClose(res[1], [[0.71053141, 0.71053141, 0.36617181, - 0.36617181, 0.72320831, 0.80555487, - 0.39102408, 0.42150158]]) + self.assertEqual(res_g[0].shape, (1, 2)) + self.assertEqual(res_s[0].c.shape, (1, 2)) + self.assertEqual(res_s[0].h.shape, (1, 2)) + self.assertEqual(res_s[1].c.shape, (1, 2)) + self.assertEqual(res_s[1].h.shape, (1, 2)) + + self.assertAllClose(res_g, ([[0.36617181, 0.36617181]],)) + self.assertAllClose( + res_s, (([[0.71053141, 0.71053141]], [[0.36617181, 0.36617181]]), + ([[0.72320831, 0.80555487]], [[0.39102408, 0.42150158]]))) # emulate a loop through the input sequence, # where we call cell() multiple times root_scope.reuse_variables() g2, s2 = cell(x, m) - self.assertEqual(g2.get_shape(), (1, 2)) - self.assertEqual(s2.get_shape(), (1, 8)) + self.assertEqual(g2[0].get_shape(), (1, 2)) + self.assertEqual(s2[0].c.get_shape(), (1, 2)) + self.assertEqual(s2[0].h.get_shape(), (1, 2)) + self.assertEqual(s2[1].c.get_shape(), (1, 2)) + self.assertEqual(s2[1].h.get_shape(), (1, 2)) - res = sess.run([g2, s2], {x: np.array([[2., 2., 2.]]), m: res[1]}) - self.assertEqual(res[0].shape, (1, 2)) - self.assertEqual(res[1].shape, (1, 8)) - self.assertAllClose(res[0], [[0.58847463, 0.58847463]]) - self.assertAllClose(res[1], [[1.40469193, 1.40469193, 0.58847463, - 0.58847463, 0.97726452, 1.04626071, - 0.4927212, 0.51137757]]) + res_g2, res_s2 = sess.run([g2, s2], + {x: np.array([[2., 2., 2.]]), + m: res_s}) + self.assertEqual(res_g2[0].shape, (1, 2)) + self.assertEqual(res_s2[0].c.shape, (1, 2)) + self.assertEqual(res_s2[0].h.shape, (1, 2)) + self.assertEqual(res_s2[1].c.shape, (1, 2)) + self.assertEqual(res_s2[1].h.shape, (1, 2)) + self.assertAllClose(res_g2[0], [[0.58847463, 0.58847463]]) + self.assertAllClose( + res_s2, (([[1.40469193, 1.40469193]], [[0.58847463, 0.58847463]]), + ([[0.97726452, 1.04626071]], [[0.4927212, 0.51137757]]))) def testGrid2BasicLSTMCellTied(self): - with self.test_session() as sess: + with self.test_session(use_gpu=False) as sess: with variable_scope.variable_scope( 'root', initializer=init_ops.constant_initializer(0.2)): x = array_ops.zeros([1, 3]) - m = array_ops.zeros([1, 8]) + m = ((array_ops.zeros([1, 2]), array_ops.zeros([1, 2])), + (array_ops.zeros([1, 2]), array_ops.zeros([1, 2]))) cell = grid_rnn_cell.Grid2BasicLSTMCell(2, tied=True) - self.assertEqual(cell.state_size, 8) + self.assertEqual(cell.state_size, ((2, 2), (2, 2))) g, s = cell(x, m) - self.assertEqual(g.get_shape(), (1, 2)) - self.assertEqual(s.get_shape(), (1, 8)) + self.assertEqual(g[0].get_shape(), (1, 2)) + self.assertEqual(s[0].c.get_shape(), (1, 2)) + self.assertEqual(s[0].h.get_shape(), (1, 2)) + self.assertEqual(s[1].c.get_shape(), (1, 2)) + self.assertEqual(s[1].h.get_shape(), (1, 2)) sess.run([variables.global_variables_initializer()]) - res = sess.run([g, s], { - x: np.array([[1., 1., 1.]]), - m: np.array([[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]]) + res_g, res_s = sess.run([g, s], { + x: + np.array([[1., 1., 1.]]), + m: ((np.array([[0.1, 0.2]]), np.array([[0.3, 0.4]])), + (np.array([[0.5, 0.6]]), np.array([[0.7, 0.8]]))) }) - self.assertEqual(res[0].shape, (1, 2)) - self.assertEqual(res[1].shape, (1, 8)) - self.assertAllClose(res[0], [[0.36617181, 0.36617181]]) - self.assertAllClose(res[1], [[0.71053141, 0.71053141, 0.36617181, - 0.36617181, 0.72320831, 0.80555487, - 0.39102408, 0.42150158]]) + self.assertEqual(res_g[0].shape, (1, 2)) + self.assertEqual(res_s[0].c.shape, (1, 2)) + self.assertEqual(res_s[0].h.shape, (1, 2)) + self.assertEqual(res_s[1].c.shape, (1, 2)) + self.assertEqual(res_s[1].h.shape, (1, 2)) - res = sess.run([g, s], {x: np.array([[1., 1., 1.]]), m: res[1]}) - self.assertEqual(res[0].shape, (1, 2)) - self.assertEqual(res[1].shape, (1, 8)) - self.assertAllClose(res[0], [[0.36703536, 0.36703536]]) - self.assertAllClose(res[1], [[0.71200621, 0.71200621, 0.36703536, - 0.36703536, 0.80941606, 0.87550586, - 0.40108523, 0.42199609]]) + self.assertAllClose(res_g[0], [[0.36617181, 0.36617181]]) + self.assertAllClose( + res_s, (([[0.71053141, 0.71053141]], [[0.36617181, 0.36617181]]), + ([[0.72320831, 0.80555487]], [[0.39102408, 0.42150158]]))) + + res_g, res_s = sess.run([g, s], {x: np.array([[1., 1., 1.]]), m: res_s}) + self.assertEqual(res_g[0].shape, (1, 2)) + + self.assertAllClose(res_g[0], [[0.36703536, 0.36703536]]) + self.assertAllClose( + res_s, (([[0.71200621, 0.71200621]], [[0.36703536, 0.36703536]]), + ([[0.80941606, 0.87550586]], [[0.40108523, 0.42199609]]))) def testGrid2BasicLSTMCellWithRelu(self): - with self.test_session() as sess: + with self.test_session(use_gpu=False) as sess: with variable_scope.variable_scope( 'root', initializer=init_ops.constant_initializer(0.2)): x = array_ops.zeros([1, 3]) - m = array_ops.zeros([1, 4]) + m = ((array_ops.zeros([1, 2]), array_ops.zeros([1, 2])),) cell = grid_rnn_cell.Grid2BasicLSTMCell( 2, tied=False, non_recurrent_fn=nn_ops.relu) - self.assertEqual(cell.state_size, 4) + self.assertEqual(cell.state_size, ((2, 2),)) g, s = cell(x, m) - self.assertEqual(g.get_shape(), (1, 2)) - self.assertEqual(s.get_shape(), (1, 4)) + self.assertEqual(g[0].get_shape(), (1, 2)) + self.assertEqual(s[0].c.get_shape(), (1, 2)) + self.assertEqual(s[0].h.get_shape(), (1, 2)) sess.run([variables.global_variables_initializer()]) - res = sess.run( - [g, s], - {x: np.array([[1., 1., 1.]]), - m: np.array([[0.1, 0.2, 0.3, 0.4]])}) - self.assertEqual(res[0].shape, (1, 2)) - self.assertEqual(res[1].shape, (1, 4)) - self.assertAllClose(res[0], [[0.31667367, 0.31667367]]) - self.assertAllClose(res[1], [[0.29530135, 0.37520045, 0.17044567, - 0.21292259]]) + res_g, res_s = sess.run([g, s], { + x: np.array([[1., 1., 1.]]), + m: ((np.array([[0.1, 0.2]]), np.array([[0.3, 0.4]])),) + }) + self.assertEqual(res_g[0].shape, (1, 2)) + self.assertAllClose(res_g[0], [[0.31667367, 0.31667367]]) + self.assertAllClose(res_s, (([[0.29530135, 0.37520045]], + [[0.17044567, 0.21292259]]),)) """LSTMCell """ def testGrid2LSTMCell(self): - with self.test_session() as sess: + with self.test_session(use_gpu=False) as sess: with variable_scope.variable_scope( 'root', initializer=init_ops.constant_initializer(0.5)): x = array_ops.zeros([1, 3]) - m = array_ops.zeros([1, 8]) + m = ((array_ops.zeros([1, 2]), array_ops.zeros([1, 2])), + (array_ops.zeros([1, 2]), array_ops.zeros([1, 2]))) cell = grid_rnn_cell.Grid2LSTMCell(2, use_peepholes=True) - self.assertEqual(cell.state_size, 8) + self.assertEqual(cell.state_size, ((2, 2), (2, 2))) g, s = cell(x, m) - self.assertEqual(g.get_shape(), (1, 2)) - self.assertEqual(s.get_shape(), (1, 8)) + self.assertEqual(g[0].get_shape(), (1, 2)) + self.assertEqual(s[0].c.get_shape(), (1, 2)) + self.assertEqual(s[0].h.get_shape(), (1, 2)) + self.assertEqual(s[1].c.get_shape(), (1, 2)) + self.assertEqual(s[1].h.get_shape(), (1, 2)) sess.run([variables.global_variables_initializer()]) - res = sess.run([g, s], { - x: np.array([[1., 1., 1.]]), - m: np.array([[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]]) + res_g, res_s = sess.run([g, s], { + x: + np.array([[1., 1., 1.]]), + m: ((np.array([[0.1, 0.2]]), np.array([[0.3, 0.4]])), + (np.array([[0.5, 0.6]]), np.array([[0.7, 0.8]]))) }) - self.assertEqual(res[0].shape, (1, 2)) - self.assertEqual(res[1].shape, (1, 8)) - self.assertAllClose(res[0], [[0.95686918, 0.95686918]]) - self.assertAllClose(res[1], [[2.41515064, 2.41515064, 0.95686918, - 0.95686918, 1.38917875, 1.49043763, - 0.83884692, 0.86036491]]) + self.assertEqual(res_g[0].shape, (1, 2)) + self.assertEqual(res_s[0].c.shape, (1, 2)) + self.assertEqual(res_s[0].h.shape, (1, 2)) + self.assertEqual(res_s[1].c.shape, (1, 2)) + self.assertEqual(res_s[1].h.shape, (1, 2)) + + self.assertAllClose(res_g[0], [[0.95686918, 0.95686918]]) + self.assertAllClose( + res_s, (([[2.41515064, 2.41515064]], [[0.95686918, 0.95686918]]), + ([[1.38917875, 1.49043763]], [[0.83884692, 0.86036491]]))) def testGrid2LSTMCellTied(self): - with self.test_session() as sess: + with self.test_session(use_gpu=False) as sess: with variable_scope.variable_scope( 'root', initializer=init_ops.constant_initializer(0.5)): x = array_ops.zeros([1, 3]) - m = array_ops.zeros([1, 8]) + m = ((array_ops.zeros([1, 2]), array_ops.zeros([1, 2])), + (array_ops.zeros([1, 2]), array_ops.zeros([1, 2]))) cell = grid_rnn_cell.Grid2LSTMCell(2, tied=True, use_peepholes=True) - self.assertEqual(cell.state_size, 8) + self.assertEqual(cell.state_size, ((2, 2), (2, 2))) g, s = cell(x, m) - self.assertEqual(g.get_shape(), (1, 2)) - self.assertEqual(s.get_shape(), (1, 8)) + self.assertEqual(g[0].get_shape(), (1, 2)) + self.assertEqual(s[0].c.get_shape(), (1, 2)) + self.assertEqual(s[0].h.get_shape(), (1, 2)) + self.assertEqual(s[1].c.get_shape(), (1, 2)) + self.assertEqual(s[1].h.get_shape(), (1, 2)) sess.run([variables.global_variables_initializer()]) - res = sess.run([g, s], { - x: np.array([[1., 1., 1.]]), - m: np.array([[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]]) + res_g, res_s = sess.run([g, s], { + x: + np.array([[1., 1., 1.]]), + m: ((np.array([[0.1, 0.2]]), np.array([[0.3, 0.4]])), + (np.array([[0.5, 0.6]]), np.array([[0.7, 0.8]]))) }) - self.assertEqual(res[0].shape, (1, 2)) - self.assertEqual(res[1].shape, (1, 8)) - self.assertAllClose(res[0], [[0.95686918, 0.95686918]]) - self.assertAllClose(res[1], [[2.41515064, 2.41515064, 0.95686918, - 0.95686918, 1.38917875, 1.49043763, - 0.83884692, 0.86036491]]) + self.assertEqual(res_g[0].shape, (1, 2)) + self.assertEqual(res_s[0].c.shape, (1, 2)) + self.assertEqual(res_s[0].h.shape, (1, 2)) + self.assertEqual(res_s[1].c.shape, (1, 2)) + self.assertEqual(res_s[1].h.shape, (1, 2)) + + self.assertAllClose(res_g[0], [[0.95686918, 0.95686918]]) + self.assertAllClose( + res_s, (([[2.41515064, 2.41515064]], [[0.95686918, 0.95686918]]), + ([[1.38917875, 1.49043763]], [[0.83884692, 0.86036491]]))) def testGrid2LSTMCellWithRelu(self): with self.test_session() as sess: with variable_scope.variable_scope( 'root', initializer=init_ops.constant_initializer(0.5)): x = array_ops.zeros([1, 3]) - m = array_ops.zeros([1, 4]) + m = ((array_ops.zeros([1, 2]), array_ops.zeros([1, 2])),) cell = grid_rnn_cell.Grid2LSTMCell( 2, use_peepholes=True, non_recurrent_fn=nn_ops.relu) - self.assertEqual(cell.state_size, 4) + self.assertEqual(cell.state_size, ((2, 2),)) g, s = cell(x, m) - self.assertEqual(g.get_shape(), (1, 2)) - self.assertEqual(s.get_shape(), (1, 4)) + self.assertEqual(g[0].get_shape(), (1, 2)) + self.assertEqual(s[0].c.get_shape(), (1, 2)) + self.assertEqual(s[0].h.get_shape(), (1, 2)) sess.run([variables.global_variables_initializer()]) - res = sess.run( - [g, s], - {x: np.array([[1., 1., 1.]]), - m: np.array([[0.1, 0.2, 0.3, 0.4]])}) - self.assertEqual(res[0].shape, (1, 2)) - self.assertEqual(res[1].shape, (1, 4)) - self.assertAllClose(res[0], [[2.1831727, 2.1831727]]) - self.assertAllClose(res[1], [[0.92270052, 1.02325559, 0.66159075, - 0.70475441]]) + res_g, res_s = sess.run([g, s], { + x: np.array([[1., 1., 1.]]), + m: ((np.array([[0.1, 0.2]]), np.array([[0.3, 0.4]])),) + }) + self.assertEqual(res_g[0].shape, (1, 2)) + self.assertAllClose(res_g[0], [[2.1831727, 2.1831727]]) + self.assertAllClose(res_s, (([[0.92270052, 1.02325559]], + [[0.66159075, 0.70475441]]),)) """RNNCell """ @@ -217,74 +265,84 @@ class GridRNNCellTest(test.TestCase): with variable_scope.variable_scope( 'root', initializer=init_ops.constant_initializer(0.5)): x = array_ops.zeros([2, 2]) - m = array_ops.zeros([2, 4]) + m = (array_ops.zeros([2, 2]), array_ops.zeros([2, 2])) cell = grid_rnn_cell.Grid2BasicRNNCell(2) - self.assertEqual(cell.state_size, 4) + self.assertEqual(cell.state_size, (2, 2)) g, s = cell(x, m) - self.assertEqual(g.get_shape(), (2, 2)) - self.assertEqual(s.get_shape(), (2, 4)) + self.assertEqual(g[0].get_shape(), (2, 2)) + self.assertEqual(s[0].get_shape(), (2, 2)) + self.assertEqual(s[1].get_shape(), (2, 2)) sess.run([variables.global_variables_initializer()]) - res = sess.run([g, s], { - x: np.array([[1., 1.], [2., 2.]]), - m: np.array([[0.1, 0.1, 0.1, 0.1], [0.2, 0.2, 0.2, 0.2]]) + res_g, res_s = sess.run([g, s], { + x: + np.array([[1., 1.], [2., 2.]]), + m: (np.array([[0.1, 0.1], [0.2, 0.2]]), np.array([[0.1, 0.1], + [0.2, 0.2]])) }) - self.assertEqual(res[0].shape, (2, 2)) - self.assertEqual(res[1].shape, (2, 4)) - self.assertAllClose(res[0], [[0.94685763, 0.94685763], - [0.99480951, 0.99480951]]) - self.assertAllClose(res[1], - [[0.94685763, 0.94685763, 0.80049908, 0.80049908], - [0.99480951, 0.99480951, 0.97574311, 0.97574311]]) + self.assertEqual(res_g[0].shape, (2, 2)) + self.assertEqual(res_s[0].shape, (2, 2)) + self.assertEqual(res_s[1].shape, (2, 2)) + + self.assertAllClose(res_g, ([[0.94685763, 0.94685763], + [0.99480951, 0.99480951]],)) + self.assertAllClose( + res_s, ([[0.94685763, 0.94685763], [0.99480951, 0.99480951]], + [[0.80049908, 0.80049908], [0.97574311, 0.97574311]])) def testGrid2BasicRNNCellTied(self): with self.test_session() as sess: with variable_scope.variable_scope( 'root', initializer=init_ops.constant_initializer(0.5)): x = array_ops.zeros([2, 2]) - m = array_ops.zeros([2, 4]) + m = (array_ops.zeros([2, 2]), array_ops.zeros([2, 2])) cell = grid_rnn_cell.Grid2BasicRNNCell(2, tied=True) - self.assertEqual(cell.state_size, 4) + self.assertEqual(cell.state_size, (2, 2)) g, s = cell(x, m) - self.assertEqual(g.get_shape(), (2, 2)) - self.assertEqual(s.get_shape(), (2, 4)) + self.assertEqual(g[0].get_shape(), (2, 2)) + self.assertEqual(s[0].get_shape(), (2, 2)) + self.assertEqual(s[1].get_shape(), (2, 2)) sess.run([variables.global_variables_initializer()]) - res = sess.run([g, s], { - x: np.array([[1., 1.], [2., 2.]]), - m: np.array([[0.1, 0.1, 0.1, 0.1], [0.2, 0.2, 0.2, 0.2]]) + res_g, res_s = sess.run([g, s], { + x: + np.array([[1., 1.], [2., 2.]]), + m: (np.array([[0.1, 0.1], [0.2, 0.2]]), np.array([[0.1, 0.1], + [0.2, 0.2]])) }) - self.assertEqual(res[0].shape, (2, 2)) - self.assertEqual(res[1].shape, (2, 4)) - self.assertAllClose(res[0], [[0.94685763, 0.94685763], - [0.99480951, 0.99480951]]) - self.assertAllClose(res[1], - [[0.94685763, 0.94685763, 0.80049908, 0.80049908], - [0.99480951, 0.99480951, 0.97574311, 0.97574311]]) + self.assertEqual(res_g[0].shape, (2, 2)) + self.assertEqual(res_s[0].shape, (2, 2)) + self.assertEqual(res_s[1].shape, (2, 2)) + + self.assertAllClose(res_g, ([[0.94685763, 0.94685763], + [0.99480951, 0.99480951]],)) + self.assertAllClose( + res_s, ([[0.94685763, 0.94685763], [0.99480951, 0.99480951]], + [[0.80049908, 0.80049908], [0.97574311, 0.97574311]])) def testGrid2BasicRNNCellWithRelu(self): with self.test_session() as sess: with variable_scope.variable_scope( 'root', initializer=init_ops.constant_initializer(0.5)): x = array_ops.zeros([1, 2]) - m = array_ops.zeros([1, 2]) + m = (array_ops.zeros([1, 2]),) cell = grid_rnn_cell.Grid2BasicRNNCell(2, non_recurrent_fn=nn_ops.relu) - self.assertEqual(cell.state_size, 2) + self.assertEqual(cell.state_size, (2,)) g, s = cell(x, m) - self.assertEqual(g.get_shape(), (1, 2)) - self.assertEqual(s.get_shape(), (1, 2)) + self.assertEqual(g[0].get_shape(), (1, 2)) + self.assertEqual(s[0].get_shape(), (1, 2)) sess.run([variables.global_variables_initializer()]) - res = sess.run([g, s], - {x: np.array([[1., 1.]]), - m: np.array([[0.1, 0.1]])}) - self.assertEqual(res[0].shape, (1, 2)) - self.assertEqual(res[1].shape, (1, 2)) - self.assertAllClose(res[0], [[1.80049896, 1.80049896]]) - self.assertAllClose(res[1], [[0.80049896, 0.80049896]]) + res_g, res_s = sess.run( + [g, s], {x: np.array([[1., 1.]]), + m: np.array([[0.1, 0.1]])}) + self.assertEqual(res_g[0].shape, (1, 2)) + self.assertEqual(res_s[0].shape, (1, 2)) + self.assertAllClose(res_g, ([[1.80049896, 1.80049896]],)) + self.assertAllClose(res_s, ([[0.80049896, 0.80049896]],)) """1-LSTM """ @@ -294,51 +352,59 @@ class GridRNNCellTest(test.TestCase): with variable_scope.variable_scope( 'root', initializer=init_ops.constant_initializer(0.5)) as root_scope: x = array_ops.zeros([1, 3]) - m = array_ops.zeros([1, 4]) + m = ((array_ops.zeros([1, 2]), array_ops.zeros([1, 2])),) cell = grid_rnn_cell.Grid1LSTMCell(2, use_peepholes=True) - self.assertEqual(cell.state_size, 4) + self.assertEqual(cell.state_size, ((2, 2),)) g, s = cell(x, m) - self.assertEqual(g.get_shape(), (1, 2)) - self.assertEqual(s.get_shape(), (1, 4)) + self.assertEqual(g[0].get_shape(), (1, 2)) + self.assertEqual(s[0].c.get_shape(), (1, 2)) + self.assertEqual(s[0].h.get_shape(), (1, 2)) sess.run([variables.global_variables_initializer()]) - res = sess.run( - [g, s], - {x: np.array([[1., 1., 1.]]), - m: np.array([[0.1, 0.2, 0.3, 0.4]])}) - self.assertEqual(res[0].shape, (1, 2)) - self.assertEqual(res[1].shape, (1, 4)) - self.assertAllClose(res[0], [[0.91287315, 0.91287315]]) - self.assertAllClose(res[1], - [[2.26285243, 2.26285243, 0.91287315, 0.91287315]]) + res_g, res_s = sess.run([g, s], { + x: np.array([[1., 1., 1.]]), + m: ((np.array([[0.1, 0.2]]), np.array([[0.3, 0.4]])),) + }) + self.assertEqual(res_g[0].shape, (1, 2)) + self.assertEqual(res_s[0].c.shape, (1, 2)) + self.assertEqual(res_s[0].h.shape, (1, 2)) + + self.assertAllClose(res_g, ([[0.91287315, 0.91287315]],)) + self.assertAllClose(res_s, (([[2.26285243, 2.26285243]], + [[0.91287315, 0.91287315]]),)) root_scope.reuse_variables() x2 = array_ops.zeros([0, 0]) g2, s2 = cell(x2, m) - self.assertEqual(g2.get_shape(), (1, 2)) - self.assertEqual(s2.get_shape(), (1, 4)) + self.assertEqual(g2[0].get_shape(), (1, 2)) + self.assertEqual(s2[0].c.get_shape(), (1, 2)) + self.assertEqual(s2[0].h.get_shape(), (1, 2)) sess.run([variables.global_variables_initializer()]) - res = sess.run([g2, s2], {m: res[1]}) - self.assertEqual(res[0].shape, (1, 2)) - self.assertEqual(res[1].shape, (1, 4)) - self.assertAllClose(res[0], [[0.9032144, 0.9032144]]) - self.assertAllClose(res[1], - [[2.79966092, 2.79966092, 0.9032144, 0.9032144]]) + res_g2, res_s2 = sess.run([g2, s2], {m: res_s}) + self.assertEqual(res_g2[0].shape, (1, 2)) + self.assertEqual(res_s2[0].c.shape, (1, 2)) + self.assertEqual(res_s2[0].h.shape, (1, 2)) + + self.assertAllClose(res_g2, ([[0.9032144, 0.9032144]],)) + self.assertAllClose(res_s2, (([[2.79966092, 2.79966092]], + [[0.9032144, 0.9032144]]),)) g3, s3 = cell(x2, m) - self.assertEqual(g3.get_shape(), (1, 2)) - self.assertEqual(s3.get_shape(), (1, 4)) + self.assertEqual(g3[0].get_shape(), (1, 2)) + self.assertEqual(s3[0].c.get_shape(), (1, 2)) + self.assertEqual(s3[0].h.get_shape(), (1, 2)) sess.run([variables.global_variables_initializer()]) - res = sess.run([g3, s3], {m: res[1]}) - self.assertEqual(res[0].shape, (1, 2)) - self.assertEqual(res[1].shape, (1, 4)) - self.assertAllClose(res[0], [[0.92727238, 0.92727238]]) - self.assertAllClose(res[1], - [[3.3529923, 3.3529923, 0.92727238, 0.92727238]]) + res_g3, res_s3 = sess.run([g3, s3], {m: res_s2}) + self.assertEqual(res_g3[0].shape, (1, 2)) + self.assertEqual(res_s3[0].c.shape, (1, 2)) + self.assertEqual(res_s3[0].h.shape, (1, 2)) + self.assertAllClose(res_g3, ([[0.92727238, 0.92727238]],)) + self.assertAllClose(res_s3, (([[3.3529923, 3.3529923]], + [[0.92727238, 0.92727238]]),)) """3-LSTM """ @@ -348,32 +414,42 @@ class GridRNNCellTest(test.TestCase): with variable_scope.variable_scope( 'root', initializer=init_ops.constant_initializer(0.5)): x = array_ops.zeros([1, 3]) - m = array_ops.zeros([1, 12]) + m = ((array_ops.zeros([1, 2]), array_ops.zeros([1, 2])), + (array_ops.zeros([1, 2]), array_ops.zeros([1, 2])), + (array_ops.zeros([1, 2]), array_ops.zeros([1, 2]))) cell = grid_rnn_cell.Grid3LSTMCell(2, use_peepholes=True) - self.assertEqual(cell.state_size, 12) + self.assertEqual(cell.state_size, ((2, 2), (2, 2), (2, 2))) g, s = cell(x, m) - self.assertEqual(g.get_shape(), (1, 2)) - self.assertEqual(s.get_shape(), (1, 12)) + self.assertEqual(g[0].get_shape(), (1, 2)) + self.assertEqual(s[0].c.get_shape(), (1, 2)) + self.assertEqual(s[0].h.get_shape(), (1, 2)) + self.assertEqual(s[1].c.get_shape(), (1, 2)) + self.assertEqual(s[1].h.get_shape(), (1, 2)) + self.assertEqual(s[2].c.get_shape(), (1, 2)) + self.assertEqual(s[2].h.get_shape(), (1, 2)) sess.run([variables.global_variables_initializer()]) - res = sess.run([g, s], { + res_g, res_s = sess.run([g, s], { x: np.array([[1., 1., 1.]]), - m: - np.array([[ - 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, -0.1, -0.2, -0.3, - -0.4 - ]]) + m: ((np.array([[0.1, 0.2]]), np.array([[0.3, 0.4]])), + (np.array([[0.5, 0.6]]), np.array([[0.7, 0.8]])), (np.array( + [[-0.1, -0.2]]), np.array([[-0.3, -0.4]]))) }) - self.assertEqual(res[0].shape, (1, 2)) - self.assertEqual(res[1].shape, (1, 12)) + self.assertEqual(res_g[0].shape, (1, 2)) + self.assertEqual(res_s[0].c.shape, (1, 2)) + self.assertEqual(res_s[0].h.shape, (1, 2)) + self.assertEqual(res_s[1].c.shape, (1, 2)) + self.assertEqual(res_s[1].h.shape, (1, 2)) + self.assertEqual(res_s[2].c.shape, (1, 2)) + self.assertEqual(res_s[2].h.shape, (1, 2)) - self.assertAllClose(res[0], [[0.96892911, 0.96892911]]) - self.assertAllClose(res[1], [[2.45227885, 2.45227885, 0.96892911, - 0.96892911, 1.33592629, 1.4373529, - 0.80867189, 0.83247656, 0.7317788, - 0.63205892, 0.56548983, 0.50446129]]) + self.assertAllClose(res_g, ([[0.96892911, 0.96892911]],)) + self.assertAllClose( + res_s, (([[2.45227885, 2.45227885]], [[0.96892911, 0.96892911]]), + ([[1.33592629, 1.4373529]], [[0.80867189, 0.83247656]]), + ([[0.7317788, 0.63205892]], [[0.56548983, 0.50446129]]))) """Edge cases """ @@ -383,7 +459,7 @@ class GridRNNCellTest(test.TestCase): with variable_scope.variable_scope( 'root', initializer=init_ops.constant_initializer(0.5)): x = array_ops.zeros([3, 2]) - m = array_ops.zeros([0, 0]) + m = () # this is equivalent to relu cell = grid_rnn_cell.GridRNNCell( @@ -394,21 +470,22 @@ class GridRNNCellTest(test.TestCase): non_recurrent_dims=0, non_recurrent_fn=nn_ops.relu) g, s = cell(x, m) - self.assertEqual(g.get_shape(), (3, 2)) - self.assertEqual(s.get_shape(), (0, 0)) + self.assertEqual(g[0].get_shape(), (3, 2)) + self.assertEqual(s, ()) sess.run([variables.global_variables_initializer()]) - res = sess.run([g, s], {x: np.array([[1., -1.], [-2, 1], [2, -1]])}) - self.assertEqual(res[0].shape, (3, 2)) - self.assertEqual(res[1].shape, (0, 0)) - self.assertAllClose(res[0], [[0, 0], [0, 0], [0.5, 0.5]]) + res_g, res_s = sess.run([g, s], + {x: np.array([[1., -1.], [-2, 1], [2, -1]])}) + self.assertEqual(res_g[0].shape, (3, 2)) + self.assertEqual(res_s, ()) + self.assertAllClose(res_g, ([[0, 0], [0, 0], [0.5, 0.5]],)) def testGridRNNEdgeCasesNoOutput(self): with self.test_session() as sess: with variable_scope.variable_scope( 'root', initializer=init_ops.constant_initializer(0.5)): x = array_ops.zeros([1, 2]) - m = array_ops.zeros([1, 4]) + m = ((array_ops.zeros([1, 2]), array_ops.zeros([1, 2])),) # This cell produces no output cell = grid_rnn_cell.GridRNNCell( @@ -419,16 +496,18 @@ class GridRNNCellTest(test.TestCase): non_recurrent_dims=0, non_recurrent_fn=nn_ops.relu) g, s = cell(x, m) - self.assertEqual(g.get_shape(), (0, 0)) - self.assertEqual(s.get_shape(), (1, 4)) + self.assertEqual(g, ()) + self.assertEqual(s[0].c.get_shape(), (1, 2)) + self.assertEqual(s[0].h.get_shape(), (1, 2)) sess.run([variables.global_variables_initializer()]) - res = sess.run( - [g, s], - {x: np.array([[1., 1.]]), - m: np.array([[0.1, 0.1, 0.1, 0.1]])}) - self.assertEqual(res[0].shape, (0, 0)) - self.assertEqual(res[1].shape, (1, 4)) + res_g, res_s = sess.run([g, s], { + x: np.array([[1., 1.]]), + m: ((np.array([[0.1, 0.1]]), np.array([[0.1, 0.1]])),) + }) + self.assertEqual(res_g, ()) + self.assertEqual(res_s[0].c.shape, (1, 2)) + self.assertEqual(res_s[0].h.shape, (1, 2)) """Test with tf.nn.rnn """ @@ -451,20 +530,29 @@ class GridRNNCellTest(test.TestCase): outputs, state = core_rnn.static_rnn(cell, inputs, dtype=dtypes.float32) self.assertEqual(len(outputs), len(inputs)) - self.assertEqual(state.get_shape(), (batch_size, 8)) + self.assertEqual(state[0].c.get_shape(), (batch_size, 2)) + self.assertEqual(state[0].h.get_shape(), (batch_size, 2)) + self.assertEqual(state[1].c.get_shape(), (batch_size, 2)) + self.assertEqual(state[1].h.get_shape(), (batch_size, 2)) for out, inp in zip(outputs, inputs): - self.assertEqual(out.get_shape()[0], inp.get_shape()[0]) - self.assertEqual(out.get_shape()[1], num_units) - self.assertEqual(out.dtype, inp.dtype) + self.assertEqual(len(out), 1) + self.assertEqual(out[0].get_shape()[0], inp.get_shape()[0]) + self.assertEqual(out[0].get_shape()[1], num_units) + self.assertEqual(out[0].dtype, inp.dtype) with self.test_session() as sess: sess.run(variables.global_variables_initializer()) input_value = np.ones((batch_size, input_size)) values = sess.run(outputs + [state], feed_dict={inputs[0]: input_value}) - for v in values: - self.assertTrue(np.all(np.isfinite(v))) + for tp in values[:-1]: + for v in tp: + self.assertTrue(np.all(np.isfinite(v))) + for tp in values[-1]: + for st in tp: + for v in st: + self.assertTrue(np.all(np.isfinite(v))) def testGrid2LSTMCellReLUWithRNN(self): batch_size = 3 @@ -478,27 +566,33 @@ class GridRNNCellTest(test.TestCase): num_units=num_units, non_recurrent_fn=nn_ops.relu) inputs = max_length * [ - array_ops.placeholder( - dtypes.float32, shape=(batch_size, input_size)) + array_ops.placeholder(dtypes.float32, shape=(batch_size, input_size)) ] outputs, state = core_rnn.static_rnn(cell, inputs, dtype=dtypes.float32) self.assertEqual(len(outputs), len(inputs)) - self.assertEqual(state.get_shape(), (batch_size, 4)) + self.assertEqual(state[0].c.get_shape(), (batch_size, 2)) + self.assertEqual(state[0].h.get_shape(), (batch_size, 2)) for out, inp in zip(outputs, inputs): - self.assertEqual(out.get_shape()[0], inp.get_shape()[0]) - self.assertEqual(out.get_shape()[1], num_units) - self.assertEqual(out.dtype, inp.dtype) + self.assertEqual(len(out), 1) + self.assertEqual(out[0].get_shape()[0], inp.get_shape()[0]) + self.assertEqual(out[0].get_shape()[1], num_units) + self.assertEqual(out[0].dtype, inp.dtype) with self.test_session() as sess: sess.run(variables.global_variables_initializer()) input_value = np.ones((batch_size, input_size)) values = sess.run(outputs + [state], feed_dict={inputs[0]: input_value}) - for v in values: - self.assertTrue(np.all(np.isfinite(v))) + for tp in values[:-1]: + for v in tp: + self.assertTrue(np.all(np.isfinite(v))) + for tp in values[-1]: + for st in tp: + for v in st: + self.assertTrue(np.all(np.isfinite(v))) def testGrid3LSTMCellReLUWithRNN(self): batch_size = 3 @@ -512,27 +606,35 @@ class GridRNNCellTest(test.TestCase): num_units=num_units, non_recurrent_fn=nn_ops.relu) inputs = max_length * [ - array_ops.placeholder( - dtypes.float32, shape=(batch_size, input_size)) + array_ops.placeholder(dtypes.float32, shape=(batch_size, input_size)) ] outputs, state = core_rnn.static_rnn(cell, inputs, dtype=dtypes.float32) self.assertEqual(len(outputs), len(inputs)) - self.assertEqual(state.get_shape(), (batch_size, 8)) + self.assertEqual(state[0].c.get_shape(), (batch_size, 2)) + self.assertEqual(state[0].h.get_shape(), (batch_size, 2)) + self.assertEqual(state[1].c.get_shape(), (batch_size, 2)) + self.assertEqual(state[1].h.get_shape(), (batch_size, 2)) for out, inp in zip(outputs, inputs): - self.assertEqual(out.get_shape()[0], inp.get_shape()[0]) - self.assertEqual(out.get_shape()[1], num_units) - self.assertEqual(out.dtype, inp.dtype) + self.assertEqual(len(out), 1) + self.assertEqual(out[0].get_shape()[0], inp.get_shape()[0]) + self.assertEqual(out[0].get_shape()[1], num_units) + self.assertEqual(out[0].dtype, inp.dtype) with self.test_session() as sess: sess.run(variables.global_variables_initializer()) input_value = np.ones((batch_size, input_size)) values = sess.run(outputs + [state], feed_dict={inputs[0]: input_value}) - for v in values: - self.assertTrue(np.all(np.isfinite(v))) + for tp in values[:-1]: + for v in tp: + self.assertTrue(np.all(np.isfinite(v))) + for tp in values[-1]: + for st in tp: + for v in st: + self.assertTrue(np.all(np.isfinite(v))) def testGrid1LSTMCellWithRNN(self): batch_size = 3 @@ -553,20 +655,91 @@ class GridRNNCellTest(test.TestCase): outputs, state = core_rnn.static_rnn(cell, inputs, dtype=dtypes.float32) self.assertEqual(len(outputs), len(inputs)) - self.assertEqual(state.get_shape(), (batch_size, 4)) + self.assertEqual(state[0].c.get_shape(), (batch_size, 2)) + self.assertEqual(state[0].h.get_shape(), (batch_size, 2)) for out, inp in zip(outputs, inputs): - self.assertEqual(out.get_shape(), (3, num_units)) - self.assertEqual(out.dtype, inp.dtype) + self.assertEqual(len(out), 1) + self.assertEqual(out[0].get_shape(), (3, num_units)) + self.assertEqual(out[0].dtype, inp.dtype) with self.test_session() as sess: sess.run(variables.global_variables_initializer()) input_value = np.ones((batch_size, input_size)) values = sess.run(outputs + [state], feed_dict={inputs[0]: input_value}) - for v in values: - self.assertTrue(np.all(np.isfinite(v))) + for tp in values[:-1]: + for v in tp: + self.assertTrue(np.all(np.isfinite(v))) + for tp in values[-1]: + for st in tp: + for v in st: + self.assertTrue(np.all(np.isfinite(v))) + def testGrid2LSTMCellWithRNNAndDynamicBatchSize(self): + """Test for #4296.""" + input_size = 5 + max_length = 6 # unrolled up to this length + num_units = 2 + + with variable_scope.variable_scope( + 'root', initializer=init_ops.constant_initializer(0.5)): + cell = grid_rnn_cell.Grid2LSTMCell(num_units=num_units) + + inputs = max_length * [ + array_ops.placeholder(dtypes.float32, shape=(None, input_size)) + ] + + outputs, state = core_rnn.static_rnn(cell, inputs, dtype=dtypes.float32) + + self.assertEqual(len(outputs), len(inputs)) + + for out, inp in zip(outputs, inputs): + self.assertEqual(len(out), 1) + self.assertTrue(out[0].get_shape()[0].value is None) + self.assertEqual(out[0].get_shape()[1], num_units) + self.assertEqual(out[0].dtype, inp.dtype) + + with self.test_session() as sess: + sess.run(variables.global_variables_initializer()) + + input_value = np.ones((3, input_size)) + values = sess.run(outputs + [state], feed_dict={inputs[0]: input_value}) + for tp in values[:-1]: + for v in tp: + self.assertTrue(np.all(np.isfinite(v))) + for tp in values[-1]: + for st in tp: + for v in st: + self.assertTrue(np.all(np.isfinite(v))) + + def testGrid2LSTMCellLegacy(self): + """Test for legacy case (when state_is_tuple=False).""" + with self.test_session() as sess: + with variable_scope.variable_scope( + 'root', initializer=init_ops.constant_initializer(0.5)): + x = array_ops.zeros([1, 3]) + m = array_ops.zeros([1, 8]) + cell = grid_rnn_cell.Grid2LSTMCell( + 2, use_peepholes=True, state_is_tuple=False, output_is_tuple=False) + self.assertEqual(cell.state_size, 8) + + g, s = cell(x, m) + self.assertEqual(g.get_shape(), (1, 2)) + self.assertEqual(s.get_shape(), (1, 8)) + + sess.run([variables.global_variables_initializer()]) + res = sess.run([g, s], { + x: np.array([[1., 1., 1.]]), + m: np.array([[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]]) + }) + self.assertEqual(res[0].shape, (1, 2)) + self.assertEqual(res[1].shape, (1, 8)) + self.assertAllClose(res[0], [[0.95686918, 0.95686918]]) + self.assertAllClose(res[1], [[ + 2.41515064, 2.41515064, 0.95686918, 0.95686918, 1.38917875, + 1.49043763, 0.83884692, 0.86036491 + ]]) if __name__ == '__main__': test.main() diff --git a/tensorflow/contrib/grid_rnn/python/ops/grid_rnn_cell.py b/tensorflow/contrib/grid_rnn/python/ops/grid_rnn_cell.py index 269b2245819..252788140f8 100644 --- a/tensorflow/contrib/grid_rnn/python/ops/grid_rnn_cell.py +++ b/tensorflow/contrib/grid_rnn/python/ops/grid_rnn_cell.py @@ -25,6 +25,8 @@ from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import nn from tensorflow.python.ops import variable_scope as vs + +from tensorflow.python.platform import tf_logging as logging from tensorflow.contrib import layers from tensorflow.contrib import rnn @@ -53,7 +55,9 @@ class GridRNNCell(rnn.RNNCell): non_recurrent_dims=None, tied=False, cell_fn=None, - non_recurrent_fn=None): + non_recurrent_fn=None, + state_is_tuple=True, + output_is_tuple=True): """Initialize the parameters of a Grid RNN cell Args: @@ -68,26 +72,47 @@ class GridRNNCell(rnn.RNNCell): non_recurrent_dims: int or list, List of dimensions that are not recurrent. The transfer function for non-recurrent dimensions is specified - via `non_recurrent_fn`, - which is default to be `tensorflow.nn.relu`. + via `non_recurrent_fn`, which is + default to be `tensorflow.nn.relu`. tied: bool, Whether to share the weights among the dimensions of this GridRNN cell. If there are non-recurrent dimensions in the grid, weights are - shared between each - group of recurrent and non-recurrent dimensions. - cell_fn: function, a function which returns the recurrent cell object. Has - to be in the following signature: - def cell_func(num_units, input_size): + shared between each group of recurrent and non-recurrent + dimensions. + cell_fn: function, a function which returns the recurrent cell object. + Has to be in the following signature: + ``` + def cell_func(num_units): # ... - + ``` and returns an object of type `RNNCell`. If None, LSTMCell with default parameters will be used. + Note that if you use a custom RNNCell (with `cell_fn`), it is your + responsibility to make sure the inner cell use `state_is_tuple=True`. + non_recurrent_fn: a tensorflow Op that will be the transfer function of the non-recurrent dimensions + state_is_tuple: If True, accepted and returned states are tuples of the + states of the recurrent dimensions. If False, they are concatenated + along the column axis. The latter behavior will soon be deprecated. + + Note that if you use a custom RNNCell (with `cell_fn`), it is your + responsibility to make sure the inner cell use `state_is_tuple=True`. + + output_is_tuple: If True, the output is a tuple of the outputs of the + recurrent dimensions. If False, they are concatenated along the + column axis. The later behavior will soon be deprecated. Raises: TypeError: if cell_fn does not return an RNNCell instance. """ + if not state_is_tuple: + logging.warning('%s: Using a concatenated state is slower and will ' + 'soon be deprecated. Use state_is_tuple=True.', self) + if not output_is_tuple: + logging.warning('%s: Using a concatenated output is slower and will' + 'soon be deprecated. Use output_is_tuple=True.', self) + if num_dims < 1: raise ValueError('dims must be >= 1: {}'.format(num_dims)) @@ -96,37 +121,41 @@ class GridRNNCell(rnn.RNNCell): non_recurrent_fn or nn.relu, tied, num_units) - cell_input_size = (self._config.num_dims - 1) * num_units + self._state_is_tuple = state_is_tuple + self._output_is_tuple = output_is_tuple + if cell_fn is None: my_cell_fn = functools.partial( - rnn.LSTMCell, - num_units=num_units, input_size=cell_input_size, - state_is_tuple=False) + rnn.LSTMCell, num_units=num_units, state_is_tuple=state_is_tuple) else: - my_cell_fn = lambda: cell_fn(num_units, cell_input_size) + my_cell_fn = lambda: cell_fn(num_units) if tied: self._cells = [my_cell_fn()] * num_dims else: self._cells = [my_cell_fn() for _ in range(num_dims)] if not isinstance(self._cells[0], rnn.RNNCell): - raise TypeError( - 'cell_fn must return an RNNCell instance, saw: %s' - % type(self._cells[0])) + raise TypeError('cell_fn must return an RNNCell instance, saw: %s' % + type(self._cells[0])) - @property - def input_size(self): - # temporarily using num_units as the input_size of each dimension. - # The actual input size only determined when this cell get invoked, - # so this information can be considered unreliable. - return self._config.num_units * len(self._config.inputs) + if self._output_is_tuple: + self._output_size = tuple(self._cells[0].output_size + for _ in self._config.outputs) + else: + self._output_size = self._cells[0].output_size * len(self._config.outputs) + + if self._state_is_tuple: + self._state_size = tuple(self._cells[0].state_size + for _ in self._config.recurrents) + else: + self._state_size = self._cell_state_size() * len(self._config.recurrents) @property def output_size(self): - return self._cells[0].output_size * len(self._config.outputs) + return self._output_size @property def state_size(self): - return self._cells[0].state_size * len(self._config.recurrents) + return self._state_size def __call__(self, inputs, state, scope=None): """Run one step of GridRNN. @@ -145,76 +174,148 @@ class GridRNNCell(rnn.RNNCell): - A 2D, batch x state_size, Tensor representing the new state of the cell after reading "inputs" when previous state was "state". """ - state_sz = state.get_shape().as_list()[1] - if self.state_size != state_sz: - raise ValueError( - 'Actual state size not same as specified: {} vs {}.'.format( - state_sz, self.state_size)) - conf = self._config - dtype = inputs.dtype if inputs is not None else state.dtype + dtype = inputs.dtype - # c_prev is `m`, and m_prev is `h` in the paper. - # Keep c and m here for consistency with the codebase - c_prev = [None] * self._config.num_dims - m_prev = [None] * self._config.num_dims - cell_output_size = self._cells[0].state_size - conf.num_units - - # for LSTM : state = memory cell + output, hence cell_output_size > 0 - # for GRU/RNN: state = output (whose size is equal to _num_units), - # hence cell_output_size = 0 - for recurrent_dim, start_idx in zip(self._config.recurrents, range( - 0, self.state_size, self._cells[0].state_size)): - if cell_output_size > 0: - c_prev[recurrent_dim] = array_ops.slice(state, [0, start_idx], - [-1, conf.num_units]) - m_prev[recurrent_dim] = array_ops.slice( - state, [0, start_idx + conf.num_units], [-1, cell_output_size]) - else: - m_prev[recurrent_dim] = array_ops.slice(state, [0, start_idx], - [-1, conf.num_units]) + c_prev, m_prev, cell_output_size = self._extract_states(state) new_output = [None] * conf.num_dims new_state = [None] * conf.num_dims with vs.variable_scope(scope or type(self).__name__): # GridRNNCell + # project input, populate c_prev and m_prev + self._project_input(inputs, c_prev, m_prev, cell_output_size > 0) - # project input - if inputs is not None and sum(inputs.get_shape().as_list()) > 0 and len( - conf.inputs) > 0: - input_splits = array_ops.split( - value=inputs, num_or_size_splits=len(conf.inputs), axis=1) - input_sz = input_splits[0].get_shape().as_list()[1] - - for i, j in enumerate(conf.inputs): - input_project_m = vs.get_variable( - 'project_m_{}'.format(j), [input_sz, conf.num_units], dtype=dtype) - m_prev[j] = math_ops.matmul(input_splits[i], input_project_m) - - if cell_output_size > 0: - input_project_c = vs.get_variable( - 'project_c_{}'.format(j), [input_sz, conf.num_units], - dtype=dtype) - c_prev[j] = math_ops.matmul(input_splits[i], input_project_c) - + # propagate along dimensions, first for non-priority dimensions + # then priority dimensions _propagate(conf.non_priority, conf, self._cells, c_prev, m_prev, new_output, new_state, True) _propagate(conf.priority, conf, self._cells, c_prev, m_prev, new_output, new_state, False) + # collect outputs and states output_tensors = [new_output[i] for i in self._config.outputs] - output = array_ops.zeros( - [0, 0], dtype) if len(output_tensors) == 0 else array_ops.concat( - output_tensors, 1) + if self._output_is_tuple: + output = tuple(output_tensors) + else: + if output_tensors: + output = array_ops.concat(output_tensors, 1) + else: + output = array_ops.zeros([0, 0], dtype) - state_tensors = [new_state[i] for i in self._config.recurrents] - states = array_ops.zeros( - [0, 0], - dtype) if len(state_tensors) == 0 else array_ops.concat(state_tensors, - 1) + if self._state_is_tuple: + states = tuple(new_state[i] for i in self._config.recurrents) + else: + # concat each state first, then flatten the whole thing + state_tensors = [ + x for i in self._config.recurrents for x in new_state[i] + ] + if state_tensors: + states = array_ops.concat(state_tensors, 1) + else: + states = array_ops.zeros([0, 0], dtype) return output, states + def _extract_states(self, state): + """Extract the cell and previous output tensors from the given state. + + Args: + state: The RNN state. + + Returns: + Tuple of the cell value, previous output, and cell_output_size. + + Raises: + ValueError: If len(self._config.recurrents) != len(state). + """ + conf = self._config + + # c_prev is `m` (cell value), and + # m_prev is `h` (previous output) in the paper. + # Keeping c and m here for consistency with the codebase + c_prev = [None] * conf.num_dims + m_prev = [None] * conf.num_dims + + # for LSTM : state = memory cell + output, hence cell_output_size > 0 + # for GRU/RNN: state = output (whose size is equal to _num_units), + # hence cell_output_size = 0 + total_cell_state_size = self._cell_state_size() + cell_output_size = total_cell_state_size - conf.num_units + + if self._state_is_tuple: + if len(conf.recurrents) != len(state): + raise ValueError('Expected state as a tuple of {} ' + 'element'.format(len(conf.recurrents))) + + for recurrent_dim, recurrent_state in zip(conf.recurrents, state): + if cell_output_size > 0: + c_prev[recurrent_dim], m_prev[recurrent_dim] = recurrent_state + else: + m_prev[recurrent_dim] = recurrent_state + else: + for recurrent_dim, start_idx in zip(conf.recurrents, + range(0, self.state_size, + total_cell_state_size)): + if cell_output_size > 0: + c_prev[recurrent_dim] = array_ops.slice(state, [0, start_idx], + [-1, conf.num_units]) + m_prev[recurrent_dim] = array_ops.slice( + state, [0, start_idx + conf.num_units], [-1, cell_output_size]) + else: + m_prev[recurrent_dim] = array_ops.slice(state, [0, start_idx], + [-1, conf.num_units]) + return c_prev, m_prev, cell_output_size + + def _project_input(self, inputs, c_prev, m_prev, with_c): + """Fills in c_prev and m_prev with projected input, for input dimensions. + + Args: + inputs: inputs tensor + c_prev: cell value + m_prev: previous output + with_c: boolean; whether to include project_c. + + Raises: + ValueError: if len(self._config.input) != len(inputs) + """ + conf = self._config + + if (inputs is not None and inputs.get_shape().with_rank(2)[1].value > 0 and + conf.inputs): + if isinstance(inputs, tuple): + if len(conf.inputs) != len(inputs): + raise ValueError('Expect inputs as a tuple of {} ' + 'tensors'.format(len(conf.inputs))) + input_splits = inputs + else: + input_splits = array_ops.split( + value=inputs, num_or_size_splits=len(conf.inputs), axis=1) + input_sz = input_splits[0].get_shape().with_rank(2)[1].value + + for i, j in enumerate(conf.inputs): + input_project_m = vs.get_variable( + 'project_m_{}'.format(j), [input_sz, conf.num_units], + dtype=inputs.dtype) + m_prev[j] = math_ops.matmul(input_splits[i], input_project_m) + + if with_c: + input_project_c = vs.get_variable( + 'project_c_{}'.format(j), [input_sz, conf.num_units], + dtype=inputs.dtype) + c_prev[j] = math_ops.matmul(input_splits[i], input_project_c) + + def _cell_state_size(self): + """Total size of the state of the inner cell used in this grid. + + Returns: + Total size of the state of the inner cell. + """ + state_sizes = self._cells[0].state_size + if isinstance(state_sizes, tuple): + return sum(state_sizes) + return state_sizes + """Specialized cells, for convenience """ @@ -223,11 +324,17 @@ class GridRNNCell(rnn.RNNCell): class Grid1BasicRNNCell(GridRNNCell): """1D BasicRNN cell""" - def __init__(self, num_units): + def __init__(self, num_units, state_is_tuple=True, output_is_tuple=True): super(Grid1BasicRNNCell, self).__init__( - num_units=num_units, num_dims=1, - input_dims=0, output_dims=0, priority_dims=0, tied=False, - cell_fn=lambda n, i: rnn.BasicRNNCell(num_units=n, input_size=i)) + num_units=num_units, + num_dims=1, + input_dims=0, + output_dims=0, + priority_dims=0, + tied=False, + cell_fn=lambda n: rnn.BasicRNNCell(num_units=n), + state_is_tuple=state_is_tuple, + output_is_tuple=output_is_tuple) class Grid2BasicRNNCell(GridRNNCell): @@ -240,71 +347,112 @@ class Grid2BasicRNNCell(GridRNNCell): specified. """ - def __init__(self, num_units, tied=False, non_recurrent_fn=None): + def __init__(self, + num_units, + tied=False, + non_recurrent_fn=None, + state_is_tuple=True, + output_is_tuple=True): super(Grid2BasicRNNCell, self).__init__( - num_units=num_units, num_dims=2, - input_dims=0, output_dims=0, priority_dims=0, tied=tied, + num_units=num_units, + num_dims=2, + input_dims=0, + output_dims=0, + priority_dims=0, + tied=tied, non_recurrent_dims=None if non_recurrent_fn is None else 0, - cell_fn=lambda n, i: rnn.BasicRNNCell(num_units=n, input_size=i), - non_recurrent_fn=non_recurrent_fn) + cell_fn=lambda n: rnn.BasicRNNCell(num_units=n), + non_recurrent_fn=non_recurrent_fn, + state_is_tuple=state_is_tuple, + output_is_tuple=output_is_tuple) class Grid1BasicLSTMCell(GridRNNCell): - """1D BasicLSTM cell""" + """1D BasicLSTM cell.""" - def __init__(self, num_units, forget_bias=1): + def __init__(self, + num_units, + forget_bias=1, + state_is_tuple=True, + output_is_tuple=True): + def cell_fn(n): + return rnn.BasicLSTMCell(num_units=n, forget_bias=forget_bias) super(Grid1BasicLSTMCell, self).__init__( - num_units=num_units, num_dims=1, - input_dims=0, output_dims=0, priority_dims=0, tied=False, - cell_fn=lambda n, i: rnn.BasicLSTMCell( - num_units=n, - forget_bias=forget_bias, input_size=i, - state_is_tuple=False)) + num_units=num_units, + num_dims=1, + input_dims=0, + output_dims=0, + priority_dims=0, + tied=False, + cell_fn=cell_fn, + state_is_tuple=state_is_tuple, + output_is_tuple=output_is_tuple) class Grid2BasicLSTMCell(GridRNNCell): - """2D BasicLSTM cell + """2D BasicLSTM cell. - This creates a 2D cell which receives input and gives output in the first - dimension. + This creates a 2D cell which receives input and gives output in the first + dimension. - The first dimension can optionally be non-recurrent if `non_recurrent_fn` is - specified. + The first dimension can optionally be non-recurrent if `non_recurrent_fn` is + specified. """ def __init__(self, num_units, tied=False, non_recurrent_fn=None, - forget_bias=1): + forget_bias=1, + state_is_tuple=True, + output_is_tuple=True): + def cell_fn(n): + return rnn.BasicLSTMCell(num_units=n, forget_bias=forget_bias) super(Grid2BasicLSTMCell, self).__init__( - num_units=num_units, num_dims=2, - input_dims=0, output_dims=0, priority_dims=0, tied=tied, + num_units=num_units, + num_dims=2, + input_dims=0, + output_dims=0, + priority_dims=0, + tied=tied, non_recurrent_dims=None if non_recurrent_fn is None else 0, - cell_fn=lambda n, i: rnn.BasicLSTMCell( - num_units=n, forget_bias=forget_bias, input_size=i, - state_is_tuple=False), - non_recurrent_fn=non_recurrent_fn) + cell_fn=cell_fn, + non_recurrent_fn=non_recurrent_fn, + state_is_tuple=state_is_tuple, + output_is_tuple=output_is_tuple) class Grid1LSTMCell(GridRNNCell): - """1D LSTM cell + """1D LSTM cell. - This is different from Grid1BasicLSTMCell because it gives options to - specify the forget bias and enabling peepholes + This is different from Grid1BasicLSTMCell because it gives options to + specify the forget bias and enabling peepholes. """ - def __init__(self, num_units, use_peepholes=False, forget_bias=1.0): + def __init__(self, + num_units, + use_peepholes=False, + forget_bias=1.0, + state_is_tuple=True, + output_is_tuple=True): + + def cell_fn(n): + return rnn.LSTMCell( + num_units=n, forget_bias=forget_bias, use_peepholes=use_peepholes) + super(Grid1LSTMCell, self).__init__( - num_units=num_units, num_dims=1, - input_dims=0, output_dims=0, priority_dims=0, - cell_fn=lambda n, i: rnn.LSTMCell( - num_units=n, input_size=i, use_peepholes=use_peepholes, - forget_bias=forget_bias, state_is_tuple=False)) + num_units=num_units, + num_dims=1, + input_dims=0, + output_dims=0, + priority_dims=0, + cell_fn=cell_fn, + state_is_tuple=state_is_tuple, + output_is_tuple=output_is_tuple) class Grid2LSTMCell(GridRNNCell): - """2D LSTM cell + """2D LSTM cell. This creates a 2D cell which receives input and gives output in the first dimension. @@ -317,19 +465,30 @@ class Grid2LSTMCell(GridRNNCell): tied=False, non_recurrent_fn=None, use_peepholes=False, - forget_bias=1.0): + forget_bias=1.0, + state_is_tuple=True, + output_is_tuple=True): + + def cell_fn(n): + return rnn.LSTMCell( + num_units=n, forget_bias=forget_bias, use_peepholes=use_peepholes) + super(Grid2LSTMCell, self).__init__( - num_units=num_units, num_dims=2, - input_dims=0, output_dims=0, priority_dims=0, tied=tied, + num_units=num_units, + num_dims=2, + input_dims=0, + output_dims=0, + priority_dims=0, + tied=tied, non_recurrent_dims=None if non_recurrent_fn is None else 0, - cell_fn=lambda n, i: rnn.LSTMCell( - num_units=n, input_size=i, forget_bias=forget_bias, - use_peepholes=use_peepholes, state_is_tuple=False), - non_recurrent_fn=non_recurrent_fn) + cell_fn=cell_fn, + non_recurrent_fn=non_recurrent_fn, + state_is_tuple=state_is_tuple, + output_is_tuple=output_is_tuple) class Grid3LSTMCell(GridRNNCell): - """3D BasicLSTM cell + """3D BasicLSTM cell. This creates a 2D cell which receives input and gives output in the first dimension. @@ -343,19 +502,30 @@ class Grid3LSTMCell(GridRNNCell): tied=False, non_recurrent_fn=None, use_peepholes=False, - forget_bias=1.0): + forget_bias=1.0, + state_is_tuple=True, + output_is_tuple=True): + + def cell_fn(n): + return rnn.LSTMCell( + num_units=n, forget_bias=forget_bias, use_peepholes=use_peepholes) + super(Grid3LSTMCell, self).__init__( - num_units=num_units, num_dims=3, - input_dims=0, output_dims=0, priority_dims=0, tied=tied, + num_units=num_units, + num_dims=3, + input_dims=0, + output_dims=0, + priority_dims=0, + tied=tied, non_recurrent_dims=None if non_recurrent_fn is None else 0, - cell_fn=lambda n, i: rnn.LSTMCell( - num_units=n, input_size=i, forget_bias=forget_bias, - use_peepholes=use_peepholes, state_is_tuple=False), - non_recurrent_fn=non_recurrent_fn) + cell_fn=cell_fn, + non_recurrent_fn=non_recurrent_fn, + state_is_tuple=state_is_tuple, + output_is_tuple=output_is_tuple) class Grid2GRUCell(GridRNNCell): - """2D LSTM cell + """2D LSTM cell. This creates a 2D cell which receives input and gives output in the first dimension. @@ -363,21 +533,31 @@ class Grid2GRUCell(GridRNNCell): specified. """ - def __init__(self, num_units, tied=False, non_recurrent_fn=None): + def __init__(self, + num_units, + tied=False, + non_recurrent_fn=None, + state_is_tuple=True, + output_is_tuple=True): super(Grid2GRUCell, self).__init__( - num_units=num_units, num_dims=2, - input_dims=0, output_dims=0, priority_dims=0, tied=tied, + num_units=num_units, + num_dims=2, + input_dims=0, + output_dims=0, + priority_dims=0, + tied=tied, non_recurrent_dims=None if non_recurrent_fn is None else 0, - cell_fn=lambda n, i: rnn.GRUCell(num_units=n, input_size=i), - non_recurrent_fn=non_recurrent_fn) + cell_fn=lambda n: rnn.GRUCell(num_units=n), + non_recurrent_fn=non_recurrent_fn, + state_is_tuple=state_is_tuple, + output_is_tuple=output_is_tuple) -"""Helpers -""" +# Helpers -_GridRNNDimension = namedtuple( - '_GridRNNDimension', - ['idx', 'is_input', 'is_output', 'is_priority', 'non_recurrent_fn']) +_GridRNNDimension = namedtuple('_GridRNNDimension', [ + 'idx', 'is_input', 'is_output', 'is_priority', 'non_recurrent_fn' +]) _GridRNNConfig = namedtuple('_GridRNNConfig', ['num_dims', 'dims', 'inputs', 'outputs', @@ -387,7 +567,6 @@ _GridRNNConfig = namedtuple('_GridRNNConfig', def _parse_rnn_config(num_dims, ls_input_dims, ls_output_dims, ls_priority_dims, ls_non_recurrent_dims, non_recurrent_fn, tied, num_units): - def check_dim_list(ls): if ls is None: ls = [] @@ -412,8 +591,8 @@ def _parse_rnn_config(num_dims, ls_input_dims, ls_output_dims, ls_priority_dims, is_input=(i in input_dims), is_output=(i in output_dims), is_priority=(i in priority_dims), - non_recurrent_fn=non_recurrent_fn if i in non_recurrent_dims else - None)) + non_recurrent_fn=non_recurrent_fn + if i in non_recurrent_dims else None)) return _GridRNNConfig( num_dims=num_dims, dims=rnn_dims, @@ -440,34 +619,40 @@ def _propagate(dim_indices, conf, cells, c_prev, m_prev, new_output, new_state, if conf.num_dims > 1: ls_cell_inputs = [None] * (conf.num_dims - 1) for d in conf.dims[:-1]: - ls_cell_inputs[d.idx] = new_output[d.idx] if new_output[ - d.idx] is not None else m_prev[d.idx] + if new_output[d.idx] is None: + ls_cell_inputs[d.idx] = m_prev[d.idx] + else: + ls_cell_inputs[d.idx] = new_output[d.idx] cell_inputs = array_ops.concat(ls_cell_inputs, 1) else: cell_inputs = array_ops.zeros([m_prev[0].get_shape().as_list()[0], 0], m_prev[0].dtype) - last_dim_output = new_output[-1] if new_output[-1] is not None else m_prev[-1] + last_dim_output = (new_output[-1] + if new_output[-1] is not None else m_prev[-1]) for i in dim_indices: d = conf.dims[i] if d.non_recurrent_fn: - linear_args = array_ops.concat( - [cell_inputs, last_dim_output], - 1) if conf.num_dims > 1 else last_dim_output + if conf.num_dims > 1: + linear_args = array_ops.concat([cell_inputs, last_dim_output], 1) + else: + linear_args = last_dim_output with vs.variable_scope('non_recurrent' if conf.tied else 'non_recurrent/cell_{}'.format(i)): if conf.tied and not (first_call and i == dim_indices[0]): vs.get_variable_scope().reuse_variables() - new_output[d.idx] = layers.legacy_fully_connected( + + new_output[d.idx] = layers.fully_connected( linear_args, - num_output_units=conf.num_units, + num_outputs=conf.num_units, activation_fn=d.non_recurrent_fn, - weight_init=vs.get_variable_scope().initializer or - layers.initializers.xavier_initializer) + weights_initializer=(vs.get_variable_scope().initializer or + layers.initializers.xavier_initializer), + weights_regularizer=vs.get_variable_scope().regularizer) else: if c_prev[i] is not None: - cell_state = array_ops.concat([c_prev[i], last_dim_output], 1) + cell_state = (c_prev[i], last_dim_output) else: # for GRU/RNN, the state is just the previous output cell_state = last_dim_output diff --git a/tensorflow/contrib/image/python/kernel_tests/image_ops_test.py b/tensorflow/contrib/image/python/kernel_tests/image_ops_test.py index 4ce33de24a0..33bd30b4e81 100644 --- a/tensorflow/contrib/image/python/kernel_tests/image_ops_test.py +++ b/tensorflow/contrib/image/python/kernel_tests/image_ops_test.py @@ -25,6 +25,7 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops +from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import math_ops from tensorflow.python.platform import googletest @@ -110,6 +111,30 @@ class ImageOpsTest(test_util.TensorFlowTestCase): [0, 1, 0, 1], [0, 1, 1, 1]]) + def _test_grad(self, shape_to_test): + with self.test_session(): + test_image_shape = shape_to_test + test_image = np.random.randn(*test_image_shape) + test_image_tensor = constant_op.constant( + test_image, shape=test_image_shape) + test_transform = image_ops.angles_to_projective_transforms( + np.pi / 2, 4, 4) + + output_shape = test_image_shape + output = image_ops.transform(test_image_tensor, test_transform) + left_err = gradient_checker.compute_gradient_error( + test_image_tensor, + test_image_shape, + output, + output_shape, + x_init_value=test_image) + self.assertLess(left_err, 1e-10) + + def test_grad(self): + self._test_grad([16, 16]) + self._test_grad([4, 12, 12]) + self._test_grad([3, 4, 12, 12]) + if __name__ == "__main__": googletest.main() diff --git a/tensorflow/contrib/image/python/ops/image_ops.py b/tensorflow/contrib/image/python/ops/image_ops.py index 889f361b19e..9efdb0d5212 100644 --- a/tensorflow/contrib/image/python/ops/image_ops.py +++ b/tensorflow/contrib/image/python/ops/image_ops.py @@ -24,6 +24,7 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.ops import array_ops +from tensorflow.python.ops import linalg_ops from tensorflow.python.ops import math_ops from tensorflow.python.platform import resource_loader @@ -214,4 +215,41 @@ def _transform_matrices_to_flat(transform_matrices): return transforms[:, :8] -ops.NotDifferentiable("ImageProjectiveTransform") +@ops.RegisterGradient("ImageProjectiveTransform") +def _image_projective_transform_grad(op, grad): + """Computes the gradient for ImageProjectiveTransform.""" + images = op.inputs[0] + transforms = op.inputs[1] + + image_or_images = ops.convert_to_tensor(images, name="images") + transform_or_transforms = ops.convert_to_tensor( + transforms, name="transforms", dtype=dtypes.float32) + + if image_or_images.dtype.base_dtype not in _IMAGE_DTYPES: + raise TypeError("Invalid dtype %s." % image_or_images.dtype) + if len(image_or_images.get_shape()) == 2: + images = image_or_images[None, :, :, None] + elif len(image_or_images.get_shape()) == 3: + images = image_or_images[None, :, :, :] + elif len(image_or_images.get_shape()) == 4: + images = image_or_images + else: + raise TypeError("Images should have rank between 2 and 4") + if len(transform_or_transforms.get_shape()) == 1: + transforms = transform_or_transforms[None] + elif len(transform_or_transforms.get_shape()) == 2: + transforms = transform_or_transforms + else: + raise TypeError("Transforms should have rank 1 or 2.") + + # Invert transformations + transforms = _flat_transforms_to_matrices(transforms=transforms) + inverse = linalg_ops.matrix_inverse(transforms) + transforms = _transform_matrices_to_flat(inverse) + output = gen_image_ops.image_projective_transform(grad, transforms) + if len(image_or_images.get_shape()) == 2: + return [output[0, :, :, 0], None] + elif len(image_or_images.get_shape()) == 3: + return [output[0, :, :, :], None] + else: + return [output, None] diff --git a/tensorflow/contrib/ios_examples/camera/CameraExampleViewController.mm b/tensorflow/contrib/ios_examples/camera/CameraExampleViewController.mm index 20c49d5b6a9..27df3d3d71c 100644 --- a/tensorflow/contrib/ios_examples/camera/CameraExampleViewController.mm +++ b/tensorflow/contrib/ios_examples/camera/CameraExampleViewController.mm @@ -323,10 +323,10 @@ didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer auto predictions = output->flat(); NSMutableDictionary *newValues = [NSMutableDictionary dictionary]; - for (int index = 0; index < predictions.size(); index += 1) { + for (int index = 0; index < predictions.size(); ++index) { const float predictionValue = predictions(index); if (predictionValue > 0.05f) { - std::string label = labels[index % predictions.size()]; + std::string label = labels[index]; NSString *labelObject = [NSString stringWithUTF8String:label.c_str()]; NSNumber *valueObject = [NSNumber numberWithFloat:predictionValue]; [newValues setObject:valueObject forKey:labelObject]; diff --git a/tensorflow/contrib/keras/python/keras/initializers_test.py b/tensorflow/contrib/keras/python/keras/initializers_test.py index c9f50c28eae..0a07eddd89a 100644 --- a/tensorflow/contrib/keras/python/keras/initializers_test.py +++ b/tensorflow/contrib/keras/python/keras/initializers_test.py @@ -120,7 +120,7 @@ class KerasInitializersTest(test.TestCase): target_mean=0., target_std=None, target_max=2 * scale) def test_orthogonal(self): - tensor_shape = (10, 10) + tensor_shape = (20, 20) with self.test_session(): self._runner(keras.initializers.orthogonal(seed=123), tensor_shape, target_mean=0.) diff --git a/tensorflow/contrib/layers/python/layers/encoders.py b/tensorflow/contrib/layers/python/layers/encoders.py index 8b6abb4b456..89c9d37bd09 100644 --- a/tensorflow/contrib/layers/python/layers/encoders.py +++ b/tensorflow/contrib/layers/python/layers/encoders.py @@ -121,7 +121,7 @@ def embed_sequence(ids, `Tensor` of `[batch_size, doc_length, embed_dim]` with embedded sequences. Raises: - ValueError: if `embed_dim` or `vocab_size` are not specified when not + ValueError: if `embed_dim` or `vocab_size` are not specified when `reuse` is `None` or `False`. """ if not (reuse or (vocab_size and embed_dim)): diff --git a/tensorflow/contrib/layers/python/layers/initializers.py b/tensorflow/contrib/layers/python/layers/initializers.py index 811e7fa7aa3..271b3c01ffc 100644 --- a/tensorflow/contrib/layers/python/layers/initializers.py +++ b/tensorflow/contrib/layers/python/layers/initializers.py @@ -34,9 +34,10 @@ def xavier_initializer(uniform=True, seed=None, dtype=dtypes.float32): This function implements the weight initialization from: Xavier Glorot and Yoshua Bengio (2010): - Understanding the difficulty of training deep feedforward neural + [Understanding the difficulty of training deep feedforward neural networks. International conference on artificial intelligence and - statistics. + statistics.]( + http://www.jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf) This initializer is designed to keep the scale of the gradients roughly the same in all layers. In uniform distribution this ends up being the range: diff --git a/tensorflow/contrib/learn/__init__.py b/tensorflow/contrib/learn/__init__.py index bd56066b1bc..05c4024d0b9 100644 --- a/tensorflow/contrib/learn/__init__.py +++ b/tensorflow/contrib/learn/__init__.py @@ -38,6 +38,7 @@ See the @{$python/contrib.learn} guide. @@LinearEstimator @@LinearRegressor @@LogisticRegressor +@@StateSavingRnnEstimator @@SVM @@SKCompat diff --git a/tensorflow/contrib/learn/python/learn/estimators/dnn_linear_combined.py b/tensorflow/contrib/learn/python/learn/estimators/dnn_linear_combined.py index 0ff5d6e8dce..53c71c6f3e7 100644 --- a/tensorflow/contrib/learn/python/learn/estimators/dnn_linear_combined.py +++ b/tensorflow/contrib/learn/python/learn/estimators/dnn_linear_combined.py @@ -35,11 +35,11 @@ from tensorflow.contrib.learn.python.learn.estimators import prediction_key from tensorflow.contrib.learn.python.learn.utils import export from tensorflow.python.framework import ops from tensorflow.python.ops import control_flow_ops -from tensorflow.python.ops import logging_ops from tensorflow.python.ops import nn from tensorflow.python.ops import partitioned_variables from tensorflow.python.ops import state_ops from tensorflow.python.ops import variable_scope +from tensorflow.python.summary import summary from tensorflow.python.training import sync_replicas_optimizer from tensorflow.python.training import training_util @@ -99,10 +99,14 @@ def _linear_learning_rate(num_linear_feature_columns): return min(_LINEAR_LEARNING_RATE, default_learning_rate) +def _add_hidden_layer_summary(value, tag): + summary.scalar("%s/fraction_of_zero_values" % tag, nn.zero_fraction(value)) + summary.histogram("%s/activation" % tag, value) + + def _add_layer_summary(value, tag): - logging_ops.scalar_summary("%s/fraction_of_zero_values" % tag, - nn.zero_fraction(value)) - logging_ops.histogram_summary("%s/activation" % tag, value) + summary.scalar("%s/fraction_of_zero_values" % tag, nn.zero_fraction(value)) + summary.histogram("%s/activation" % tag, value) def _get_embedding_variable(column, collection_key, input_layer_scope): diff --git a/tensorflow/contrib/learn/python/learn/estimators/dynamic_rnn_estimator.py b/tensorflow/contrib/learn/python/learn/estimators/dynamic_rnn_estimator.py index 525f84d5115..d86ef8d477d 100644 --- a/tensorflow/contrib/learn/python/learn/estimators/dynamic_rnn_estimator.py +++ b/tensorflow/contrib/learn/python/learn/estimators/dynamic_rnn_estimator.py @@ -19,7 +19,6 @@ from __future__ import division from __future__ import print_function from tensorflow.contrib import layers -from tensorflow.contrib.framework.python.framework import deprecated from tensorflow.contrib.layers.python.layers import optimizers from tensorflow.contrib.learn.python.learn.estimators import constants from tensorflow.contrib.learn.python.learn.estimators import estimator @@ -540,20 +539,6 @@ def _get_dynamic_rnn_model_fn( return _dynamic_rnn_model_fn -def _get_dropout_and_num_units(num_units, - num_rnn_layers, - input_keep_probability, - output_keep_probability): - """Helper function for deprecated factory functions.""" - dropout_keep_probabilities = None - num_units = [num_units for _ in range(num_rnn_layers)] - if input_keep_probability or output_keep_probability: - dropout_keep_probabilities = ([input_keep_probability] - + [1.0] * (num_rnn_layers - 1) - + [output_keep_probability]) - return dropout_keep_probabilities, num_units - - class DynamicRnnEstimator(estimator.Estimator): def __init__(self, @@ -704,339 +689,3 @@ class DynamicRnnEstimator(estimator.Estimator): model_dir=model_dir, config=config, feature_engineering_fn=feature_engineering_fn) - - -@deprecated('2017-04-01', - 'multi_value_rnn_regressor is deprecated. ' - 'Please construct a DynamicRnnEstimator directly.') -def multi_value_rnn_regressor(num_units, - sequence_feature_columns, - context_feature_columns=None, - cell_type='basic_rnn', - num_rnn_layers=1, - optimizer_type='SGD', - learning_rate=0.1, - momentum=None, - gradient_clipping_norm=5.0, - input_keep_probability=None, - output_keep_probability=None, - model_dir=None, - config=None, - feature_engineering_fn=None): - """Creates a `DynamicRnnEstimator` for multi-value regression. - - Returns an `Estimator` that given input sequences, processes them in a dynamic - recurrent network and outputs a sequence of continuous values. - - Args: - num_units: The size of the RNN cells. - sequence_feature_columns: An iterable containing all the feature columns - describing sequence features. All items in the set should be instances - of classes derived from `FeatureColumn`. - context_feature_columns: An iterable containing all the feature columns - describing context features, i.e., features that apply accross all time - steps. All items in the set should be instances of classes derived from - `FeatureColumn`. - cell_type: A subclass of `RNNCell` or one of 'basic_rnn,' 'lstm' or 'gru'. - num_rnn_layers: Number of RNN layers. Leave this at its default value 1 - if passing a `cell_type` that is already a MultiRNNCell. - optimizer_type: The type of optimizer to use. Either a subclass of - `Optimizer`, an instance of an `Optimizer`, a callback that returns an - optimizer, or a string. Strings must be one of 'Adagrad', 'Adam', - 'Ftrl', 'Momentum', 'RMSProp' or 'SGD. See `layers.optimize_loss` for - more details. - learning_rate: Learning rate. This argument has no effect if `optimizer` - is an instance of an `Optimizer`. - momentum: Momentum value. Only used if `optimizer_type` is 'Momentum'. - gradient_clipping_norm: Parameter used for gradient clipping. If `None`, - then no clipping is performed. - input_keep_probability: Probability to keep inputs to `cell`. If `None`, - no dropout is applied. - output_keep_probability: Probability to keep outputs of `cell`. If `None`, - no dropout is applied. - model_dir: The directory in which to save and restore the model graph, - parameters, etc. - config: A `RunConfig` instance. - feature_engineering_fn: Takes features and labels which are the output of - `input_fn` and returns features and labels which will be fed into - `model_fn`. Please check `model_fn` for a definition of features and - labels. - Returns: - An initialized `Estimator`. - """ - dropout_keep_probabilities, num_units = _get_dropout_and_num_units( - num_units, - num_rnn_layers, - input_keep_probability, - output_keep_probability) - return DynamicRnnEstimator( - problem_type=constants.ProblemType.LINEAR_REGRESSION, - prediction_type=rnn_common.PredictionType.MULTIPLE_VALUE, - sequence_feature_columns=sequence_feature_columns, - context_feature_columns=context_feature_columns, - num_units=num_units, - cell_type=cell_type, - optimizer=optimizer_type, - learning_rate=learning_rate, - momentum=momentum, - gradient_clipping_norm=gradient_clipping_norm, - dropout_keep_probabilities=dropout_keep_probabilities, - model_dir=model_dir, - feature_engineering_fn=feature_engineering_fn, - config=config) - - -@deprecated('2017-04-01', - 'multi_value_rnn_classifier is deprecated. ' - 'Please construct a DynamicRNNEstimator directly.') -def multi_value_rnn_classifier(num_classes, - num_units, - sequence_feature_columns, - context_feature_columns=None, - cell_type='basic_rnn', - num_rnn_layers=1, - optimizer_type='SGD', - learning_rate=0.1, - predict_probabilities=False, - momentum=None, - gradient_clipping_norm=5.0, - input_keep_probability=None, - output_keep_probability=None, - model_dir=None, - config=None, - feature_engineering_fn=None): - """Creates a `DynamicRNNEstimator` for multi-value classification. - - Returns an `Estimator` that given input sequences, processes them in a dynamic - recurrent network and outputs a sequence of classifications, along with - (optionally) a probability distribution over classes. - - Args: - num_classes: The number of classes for categorization. - num_units: The size of the RNN cells. - sequence_feature_columns: An iterable containing all the feature columns - describing sequence features. All items in the set should be instances - of classes derived from `FeatureColumn`. - context_feature_columns: An iterable containing all the feature columns - describing context features, i.e., features that apply accross all time - steps. All items in the set should be instances of classes derived from - `FeatureColumn`. - cell_type: A subclass of `RNNCell` or one of 'basic_rnn,' 'lstm' or 'gru'. - num_rnn_layers: Number of RNN layers. Leave this at its default value 1 - if passing a `cell_type` that is already a MultiRNNCell. - optimizer_type: The type of optimizer to use. Either a subclass of - `Optimizer`, an instance of an `Optimizer`, a callback that returns an - optimizer, or a string. Strings must be one of 'Adagrad', 'Adam', - 'Ftrl', 'Momentum', 'RMSProp' or 'SGD. See `layers.optimize_loss` for - more details. - learning_rate: Learning rate. This argument has no effect if `optimizer` - is an instance of an `Optimizer`. - predict_probabilities: A boolean indicating whether to predict probabilities - for all classes. - momentum: Momentum value. Only used if `optimizer_type` is 'Momentum'. - gradient_clipping_norm: Parameter used for gradient clipping. If `None`, - then no clipping is performed. - input_keep_probability: Probability to keep inputs to `cell`. If `None`, - no dropout is applied. - output_keep_probability: Probability to keep outputs of `cell`. If `None`, - no dropout is applied. - model_dir: The directory in which to save and restore the model graph, - parameters, etc. - config: A `RunConfig` instance. - feature_engineering_fn: Takes features and labels which are the output of - `input_fn` and returns features and labels which will be fed into - `model_fn`. Please check `model_fn` for a definition of features and - labels. - Returns: - An initialized `Estimator`. - """ - dropout_keep_probabilities, num_units = _get_dropout_and_num_units( - num_units, - num_rnn_layers, - input_keep_probability, - output_keep_probability) - return DynamicRnnEstimator( - problem_type=constants.ProblemType.CLASSIFICATION, - prediction_type=rnn_common.PredictionType.MULTIPLE_VALUE, - num_classes=num_classes, - sequence_feature_columns=sequence_feature_columns, - context_feature_columns=context_feature_columns, - num_units=num_units, - cell_type=cell_type, - optimizer=optimizer_type, - learning_rate=learning_rate, - predict_probabilities=predict_probabilities, - momentum=momentum, - gradient_clipping_norm=gradient_clipping_norm, - dropout_keep_probabilities=dropout_keep_probabilities, - model_dir=model_dir, - feature_engineering_fn=feature_engineering_fn, - config=config) - - -@deprecated('2017-04-01', - 'single_value_rnn_regressor is deprecated. ' - 'Please construct a DynamicRnnEstimator directly.') -def single_value_rnn_regressor(num_units, - sequence_feature_columns, - context_feature_columns=None, - cell_type='basic_rnn', - num_rnn_layers=1, - optimizer_type='SGD', - learning_rate=0.1, - momentum=None, - gradient_clipping_norm=5.0, - input_keep_probability=None, - output_keep_probability=None, - model_dir=None, - config=None, - feature_engineering_fn=None): - """Creates a `DynamicRnnEstimator` for single-value regression. - - Returns an `Estimator` that given input sequences, processes them in a dynamic - recurrent network and outputs a single continuous values. - - Args: - num_units: The size of the RNN cells. - sequence_feature_columns: An iterable containing all the feature columns - describing sequence features. All items in the set should be instances - of classes derived from `FeatureColumn`. - context_feature_columns: An iterable containing all the feature columns - describing context features, i.e., features that apply accross all time - steps. All items in the set should be instances of classes derived from - `FeatureColumn`. - cell_type: A subclass of `RNNCell` or one of 'basic_rnn,' 'lstm' or 'gru'. - num_rnn_layers: Number of RNN layers. Leave this at its default value 1 - if passing a `cell_type` that is already a MultiRNNCell. - optimizer_type: The type of optimizer to use. Either a subclass of - `Optimizer`, an instance of an `Optimizer`, a callback that returns an - optimizer, or a string. Strings must be one of 'Adagrad', 'Adam', - 'Ftrl', 'Momentum', 'RMSProp' or 'SGD. See `layers.optimize_loss` for - more details. - learning_rate: Learning rate. This argument has no effect if `optimizer` - is an instance of an `Optimizer`. - momentum: Momentum value. Only used if `optimizer_type` is 'Momentum'. - gradient_clipping_norm: Parameter used for gradient clipping. If `None`, - then no clipping is performed. - input_keep_probability: Probability to keep inputs to `cell`. If `None`, - no dropout is applied. - output_keep_probability: Probability to keep outputs of `cell`. If `None`, - no dropout is applied. - model_dir: The directory in which to save and restore the model graph, - parameters, etc. - config: A `RunConfig` instance. - feature_engineering_fn: Takes features and labels which are the output of - `input_fn` and returns features and labels which will be fed into - `model_fn`. Please check `model_fn` for a definition of features and - labels. - Returns: - An initialized `Estimator`. - """ - dropout_keep_probabilities, num_units = _get_dropout_and_num_units( - num_units, - num_rnn_layers, - input_keep_probability, - output_keep_probability) - return DynamicRnnEstimator( - problem_type=constants.ProblemType.LINEAR_REGRESSION, - prediction_type=rnn_common.PredictionType.SINGLE_VALUE, - sequence_feature_columns=sequence_feature_columns, - context_feature_columns=context_feature_columns, - num_units=num_units, - cell_type=cell_type, - optimizer=optimizer_type, - learning_rate=learning_rate, - momentum=momentum, - gradient_clipping_norm=gradient_clipping_norm, - dropout_keep_probabilities=dropout_keep_probabilities, - model_dir=model_dir, - feature_engineering_fn=feature_engineering_fn, - config=config) - - -@deprecated('2017-04-01', - 'single_value_rnn_classifier is deprecated. ' - 'Please construct a DynamicRnnEstimator directly.') -def single_value_rnn_classifier(num_classes, - num_units, - sequence_feature_columns, - context_feature_columns=None, - cell_type='basic_rnn', - num_rnn_layers=1, - optimizer_type='SGD', - learning_rate=0.1, - predict_probabilities=False, - momentum=None, - gradient_clipping_norm=5.0, - input_keep_probability=None, - output_keep_probability=None, - model_dir=None, - config=None, - feature_engineering_fn=None): - """Creates a `DynamicRnnEstimator` for single-value classification. - - Returns an `Estimator` that given input sequences, processes them in a dynamic - recurrent network and outputs a single classifications, along with - (optionally) a probability distribution over classes. - - Args: - num_classes: The number of classes for categorization. - num_units: The size of the RNN cells. - sequence_feature_columns: An iterable containing all the feature columns - describing sequence features. All items in the set should be instances - of classes derived from `FeatureColumn`. - context_feature_columns: An iterable containing all the feature columns - describing context features, i.e., features that apply accross all time - steps. All items in the set should be instances of classes derived from - `FeatureColumn`. - cell_type: A subclass of `RNNCell` or one of 'basic_rnn,' 'lstm' or 'gru'. - num_rnn_layers: Number of RNN layers. Leave this at its default value 1 - if passing a `cell_type` that is already a MultiRNNCell. - optimizer_type: The type of optimizer to use. Either a subclass of - `Optimizer`, an instance of an `Optimizer`, a callback that returns an - optimizer, or a string. Strings must be one of 'Adagrad', 'Adam', - 'Ftrl', 'Momentum', 'RMSProp' or 'SGD. See `layers.optimize_loss` for - more details. - learning_rate: Learning rate. This argument has no effect if `optimizer` - is an instance of an `Optimizer`. - predict_probabilities: A boolean indicating whether to predict probabilities - for all classes. - momentum: Momentum value. Only used if `optimizer_type` is 'Momentum'. - gradient_clipping_norm: Parameter used for gradient clipping. If `None`, - then no clipping is performed. - input_keep_probability: Probability to keep inputs to `cell`. If `None`, - no dropout is applied. - output_keep_probability: Probability to keep outputs of `cell`. If `None`, - no dropout is applied. - model_dir: The directory in which to save and restore the model graph, - parameters, etc. - config: A `RunConfig` instance. - feature_engineering_fn: Takes features and labels which are the output of - `input_fn` and returns features and labels which will be fed into - `model_fn`. Please check `model_fn` for a definition of features and - labels. - Returns: - An initialized `Estimator`. - """ - dropout_keep_probabilities, num_units = _get_dropout_and_num_units( - num_units, - num_rnn_layers, - input_keep_probability, - output_keep_probability) - return DynamicRnnEstimator( - problem_type=constants.ProblemType.CLASSIFICATION, - prediction_type=rnn_common.PredictionType.SINGLE_VALUE, - num_classes=num_classes, - sequence_feature_columns=sequence_feature_columns, - context_feature_columns=context_feature_columns, - num_units=num_units, - cell_type=cell_type, - optimizer=optimizer_type, - learning_rate=learning_rate, - predict_probabilities=predict_probabilities, - momentum=momentum, - gradient_clipping_norm=gradient_clipping_norm, - dropout_keep_probabilities=dropout_keep_probabilities, - model_dir=model_dir, - feature_engineering_fn=feature_engineering_fn, - config=config) diff --git a/tensorflow/contrib/learn/python/learn/estimators/dynamic_rnn_estimator_test.py b/tensorflow/contrib/learn/python/learn/estimators/dynamic_rnn_estimator_test.py index 58072500d10..6fc028ab706 100644 --- a/tensorflow/contrib/learn/python/learn/estimators/dynamic_rnn_estimator_test.py +++ b/tensorflow/contrib/learn/python/learn/estimators/dynamic_rnn_estimator_test.py @@ -410,56 +410,6 @@ class DynamicRnnEstimatorTest(test.TestCase): state_piece = prediction_dict[dynamic_rnn_estimator._get_state_name(i)] self.assertListEqual(list(state_piece.shape), [batch_size, state_size]) - def testLegacyConstructor(self): - """Exercise legacy constructor function.""" - num_units = 16 - num_layers = 6 - output_keep_prob = 0.9 - input_keep_prob = 0.7 - batch_size = 11 - learning_rate = 0.1 - train_sequence_length = 21 - train_steps = 121 - - def get_input_fn(batch_size, sequence_length, state_dict, starting_step=0): - - def input_fn(): - sequence = constant_op.constant( - [[(starting_step + i + j) % 2 for j in range(sequence_length + 1)] - for i in range(batch_size)], - dtype=dtypes.int32) - labels = array_ops.slice(sequence, [0, 0], - [batch_size, sequence_length]) - inputs = array_ops.expand_dims( - math_ops.to_float( - array_ops.slice(sequence, [0, 1], [batch_size, sequence_length - ])), 2) - input_dict = state_dict - input_dict['inputs'] = inputs - return input_dict, labels - - return input_fn - - seq_columns = [feature_column.real_valued_column('inputs', dimension=1)] - config = run_config.RunConfig(tf_random_seed=21212) - - model_dir = tempfile.mkdtemp() - sequence_estimator = dynamic_rnn_estimator.multi_value_rnn_classifier( - num_classes=2, - num_units=num_units, - num_rnn_layers=num_layers, - input_keep_probability=input_keep_prob, - output_keep_probability=output_keep_prob, - sequence_feature_columns=seq_columns, - learning_rate=learning_rate, - config=config, - model_dir=model_dir) - - train_input_fn = get_input_fn( - batch_size, train_sequence_length, state_dict={}) - - sequence_estimator.fit(input_fn=train_input_fn, steps=train_steps) - def testMultipleRuns(self): """Tests resuming training by feeding state.""" cell_sizes = [4, 7] diff --git a/tensorflow/contrib/learn/python/learn/estimators/kmeans.py b/tensorflow/contrib/learn/python/learn/estimators/kmeans.py index a0f501dfbaf..5be07d271d6 100644 --- a/tensorflow/contrib/learn/python/learn/estimators/kmeans.py +++ b/tensorflow/contrib/learn/python/learn/estimators/kmeans.py @@ -27,11 +27,11 @@ from tensorflow.contrib.learn.python.learn.estimators import estimator from tensorflow.contrib.learn.python.learn.estimators.model_fn import ModelFnOps from tensorflow.python.framework import ops from tensorflow.python.ops import array_ops -from tensorflow.python.ops import logging_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import state_ops from tensorflow.python.ops.control_flow_ops import with_dependencies from tensorflow.python.platform import tf_logging as logging +from tensorflow.python.summary import summary from tensorflow.python.training import session_run_hook from tensorflow.python.training.session_run_hook import SessionRunArgs @@ -118,7 +118,7 @@ def _kmeans_clustering_model_fn(features, labels, mode, params, config): 'kmeans_plus_plus_num_retries')).training_graph() incr_step = state_ops.assign_add(variables.get_global_step(), 1) loss = math_ops.reduce_sum(losses, name=KMeansClustering.LOSS_OP_NAME) - logging_ops.scalar_summary('loss/raw', loss) + summary.scalar('loss/raw', loss) training_op = with_dependencies([training_op, incr_step], loss) predictions = { KMeansClustering.ALL_SCORES: all_scores[0], @@ -257,4 +257,3 @@ class KMeansClustering(estimator.Estimator): def clusters(self): """Returns cluster centers.""" return super(KMeansClustering, self).get_variable_value(self.CLUSTERS) - diff --git a/tensorflow/contrib/learn/python/learn/estimators/state_saving_rnn_estimator.py b/tensorflow/contrib/learn/python/learn/estimators/state_saving_rnn_estimator.py index e09278bc636..02acd708123 100644 --- a/tensorflow/contrib/learn/python/learn/estimators/state_saving_rnn_estimator.py +++ b/tensorflow/contrib/learn/python/learn/estimators/state_saving_rnn_estimator.py @@ -20,7 +20,6 @@ from __future__ import print_function from tensorflow.contrib import layers from tensorflow.contrib import rnn as rnn_cell -from tensorflow.contrib.framework.python.framework import deprecated from tensorflow.contrib.layers.python.layers import feature_column_ops from tensorflow.contrib.layers.python.layers import optimizers from tensorflow.contrib.learn.python.learn.estimators import constants @@ -652,180 +651,3 @@ class StateSavingRnnEstimator(estimator.Estimator): model_dir=model_dir, config=config, feature_engineering_fn=feature_engineering_fn) - - -@deprecated('2017-04-01', 'multi_value_rnn_regressor is deprecated. ' - 'Please construct a StateSavingRnnEstimator directly.') -def multi_value_rnn_regressor(num_units, - num_unroll, - batch_size, - sequence_feature_columns, - context_feature_columns=None, - num_rnn_layers=1, - optimizer_type='SGD', - learning_rate=0.1, - momentum=None, - gradient_clipping_norm=5.0, - dropout_keep_probabilities=None, - model_dir=None, - config=None, - feature_engineering_fn=None, - num_threads=3, - queue_capacity=1000, - seed=None): - """Creates a RNN `Estimator` that predicts sequences of values. - - Args: - num_units: The size of the RNN cells. - num_unroll: Python integer, how many time steps to unroll at a time. - The input sequences of length `k` are then split into `k / num_unroll` - many segments. - batch_size: Python integer, the size of the minibatch. - sequence_feature_columns: An iterable containing all the feature columns - describing sequence features. All items in the set should be instances - of classes derived from `FeatureColumn`. - context_feature_columns: An iterable containing all the feature columns - describing context features, i.e., features that apply accross all time - steps. All items in the set should be instances of classes derived from - `FeatureColumn`. - num_rnn_layers: Number of RNN layers. - optimizer_type: The type of optimizer to use. Either a subclass of - `Optimizer`, an instance of an `Optimizer` or a string. Strings must be - one of 'Adagrad', 'Momentum' or 'SGD'. - learning_rate: Learning rate. This argument has no effect if `optimizer` - is an instance of an `Optimizer`. - momentum: Momentum value. Only used if `optimizer_type` is 'Momentum'. - gradient_clipping_norm: Parameter used for gradient clipping. If `None`, - then no clipping is performed. - dropout_keep_probabilities: a list of dropout keep probabilities or `None`. - If given a list, it must have length `num_rnn_layers + 1`. - model_dir: The directory in which to save and restore the model graph, - parameters, etc. - config: A `RunConfig` instance. - feature_engineering_fn: Takes features and labels which are the output of - `input_fn` and returns features and labels which will be fed into - `model_fn`. Please check `model_fn` for a definition of features and - labels. - num_threads: The Python integer number of threads enqueuing input examples - into a queue. Defaults to 3. - queue_capacity: The max capacity of the queue in number of examples. - Needs to be at least `batch_size`. Defaults to 1000. When iterating - over the same input example multiple times reusing their keys the - `queue_capacity` must be smaller than the number of examples. - seed: Fixes the random seed used for generating input keys by the SQSS. - Returns: - An initialized `Estimator`. - """ - num_units = [num_units for _ in range(num_rnn_layers)] - return StateSavingRnnEstimator( - constants.ProblemType.LINEAR_REGRESSION, - num_unroll, - batch_size, - sequence_feature_columns, - context_feature_columns=context_feature_columns, - num_classes=None, - num_units=num_units, - cell_type='lstm', - optimizer_type=optimizer_type, - learning_rate=learning_rate, - predict_probabilities=False, - momentum=momentum, - gradient_clipping_norm=gradient_clipping_norm, - dropout_keep_probabilities=dropout_keep_probabilities, - model_dir=model_dir, - config=config, - feature_engineering_fn=feature_engineering_fn, - num_threads=num_threads, - queue_capacity=queue_capacity, - seed=seed) - - -@deprecated('2017-04-01', 'multi_value_rnn_classifier is deprecated. ' - 'Please construct a StateSavingRnnEstimator directly.') -def multi_value_rnn_classifier(num_classes, - num_units, - num_unroll, - batch_size, - sequence_feature_columns, - context_feature_columns=None, - num_rnn_layers=1, - optimizer_type='SGD', - learning_rate=0.1, - predict_probabilities=False, - momentum=None, - gradient_clipping_norm=5.0, - dropout_keep_probabilities=None, - model_dir=None, - config=None, - feature_engineering_fn=None, - num_threads=3, - queue_capacity=1000, - seed=None): - """Creates a RNN `Estimator` that predicts sequences of labels. - - Args: - num_classes: The number of classes for categorization. - num_units: The size of the RNN cells. - num_unroll: Python integer, how many time steps to unroll at a time. - The input sequences of length `k` are then split into `k / num_unroll` - many segments. - batch_size: Python integer, the size of the minibatch. - sequence_feature_columns: An iterable containing all the feature columns - describing sequence features. All items in the set should be instances - of classes derived from `FeatureColumn`. - context_feature_columns: An iterable containing all the feature columns - describing context features, i.e., features that apply accross all time - steps. All items in the set should be instances of classes derived from - `FeatureColumn`. - num_rnn_layers: Number of RNN layers. - optimizer_type: The type of optimizer to use. Either a subclass of - `Optimizer`, an instance of an `Optimizer` or a string. Strings must be - one of 'Adagrad', 'Momentum' or 'SGD'. - learning_rate: Learning rate. This argument has no effect if `optimizer` - is an instance of an `Optimizer`. - predict_probabilities: A boolean indicating whether to predict probabilities - for all classes. - momentum: Momentum value. Only used if `optimizer_type` is 'Momentum'. - gradient_clipping_norm: Parameter used for gradient clipping. If `None`, - then no clipping is performed. - dropout_keep_probabilities: a list of dropout keep probabilities or `None`. - If given a list, it must have length `num_rnn_layers + 1`. - model_dir: The directory in which to save and restore the model graph, - parameters, etc. - config: A `RunConfig` instance. - feature_engineering_fn: Takes features and labels which are the output of - `input_fn` and returns features and labels which will be fed into - `model_fn`. Please check `model_fn` for a definition of features and - labels. - num_threads: The Python integer number of threads enqueuing input examples - into a queue. Defaults to 3. - queue_capacity: The max capacity of the queue in number of examples. - Needs to be at least `batch_size`. Defaults to 1000. When iterating - over the same input example multiple times reusing their keys the - `queue_capacity` must be smaller than the number of examples. - seed: Fixes the random seed used for generating input keys by the SQSS. - Returns: - An initialized `Estimator`. - """ - num_units = [num_units for _ in range(num_rnn_layers)] - return StateSavingRnnEstimator( - constants.ProblemType.CLASSIFICATION, - num_unroll, - batch_size, - sequence_feature_columns, - context_feature_columns=context_feature_columns, - num_classes=num_classes, - num_units=num_units, - cell_type='lstm', - optimizer_type=optimizer_type, - learning_rate=learning_rate, - predict_probabilities=predict_probabilities, - momentum=momentum, - gradient_clipping_norm=gradient_clipping_norm, - dropout_keep_probabilities=dropout_keep_probabilities, - model_dir=model_dir, - config=config, - feature_engineering_fn=feature_engineering_fn, - num_threads=num_threads, - queue_capacity=queue_capacity, - seed=seed) diff --git a/tensorflow/contrib/learn/python/learn/estimators/state_saving_rnn_estimator_test.py b/tensorflow/contrib/learn/python/learn/estimators/state_saving_rnn_estimator_test.py index feea6c5fed3..886aab5b4fe 100644 --- a/tensorflow/contrib/learn/python/learn/estimators/state_saving_rnn_estimator_test.py +++ b/tensorflow/contrib/learn/python/learn/estimators/state_saving_rnn_estimator_test.py @@ -455,56 +455,6 @@ class LegacyConstructorTest(test.TestCase): return {'inputs': inputs}, labels return input_fn - def testClassifierConstructor(self): - batch_size = 16 - num_classes = 2 - num_unroll = 32 - sequence_length = 32 - num_units = 4 - learning_rate = 0.5 - steps = 100 - input_fn = self._get_input_fn(sequence_length, - seed=1234) - model_dir = tempfile.mkdtemp() - seq_columns = [ - feature_column.real_valued_column( - 'inputs', dimension=num_units) - ] - estimator = ssre.multi_value_rnn_classifier(num_classes, - num_units, - num_unroll, - batch_size, - seq_columns, - learning_rate=learning_rate, - model_dir=model_dir, - queue_capacity=batch_size+2, - seed=1234) - estimator.fit(input_fn=input_fn, steps=steps) - - def testRegressorConstructor(self): - batch_size = 16 - num_unroll = 32 - sequence_length = 32 - num_units = 4 - learning_rate = 0.5 - steps = 100 - input_fn = self._get_input_fn(sequence_length, - seed=4321) - model_dir = tempfile.mkdtemp() - seq_columns = [ - feature_column.real_valued_column( - 'inputs', dimension=num_units) - ] - estimator = ssre.multi_value_rnn_regressor(num_units, - num_unroll, - batch_size, - seq_columns, - learning_rate=learning_rate, - model_dir=model_dir, - queue_capacity=batch_size+2, - seed=1234) - estimator.fit(input_fn=input_fn, steps=steps) - # TODO(jtbates): move all tests below to a benchmark test. class StateSavingRNNEstimatorLearningTest(test.TestCase): diff --git a/tensorflow/contrib/rnn/__init__.py b/tensorflow/contrib/rnn/__init__.py index a7448781241..d2f9cde4f6b 100644 --- a/tensorflow/contrib/rnn/__init__.py +++ b/tensorflow/contrib/rnn/__init__.py @@ -42,6 +42,8 @@ See @{$python/contrib.rnn} guide. @@GridLSTMCell @@BidirectionalGridLSTMCell @@NASCell +@@UGRNNCell +@@IntersectionRNNCell @@PhasedLSTMCell @@HighwayWrapper diff --git a/tensorflow/contrib/signal/BUILD b/tensorflow/contrib/signal/BUILD new file mode 100644 index 00000000000..5b65a6ae05e --- /dev/null +++ b/tensorflow/contrib/signal/BUILD @@ -0,0 +1,46 @@ +package(default_visibility = ["//tensorflow:__subpackages__"]) + +licenses(["notice"]) # Apache 2.0 + +exports_files(["LICENSE"]) + +load("//tensorflow:tensorflow.bzl", "cuda_py_tests") + +py_library( + name = "signal_py", + srcs = ["__init__.py"] + glob(["python/ops/*.py"]), + srcs_version = "PY2AND3", + deps = [ + "//tensorflow/python:array_ops", + "//tensorflow/python:framework", + "//tensorflow/python:math_ops", + ], +) + +cuda_py_tests( + name = "shape_ops_test", + size = "small", + srcs = ["python/kernel_tests/shape_ops_test.py"], + additional_deps = [ + ":signal_py", + "//third_party/py/numpy", + "//tensorflow/python:array_ops", + "//tensorflow/python:client_testlib", + "//tensorflow/python:framework", + "//tensorflow/python:framework_for_generated_wrappers", + "//tensorflow/python:framework_test_lib", + "//tensorflow/python:platform_test", + ], +) + +filegroup( + name = "all_files", + srcs = glob( + ["**/*"], + exclude = [ + "**/METADATA", + "**/OWNERS", + ], + ), + visibility = ["//tensorflow:__subpackages__"], +) diff --git a/tensorflow/contrib/signal/__init__.py b/tensorflow/contrib/signal/__init__.py new file mode 100644 index 00000000000..9f906dd28e8 --- /dev/null +++ b/tensorflow/contrib/signal/__init__.py @@ -0,0 +1,27 @@ +# Copyright 2016 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""##Signal ops. + +@@frames +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.contrib.signal.python.ops.shape_ops import frames + +from tensorflow.python.util.all_util import remove_undocumented +remove_undocumented(__name__) diff --git a/tensorflow/contrib/signal/python/__init__.py b/tensorflow/contrib/signal/python/__init__.py new file mode 100644 index 00000000000..e672d1146c5 --- /dev/null +++ b/tensorflow/contrib/signal/python/__init__.py @@ -0,0 +1,19 @@ +# Copyright 2016 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Signal ops.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function diff --git a/tensorflow/contrib/signal/python/kernel_tests/shape_ops_test.py b/tensorflow/contrib/signal/python/kernel_tests/shape_ops_test.py new file mode 100644 index 00000000000..e07942875fd --- /dev/null +++ b/tensorflow/contrib/signal/python/kernel_tests/shape_ops_test.py @@ -0,0 +1,68 @@ +# Copyright 2015 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for shape_ops.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np + +from tensorflow.contrib.signal.python.ops import shape_ops +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes +from tensorflow.python.ops import array_ops +from tensorflow.python.platform import test + + +class FramesTest(test.TestCase): + + def test_mapping_of_indices_without_padding(self): + with self.test_session(): + tensor = constant_op.constant(np.arange(9152), dtypes.int32) + tensor = array_ops.expand_dims(tensor, 0) + + result = shape_ops.frames(tensor, 512, 180) + result = result.eval() + + expected = np.tile(np.arange(512), (49, 1)) + expected += np.tile(np.arange(49) * 180, (512, 1)).T + + expected = np.expand_dims(expected, axis=0) + expected = np.array(expected, dtype=np.int32) + + self.assertAllEqual(expected, result) + + def test_mapping_of_indices_with_padding(self): + with self.test_session(): + tensor = constant_op.constant(np.arange(10000), dtypes.int32) + tensor = array_ops.expand_dims(tensor, 0) + + result = shape_ops.frames(tensor, 512, 192) + result = result.eval() + + expected = np.tile(np.arange(512), (51, 1)) + expected += np.tile(np.arange(51) * 192, (512, 1)).T + + expected[expected >= 10000] = 0 + + expected = np.expand_dims(expected, axis=0) + expected = np.array(expected, dtype=np.int32) + + self.assertAllEqual(expected, result) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/contrib/signal/python/ops/__init__.py b/tensorflow/contrib/signal/python/ops/__init__.py new file mode 100644 index 00000000000..e672d1146c5 --- /dev/null +++ b/tensorflow/contrib/signal/python/ops/__init__.py @@ -0,0 +1,19 @@ +# Copyright 2016 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Signal ops.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function diff --git a/tensorflow/contrib/signal/python/ops/shape_ops.py b/tensorflow/contrib/signal/python/ops/shape_ops.py new file mode 100644 index 00000000000..4914f19be75 --- /dev/null +++ b/tensorflow/contrib/signal/python/ops/shape_ops.py @@ -0,0 +1,87 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""General shape ops for frames.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import ops + +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import math_ops + + +def frames(signal, frame_length, frame_step, name=None): + """Frame a signal into overlapping frames. + + May be used in front of spectral functions. + + For example: + + ```python + pcm = tf.placeholder(tf.float32, [None, 9152]) + frames = tf.contrib.signal.frames(pcm, 512, 180) + magspec = tf.abs(tf.spectral.rfft(frames, [512])) + image = tf.expand_dims(magspec, 3) + ``` + + Args: + signal: A `Tensor` of shape `[batch_size, signal_length]`. + frame_length: An `int32` or `int64` `Tensor`. The length of each frame. + frame_step: An `int32` or `int64` `Tensor`. The step between frames. + name: A name for the operation (optional). + + Returns: + A `Tensor` of frames with shape `[batch_size, num_frames, frame_length]`. + + Raises: + ValueError: if signal does not have rank 2. + """ + with ops.name_scope(name, "frames", [signal, frame_length, frame_step]): + signal = ops.convert_to_tensor(signal, name="signal") + frame_length = ops.convert_to_tensor(frame_length, name="frame_length") + frame_step = ops.convert_to_tensor(frame_step, name="frame_step") + + signal_rank = signal.shape.ndims + + if signal_rank != 2: + raise ValueError("expected signal to have rank 2 but was " + signal_rank) + + signal_length = array_ops.shape(signal)[1] + + num_frames = math_ops.ceil((signal_length - frame_length) / frame_step) + num_frames = 1 + math_ops.cast(num_frames, dtypes.int32) + + pad_length = (num_frames - 1) * frame_step + frame_length + pad_signal = array_ops.pad(signal, [[0, 0], [0, + pad_length - signal_length]]) + + indices_frame = array_ops.expand_dims(math_ops.range(frame_length), 0) + indices_frames = array_ops.tile(indices_frame, [num_frames, 1]) + + indices_step = array_ops.expand_dims( + math_ops.range(num_frames) * frame_step, 1) + indices_steps = array_ops.tile(indices_step, [1, frame_length]) + + indices = indices_frames + indices_steps + + # TODO(androbin): remove `transpose` when `gather` gets `axis` support + pad_signal = array_ops.transpose(pad_signal) + signal_frames = array_ops.gather(pad_signal, indices) + signal_frames = array_ops.transpose(signal_frames, perm=[2, 0, 1]) + + return signal_frames diff --git a/tensorflow/contrib/slim/README.md b/tensorflow/contrib/slim/README.md index c8842dd57b1..61148c0b269 100644 --- a/tensorflow/contrib/slim/README.md +++ b/tensorflow/contrib/slim/README.md @@ -447,7 +447,7 @@ vgg = tf.contrib.slim.nets.vgg images, labels = ... # Create the model. -predictions = vgg.vgg_16(images) +predictions, _ = vgg.vgg_16(images) # Define the loss functions and get the total loss. loss = slim.losses.softmax_cross_entropy(predictions, labels) diff --git a/tensorflow/contrib/slim/python/slim/data/README.md b/tensorflow/contrib/slim/python/slim/data/README.md index 858c6949902..fe15a10b99d 100644 --- a/tensorflow/contrib/slim/python/slim/data/README.md +++ b/tensorflow/contrib/slim/python/slim/data/README.md @@ -71,27 +71,27 @@ for item in data_decoder.list_items(): print(item) ``` -## Example: TFExampleDataDecoder +## Example: TFExampleDecoder The -[tfexample_data_decoder.py](https://www.tensorflow.org/code/tensorflow/contrib/slim/python/slim/data/tfexample_data_decoder.py) +[tfexample_decoder.py](https://www.tensorflow.org/code/tensorflow/contrib/slim/python/slim/data/tfexample_decoder.py) is a data decoder which decodes serialized `TFExample` protocol buffers. A `TFExample` protocol buffer is a map from keys (strings) to either a `tf.FixedLenFeature` or `tf.VarLenFeature`. Consequently, to decode a `TFExample`, one must provide a mapping from one or more `TFExample` fields -to each of the `items` that the `tfexample_data_decoder` can provide. For +to each of the `items` that the `tfexample_decoder` can provide. For example, a dataset of `TFExamples` might store images in various formats and each `TFExample` might contain an `encoding` key and a `format` key which can be used to decode the image using the appropriate decoder (jpg, png, etc). -To make this possible, the `tfexample_data_decoder` is constructed by specifying +To make this possible, the `tfexample_decoder` is constructed by specifying the a map of `TFExample` keys to either `tf.FixedLenFeature` or `tf.VarLenFeature` as well as a set of `ItemHandlers`. An `ItemHandler` provides a mapping from `TFExample` keys to the item being provided. Because a -`tfexample_data_decoder` might return multiple `items`, one often constructs a -`tfexample_data_decoder` using multiple `ItemHandlers`. +`tfexample_decoder` might return multiple `items`, one often constructs a +`tfexample_decoder` using multiple `ItemHandlers`. -`tfexample_data_decoder` provides some predefined `ItemHandlers` which take care +`tfexample_decoder` provides some predefined `ItemHandlers` which take care of the common cases of mapping `TFExamples` to images, `Tensors` and `SparseTensors`. For example, the following specification might be used to decode a dataset of images: diff --git a/tensorflow/contrib/slim/python/slim/nets/resnet_v2.py b/tensorflow/contrib/slim/python/slim/nets/resnet_v2.py index f260ede348a..bd811e3726a 100644 --- a/tensorflow/contrib/slim/python/slim/nets/resnet_v2.py +++ b/tensorflow/contrib/slim/python/slim/nets/resnet_v2.py @@ -64,6 +64,8 @@ from tensorflow.python.ops import math_ops from tensorflow.python.ops import nn_ops from tensorflow.python.ops import variable_scope +resnet_arg_scope = resnet_utils.resnet_arg_scope + @add_arg_scope def bottleneck(inputs, diff --git a/tensorflow/contrib/testing/python/framework/fake_summary_writer.py b/tensorflow/contrib/testing/python/framework/fake_summary_writer.py index 02f2d7fae86..f2065c66625 100644 --- a/tensorflow/contrib/testing/python/framework/fake_summary_writer.py +++ b/tensorflow/contrib/testing/python/framework/fake_summary_writer.py @@ -127,3 +127,6 @@ class FakeSummaryWriter(object): def reopen(self): pass + + def close(self): + pass diff --git a/tensorflow/contrib/verbs/README.md b/tensorflow/contrib/verbs/README.md index 37a543dda8d..da5f2b0223b 100644 --- a/tensorflow/contrib/verbs/README.md +++ b/tensorflow/contrib/verbs/README.md @@ -1,54 +1,54 @@ -## How to compile and use Rdma-enabled tensorflow -1. Follow the regular TF compilation instructions. During configure step, if you want ibverbs based Rdma support, answer yes to this question: +## How to compile and use RDMA-enabled TensorFlow +1. Follow the regular TF compilation instructions. During configure step, if you want ibverbs based RDMA support, answer yes to this question: ```Do you wish to build TensorFlow with VERBS-RDMA support [y/N]``` -2. To turn on Rdma connection, add the protocol "grpc+verbs" in server definition: +2. To turn on RDMA connection, add the protocol "grpc+verbs" in server definition: ```server = tf.train.Server(cluster, job_name="local", task_index=0, protocol='grpc+verbs') # default protocol is 'grpc'``` ## Overview -The design is based on Tensorflow r1.0. An Rdma path is added between servers for tensor transfer (weights, gradients, etc). The existing GRPC path remains and is responsible for "administrative" tasks, such as setting up the Rdma path, exchanging computation graphs, etc. +The design is based on TensorFlow r1.0. An RDMA path is added between servers for tensor transfer (weights, gradients, etc). The existing GRPC path remains and is responsible for "administrative" tasks, such as setting up the RDMA path, exchanging computation graphs, etc. -During the server setup, an Rdma manager is created to manage low-level Rdma components such as Rdma channel and Rdma adapter, an Rdma rendezvous manager is created to oversee send/recv operations between servers. Following the distributed Tensorflow design philosophy, the send operation is passive, i.e. merely placing a tensor in the local out-going table. It is the receive operation that actually initiates the tensor transfer. +During the server setup, an RDMA manager is created to manage low-level RDMA components such as RDMA channel and RDMA adapter, an RDMA rendezvous manager is created to oversee send/recv operations between servers. Following the distributed TensorFlow design philosophy, the send operation is passive, i.e. merely placing a tensor in the local out-going table. It is the receive operation that actually initiates the tensor transfer. -Tensorflow dynamically allocates memory for tensors that are to be sent or received. This causes difficulty for Rdma operations where pinned memory is required. Two remedies are possible, either the memory is pinned, transfer, then unpinned for each and every tensor to be transferred, or a buffer is pre-allocated and pinned for each tensor. The former incurs significant operation overhead since pinning and unpinning memory for each dynamically generated tensor is slow. The latter incurs large memory overhead and extra copying from the tensor to its pinned buffer, but may still be faster than the former. The second approach is adopted in this design. Each Rdma channel, representing a Rdma connection to a peer, contains a table of pinned buffers for all the seen tensors that requires transfer. It is assumed that the tensor size rarely changes across different steps. So only one buffer is created for the same tensor across all the steps. In the rare case when the tensor size does increases, the old buffer is discarded and new buffer of larger size is created and pinned. +TensorFlow dynamically allocates memory for tensors that are to be sent or received. This causes difficulty for RDMA operations where pinned memory is required. Two remedies are possible, either the memory is pinned, transfer, then unpinned for each and every tensor to be transferred, or a buffer is pre-allocated and pinned for each tensor. The former incurs significant operation overhead since pinning and unpinning memory for each dynamically generated tensor is slow. The latter incurs large memory overhead and extra copying from the tensor to its pinned buffer, but may still be faster than the former. The second approach is adopted in this design. Each RDMA channel, representing a RDMA connection to a peer, contains a table of pinned buffers for all the seen tensors that requires transfer. It is assumed that the tensor size rarely changes across different steps. So only one buffer is created for the same tensor across all the steps. In the rare case when the tensor size does increases, the old buffer is discarded and new buffer of larger size is created and pinned. -When a tensor is prepared fro transfer, it is first converted to TensorProto, then the proto is serialized to byte array and copied to the pinned buffer. The content of the buffer is transferred to the remote node via Rdma write. On the remote side, the process is reversed. This is illustrated in the diagram below. The conversion of TensorProto is introduced to simplify transfer of string-tensors. Also since the TensorProto lives in host memory, even if the origin tensor lives in the device, the pinned buffers are all allocated in the host memory. -![Tensorflow Rdma path](./design_diagram.png) +When a tensor is prepared for transfer, it is first converted to TensorProto, then the proto is serialized to byte array and copied to the pinned buffer. The content of the buffer is transferred to the remote node via RDMA write. On the remote side, the process is reversed. This is illustrated in the diagram below. The conversion of TensorProto is introduced to simplify transfer of string-tensors. Also since the TensorProto lives in host memory, even if the origin tensor lives in the device, the pinned buffers are all allocated in the host memory. +![TensorFlow RDMA path](./design_diagram.png) The following improvements can be made in the future. First, conversion to TensorProto and serialization can be avoided for numeric (float/int) tensors since their internal buffer can be access directly as byte array. Second, the pinned buffer may be allocated on device if the tensor is located in the device. This avoids extra device-to-host copy at the expense of extra device memory consumption. ## Design details -### Rdma components +### RDMA components -* **Rdma adapter:** The base for Rdma communications. It may contain multiple channels and buffers. It is responsible for handling various incoming Rdma messages. -* **Rdma channel:** Responsible for Rdma connection to a particular node. It manages multiple buffers. A channel has a callback table which stores all the callbacks for the requested tensors. -* **Rdma buffer:** Responsible for sending or receiving data. It has a fixed size memory to store the data. It has a queue to store the pending jobs. There are three types of buffers, message buffer, ACK buffer and tensor buffer. A channel has two message buffers, two ack buffers and many tensor buffers. -* **Rdma manager:** Manages the adapter and channels, including channel creation, channel setup via GRPC service, channel lookup, etc. -* **Rdma rendezvous manager:** manages multiple rdma rendezvous. -* **Rdma rendezvous:** a derived class of BaseRemoteRendezvous. This class is the back end for "send" and "recv" ops. When the sendrecv_op wants to send or receive a tensor, it calls the rendezvous' "send" and "recv" functions respectively. Rendezvous are identified by "step_id", a random number, so that tensors for different iterations don't get mixed up. +* **RDMA adapter:** The base for RDMA communications. It may contain multiple channels and buffers. It is responsible for handling various incoming RDMA messages. +* **RDMA channel:** Responsible for RDMA connection to a particular node. It manages multiple buffers. A channel has a callback table which stores all the callbacks for the requested tensors. +* **RDMA buffer:** Responsible for sending or receiving data. It has a fixed size memory to store the data. It has a queue to store the pending jobs. There are three types of buffers, message buffer, ACK buffer and tensor buffer. A channel has two message buffers, two ack buffers and many tensor buffers. +* **RDMA manager:** Manages the adapter and channels, including channel creation, channel setup via GRPC service, channel lookup, etc. +* **RDMA rendezvous manager:** manages multiple rdma rendezvous. +* **RDMA rendezvous:** a derived class of BaseRemoteRendezvous. This class is the back end for "send" and "recv" ops. When the sendrecv_op wants to send or receive a tensor, it calls the rendezvous' "send" and "recv" functions respectively. Rendezvous are identified by "step_id", a random number, so that tensors for different iterations don't get mixed up. ### The SEND operation -In tensorflow, when rendezvous sends a tensor, it merely puts a tensor in a local table in the corresponding rendezvous. If the tensor has been requested, a callback exists in the table. "send" will activate the callback, which tries to send the tensor across the node. +In TensorFlow, when rendezvous sends a tensor, it merely puts a tensor in a local table in the corresponding rendezvous. If the tensor has been requested, a callback exists in the table. "send" will activate the callback, which tries to send the tensor across the node. ### The RECV operation -When a tensor is requested, rendezvous' recv function is called. The function first places a callback in the channel's callback table, which will be activated once the tensor is sent from the source. In the next step, a message is sent to notify the source of the requested tensor. Once the source receives the message, it will check locally for the tensor, if not found, a callback is placed in the table, otherwise, the tensor id will be placed at corresponding Rdma buffer's job queue for future transmission. When a tensor is scheduled to be transmitted, the Rdma buffer needs to have the memory allocated and initialized (registered with the remote buffer info). If the memory is not ready, the transmission is deferred, a message is sent to the destination to establish the memory first. The other case a transimssion can be deferred is when the buffer is still being used by an on-going transmission. +When a tensor is requested, rendezvous' recv function is called. The function first places a callback in the channel's callback table, which will be activated once the tensor is sent from the source. In the next step, a message is sent to notify the source of the requested tensor. Once the source receives the message, it will check locally for the tensor, if not found, a callback is placed in the table, otherwise, the tensor id will be placed at corresponding RDMA buffer's job queue for future transmission. When a tensor is scheduled to be transmitted, the RDMA buffer needs to have the memory allocated and initialized (registered with the remote buffer info). If the memory is not ready, the transmission is deferred, a message is sent to the destination to establish the memory first. The other case a transmission can be deferred is when the buffer is still being used by an on-going transmission. -### Three types of Rdma buffers +### Three types of RDMA buffers * **Message buffer:** responsible for sending message only. * **Ack buffer:** once a message is sent, the recipient needs to send an ack via the ack buffer to free up the message buffer. An ack buffer is exclusively for its coupled message buffer. * **Tensor buffer:** responsible for sending tensors. The recipient needs to send back a message to free up the sending buffer. -### Rdma packet format +### RDMA packet format |type|name_size|name|step_id|buffer_size|remote_addr|rkey|is_dead|data_type|tensor_shape|tensor_bytes|tensor_buffer| -### Six types of Rdma messages +### Six types of RDMA messages * RDMA_MESSAGE_ACK * RDMA_MESSAGE_BUFFER_IDLE * RDMA_MESSAGE_BUFFER_REQUEST @@ -56,7 +56,7 @@ When a tensor is requested, rendezvous' recv function is called. The function fi * RDMA_MESSAGE_TENSOR_REQUEST * RDMA_MESSAGE_TENSOR_WRITE -### Actions upon receiving Rdma messages +### Actions upon receiving RDMA messages * RDMA_MESSAGE_ACK * sender: mark local ack buffer idle. * receiver: mark remote message buffer idle, send next item. diff --git a/tensorflow/contrib/verbs/grpc_verbs_service.cc b/tensorflow/contrib/verbs/grpc_verbs_service.cc index e73b2700bd9..f2af6b79fba 100644 --- a/tensorflow/contrib/verbs/grpc_verbs_service.cc +++ b/tensorflow/contrib/verbs/grpc_verbs_service.cc @@ -117,6 +117,8 @@ Status GrpcVerbsService::GetRemoteAddressSync( ra.lid = request->channel().lid(); ra.qpn = request->channel().qpn(); ra.psn = request->channel().psn(); + ra.snp = request->channel().snp(); + ra.iid = request->channel().iid(); rc->SetRemoteAddress(ra, false); rc->Connect(); int i = 0; @@ -146,6 +148,8 @@ Status GrpcVerbsService::GetRemoteAddressSync( channel_info->set_lid(rc->self().lid); channel_info->set_qpn(rc->self().qpn); channel_info->set_psn(rc->self().psn); + channel_info->set_snp(rc->self().snp); + channel_info->set_iid(rc->self().iid); for (int i = 0; i < RdmaChannel::kNumMessageBuffers; i++) { MemoryRegion* mr = response->add_mr(); mr->set_remote_addr(reinterpret_cast(mb[i]->buffer())); diff --git a/tensorflow/contrib/verbs/rdma.cc b/tensorflow/contrib/verbs/rdma.cc index 53d840f5d1c..05df05de353 100644 --- a/tensorflow/contrib/verbs/rdma.cc +++ b/tensorflow/contrib/verbs/rdma.cc @@ -271,6 +271,11 @@ RdmaChannel::RdmaChannel(const RdmaAdapter* adapter, const string local_name, self_.lid = attr.lid; self_.qpn = qp_->qp_num; self_.psn = static_cast(random::New64()) & 0xffffff; + union ibv_gid gid; + CHECK(!ibv_query_gid(adapter_->context_, (uint8_t)1, 0, &gid)) + << "Query gid"; + self_.snp = gid.global.subnet_prefix; + self_.iid = gid.global.interface_id; } // create message and ack buffers, then initialize the tables. @@ -320,11 +325,15 @@ void RdmaChannel::SetRemoteAddress(const RdmaAddress& ra, bool override) { remote_.lid = ra.lid; remote_.qpn = ra.qpn; remote_.psn = ra.psn; + remote_.snp = ra.snp; + remote_.iid = ra.iid; remote_set_ = true; } else { CHECK(remote_.lid == ra.lid); CHECK(remote_.qpn == ra.qpn); CHECK(remote_.psn == ra.psn); + CHECK(remote_.snp == ra.snp); + CHECK(remote_.iid == ra.iid); } } @@ -472,7 +481,11 @@ void RdmaChannel::Connect(const RdmaAddress& remoteAddr) { attr.rq_psn = remoteAddr.psn; attr.max_dest_rd_atomic = 1; attr.min_rnr_timer = 12; - attr.ah_attr.is_global = 0; + attr.ah_attr.is_global = 1; + attr.ah_attr.grh.dgid.global.subnet_prefix = remoteAddr.snp; + attr.ah_attr.grh.dgid.global.interface_id = remoteAddr.iid; + attr.ah_attr.grh.flow_label = 0; + attr.ah_attr.grh.hop_limit = 255; attr.ah_attr.dlid = remoteAddr.lid; attr.ah_attr.sl = 0; attr.ah_attr.src_path_bits = 0; diff --git a/tensorflow/contrib/verbs/rdma.h b/tensorflow/contrib/verbs/rdma.h index ae2aa63e3f6..10cbbe58d9a 100644 --- a/tensorflow/contrib/verbs/rdma.h +++ b/tensorflow/contrib/verbs/rdma.h @@ -40,6 +40,8 @@ struct RdmaAddress { uint32_t lid; uint32_t qpn; uint32_t psn; + uint64_t snp; + uint64_t iid; }; // structure to save information for remote memory regions. struct RemoteMR { diff --git a/tensorflow/contrib/verbs/rdma_mgr.cc b/tensorflow/contrib/verbs/rdma_mgr.cc index e28b80c6f6b..09b878843f5 100644 --- a/tensorflow/contrib/verbs/rdma_mgr.cc +++ b/tensorflow/contrib/verbs/rdma_mgr.cc @@ -69,6 +69,8 @@ void RdmaMgr::SetupChannels() { channel_info->set_lid(rc->self_.lid); channel_info->set_qpn(rc->self_.qpn); channel_info->set_psn(rc->self_.psn); + channel_info->set_snp(rc->self_.snp); + channel_info->set_iid(rc->self_.iid); for (int i = 0; i < RdmaChannel::kNumMessageBuffers; i++) { MemoryRegion* mr = req.add_mr(); mr->set_remote_addr( @@ -85,6 +87,8 @@ void RdmaMgr::SetupChannels() { ra.lid = resp.channel().lid(); ra.qpn = resp.channel().qpn(); ra.psn = resp.channel().psn(); + ra.snp = resp.channel().snp(); + ra.iid = resp.channel().iid(); rc->SetRemoteAddress(ra, false); rc->Connect(); int i = 0; diff --git a/tensorflow/contrib/verbs/verbs_service.proto b/tensorflow/contrib/verbs/verbs_service.proto index b985febfb8c..0df1fed4b9d 100644 --- a/tensorflow/contrib/verbs/verbs_service.proto +++ b/tensorflow/contrib/verbs/verbs_service.proto @@ -30,6 +30,8 @@ message Channel { int32 lid = 1; int32 qpn = 2; int32 psn = 3; + uint64 snp = 4; + uint64 iid = 5; } message MemoryRegion { diff --git a/tensorflow/core/distributed_runtime/rpc/grpc_call.h b/tensorflow/core/distributed_runtime/rpc/grpc_call.h index 35f849c7a5e..3b45e7e8a70 100644 --- a/tensorflow/core/distributed_runtime/rpc/grpc_call.h +++ b/tensorflow/core/distributed_runtime/rpc/grpc_call.h @@ -16,6 +16,7 @@ limitations under the License. #ifndef THIRD_PARTY_TENSORFLOW_CORE_DISTRIBUTED_RUNTIME_RPC_GRPC_CALL_H_ #define THIRD_PARTY_TENSORFLOW_CORE_DISTRIBUTED_RUNTIME_RPC_GRPC_CALL_H_ +#include "tensorflow/core/lib/core/refcount.h" #include "tensorflow/core/platform/macros.h" #include "grpc++/grpc++.h" diff --git a/tensorflow/core/distributed_runtime/rpc/grpc_tensor_coding.cc b/tensorflow/core/distributed_runtime/rpc/grpc_tensor_coding.cc index c6260afa20e..ba206890ce8 100644 --- a/tensorflow/core/distributed_runtime/rpc/grpc_tensor_coding.cc +++ b/tensorflow/core/distributed_runtime/rpc/grpc_tensor_coding.cc @@ -16,6 +16,7 @@ limitations under the License. #include "tensorflow/core/distributed_runtime/rpc/grpc_tensor_coding.h" #include "grpc++/support/byte_buffer.h" #include "grpc++/support/slice.h" +#include "tensorflow/core/common_runtime/dma_helper.h" #include "tensorflow/core/framework/tensor.h" #include "tensorflow/core/framework/tensor_reference.h" #include "tensorflow/core/lib/gtl/inlined_vector.h" @@ -27,10 +28,9 @@ namespace tensorflow { namespace grpc { static void do_nothing(void* raw) {} -static void unref_tensorreference(void* raw) { - TensorReference* ref = static_cast(raw); - ref->Unref(); - delete ref; +static void unref_tensorbuffer(void* raw) { + TensorBuffer* buf = static_cast(raw); + buf->Unref(); } void EncodeRecvTensorResponseToByteBuffer(const RecvTensorResponse& proto, @@ -219,8 +219,8 @@ void EncodeTensorToByteBuffer(bool is_dead, const Tensor& val, if (tensor_data_is_large) { // Encode the actual tensor data by pointing to the backing store, - // and add a special zero-length slice that is really a TensorReference - // object that we will destroy when we are done. + // and add a special zero-length slice that is really a TensorBuffer + // reference that we will unref when we are done. // // TODO(jeff): Note that this approach relies on the fact that // slices are destroyed in the order in which they are added to @@ -241,17 +241,15 @@ void EncodeTensorToByteBuffer(bool is_dead, const Tensor& val, // (E) Encode tensor data, but by sharing backing store - // TODO(jeff,sanjay): It'd be nice to avoid this TensorReference - // allocation, and instead get our hands on the underlying - // TensorBuffer object and just directly ref it here and unref - // it in unref_tensorreference. - TensorReference* ref = new TensorReference(val); + const TensorBuffer* buf = DMAHelper::buffer(&val); + buf->Ref(); gpr_slice s1 = gpr_slice_new( const_cast(static_cast(tdata.data())), tdata.size(), do_nothing); slices[1] = ::grpc::Slice(s1, ::grpc::Slice::STEAL_REF); - gpr_slice s2 = gpr_slice_new(ref, 0, unref_tensorreference); + gpr_slice s2 = + gpr_slice_new(const_cast(buf), 0, unref_tensorbuffer); slices[2] = ::grpc::Slice(s2, ::grpc::Slice::STEAL_REF); num_slices += 2; } diff --git a/tensorflow/core/kernels/cwise_op_atan2.cc b/tensorflow/core/kernels/cwise_op_atan2.cc new file mode 100644 index 00000000000..68f67c444ef --- /dev/null +++ b/tensorflow/core/kernels/cwise_op_atan2.cc @@ -0,0 +1,23 @@ +/* Copyright 2015 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/core/kernels/cwise_ops_common.h" + +namespace tensorflow { +REGISTER2(BinaryOp, CPU, "Atan2", functor::atan2, float, double); +#if GOOGLE_CUDA +REGISTER2(BinaryOp, GPU, "Atan2", functor::atan2, float, double); +#endif +} // namespace tensorflow diff --git a/tensorflow/core/kernels/cwise_op_gpu_atan2.cu.cc b/tensorflow/core/kernels/cwise_op_gpu_atan2.cu.cc new file mode 100644 index 00000000000..137e14ef840 --- /dev/null +++ b/tensorflow/core/kernels/cwise_op_gpu_atan2.cu.cc @@ -0,0 +1,26 @@ +/* Copyright 2016 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#if GOOGLE_CUDA + +#include "tensorflow/core/kernels/cwise_ops_gpu_common.cu.h" + +namespace tensorflow { +namespace functor { +DEFINE_BINARY2(atan2, float, double); +} // namespace functor +} // namespace tensorflow + +#endif // GOOGLE_CUDA diff --git a/tensorflow/core/kernels/cwise_ops.h b/tensorflow/core/kernels/cwise_ops.h index fb4c649a82b..423307fd4cd 100644 --- a/tensorflow/core/kernels/cwise_ops.h +++ b/tensorflow/core/kernels/cwise_ops.h @@ -658,6 +658,22 @@ struct zeta : base> {}; template struct polygamma : base> {}; +template +struct scalar_atan2_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_atan2_op) + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar + operator()(const Scalar& y, const Scalar& x) const { +#if GOOGLE_CUDA + return ::atan2(y, x); +#else + return std::atan2(y, x); +#endif + } +}; + +template +struct atan2 : base> {}; + template struct squared_difference : base + #include "third_party/eigen3/Eigen/Core" #include "tensorflow/core/framework/device_base.h" #include "tensorflow/core/framework/kernel_def_builder.h" @@ -153,10 +155,9 @@ void LinearAlgebraOp::AnalyzeInputs(OpKernelContext* context, const int col_dimension = input_rank - 1; const int64 num_rows = in.dim_size(row_dimension); const int64 num_cols = in.dim_size(col_dimension); - // TODO(rmlarsen): Use emplace_back when it is added to InlinedVector. Same - // in several places below. - input_matrix_shapes->push_back(TensorShape({num_rows, num_cols})); - inputs->push_back(&in); + input_matrix_shapes->emplace_back( + std::initializer_list({num_rows, num_cols})); + inputs->emplace_back(&in); } // Have the derived class validate that the inputs are as expected. ValidateInputMatrixShapes(context, *input_matrix_shapes); @@ -198,9 +199,7 @@ void LinearAlgebraOp::PrepareOutputs( // concatenated with the output_matrix_shape (if the output is not // scalar). output_tensor_shape = batch_shape; - for (int dim = 0; dim < output_matrix_shape.dims(); ++dim) { - output_tensor_shape.AddDim(output_matrix_shape.dim_size(dim)); - } + output_tensor_shape.AppendShape(output_matrix_shape); } Tensor* out = nullptr; // See if there is an input buffer we can reuse for this output. @@ -219,7 +218,7 @@ void LinearAlgebraOp::PrepareOutputs( OP_REQUIRES_OK(context, context->allocate_output( output_idx, output_tensor_shape, &out)); } - outputs->push_back(out); + outputs->emplace_back(out); } } @@ -232,11 +231,10 @@ void LinearAlgebraOp::ComputeTensorSlice( for (size_t i = 0; i < inputs.size(); ++i) { // TODO(kalakris): Handle alignment if possible. Eigen::Map is // unaligned by default. - matrix_inputs.push_back( - ConstMatrixMap(inputs[i]->flat().data() + - matrix_index * input_matrix_shapes[i].num_elements(), - input_matrix_shapes[i].dim_size(0), - input_matrix_shapes[i].dim_size(1))); + matrix_inputs.emplace_back( + inputs[i]->flat().data() + + matrix_index * input_matrix_shapes[i].num_elements(), + input_matrix_shapes[i].dim_size(0), input_matrix_shapes[i].dim_size(1)); } MatrixMaps matrix_outputs; @@ -248,10 +246,10 @@ void LinearAlgebraOp::ComputeTensorSlice( int num_output_cols = output_matrix_shapes[i].dims() == 2 ? output_matrix_shapes[i].dim_size(1) : 1; - matrix_outputs.push_back( - MatrixMap(outputs[i]->flat().data() + - matrix_index * output_matrix_shapes[i].num_elements(), - num_output_rows, num_output_cols)); + matrix_outputs.emplace_back( + outputs[i]->flat().data() + + matrix_index * output_matrix_shapes[i].num_elements(), + num_output_rows, num_output_cols); } ComputeMatrix(context, matrix_inputs, &matrix_outputs); } diff --git a/tensorflow/core/kernels/linalg_ops_common.h b/tensorflow/core/kernels/linalg_ops_common.h index fcb735bfdb9..75d1d297934 100644 --- a/tensorflow/core/kernels/linalg_ops_common.h +++ b/tensorflow/core/kernels/linalg_ops_common.h @@ -21,10 +21,7 @@ limitations under the License. // computations across different threads if necessary. #include -#define EIGEN_USE_THREADS - #include "third_party/eigen3/Eigen/Core" -#include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor" #include "tensorflow/core/framework/kernel_def_builder.h" #include "tensorflow/core/framework/op_kernel.h" #include "tensorflow/core/framework/tensor.h" diff --git a/tensorflow/core/ops/math_ops.cc b/tensorflow/core/ops/math_ops.cc index 494358fec69..01b35064b21 100644 --- a/tensorflow/core/ops/math_ops.cc +++ b/tensorflow/core/ops/math_ops.cc @@ -731,6 +731,21 @@ The polygamma function is defined as: where \\(\psi(x)\\) is the digamma function. )doc"); +REGISTER_OP("Atan2") + .Input("y: T") + .Input("x: T") + .Output("z: T") + .Attr("T: {float, double}") + .SetShapeFn(shape_inference::BroadcastBinaryOpShapeFn) + .Doc(R"doc( +Computes arctangent of `y/x` element-wise, respecting signs of the arguments. +This is the angle \( \theta \in [-\pi, \pi] \) such that +\[ x = r \cos(\theta) \] +and +\[ y = r \sin(\theta) \] +where \(r = \sqrt(x^2 + y^2) \). +)doc"); + REGISTER_OP("Betainc") .Input("a: T") .Input("b: T") diff --git a/tensorflow/docs_src/community/documentation.md b/tensorflow/docs_src/community/documentation.md index be18d3e8be3..27b8c8d3026 100644 --- a/tensorflow/docs_src/community/documentation.md +++ b/tensorflow/docs_src/community/documentation.md @@ -4,12 +4,24 @@ We welcome contributions to the Tensorflow documentation from the community. This document explains how you can contribute to that documentation. In particular, this document explains the following: -- Where the documentation is located. -- How to make conformant edits. -- How to build and test your documentation changes before you submit them. +* Where the documentation is located. +* How to make conformant edits. +* How to build and test your documentation changes before you submit them. -You can view Tensorflow documentation on tensorflow.org, and you can view and -edit the raw files on Github. +You can view Tensorflow documentation on https://www.tensorflow.org, and you +can view and edit the raw files on Github. We're publishing our docs on Github +so everybody can contribute. Whatever gets checked in tensorflow/docs_src will +be published soon after on https://www.tensorflow.org. + +Republishing TensorFlow documentation in different forms is absolutely allowed, +but we are unlikely to accept other documentation formats (or the tooling to +generate them) into our repository. If you do choose to republish our +documentation in another form, please be sure to include: + +* The version of the API this represents (i.e. r1.0, master, etc.) +* The commit or version from which the documentation was generated +* Where to get the latest documentation (that is, https://www.tensorflow.org) +* The Apache 2.0 license. ## A Note on Versions diff --git a/tensorflow/docs_src/get_started/input_fn.md b/tensorflow/docs_src/get_started/input_fn.md index 74ed5fbebff..a053617b589 100644 --- a/tensorflow/docs_src/get_started/input_fn.md +++ b/tensorflow/docs_src/get_started/input_fn.md @@ -12,7 +12,7 @@ When training a neural network using tf.contrib.learn, it's possible to pass your feature and target data directly into your `fit`, `evaluate`, or `predict` operations. Here's an example taken from the @{$tflearn$tf.contrib.learn quickstart tutorial}: -```py +```python training_set = tf.contrib.learn.datasets.base.load_csv_with_header( filename=IRIS_TRAINING, target_dtype=np.int, features_dtype=np.float32) test_set = tf.contrib.learn.datasets.base.load_csv_with_header( diff --git a/tensorflow/docs_src/install/install_linux.md b/tensorflow/docs_src/install/install_linux.md index 8ee31fe6922..e2f7ae6bf9d 100644 --- a/tensorflow/docs_src/install/install_linux.md +++ b/tensorflow/docs_src/install/install_linux.md @@ -166,7 +166,7 @@ Take the following steps to install TensorFlow with Virtualenv: virtualenv environment:
(tensorflow)$ pip3 install --upgrade \
-     https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-1.1.0rc2-cp34-cp34m-linux_x86_64.whl
+ https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-1.1.0-cp34-cp34m-linux_x86_64.whl If you encounter installation problems, see [Common Installation Problems](#common_installation_problems). @@ -271,7 +271,7 @@ take the following steps:
      $ sudo pip3 install --upgrade \
-     https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-1.1.0rc2-cp34-cp34m-linux_x86_64.whl
+     https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-1.1.0-cp34-cp34m-linux_x86_64.whl
      
If this step fails, see @@ -458,7 +458,7 @@ Take the following steps to install TensorFlow in an Anaconda environment:
      (tensorflow)$ pip install --ignore-installed --upgrade \
-     https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-1.1.0rc2-cp34-cp34m-linux_x86_64.whl
+ https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-1.1.0-cp34-cp34m-linux_x86_64.whl @@ -626,14 +626,14 @@ This section documents the relevant values for Linux installations. CPU only:
-https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-1.1.0rc2-cp27-none-linux_x86_64.whl
+https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-1.1.0-cp27-none-linux_x86_64.whl
 
GPU support:
-https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-1.1.0rc2-cp27-none-linux_x86_64.whl
+https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-1.1.0-cp27-none-linux_x86_64.whl
 
Note that GPU support requires the NVIDIA hardware and software described in @@ -645,14 +645,14 @@ Note that GPU support requires the NVIDIA hardware and software described in CPU only:
-https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-1.1.0rc2-cp34-cp34m-linux_x86_64.whl
+https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-1.1.0-cp34-cp34m-linux_x86_64.whl
 
GPU support:
-https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-1.1.0rc2-cp34-cp34m-linux_x86_64.whl
+https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-1.1.0-cp34-cp34m-linux_x86_64.whl
 
Note that GPU support requires the NVIDIA hardware and software described in @@ -664,14 +664,14 @@ Note that GPU support requires the NVIDIA hardware and software described in CPU only:
-https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-1.1.0rc2-cp35-cp35m-linux_x86_64.whl
+https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-1.1.0-cp35-cp35m-linux_x86_64.whl
 
GPU support:
-https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-1.1.0rc2-cp35-cp35m-linux_x86_64.whl
+https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-1.1.0-cp35-cp35m-linux_x86_64.whl
 
@@ -683,14 +683,14 @@ Note that GPU support requires the NVIDIA hardware and software described in CPU only:
-https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-1.1.0rc2-cp36-cp36m-linux_x86_64.whl
+https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-1.1.0-cp36-cp36m-linux_x86_64.whl
 
GPU support:
-https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-1.1.0rc2-cp36-cp36m-linux_x86_64.whl
+https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-1.1.0-cp36-cp36m-linux_x86_64.whl
 
diff --git a/tensorflow/docs_src/install/install_mac.md b/tensorflow/docs_src/install/install_mac.md index b6a5758afec..73e143b145b 100644 --- a/tensorflow/docs_src/install/install_mac.md +++ b/tensorflow/docs_src/install/install_mac.md @@ -112,7 +112,7 @@ Take the following steps to install TensorFlow with Virtualenv: https://storage.googleapis.com/tensorflow/mac/cpu/tensorflow-1.1.0rc2-py2-none-any.whl If you encounter installation problems, see -[Common Installation Problems](#CommonInstallationProblems). +[Common Installation Problems](#common-installation-problems). ### Next Steps @@ -233,7 +233,7 @@ take the following steps: https://storage.googleapis.com/tensorflow/mac/cpu/tensorflow-1.1.0rc2-py2-none-any.whl If the preceding command fails, see - [Common installation problems](#CommonInstallationProblems). + [installation problems](#common-installation-problems). diff --git a/tensorflow/docs_src/install/install_sources.md b/tensorflow/docs_src/install/install_sources.md index 88268ba62f8..8dd7870faa5 100644 --- a/tensorflow/docs_src/install/install_sources.md +++ b/tensorflow/docs_src/install/install_sources.md @@ -320,10 +320,10 @@ Invoke `pip install` to install that pip package. The filename of the `.whl` file depends on your platform. For example, the following command will install the pip package -for TensorFlow 1.1.0rc2 on Linux: +for TensorFlow 1.1.0 on Linux:
-$ sudo pip install /tmp/tensorflow_pkg/tensorflow-1.1.0rc2-py2-none-any.whl
+$ sudo pip install /tmp/tensorflow_pkg/tensorflow-1.1.0-py2-none-any.whl
 
## Validate your installation diff --git a/tensorflow/docs_src/install/install_windows.md b/tensorflow/docs_src/install/install_windows.md index 5f7c27c0282..db7c661aa13 100644 --- a/tensorflow/docs_src/install/install_windows.md +++ b/tensorflow/docs_src/install/install_windows.md @@ -103,7 +103,7 @@ Take the following steps to install TensorFlow in an Anaconda environment: 2. Create a conda environment named tensorflow by invoking the following command: -
C:\> conda create -n tensorflow 
+
C:\> conda create -n tensorflow python=3.5 
3. Activate the conda environment by issuing the following command: @@ -114,12 +114,12 @@ Take the following steps to install TensorFlow in an Anaconda environment: environment. To install the CPU-only version of TensorFlow, enter the following command: -
(tensorflow)C:\> pip install --ignore-installed --upgrade https://storage.googleapis.com/tensorflow/windows/cpu/tensorflow-1.1.0rc2-cp35-cp35m-win_amd64.whl 
+
(tensorflow)C:\> pip install --ignore-installed --upgrade https://storage.googleapis.com/tensorflow/windows/cpu/tensorflow-1.1.0-cp35-cp35m-win_amd64.whl 
To install the GPU version of TensorFlow, enter the following command (on a single line): -
(tensorflow)C:\> pip install --ignore-installed --upgrade https://storage.googleapis.com/tensorflow/windows/gpu/tensorflow_gpu-1.1.0rc2-cp35-cp35m-win_amd64.whl 
+
(tensorflow)C:\> pip install --ignore-installed --upgrade https://storage.googleapis.com/tensorflow/windows/gpu/tensorflow_gpu-1.1.0-cp35-cp35m-win_amd64.whl 
## Validate your installation @@ -193,5 +193,20 @@ ImportError: cannot import name 'descriptor'
No module named "pywrap_tensorflow"
+ + 42217532 + +
OpKernel ('op: "BestSplits" device_type: "CPU"') for unknown op: BestSplits
+ + + + + 43134753 + +
The TensorFlow library wasn't compiled to use SSE instructions
+ + + + diff --git a/tensorflow/examples/image_retraining/retrain.py b/tensorflow/examples/image_retraining/retrain.py index 5f4b6bed482..6c1b40b442b 100644 --- a/tensorflow/examples/image_retraining/retrain.py +++ b/tensorflow/examples/image_retraining/retrain.py @@ -369,9 +369,12 @@ def create_bottleneck_file(bottleneck_path, image_lists, label_name, index, if not gfile.Exists(image_path): tf.logging.fatal('File does not exist %s', image_path) image_data = gfile.FastGFile(image_path, 'rb').read() - bottleneck_values = run_bottleneck_on_image(sess, image_data, - jpeg_data_tensor, - bottleneck_tensor) + try: + bottleneck_values = run_bottleneck_on_image( + sess, image_data, jpeg_data_tensor, bottleneck_tensor) + except: + raise RuntimeError('Error during processing file %s' % image_path) + bottleneck_string = ','.join(str(x) for x in bottleneck_values) with open(bottleneck_path, 'w') as bottleneck_file: bottleneck_file.write(bottleneck_string) diff --git a/tensorflow/python/estimator/estimator_test.py b/tensorflow/python/estimator/estimator_test.py index b8064f0a776..5d9913d734d 100644 --- a/tensorflow/python/estimator/estimator_test.py +++ b/tensorflow/python/estimator/estimator_test.py @@ -54,6 +54,7 @@ from tensorflow.python.platform import test from tensorflow.python.platform import tf_logging as logging from tensorflow.python.saved_model import loader from tensorflow.python.saved_model import tag_constants +from tensorflow.python.summary.writer import writer_cache from tensorflow.python.training import checkpoint_state_pb2 from tensorflow.python.training import saver from tensorflow.python.training import saver_test_utils @@ -436,8 +437,12 @@ class EstimatorTrainTest(test.TestCase): model_fn=model_fn_global_step_incrementer) est1.train(dummy_input_fn, steps=5) + # We have to clear the cache before we can rename the directory, + # otherwise open file handles will prevent the delete on Windows. + writer_cache.FileWriterCache.clear() model_dir2 = os.path.join(tmpdir, 'model_dir2') os.renames(model_dir1, model_dir2) + est2 = estimator.Estimator( model_dir=model_dir2, model_fn=model_fn_global_step_incrementer) diff --git a/tensorflow/python/framework/ops.py b/tensorflow/python/framework/ops.py index 05972022d03..0b04904ec23 100644 --- a/tensorflow/python/framework/ops.py +++ b/tensorflow/python/framework/ops.py @@ -2705,11 +2705,11 @@ class Graph(object): Args: name: The key for the collection. For example, the `GraphKeys` class contains many standard names for collections. - scope: (Optional.) If supplied, the resulting list is filtered to include - only items whose `name` attribute matches using `re.match`. Items - without a `name` attribute are never returned if a scope is supplied and - the choice or `re.match` means that a `scope` without special tokens - filters by prefix. + scope: (Optional.) A string. If supplied, the resulting list is filtered + to include only items whose `name` attribute matches `scope` using + `re.match`. Items without a `name` attribute are never returned if a + scope is supplied. The choice of `re.match` means that a `scope` without + special tokens filters by prefix. Returns: The list of values in the collection with the given `name`, or diff --git a/tensorflow/python/kernel_tests/cwise_ops_test.py b/tensorflow/python/kernel_tests/cwise_ops_test.py index cd0d33ecf35..0846470abc6 100644 --- a/tensorflow/python/kernel_tests/cwise_ops_test.py +++ b/tensorflow/python/kernel_tests/cwise_ops_test.py @@ -615,6 +615,13 @@ class BinaryOpTest(test.TestCase): self._compareBoth(x, y, np.multiply, _MUL) self._compareBoth(x, y + 0.1, np.true_divide, _TRUEDIV) self._compareBoth(x, y + 0.1, np.floor_divide, _FLOORDIV) + self._compareBoth(x, y, np.arctan2, math_ops.atan2) + x1 = np.random.randn(5, 6).astype(np.float32) + x2 = np.random.randn(5, 6).astype(np.float32) + # Remove tiny values--atan2 gradients are flaky near the origin. + x1[np.abs(x1) < 0.05] = 0.05 * np.sign(x1[np.abs(x1) < 0.05]) + x2[np.abs(x2) < 0.05] = 0.05 * np.sign(x2[np.abs(x2) < 0.05]) + self._compareBoth(x1, x2, np.arctan2, math_ops.atan2) try: from scipy import special # pylint: disable=g-import-not-at-top a_pos_small = np.linspace(0.1, 2, 15).reshape(1, 3, 5).astype(np.float32) @@ -672,6 +679,13 @@ class BinaryOpTest(test.TestCase): self._compareBoth(x, y, np.multiply, _MUL) self._compareBoth(x, y + 0.1, np.true_divide, _TRUEDIV) self._compareBoth(x, y + 0.1, np.floor_divide, _FLOORDIV) + self._compareBoth(x, y, np.arctan2, math_ops.atan2) + x1 = np.random.randn(7, 4).astype(np.float64) + x2 = np.random.randn(7, 4).astype(np.float64) + # Remove tiny values--atan2 gradients are flaky near the origin. + x1[np.abs(x1) < 0.5] = 0.5 * np.sign(x1[np.abs(x1) < 0.5]) + x2[np.abs(x2) < 0.5] = 0.5 * np.sign(x2[np.abs(x2) < 0.5]) + self._compareBoth(x1, x2, np.arctan2, math_ops.atan2) try: from scipy import special # pylint: disable=g-import-not-at-top a_pos_small = np.linspace(0.1, 2, 15).reshape(1, 3, 5).astype(np.float32) @@ -1090,6 +1104,19 @@ class BinaryOpTest(test.TestCase): error = gradient_checker.compute_gradient_error(y, [], z, []) self.assertLess(error, 2e-4) + def testAtan2SpecialValues(self): + x1l, x2l = zip((+0.0, +0.0), (+0.0, -0.0), (-0.0, +0.0), (-0.0, -0.0), + (1.2345, float("inf")), (1.2345, -float("inf")), + (-4.321, float("inf")), (-4.125, -float("inf")), + (float("inf"), float("inf")), (float("inf"), -float("inf")), + (-float("inf"), float("inf")), (-float("inf"), + -float("inf"))) + for dtype in np.float32, np.float64: + x1 = np.array(x1l).astype(dtype) + x2 = np.array(x2l).astype(dtype) + self._compareCpu(x1, x2, np.arctan2, math_ops.atan2) + self._compareGpu(x1, x2, np.arctan2, math_ops.atan2) + class ComparisonOpTest(test.TestCase): diff --git a/tensorflow/python/kernel_tests/tensor_priority_test.py b/tensorflow/python/kernel_tests/tensor_priority_test.py new file mode 100644 index 00000000000..574538a837a --- /dev/null +++ b/tensorflow/python/kernel_tests/tensor_priority_test.py @@ -0,0 +1,86 @@ +# Copyright 2015 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for the binary ops priority mechanism.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np + +from tensorflow.python.framework import ops +from tensorflow.python.platform import test as test_lib + + +class TensorPriorityTest(test_lib.TestCase): + + def testSupportedRhsWithoutDelegation(self): + + class NumpyArraySubclass(np.ndarray): + pass + + supported_rhs_without_delegation = (3, 3.0, [1.0, 2.0], np.array( + [1.0, 2.0]), NumpyArraySubclass( + shape=(1, 2), buffer=np.array([1.0, 2.0])), + ops.convert_to_tensor([[1.0, 2.0]])) + for rhs in supported_rhs_without_delegation: + tensor = ops.convert_to_tensor([[10.0, 20.0]]) + res = tensor + rhs + self.assertIsInstance(res, ops.Tensor) + + def testUnsupportedRhsWithoutDelegation(self): + + class WithoutReverseAdd(object): + pass + + tensor = ops.convert_to_tensor([[10.0, 20.0]]) + rhs = WithoutReverseAdd() + with self.assertRaisesWithPredicateMatch( + TypeError, lambda e: "Expected float" in str(e)): + # pylint: disable=pointless-statement + tensor + rhs + + def testUnsupportedRhsWithDelegation(self): + + class WithReverseAdd(object): + + def __radd__(self, lhs): + return "Works!" + + tensor = ops.convert_to_tensor([[10.0, 20.0]]) + rhs = WithReverseAdd() + res = tensor + rhs + self.assertEqual(res, "Works!") + + def testFullDelegationControlUsingRegistry(self): + + class NumpyArraySubclass(np.ndarray): + + def __radd__(self, lhs): + return "Works!" + + def raise_to_delegate(value, dtype=None, name=None, as_ref=False): + del value, dtype, name, as_ref # Unused. + raise TypeError + + ops.register_tensor_conversion_function( + NumpyArraySubclass, raise_to_delegate, priority=0) + tensor = ops.convert_to_tensor([[10.0, 20.0]]) + rhs = NumpyArraySubclass(shape=(1, 2), buffer=np.array([1.0, 2.0])) + res = tensor + rhs + self.assertEqual(res, "Works!") + + +if __name__ == "__main__": + test_lib.main() diff --git a/tensorflow/python/layers/convolutional.py b/tensorflow/python/layers/convolutional.py index b2fe9feb442..938161f426a 100644 --- a/tensorflow/python/layers/convolutional.py +++ b/tensorflow/python/layers/convolutional.py @@ -972,7 +972,7 @@ def separable_conv2d(inputs, class Conv2DTranspose(Conv2D): - """Transposed convolution layer (sometimes called Deconvolution). + """Transposed 2D convolution layer (sometimes called 2D Deconvolution). The need for transposed convolutions generally arises from the desire to use a transformation going in the opposite direction @@ -1086,19 +1086,9 @@ class Conv2DTranspose(Conv2D): kernel_h, kernel_w = self.kernel_size stride_h, stride_w = self.strides - def get_deconv_dim(dim_size, stride_size, kernel_size, padding): - if isinstance(dim_size, ops.Tensor): - dim_size = math_ops.multiply(dim_size, stride_size) - elif dim_size is not None: - dim_size *= stride_size - - if padding == 'valid' and dim_size is not None: - dim_size += max(kernel_size - stride_size, 0) - return dim_size - # Infer the dynamic output shape: - out_height = get_deconv_dim(height, stride_h, kernel_h, self.padding) - out_width = get_deconv_dim(width, stride_w, kernel_w, self.padding) + out_height = utils.get_deconv_dim(height, stride_h, kernel_h, self.padding) + out_width = utils.get_deconv_dim(width, stride_w, kernel_w, self.padding) if self.data_format == 'channels_first': output_shape = (batch_size, self.filters, out_height, out_width) @@ -1119,10 +1109,10 @@ class Conv2DTranspose(Conv2D): # Infer the static output shape: out_shape = inputs.get_shape().as_list() out_shape[c_axis] = self.filters - out_shape[h_axis] = get_deconv_dim( - out_shape[h_axis], stride_h, kernel_h, self.padding) - out_shape[w_axis] = get_deconv_dim( - out_shape[w_axis], stride_w, kernel_w, self.padding) + out_shape[h_axis] = utils.get_deconv_dim(out_shape[h_axis], stride_h, + kernel_h, self.padding) + out_shape[w_axis] = utils.get_deconv_dim(out_shape[w_axis], stride_w, + kernel_w, self.padding) outputs.set_shape(out_shape) if self.bias: @@ -1152,7 +1142,7 @@ def conv2d_transpose(inputs, trainable=True, name=None, reuse=None): - """Transposed convolution layer (sometimes called Deconvolution). + """Functional interface for transposed 2D convolution layer. The need for transposed convolutions generally arises from the desire to use a transformation going in the opposite direction @@ -1177,12 +1167,12 @@ def conv2d_transpose(inputs, `channels_last` corresponds to inputs with shape `(batch, height, width, channels)` while `channels_first` corresponds to inputs with shape `(batch, channels, height, width)`. - activation: Activation function. Set it to None to maintain a + activation: Activation function. Set it to `None` to maintain a linear activation. use_bias: Boolean, whether the layer uses a bias. kernel_initializer: An initializer for the convolution kernel. - bias_initializer: An initializer for the bias vector. If None, no bias will - be applied. + bias_initializer: An initializer for the bias vector. If `None`, then no + bias will be applied. kernel_regularizer: Optional regularizer for the convolution kernel. bias_regularizer: Optional regularizer for the bias vector. activity_regularizer: Regularizer function for the output. @@ -1215,6 +1205,250 @@ def conv2d_transpose(inputs, return layer.apply(inputs) +class Conv3DTranspose(Conv3D): + """Transposed 3D convolution layer (sometimes called 3D Deconvolution). + + Arguments: + filters: Integer, the dimensionality of the output space (i.e. the number + of filters in the convolution). + kernel_size: An integer or tuple/list of 3 integers, specifying the + depth, height and width of the 3D convolution window. + Can be a single integer to specify the same value for all spatial + dimensions. + strides: An integer or tuple/list of 3 integers, specifying the strides + of the convolution along the depth, height and width. + Can be a single integer to specify the same value for all spatial + dimensions. + padding: One of `"valid"` or `"same"` (case-insensitive). + data_format: A string, one of `channels_last` (default) or `channels_first`. + The ordering of the dimensions in the inputs. + `channels_last` corresponds to inputs with shape + `(batch, depth, height, width, channels)` while `channels_first` + corresponds to inputs with shape + `(batch, channels, depth, height, width)`. + activation: Activation function. Set it to `None` to maintain a + linear activation. + use_bias: Boolean, whether the layer uses a bias. + kernel_initializer: An initializer for the convolution kernel. + bias_initializer: An initializer for the bias vector. If `None`, then no + bias will be applied. + kernel_regularizer: Optional regularizer for the convolution kernel. + bias_regularizer: Optional regularizer for the bias vector. + activity_regularizer: Regularizer function for the output. + trainable: Boolean, if `True` also add variables to the graph collection + `GraphKeys.TRAINABLE_VARIABLES` (see `tf.Variable`). + name: A string, the name of the layer. + """ + + def __init__(self, + filters, + kernel_size, + strides=(1, 1, 1), + padding='valid', + data_format='channels_last', + activation=None, + use_bias=True, + kernel_initializer=None, + bias_initializer=init_ops.zeros_initializer(), + kernel_regularizer=None, + bias_regularizer=None, + activity_regularizer=None, + trainable=True, + name=None, + **kwargs): + super(Conv3DTranspose, self).__init__( + filters=filters, + kernel_size=kernel_size, + strides=strides, + padding=padding, + data_format=data_format, + activation=activation, + use_bias=use_bias, + kernel_initializer=kernel_initializer, + bias_initializer=bias_initializer, + kernel_regularizer=kernel_regularizer, + bias_regularizer=bias_regularizer, + activity_regularizer=activity_regularizer, + trainable=trainable, + name=name, + **kwargs) + + def build(self, input_shape): + if len(input_shape) != 5: + raise ValueError('Inputs should have rank 5, received input shape:', + str(input_shape)) + if self.data_format == 'channels_first': + channel_axis = 1 + else: + channel_axis = -1 + if input_shape[channel_axis] is None: + raise ValueError('The channel dimension of the inputs ' + 'should be defined, found None: ' + str(input_shape)) + input_dim = input_shape[channel_axis] + kernel_shape = self.kernel_size + (self.filters, input_dim) + + self.kernel = self.add_variable( + 'kernel', + shape=kernel_shape, + initializer=self.kernel_initializer, + regularizer=self.kernel_regularizer, + trainable=True, + dtype=self.dtype) + if self.use_bias: + self.bias = self.add_variable( + 'bias', + shape=(self.filters,), + initializer=self.bias_initializer, + regularizer=self.bias_regularizer, + trainable=True, + dtype=self.dtype) + else: + self.bias = None + + def call(self, inputs): + inputs_shape = array_ops.shape(inputs) + batch_size = inputs_shape[0] + if self.data_format == 'channels_first': + c_axis, d_axis, h_axis, w_axis = 1, 2, 3, 4 + else: + c_axis, d_axis, h_axis, w_axis = 4, 1, 2, 3 + + depth = inputs_shape[d_axis] + height = inputs_shape[h_axis] + width = inputs_shape[w_axis] + + kernel_d, kernel_h, kernel_w = self.kernel_size + stride_d, stride_h, stride_w = self.strides + + # Infer the dynamic output shape: + out_depth = utils.get_deconv_dim(depth, stride_d, kernel_d, self.padding) + out_height = utils.get_deconv_dim(height, stride_h, kernel_h, self.padding) + out_width = utils.get_deconv_dim(width, stride_w, kernel_w, self.padding) + + if self.data_format == 'channels_first': + output_shape = (batch_size, self.filters, out_depth, out_height, + out_width) + strides = (1, 1, stride_d, stride_h, stride_w) + else: + output_shape = (batch_size, out_depth, out_height, out_width, + self.filters) + strides = (1, stride_d, stride_h, stride_w, 1) + + output_shape_tensor = array_ops.stack(output_shape) + outputs = nn.conv3d_transpose( + inputs, + self.kernel, + output_shape_tensor, + strides, + data_format=utils.convert_data_format(self.data_format, ndim=5), + padding=self.padding.upper()) + + # Infer the static output shape: + out_shape = inputs.get_shape().as_list() + out_shape[c_axis] = self.filters + out_shape[d_axis] = utils.get_deconv_dim(out_shape[d_axis], stride_d, + kernel_d, self.padding) + out_shape[h_axis] = utils.get_deconv_dim(out_shape[h_axis], stride_h, + kernel_h, self.padding) + out_shape[w_axis] = utils.get_deconv_dim(out_shape[w_axis], stride_w, + kernel_w, self.padding) + outputs.set_shape(out_shape) + + if self.bias: + outputs_shape = outputs.shape.as_list() + if self.data_format == 'channels_first': + outputs_4d = array_ops.reshape(outputs, [ + outputs_shape[0], outputs_shape[1], + outputs_shape[2] * outputs_shape[3], outputs_shape[4] + ]) + else: + outputs_4d = array_ops.reshape(outputs, [ + outputs_shape[0], outputs_shape[1] * outputs_shape[2], + outputs_shape[3], outputs_shape[4] + ]) + outputs_4d = nn.bias_add( + outputs_4d, + self.bias, + data_format=utils.convert_data_format(self.data_format, ndim=4)) + outputs = array_ops.reshape(outputs_4d, outputs_shape) + + if self.activation is not None: + return self.activation(outputs) + return outputs + + +def conv3d_transpose(inputs, + filters, + kernel_size, + strides=(1, 1, 1), + padding='valid', + data_format='channels_last', + activation=None, + use_bias=True, + kernel_initializer=None, + bias_initializer=init_ops.zeros_initializer(), + kernel_regularizer=None, + bias_regularizer=None, + activity_regularizer=None, + trainable=True, + name=None, + reuse=None): + """Functional interface for transposed 3D convolution layer. + + Arguments: + inputs: Input tensor. + filters: Integer, the dimensionality of the output space (i.e. the number + of filters in the convolution). + kernel_size: A tuple or list of 3 positive integers specifying the spatial + dimensions of of the filters. Can be a single integer to specify the same + value for all spatial dimensions. + strides: A tuple or list of 3 positive integers specifying the strides + of the convolution. Can be a single integer to specify the same value for + all spatial dimensions. + padding: one of `"valid"` or `"same"` (case-insensitive). + data_format: A string, one of `channels_last` (default) or `channels_first`. + The ordering of the dimensions in the inputs. + `channels_last` corresponds to inputs with shape + `(batch, height, width, channels)` while `channels_first` corresponds to + inputs with shape `(batch, channels, height, width)`. + activation: Activation function. Set it to None to maintain a + linear activation. + use_bias: Boolean, whether the layer uses a bias. + kernel_initializer: An initializer for the convolution kernel. + bias_initializer: An initializer for the bias vector. If None, no bias will + be applied. + kernel_regularizer: Optional regularizer for the convolution kernel. + bias_regularizer: Optional regularizer for the bias vector. + activity_regularizer: Regularizer function for the output. + trainable: Boolean, if `True` also add variables to the graph collection + `GraphKeys.TRAINABLE_VARIABLES` (see `tf.Variable`). + name: A string, the name of the layer. + reuse: Boolean, whether to reuse the weights of a previous layer + by the same name. + + Returns: + Output tensor. + """ + layer = Conv3DTranspose( + filters=filters, + kernel_size=kernel_size, + strides=strides, + padding=padding, + data_format=data_format, + activation=activation, + use_bias=use_bias, + kernel_initializer=kernel_initializer, + bias_initializer=bias_initializer, + kernel_regularizer=kernel_regularizer, + bias_regularizer=bias_regularizer, + activity_regularizer=activity_regularizer, + trainable=trainable, + name=name, + _reuse=reuse, + _scope=name) + return layer.apply(inputs) + + # Aliases Convolution1D = Conv1D @@ -1222,8 +1456,10 @@ Convolution2D = Conv2D Convolution3D = Conv3D SeparableConvolution2D = SeparableConv2D Convolution2DTranspose = Deconvolution2D = Deconv2D = Conv2DTranspose +Convolution3DTranspose = Deconvolution3D = Deconv3D = Conv3DTranspose convolution1d = conv1d convolution2d = conv2d convolution3d = conv3d separable_convolution2d = separable_conv2d convolution2d_transpose = deconvolution2d = deconv2d = conv2d_transpose +convolution3d_transpose = deconvolution3d = deconv3d = conv3d_transpose diff --git a/tensorflow/python/layers/convolutional_test.py b/tensorflow/python/layers/convolutional_test.py index da962b2f99e..42a2d775349 100644 --- a/tensorflow/python/layers/convolutional_test.py +++ b/tensorflow/python/layers/convolutional_test.py @@ -651,5 +651,174 @@ class Conv2DTransposeTest(test.TestCase): self.assertEqual(len(variables.trainable_variables()), 4) +class Conv3DTransposeTest(test.TestCase): + + def testInvalidDataFormat(self): + depth, height, width = 5, 7, 9 + volumes = random_ops.random_uniform((5, depth, height, width, 32), seed=1) + with self.assertRaisesRegexp(ValueError, 'data_format'): + conv_layers.conv3d_transpose(volumes, 4, 3, data_format='invalid') + + def testInvalidStrides(self): + depth, height, width = 5, 7, 9 + volumes = random_ops.random_uniform((5, depth, height, width, 32), seed=1) + with self.assertRaisesRegexp(ValueError, 'strides'): + conv_layers.conv3d_transpose(volumes, 4, 3, strides=(1, 2)) + + with self.assertRaisesRegexp(ValueError, 'strides'): + conv_layers.conv3d_transpose(volumes, 4, 3, strides=None) + + def testInvalidKernelSize(self): + depth, height, width = 5, 7, 9 + volumes = random_ops.random_uniform((5, depth, height, width, 32), seed=1) + with self.assertRaisesRegexp(ValueError, 'kernel_size'): + conv_layers.conv3d_transpose(volumes, 4, (1, 2)) + + with self.assertRaisesRegexp(ValueError, 'kernel_size'): + conv_layers.conv3d_transpose(volumes, 4, None) + + def testCreateConv3DTranspose(self): + depth, height, width = 5, 7, 9 + volumes = random_ops.random_uniform((5, depth, height, width, 32)) + layer = conv_layers.Conv3DTranspose(4, [3, 3, 3], activation=nn_ops.relu) + output = layer.apply(volumes) + self.assertEqual(output.op.name, 'conv3d_transpose/Relu') + self.assertListEqual(output.get_shape().as_list(), + [5, depth + 2, height + 2, width + 2, 4]) + self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 3, 3, 4, 32]) + self.assertListEqual(layer.bias.get_shape().as_list(), [4]) + + def testCreateConv3DTransposeIntegerKernelSize(self): + depth, height, width = 5, 7, 9 + volumes = random_ops.random_uniform((5, depth, height, width, 32)) + layer = conv_layers.Conv3DTranspose(4, 3) + output = layer.apply(volumes) + self.assertListEqual(output.get_shape().as_list(), + [5, depth + 2, height + 2, width + 2, 4]) + self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 3, 3, 4, 32]) + self.assertListEqual(layer.bias.get_shape().as_list(), [4]) + + def testCreateConv3DTransposeChannelsFirst(self): + depth, height, width = 5, 7, 9 + volumes = random_ops.random_uniform((5, 32, depth, height, width)) + layer = conv_layers.Conv3DTranspose( + 4, [3, 3, 3], data_format='channels_first') + output = layer.apply(volumes) + self.assertListEqual(output.get_shape().as_list(), + [5, 4, depth + 2, height + 2, width + 2]) + self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 3, 3, 4, 32]) + self.assertListEqual(layer.bias.get_shape().as_list(), [4]) + + def testConv3DTransposePaddingSame(self): + depth, height, width = 5, 7, 9 + volumes = random_ops.random_uniform((5, depth, height, width, 64), seed=1) + layer = conv_layers.Conv3DTranspose( + 32, volumes.get_shape()[1:4], padding='same') + output = layer.apply(volumes) + self.assertListEqual(output.get_shape().as_list(), + [5, depth, height, width, 32]) + + def testCreateConv3DTransposeWithStrides(self): + depth, height, width = 4, 6, 8 + # Test strides tuple. + volumes = random_ops.random_uniform((5, depth, height, width, 32), seed=1) + layer = conv_layers.Conv3DTranspose( + 4, [3, 3, 3], strides=(2, 2, 2), padding='same') + output = layer.apply(volumes) + self.assertListEqual(output.get_shape().as_list(), + [5, depth * 2, height * 2, width * 2, 4]) + + # Test strides integer. + layer = conv_layers.Conv3DTranspose(4, [3, 3, 3], strides=2, padding='same') + output = layer.apply(volumes) + self.assertListEqual(output.get_shape().as_list(), + [5, depth * 2, height * 2, width * 2, 4]) + + # Test unequal strides. + layer = conv_layers.Conv3DTranspose( + 4, [3, 3, 3], strides=(2, 1, 1), padding='same') + output = layer.apply(volumes) + self.assertListEqual(output.get_shape().as_list(), + [5, depth * 2, height, width, 4]) + + def testConv3DTransposeKernelRegularizer(self): + depth, height, width = 5, 7, 9 + volumes = random_ops.random_uniform((5, depth, height, width, 32)) + reg = lambda x: 0.1 * math_ops.reduce_sum(x) + layer = conv_layers.Conv3DTranspose(4, [3, 3, 3], kernel_regularizer=reg) + layer.apply(volumes) + loss_keys = ops.get_collection(ops.GraphKeys.REGULARIZATION_LOSSES) + self.assertEqual(len(loss_keys), 1) + self.assertListEqual(layer.losses, loss_keys) + + def testConv3DTransposeBiasRegularizer(self): + depth, height, width = 5, 7, 9 + volumes = random_ops.random_uniform((5, depth, height, width, 32)) + reg = lambda x: 0.1 * math_ops.reduce_sum(x) + layer = conv_layers.Conv3DTranspose(4, [3, 3, 3], bias_regularizer=reg) + layer.apply(volumes) + loss_keys = ops.get_collection(ops.GraphKeys.REGULARIZATION_LOSSES) + self.assertEqual(len(loss_keys), 1) + self.assertListEqual(layer.losses, loss_keys) + + def testConv3DTransposeNoBias(self): + depth, height, width = 5, 7, 9 + volumes = random_ops.random_uniform((5, depth, height, width, 32)) + layer = conv_layers.Conv3DTranspose( + 4, [3, 3, 3], activation=nn_ops.relu, use_bias=False) + output = layer.apply(volumes) + self.assertEqual(output.op.name, 'conv3d_transpose/Relu') + self.assertListEqual(output.get_shape().as_list(), + [5, depth + 2, height + 2, width + 2, 4]) + self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 3, 3, 4, 32]) + self.assertEqual(layer.bias, None) + + def testFunctionalConv3DTransposeReuse(self): + depth, height, width = 5, 7, 9 + volumes = random_ops.random_uniform((5, depth, height, width, 32), seed=1) + conv_layers.conv3d_transpose(volumes, 4, [3, 3, 3], name='deconv1') + self.assertEqual(len(variables.trainable_variables()), 2) + conv_layers.conv3d_transpose( + volumes, 4, [3, 3, 3], name='deconv1', reuse=True) + self.assertEqual(len(variables.trainable_variables()), 2) + + def testFunctionalConv3DTransposeReuseFromScope(self): + with variable_scope.variable_scope('scope'): + depth, height, width = 5, 7, 9 + volumes = random_ops.random_uniform((5, depth, height, width, 32), seed=1) + conv_layers.conv3d_transpose(volumes, 4, [3, 3, 3], name='deconv1') + self.assertEqual(len(variables.trainable_variables()), 2) + with variable_scope.variable_scope('scope', reuse=True): + conv_layers.conv3d_transpose(volumes, 4, [3, 3, 3], name='deconv1') + self.assertEqual(len(variables.trainable_variables()), 2) + + def testFunctionalConv3DTransposeInitializerFromScope(self): + with self.test_session() as sess: + with variable_scope.variable_scope( + 'scope', initializer=init_ops.ones_initializer()): + depth, height, width = 5, 7, 9 + volumes = random_ops.random_uniform( + (5, depth, height, width, 32), seed=1) + conv_layers.conv3d_transpose(volumes, 4, [3, 3, 3], name='deconv1') + weights = variables.trainable_variables() + # Check the names of weights in order. + self.assertTrue('kernel' in weights[0].name) + self.assertTrue('bias' in weights[1].name) + sess.run(variables.global_variables_initializer()) + weights = sess.run(weights) + # Check that the kernel weights got initialized to ones (from scope) + self.assertAllClose(weights[0], np.ones((3, 3, 3, 4, 32))) + # Check that the bias still got initialized to zeros. + self.assertAllClose(weights[1], np.zeros((4))) + + def testFunctionalConv3DTransposeNoReuse(self): + depth, height, width = 5, 7, 9 + volumes = random_ops.random_uniform((5, depth, height, width, 32), seed=1) + conv_layers.conv3d_transpose(volumes, 4, [3, 3, 3]) + self.assertEqual(len(variables.trainable_variables()), 2) + conv_layers.conv3d_transpose(volumes, 4, [3, 3, 3]) + self.assertEqual(len(variables.trainable_variables()), 4) + + if __name__ == '__main__': test.main() diff --git a/tensorflow/python/layers/layers.py b/tensorflow/python/layers/layers.py index 9f02757d5bc..aa46eb5d27d 100644 --- a/tensorflow/python/layers/layers.py +++ b/tensorflow/python/layers/layers.py @@ -23,6 +23,7 @@ @@conv3d @@separable_conv2d @@conv2d_transpose +@@conv3d_transpose @@average_pooling1d @@max_pooling1d @@average_pooling2d @@ -50,6 +51,7 @@ from tensorflow.python.layers.convolutional import conv2d from tensorflow.python.layers.convolutional import conv3d from tensorflow.python.layers.convolutional import separable_conv2d from tensorflow.python.layers.convolutional import conv2d_transpose +from tensorflow.python.layers.convolutional import conv3d_transpose # Pooling layers. from tensorflow.python.layers.pooling import average_pooling1d diff --git a/tensorflow/python/layers/utils.py b/tensorflow/python/layers/utils.py index 666d475690b..64b948c70f5 100644 --- a/tensorflow/python/layers/utils.py +++ b/tensorflow/python/layers/utils.py @@ -26,6 +26,7 @@ import numpy as np from tensorflow.python.ops import variables from tensorflow.python.ops import control_flow_ops +from tensorflow.python.ops import math_ops from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_util @@ -164,3 +165,28 @@ def constant_value(pred): else: raise TypeError('`pred` must be a Tensor, a Variable, or a Python bool.') return pred_value + + +def get_deconv_dim(dim_size, stride_size, kernel_size, padding): + """Return output dimension of a deconv layer, based on input dimension. + + Arguments: + dim_size: An int representing size of dimension, can be height, width + or depth. + stride_size: An int representing the stride of deconvolution filters + along the same dimension. + kernel_size: An int representing size of deconv kernel (filter) along + the same dimension. + padding: one of `"valid"` or `"same"` (case-insensitive). + + Returns: + An int representing the size of output dimension of the layer. + """ + if isinstance(dim_size, ops.Tensor): + dim_size = math_ops.multiply(dim_size, stride_size) + elif dim_size is not None: + dim_size *= stride_size + + if padding == 'valid' and dim_size is not None: + dim_size += max(kernel_size - stride_size, 0) + return dim_size diff --git a/tensorflow/python/layers/utils_test.py b/tensorflow/python/layers/utils_test.py index 54e757c112b..7969e957d8d 100644 --- a/tensorflow/python/layers/utils_test.py +++ b/tensorflow/python/layers/utils_test.py @@ -62,6 +62,13 @@ class ConvUtilsTest(test.TestCase): with self.assertRaises(ValueError): utils.normalize_padding('invalid') + def testGetDeconvDim(self): + self.assertEqual(utils.get_deconv_dim(30, 1, 3, 'valid'), 32) + self.assertEqual(utils.get_deconv_dim(28, 1, 5, 'valid'), 32) + self.assertEqual(utils.get_deconv_dim(28, 2, 5, 'valid'), 59) + self.assertEqual(utils.get_deconv_dim(32, 1, 3, 'same'), 32) + self.assertEqual(utils.get_deconv_dim(32, 1, 5, 'same'), 32) + self.assertEqual(utils.get_deconv_dim(32, 2, 5, 'same'), 64) if __name__ == '__main__': test.main() diff --git a/tensorflow/python/ops/array_ops.py b/tensorflow/python/ops/array_ops.py index 77db63dd0f8..5ac630c321c 100644 --- a/tensorflow/python/ops/array_ops.py +++ b/tensorflow/python/ops/array_ops.py @@ -470,7 +470,10 @@ def _SliceHelper(tensor, slice_spec, var=None): else: begin.append(s) end.append(s + 1) - strides.append(1) + if isinstance(s, ops.Tensor): + strides.append(constant(1, s.dtype)) + else: + strides.append(np.ones_like(s).dtype.type(1)) shrink_axis_mask |= (1 << index) index += 1 diff --git a/tensorflow/python/ops/ctc_ops.py b/tensorflow/python/ops/ctc_ops.py index b0a1fc3dd1b..ee5b2952f40 100644 --- a/tensorflow/python/ops/ctc_ops.py +++ b/tensorflow/python/ops/ctc_ops.py @@ -197,7 +197,7 @@ def ctc_greedy_decoder(inputs, sequence_length, merge_repeated=True): merge_repeated: Boolean. Default: True. Returns: - A tuple `(decoded, log_probabilities)` where + A tuple `(decoded, neg_sum_logits)` where decoded: A single-element list. `decoded[0]` is an `SparseTensor` containing the decoded outputs s.t.: `decoded.indices`: Indices matrix `(total_decoded_outputs x 2)`. @@ -206,8 +206,9 @@ def ctc_greedy_decoder(inputs, sequence_length, merge_repeated=True): The vector stores the decoded classes. `decoded.shape`: Shape vector, size `(2)`. The shape values are: `[batch_size, max_decoded_length]` - log_probability: A `float` matrix `(batch_size x 1)` containing sequence - log-probabilities. + neg_sum_logits: A `float` matrix `(batch_size x 1)` containing, for the + sequence found, the negative of the sum of the greatest logit at each + timeframe. """ outputs = gen_ctc_ops._ctc_greedy_decoder( inputs, sequence_length, merge_repeated=merge_repeated) diff --git a/tensorflow/python/ops/init_ops.py b/tensorflow/python/ops/init_ops.py index 67fff9c803b..42b4f952bbc 100644 --- a/tensorflow/python/ops/init_ops.py +++ b/tensorflow/python/ops/init_ops.py @@ -39,6 +39,7 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.ops import array_ops from tensorflow.python.ops import linalg_ops +from tensorflow.python.ops import math_ops from tensorflow.python.ops import random_ops @@ -487,16 +488,18 @@ class Orthogonal(Initializer): flat_shape = (num_rows, num_cols) # Generate a random matrix - a = random_ops.random_uniform(flat_shape, dtype=dtype, seed=self.seed) - # Compute the svd - _, u, v = linalg_ops.svd(a, full_matrices=False) - # Pick the appropriate singular value decomposition - if num_rows > num_cols: - q = u - else: - # Tensorflow departs from numpy conventions - # such that we need to transpose axes here - q = array_ops.transpose(v) + a = random_ops.random_normal(flat_shape, dtype=dtype, seed=self.seed) + # Compute the qr factorization + q, r = linalg_ops.qr(a, full_matrices=False) + # Make Q uniform + square_len = math_ops.minimum(num_rows, num_cols) + d = array_ops.diag_part(r[:square_len, :square_len]) + ph = d / math_ops.abs(d) + q *= ph + # Pad zeros to Q (if rows smaller than cols) + if num_rows < num_cols: + padding = array_ops.zeros([num_rows, num_cols - num_rows], dtype=dtype) + q = array_ops.concat([q, padding], 1) return self.gain * array_ops.reshape(q, shape) def get_config(self): diff --git a/tensorflow/python/ops/logging_ops.py b/tensorflow/python/ops/logging_ops.py index 9c49ef78896..dbb13e0c8f2 100644 --- a/tensorflow/python/ops/logging_ops.py +++ b/tensorflow/python/ops/logging_ops.py @@ -124,7 +124,7 @@ def image_summary(tag, tensor, max_images=3, collections=None, name=None): """Outputs a `Summary` protocol buffer with images. For an explanation of why this op was deprecated, and information on how to - migrate, look ['here'](https://www.tensorflow.org/code/tensorflow/contrib/deprecated/__init__.py) + migrate, look ['here'](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/deprecated/__init__.py) The summary has up to `max_images` summary values containing images. The images are built from `tensor` which must be 4-D with shape `[batch_size, diff --git a/tensorflow/python/ops/math_grad.py b/tensorflow/python/ops/math_grad.py index 409e3c5111e..024158e7097 100644 --- a/tensorflow/python/ops/math_grad.py +++ b/tensorflow/python/ops/math_grad.py @@ -613,6 +613,16 @@ def _AtanGrad(op, grad): return grad * inv +@ops.RegisterGradient("Atan2") +def _Atan2Grad(op, grad): + """Returns grad * x / (x^2 + y^2), grad * -y / (x^2 + y^2).""" + y = op.inputs[0] + x = op.inputs[1] + with ops.control_dependencies([grad.op]): + grad_inv = grad / (math_ops.square(x) + math_ops.square(y)) + return x * grad_inv, -y * grad_inv + + @ops.RegisterGradient("AddN") def _AddNGrad(op, grad): """Copies the gradient to all inputs.""" diff --git a/tensorflow/python/ops/math_ops.py b/tensorflow/python/ops/math_ops.py index 92e8723ced8..b762205cf70 100644 --- a/tensorflow/python/ops/math_ops.py +++ b/tensorflow/python/ops/math_ops.py @@ -56,6 +56,7 @@ See the @{$python/math_ops} guide. @@acos @@asin @@atan +@@atan2 @@lgamma @@digamma @@erf @@ -824,7 +825,16 @@ def _OverrideBinaryOperatorHelper(func, op_name, clazz_object=ops.Tensor): def binary_op_wrapper(x, y): with ops.name_scope(None, op_name, [x, y]) as name: if not isinstance(y, sparse_tensor.SparseTensor): - y = ops.convert_to_tensor(y, dtype=x.dtype.base_dtype, name="y") + try: + y = ops.convert_to_tensor(y, dtype=x.dtype.base_dtype, name="y") + except TypeError: + # If the RHS is not a tensor, it might be a tensor aware object + # that can implement the operator with knowledge of itself + # and the tensor. + if hasattr(type(y), "__r%s__" % op_name): + return NotImplemented + else: + raise return func(x, y, name=name) def binary_op_wrapper_sparse(sp_x, y): diff --git a/tensorflow/python/ops/nn_impl.py b/tensorflow/python/ops/nn_impl.py index 7c17cf2cb61..0a00e3d7650 100644 --- a/tensorflow/python/ops/nn_impl.py +++ b/tensorflow/python/ops/nn_impl.py @@ -301,9 +301,8 @@ def zero_fraction(value, name=None): This is useful in summaries to measure and report sparsity. For example, ```python - z = tf.Relu(...) - summ = tf.contrib.deprecated.scalar_summary('sparsity', - tf.nn.zero_fraction(z)) + z = tf.nn.relu(...) + summ = tf.summary.scalar('sparsity', tf.nn.zero_fraction(z)) ``` Args: diff --git a/tensorflow/python/ops/nn_ops.py b/tensorflow/python/ops/nn_ops.py index ccce9402c77..61fda3a7985 100644 --- a/tensorflow/python/ops/nn_ops.py +++ b/tensorflow/python/ops/nn_ops.py @@ -840,6 +840,11 @@ def pool(input, # pylint: disable=redefined-builtin def atrous_conv2d(value, filters, rate, padding, name=None): """Atrous convolution (a.k.a. convolution with holes or dilated convolution). + This function is a simpler wrapper around the more general + @{tf.nn.convolution}, and exists only for backwards compatibility. You can + use @{tf.nn.convolution} to perform 1-D, 2-D, or 3-D atrous convolution. + + Computes a 2-D atrous convolution, also known as convolution with holes or dilated convolution, given 4-D `value` and `filters` tensors. If the `rate` parameter is equal to one, it performs regular 2-D convolution. If the `rate` @@ -959,93 +964,12 @@ def atrous_conv2d(value, filters, rate, padding, name=None): ValueError: If input/output depth does not match `filters`' shape, or if padding is other than `'VALID'` or `'SAME'`. """ - with ops.name_scope(name, "atrous_conv2d", [value, filters]) as name: - value = ops.convert_to_tensor(value, name="value") - filters = ops.convert_to_tensor(filters, name="filters") - if not value.get_shape()[3].is_compatible_with(filters.get_shape()[2]): - raise ValueError( - "value's input channels does not match filters' input channels, " - "{} != {}".format(value.get_shape()[3], filters.get_shape()[2])) - if rate < 1: - raise ValueError("rate {} cannot be less than one".format(rate)) - - if rate == 1: - value = gen_nn_ops.conv2d(input=value, - filter=filters, - strides=[1, 1, 1, 1], - padding=padding) - return value - - # We have two padding contributions. The first is used for converting "SAME" - # to "VALID". The second is required so that the height and width of the - # zero-padded value tensor are multiples of rate. - - # Padding required to reduce to "VALID" convolution - if padding == "SAME": - # Handle filters whose shape is unknown during graph creation. - if filters.get_shape().is_fully_defined(): - filter_shape = filters.get_shape().as_list() - else: - filter_shape = array_ops.shape(filters) - filter_height, filter_width = filter_shape[0], filter_shape[1] - - # Spatial dimensions of the filters and the upsampled filters in which we - # introduce (rate - 1) zeros between consecutive filter values. - filter_height_up = filter_height + (filter_height - 1) * (rate - 1) - filter_width_up = filter_width + (filter_width - 1) * (rate - 1) - - pad_height = filter_height_up - 1 - pad_width = filter_width_up - 1 - - # When pad_height (pad_width) is odd, we pad more to bottom (right), - # following the same convention as conv2d(). - pad_top = pad_height // 2 - pad_bottom = pad_height - pad_top - pad_left = pad_width // 2 - pad_right = pad_width - pad_left - elif padding == "VALID": - pad_top = 0 - pad_bottom = 0 - pad_left = 0 - pad_right = 0 - else: - raise ValueError("Invalid padding") - - # Handle input whose shape is unknown during graph creation. - if value.get_shape().is_fully_defined(): - value_shape = value.get_shape().as_list() - else: - value_shape = array_ops.shape(value) - - in_height = value_shape[1] + pad_top + pad_bottom - in_width = value_shape[2] + pad_left + pad_right - - # More padding so that rate divides the height and width of the input. - pad_bottom_extra = (rate - in_height % rate) % rate - pad_right_extra = (rate - in_width % rate) % rate - - # The paddings argument to space_to_batch includes both padding components. - space_to_batch_pad = [[pad_top, pad_bottom + pad_bottom_extra], - [pad_left, pad_right + pad_right_extra]] - - value = array_ops.space_to_batch(input=value, - paddings=space_to_batch_pad, - block_size=rate) - - value = gen_nn_ops.conv2d(input=value, - filter=filters, - strides=[1, 1, 1, 1], - padding="VALID", - name=name) - - # The crops argument to batch_to_space is just the extra padding component. - batch_to_space_crop = [[0, pad_bottom_extra], [0, pad_right_extra]] - - value = array_ops.batch_to_space(input=value, - crops=batch_to_space_crop, - block_size=rate) - - return value + return convolution( + input=value, + filter=filters, + padding=padding, + dilation_rate=np.broadcast_to(rate, (2,)), + name=name) def conv2d_transpose(value, @@ -1272,7 +1196,7 @@ def conv3d_transpose(value, output_shape, strides, padding="SAME", - data_format=None, + data_format="NDHWC", name=None): """The transpose of `conv3d`. @@ -1308,10 +1232,11 @@ def conv3d_transpose(value, [value, filter, output_shape]) as name: value = ops.convert_to_tensor(value, name="value") filter = ops.convert_to_tensor(filter, name="filter") - if not value.get_shape()[4].is_compatible_with(filter.get_shape()[4]): + axis = 1 if data_format == "NCDHW" else 4 + if not value.get_shape()[axis].is_compatible_with(filter.get_shape()[4]): raise ValueError("input channels does not match filter's input channels, " - "{} != {}".format(value.get_shape()[4], filter.get_shape( - )[4])) + "{} != {}".format(value.get_shape()[axis], + filter.get_shape()[4])) output_shape_ = ops.convert_to_tensor(output_shape, name="output_shape") if not output_shape_.get_shape().is_compatible_with(tensor_shape.vector(5)): diff --git a/tensorflow/python/ops/parsing_ops.py b/tensorflow/python/ops/parsing_ops.py index b1994acdc4b..796ea20eb76 100644 --- a/tensorflow/python/ops/parsing_ops.py +++ b/tensorflow/python/ops/parsing_ops.py @@ -845,7 +845,7 @@ def parse_single_sequence_example( Parses a single serialized [`SequenceExample`](https://www.tensorflow.org/code/tensorflow/core/example/example.proto) proto given in `serialized`. - This op parses a serialize sequence example into a tuple of dictionaries + This op parses a serialized sequence example into a tuple of dictionaries mapping keys to `Tensor` and `SparseTensor` objects respectively. The first dictionary contains mappings for keys appearing in `context_features`, and the second dictionary contains mappings for keys diff --git a/tensorflow/python/ops/random_ops.py b/tensorflow/python/ops/random_ops.py index 19689622b14..f06980783a5 100644 --- a/tensorflow/python/ops/random_ops.py +++ b/tensorflow/python/ops/random_ops.py @@ -324,7 +324,7 @@ def multinomial(logits, num_samples, seed=None, name=None): Args: logits: 2-D Tensor with shape `[batch_size, num_classes]`. Each slice - `[i, :]` represents the unnormalized log probabilities for all classes. + `[i, :]` represents the log-odds for all classes. num_samples: 0-D. Number of independent samples to draw for each row slice. seed: A Python integer. Used to create a random seed for the distribution. See diff --git a/tensorflow/python/summary/writer/writer_cache.py b/tensorflow/python/summary/writer/writer_cache.py index 21870e788ef..bad289303c0 100644 --- a/tensorflow/python/summary/writer/writer_cache.py +++ b/tensorflow/python/summary/writer/writer_cache.py @@ -39,6 +39,10 @@ class FileWriterCache(object): def clear(): """Clear cached summary writers. Currently only used for unit tests.""" with FileWriterCache._lock: + # Make sure all the writers are closed now (otherwise open file handles + # may hang around, blocking deletions on Windows). + for item in FileWriterCache._cache.values(): + item.close() FileWriterCache._cache = {} @staticmethod diff --git a/tensorflow/python/tools/import_pb_to_tensorboard.py b/tensorflow/python/tools/import_pb_to_tensorboard.py new file mode 100644 index 00000000000..caeb04a24bf --- /dev/null +++ b/tensorflow/python/tools/import_pb_to_tensorboard.py @@ -0,0 +1,50 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ================================ +"""Imports a protobuf model as a graph in Tensorboard.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.core.framework import graph_pb2 +from tensorflow.python.client import session +from tensorflow.python.framework import importer +from tensorflow.python.framework import ops +from tensorflow.python.platform import gfile +from tensorflow.python.summary import summary + + +def import_to_tensorboard(model_dir, log_dir): + """View an imported protobuf model (`.pb` file) as a graph in Tensorboard. + + Args: + model_dir: The location of the protobuf (`pb`) model to visualize + log_dir: The location for the Tensorboard log to begin visualisation from. + + Usage: + Call this function with your model location and desired log directory. + Launch Tensorboard by pointing it to the log directory. + View your imported `.pb` model as a graph. + """ + with session.Session(graph=ops.Graph()) as sess: + with gfile.FastGFile(model_dir, "rb") as f: + graph_def = graph_pb2.GraphDef() + graph_def.ParseFromString(f.read()) + importer.import_graph_def(graph_def) + + pb_visual_writer = summary.FileWriter(log_dir) + pb_visual_writer.add_graph(sess.graph) + print("Model Imported. Visualize by running: " + "> tensorboard --logdir={}".format(log_dir)) diff --git a/tensorflow/python/training/checkpoint_utils.py b/tensorflow/python/training/checkpoint_utils.py index 35d1a069d8a..d52cf9a4367 100644 --- a/tensorflow/python/training/checkpoint_utils.py +++ b/tensorflow/python/training/checkpoint_utils.py @@ -59,14 +59,14 @@ def load_checkpoint(ckpt_dir_or_file): def load_variable(ckpt_dir_or_file, name): - """Returns a tensor with the contents of the given variable in the checkpoint. + """Returns the tensor value of the given variable in the checkpoint. Args: ckpt_dir_or_file: Directory with checkpoints file or path to checkpoint. - name: Name of the tensor to return. + name: Name of the variable to return. Returns: - `Tensor` object. + A numpy `ndarray` with a copy of the value of this variable. """ # TODO(b/29227106): Fix this in the right place and remove this. if name.endswith(":0"): @@ -210,9 +210,8 @@ def init_from_checkpoint(ckpt_dir_or_file, assignment_map): else: var_name = ",".join([v.name for v in var]) _set_variable_or_list_initializer(var, ckpt_file, tensor_name_in_ckpt) - logging.info("Initialize variable %s from checkpoint %s with %s" % ( - var_name, ckpt_dir_or_file, tensor_name_in_ckpt - )) + logging.info("Initialize variable %s from checkpoint %s with %s", + var_name, ckpt_dir_or_file, tensor_name_in_ckpt) else: scopes = "" # TODO(vihanjain): Support list of 'current_var_or_name' here. @@ -250,9 +249,8 @@ def init_from_checkpoint(ckpt_dir_or_file, assignment_map): if var is None: var = _collect_partitioned_variable(var_name, store_vars) _set_variable_or_list_initializer(var, ckpt_file, full_tensor_name) - logging.info("Initialize variable %s from checkpoint %s with %s" % ( - var_name, ckpt_dir_or_file, full_tensor_name - )) + logging.info("Initialize variable %s from checkpoint %s with %s", + var_name, ckpt_dir_or_file, full_tensor_name) def _get_checkpoint_filename(ckpt_dir_or_file): diff --git a/tensorflow/python/training/input.py b/tensorflow/python/training/input.py index 83f1ac4abd8..e9fe9215ae4 100644 --- a/tensorflow/python/training/input.py +++ b/tensorflow/python/training/input.py @@ -879,9 +879,6 @@ def batch(tensors, batch_size, num_threads=1, capacity=32, `get_shape` method will have a first `Dimension` value of `None`, and operations that depend on fixed batch_size would fail. - Note: if `num_epochs` is not `None`, this function creates local counter - `epochs`. Use `local_variables_initializer()` to initialize local variables. - Args: tensors: The list or dictionary of tensors to enqueue. batch_size: The new batch size pulled from the queue. @@ -1181,9 +1178,6 @@ def shuffle_batch(tensors, batch_size, capacity, min_after_dequeue, `get_shape` method will have a first `Dimension` value of `None`, and operations that depend on fixed batch_size would fail. - Note: if `num_epochs` is not `None`, this function creates local counter - `epochs`. Use `local_variables_initializer()` to initialize local variables. - Args: tensors: The list or dictionary of tensors to enqueue. batch_size: The new batch size pulled from the queue. diff --git a/tensorflow/python/training/monitored_session.py b/tensorflow/python/training/monitored_session.py index fcec3ed97c7..a891bae5f23 100644 --- a/tensorflow/python/training/monitored_session.py +++ b/tensorflow/python/training/monitored_session.py @@ -559,7 +559,7 @@ class MonitoredSession(_MonitoredSession): ```python saver_hook = CheckpointSaverHook(...) - summary_hook = SummaryHook(...) + summary_hook = SummarySaverHook(...) with MonitoredSession(session_creator=ChiefSessionCreator(...), hooks=[saver_hook, summary_hook]) as sess: while not sess.should_stop(): @@ -648,7 +648,7 @@ class SingularMonitoredSession(_MonitoredSession): Example usage: ```python saver_hook = CheckpointSaverHook(...) - summary_hook = SummaryHook(...) + summary_hook = SummarySaverHook(...) with SingularMonitoredSession(hooks=[saver_hook, summary_hook]) as sess: while not sess.should_stop(): sess.run(train_op) diff --git a/tensorflow/python/training/saver.py b/tensorflow/python/training/saver.py index 43b61742467..a65ab794956 100644 --- a/tensorflow/python/training/saver.py +++ b/tensorflow/python/training/saver.py @@ -935,11 +935,11 @@ def get_checkpoint_state(checkpoint_dir, latest_filename=None): ckpt.all_model_checkpoint_paths[i] = os.path.join(checkpoint_dir, p) except errors.OpError as e: # It's ok if the file cannot be read - logging.warning(str(e)) + logging.warning("%s: %s", type(e).__name__, e) logging.warning("%s: Checkpoint ignored", coord_checkpoint_filename) return None except text_format.ParseError as e: - logging.warning(str(e)) + logging.warning("%s: %s", type(e).__name__, e) logging.warning("%s: Checkpoint ignored", coord_checkpoint_filename) return None finally: diff --git a/tensorflow/stream_executor/cuda/cuda_gpu_executor.cc b/tensorflow/stream_executor/cuda/cuda_gpu_executor.cc index 1bb90afd63e..c1e72bb5655 100644 --- a/tensorflow/stream_executor/cuda/cuda_gpu_executor.cc +++ b/tensorflow/stream_executor/cuda/cuda_gpu_executor.cc @@ -67,14 +67,6 @@ limitations under the License. extern bool FLAGS_check_gpu_leaks; bool FLAGS_prefer_cubin_to_ptx = true; -namespace perftools { -namespace gputools { -namespace rng { -class RngSupport; -} // namespace rng -} // namespace gputools -} // namespace perftools - namespace perftools { namespace gputools { namespace cuda { diff --git a/tensorflow/stream_executor/cuda/cuda_gpu_executor.h b/tensorflow/stream_executor/cuda/cuda_gpu_executor.h index 9d386b5ed9e..6c5b9dca90b 100644 --- a/tensorflow/stream_executor/cuda/cuda_gpu_executor.h +++ b/tensorflow/stream_executor/cuda/cuda_gpu_executor.h @@ -35,17 +35,6 @@ limitations under the License. #include "tensorflow/stream_executor/platform/thread_annotations.h" #include "tensorflow/stream_executor/stream_executor_internal.h" -namespace perftools { -namespace gputools { -namespace blas { -class BlasSupport; -} -namespace internal { -class RngSupport; -} // namespace internal -} // namespace gputools -} // namespace perftools - namespace perftools { namespace gputools { namespace cuda { diff --git a/tensorflow/tensorboard/backend/application_test.py b/tensorflow/tensorboard/backend/application_test.py index a5181401fa2..4ea627def7c 100644 --- a/tensorflow/tensorboard/backend/application_test.py +++ b/tensorflow/tensorboard/backend/application_test.py @@ -227,6 +227,19 @@ class TensorboardServerTest(test.TestCase): response.read() connection.close() + def testScalars(self): + """Test the format of /data/scalars.""" + data = self._getJson('/data/scalars?run=run1&tag=simple_values') + self.assertEqual(len(data), self._SCALAR_COUNT) + + def testScalarsCsv(self): + """Test the csv format of /data/scalars.""" + data = self._get( + '/data/scalars?run=run1&tag=simple_values&format=csv').read() + line_count = data.count('\n') + self.assertEqual(line_count, + self._SCALAR_COUNT + 1) # include 1 more line for header + def testHistograms(self): """Test the format of /data/histograms.""" self.assertEqual( diff --git a/tensorflow/tensorboard/backend/event_processing/event_accumulator_test.py b/tensorflow/tensorboard/backend/event_processing/event_accumulator_test.py index 3734e470b69..f7d424cb912 100644 --- a/tensorflow/tensorboard/backend/event_processing/event_accumulator_test.py +++ b/tensorflow/tensorboard/backend/event_processing/event_accumulator_test.py @@ -225,6 +225,7 @@ class MockingEventAccumulatorTest(EventAccumulatorTest): self.assertTagsEqual(x.Tags(), {}) def testTags(self): + """Tags should be found in EventAccumulator after adding some events.""" gen = _EventGenerator(self) gen.AddScalar('s1') gen.AddScalar('s2') @@ -245,6 +246,7 @@ class MockingEventAccumulatorTest(EventAccumulatorTest): }) def testReload(self): + """EventAccumulator contains suitable tags after calling Reload.""" gen = _EventGenerator(self) acc = ea.EventAccumulator(gen) acc.Reload() @@ -267,6 +269,7 @@ class MockingEventAccumulatorTest(EventAccumulatorTest): }) def testScalars(self): + """Tests whether EventAccumulator contains scalars after adding them.""" gen = _EventGenerator(self) acc = ea.EventAccumulator(gen) s1 = ea.ScalarEvent(wall_time=1, step=10, value=32) @@ -293,6 +296,7 @@ class MockingEventAccumulatorTest(EventAccumulatorTest): self.assertEqual(expected_value, gotten_event.value[i]) def testHealthPills(self): + """HealthPills should be properly inserted into EventAccumulator.""" gen = _EventGenerator(self) acc = ea.EventAccumulator(gen) gen.AddHealthPill(13371337, 41, 'Add', 0, range(1, 13)) @@ -328,6 +332,7 @@ class MockingEventAccumulatorTest(EventAccumulatorTest): self.assertItemsEqual(['Add', 'MatMul'], acc.GetOpsWithHealthPills()) def testHistograms(self): + """Tests whether histograms are inserted into EventAccumulator.""" gen = _EventGenerator(self) acc = ea.EventAccumulator(gen) @@ -377,6 +382,7 @@ class MockingEventAccumulatorTest(EventAccumulatorTest): self.assertEqual(acc.Histograms('hst2'), [hst2]) def testCompressedHistograms(self): + """Tests compressed histograms inserted into EventAccumulator.""" gen = _EventGenerator(self) acc = ea.EventAccumulator(gen, compression_bps=(0, 2500, 5000, 7500, 10000)) @@ -428,6 +434,7 @@ class MockingEventAccumulatorTest(EventAccumulatorTest): self.assertEqual(acc.CompressedHistograms('hst2'), [expected_cmphst2]) def testCompressedHistogramsWithEmptyHistogram(self): + """Tests that empty histograms compressed properly in EventAccumulator.""" gen = _EventGenerator(self) acc = ea.EventAccumulator(gen, compression_bps=(0, 2500, 5000, 7500, 10000)) @@ -481,6 +488,7 @@ class MockingEventAccumulatorTest(EventAccumulatorTest): self.assertAlmostEqual(vals[8].value, 1.0) def testImages(self): + """Tests 2 images inserted/accessed in EventAccumulator.""" gen = _EventGenerator(self) acc = ea.EventAccumulator(gen) im1 = ea.ImageEvent( @@ -514,6 +522,7 @@ class MockingEventAccumulatorTest(EventAccumulatorTest): self.assertEqual(acc.Images('im2'), [im2]) def testAudio(self): + """Tests 2 audio events inserted/accessed in EventAccumulator.""" gen = _EventGenerator(self) acc = ea.EventAccumulator(gen) snd1 = ea.AudioEvent( @@ -551,6 +560,7 @@ class MockingEventAccumulatorTest(EventAccumulatorTest): self.assertEqual(acc.Audio('snd2'), [snd2]) def testKeyError(self): + """KeyError should be raised when accessing non-existing keys.""" gen = _EventGenerator(self) acc = ea.EventAccumulator(gen) acc.Reload() @@ -574,7 +584,7 @@ class MockingEventAccumulatorTest(EventAccumulatorTest): acc.Audio('hst1') def testNonValueEvents(self): - """Tests that non-value events in the generator don't cause early exits.""" + """Non-value events in the generator don't cause early exits.""" gen = _EventGenerator(self) acc = ea.EventAccumulator(gen) gen.AddScalar('s1', wall_time=1, step=10, value=20) diff --git a/tensorflow/tensorboard/dist/tf-tensorboard.html b/tensorflow/tensorboard/dist/tf-tensorboard.html index 8610940ac3c..9f13cdfb478 100644 --- a/tensorflow/tensorboard/dist/tf-tensorboard.html +++ b/tensorflow/tensorboard/dist/tf-tensorboard.html @@ -20112,7 +20112,7 @@ var TF; new TF.Dashboard.TfGraphDashboard(backend, debuggerDataEnabled), new TF.Dashboard.TfDistributionDashboard(backend), new TF.Dashboard.TfHistogramDashboard(backend), - new TF.Dashboard.VzProjectorDashboard('/data/plugin/projector'), + new TF.Dashboard.VzProjectorDashboard('data/plugin/projector'), new TF.Dashboard.TfTextDashboard(backend), ]; }, diff --git a/tensorflow/tensorflow.bzl b/tensorflow/tensorflow.bzl index ddffabd8cb3..7baddf301c6 100644 --- a/tensorflow/tensorflow.bzl +++ b/tensorflow/tensorflow.bzl @@ -1185,7 +1185,7 @@ def tf_version_info_genrule(): ], outs=["util/version_info.cc"], cmd= - "$(location //tensorflow/tools/git:gen_git_source.py) --generate $(SRCS) \"$@\"", + "$(PYTHON_BIN_PATH) $(location //tensorflow/tools/git:gen_git_source.py) --generate $(SRCS) \"$@\"", local=1, tools=[clean_dep("//tensorflow/tools/git:gen_git_source.py")],) diff --git a/tensorflow/tools/api/golden/tensorflow.layers.pbtxt b/tensorflow/tools/api/golden/tensorflow.layers.pbtxt index 6ca38e259bf..78b10c44a23 100644 --- a/tensorflow/tools/api/golden/tensorflow.layers.pbtxt +++ b/tensorflow/tools/api/golden/tensorflow.layers.pbtxt @@ -32,6 +32,10 @@ tf_module { name: "conv3d" argspec: "args=[\'inputs\', \'filters\', \'kernel_size\', \'strides\', \'padding\', \'data_format\', \'dilation_rate\', \'activation\', \'use_bias\', \'kernel_initializer\', \'bias_initializer\', \'kernel_regularizer\', \'bias_regularizer\', \'activity_regularizer\', \'trainable\', \'name\', \'reuse\'], varargs=None, keywords=None, defaults=[\'(1, 1, 1)\', \'valid\', \'channels_last\', \'(1, 1, 1)\', \'None\', \'True\', \'None\', \'\', \'None\', \'None\', \'None\', \'True\', \'None\', \'None\'], " } + member_method { + name: "conv3d_transpose" + argspec: "args=[\'inputs\', \'filters\', \'kernel_size\', \'strides\', \'padding\', \'data_format\', \'activation\', \'use_bias\', \'kernel_initializer\', \'bias_initializer\', \'kernel_regularizer\', \'bias_regularizer\', \'activity_regularizer\', \'trainable\', \'name\', \'reuse\'], varargs=None, keywords=None, defaults=[\'(1, 1, 1)\', \'valid\', \'channels_last\', \'None\', \'True\', \'None\', \'\', \'None\', \'None\', \'None\', \'True\', \'None\', \'None\'], " + } member_method { name: "dense" argspec: "args=[\'inputs\', \'units\', \'activation\', \'use_bias\', \'kernel_initializer\', \'bias_initializer\', \'kernel_regularizer\', \'bias_regularizer\', \'activity_regularizer\', \'trainable\', \'name\', \'reuse\'], varargs=None, keywords=None, defaults=[\'None\', \'True\', \'None\', \'\', \'None\', \'None\', \'None\', \'True\', \'None\', \'None\'], " diff --git a/tensorflow/tools/api/golden/tensorflow.nn.pbtxt b/tensorflow/tools/api/golden/tensorflow.nn.pbtxt index 192ceac2ddf..3a448798b27 100644 --- a/tensorflow/tools/api/golden/tensorflow.nn.pbtxt +++ b/tensorflow/tools/api/golden/tensorflow.nn.pbtxt @@ -70,7 +70,7 @@ tf_module { } member_method { name: "conv3d_transpose" - argspec: "args=[\'value\', \'filter\', \'output_shape\', \'strides\', \'padding\', \'data_format\', \'name\'], varargs=None, keywords=None, defaults=[\'SAME\', \'None\', \'None\'], " + argspec: "args=[\'value\', \'filter\', \'output_shape\', \'strides\', \'padding\', \'data_format\', \'name\'], varargs=None, keywords=None, defaults=[\'SAME\', \'NDHWC\', \'None\'], " } member_method { name: "convolution" diff --git a/tensorflow/tools/api/golden/tensorflow.pbtxt b/tensorflow/tools/api/golden/tensorflow.pbtxt index fb636d9525f..046d82c2d51 100644 --- a/tensorflow/tools/api/golden/tensorflow.pbtxt +++ b/tensorflow/tools/api/golden/tensorflow.pbtxt @@ -636,6 +636,10 @@ tf_module { name: "atan" argspec: "args=[\'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "atan2" + argspec: "args=[\'y\', \'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } member_method { name: "batch_to_space" argspec: "args=[\'input\', \'crops\', \'block_size\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/ci_build/update_version.sh b/tensorflow/tools/ci_build/update_version.sh index e0ca8c3259c..682f5329f58 100755 --- a/tensorflow/tools/ci_build/update_version.sh +++ b/tensorflow/tools/ci_build/update_version.sh @@ -73,8 +73,11 @@ OLD_MAJOR=$(cat ${VERSION_H} | grep -E "^#define TF_MAJOR_VERSION [0-9]+" | \ cut -d ' ' -f 3) OLD_MINOR=$(cat ${VERSION_H} | grep -E "^#define TF_MINOR_VERSION [0-9]+" | \ cut -d ' ' -f 3) -OLD_PATCH=$(cat ${VERSION_H} | grep -E "^#define TF_PATCH_VERSION [[:alnum:]-]+" | \ +OLD_PATCH_NUM=$(cat ${VERSION_H} | grep -E "^#define TF_PATCH_VERSION [[:alnum:]-]+" | \ cut -d ' ' -f 3) +OLD_EXTENSION=$(cat ${VERSION_H} | grep -E "^#define TF_VERSION_SUFFIX \"[[:alnum:]-]+\"" | \ +cut -d ' ' -f 3) +OLD_PATCH="$OLD_PATCH_NUM${OLD_EXTENSION//\"}" OLD_PIP_PATCH="${OLD_PATCH//-}" sed -i -e "s/^#define TF_MAJOR_VERSION ${OLD_MAJOR}/#define TF_MAJOR_VERSION ${MAJOR}/g" ${VERSION_H} diff --git a/tensorflow/tools/common/public_api.py b/tensorflow/tools/common/public_api.py index 837f11f690e..cab3b2ff6a0 100644 --- a/tensorflow/tools/common/public_api.py +++ b/tensorflow/tools/common/public_api.py @@ -38,7 +38,7 @@ class PublicAPIVisitor(object): self._visitor = visitor # Modules/classes we do not want to descend into if we hit them. Usually, - # sytem modules exposed through platforms for compatibility reasons. + # system modules exposed through platforms for compatibility reasons. # Each entry maps a module path to a name to ignore in traversal. self._do_not_descend_map = { '': [ diff --git a/tensorflow/tools/compatibility/tf_upgrade.py b/tensorflow/tools/compatibility/tf_upgrade.py index 80439f835a6..9a4a8ff71d9 100644 --- a/tensorflow/tools/compatibility/tf_upgrade.py +++ b/tensorflow/tools/compatibility/tf_upgrade.py @@ -34,6 +34,10 @@ class APIChangeSpec(object): # Maps from a function name to a dictionary that describes how to # map from an old argument keyword to the new argument keyword. self.function_keyword_renames = { + "tf.batch_matmul": { + "adj_x": "adjoint_a", + "adj_y": "adjoint_b", + }, "tf.count_nonzero": { "reduction_indices": "axis" }, diff --git a/tensorflow/tools/docker/Dockerfile.devel b/tensorflow/tools/docker/Dockerfile.devel index bfac54c6019..a0e0f88d9df 100644 --- a/tensorflow/tools/docker/Dockerfile.devel +++ b/tensorflow/tools/docker/Dockerfile.devel @@ -92,7 +92,8 @@ WORKDIR /tensorflow ENV CI_BUILD_PYTHON python RUN tensorflow/tools/ci_build/builds/configured CPU \ - bazel build -c opt tensorflow/tools/pip_package:build_pip_package && \ + bazel build -c opt --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" \ + tensorflow/tools/pip_package:build_pip_package && \ bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/pip && \ pip --no-cache-dir install --upgrade /tmp/pip/tensorflow-*.whl && \ rm -rf /tmp/pip && \ diff --git a/tensorflow/tools/docker/Dockerfile.devel-gpu b/tensorflow/tools/docker/Dockerfile.devel-gpu index 7726cbdfbf8..743c05ef887 100644 --- a/tensorflow/tools/docker/Dockerfile.devel-gpu +++ b/tensorflow/tools/docker/Dockerfile.devel-gpu @@ -92,7 +92,8 @@ ENV TF_NEED_CUDA 1 ENV TF_CUDA_COMPUTE_CAPABILITIES=3.0,3.5,5.2,6.0,6.1 RUN tensorflow/tools/ci_build/builds/configured GPU \ - bazel build -c opt --config=cuda tensorflow/tools/pip_package:build_pip_package && \ + bazel build -c opt --config=cuda --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" \ + tensorflow/tools/pip_package:build_pip_package && \ bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/pip && \ pip --no-cache-dir install --upgrade /tmp/pip/tensorflow-*.whl && \ rm -rf /tmp/pip && \ diff --git a/tensorflow/tools/docs/doc_generator_visitor.py b/tensorflow/tools/docs/doc_generator_visitor.py index 119305bece3..8f7b91fa752 100644 --- a/tensorflow/tools/docs/doc_generator_visitor.py +++ b/tensorflow/tools/docs/doc_generator_visitor.py @@ -170,7 +170,7 @@ class DocGeneratorVisitor(object): master names to a lexicographically sorted list of all aliases for that name (incl. the master name). - All these are computed and set as fields if they haven't aready. + All these are computed and set as fields if they haven't already. """ if self._reverse_index is not None: return diff --git a/tensorflow/tools/docs/pretty_docs.py b/tensorflow/tools/docs/pretty_docs.py index 824f46170ed..657d6bf8490 100644 --- a/tensorflow/tools/docs/pretty_docs.py +++ b/tensorflow/tools/docs/pretty_docs.py @@ -230,7 +230,7 @@ def _build_signature(obj_info): def _build_compatibility(compatibility): - """Return the compatability section as an md string.""" + """Return the compatibility section as an md string.""" parts = [] sorted_keys = sorted(compatibility.keys()) for key in sorted_keys: diff --git a/tensorflow/tools/graph_transforms/README.md b/tensorflow/tools/graph_transforms/README.md index c9f0a9b2229..9bb438fa719 100644 --- a/tensorflow/tools/graph_transforms/README.md +++ b/tensorflow/tools/graph_transforms/README.md @@ -81,10 +81,10 @@ bazel-bin/tensorflow/tools/graph_transforms/transform_graph \ --out_graph=optimized_inception_graph.pb \ --inputs='Mul:0' \ --outputs='softmax:0' \ ---transforms='\ -strip_unused_nodes(type=float, shape="1,299,299,3") \ -remove_nodes(op=Identity, op=CheckNumerics) \ -fold_old_batch_norms \ +--transforms=' +strip_unused_nodes(type=float, shape="1,299,299,3") +remove_nodes(op=Identity, op=CheckNumerics) +fold_old_batch_norms ' ``` @@ -94,7 +94,10 @@ transforms to modify the graph with. The transforms are given as a list of names, and can each have arguments themselves. These transforms define the pipeline of modifications that are applied in order to produce the output. Sometimes you need some transforms to happen before others, and the ordering -within the list lets you specify which happen first. +within the list lets you specify which happen first. +Note that the optimization +`remove_nodes(op=Identity, op=CheckNumerics)` will break the model with control +flow operations, such as `tf.cond`, `tf.map_fn`, and `tf.while`. ## Inspecting Graphs @@ -169,7 +172,7 @@ then you'll need to make local modifications to the build files to include the right .cc file that defines it. In a lot of cases the op is just a vestigial remnant from the training process though, and if that's true then you can run the [strip_unused_nodes](#strip_unused_nodes), specifying the inputs and outputs -of your inference usage, to remove those unneccessary nodes: +of your inference usage, to remove those unnecessary nodes: ```bash bazel build tensorflow/tools/graph_transforms:transform_graph diff --git a/tensorflow/tools/pip_package/BUILD b/tensorflow/tools/pip_package/BUILD index c17a7f7fb19..83be430e7d6 100644 --- a/tensorflow/tools/pip_package/BUILD +++ b/tensorflow/tools/pip_package/BUILD @@ -68,6 +68,7 @@ py_binary( ":included_headers", "//tensorflow/contrib/nn:nn_py", "//tensorflow/contrib/session_bundle:session_bundle_pip", + "//tensorflow/contrib/signal:signal_py", "//tensorflow/contrib/slim/python/slim/data:data_pip", "//tensorflow/python:util_example_parser_configuration", "//tensorflow/python/debug:debug_pip", @@ -141,6 +142,7 @@ sh_binary( "//tensorflow/contrib/ndlstm:ndlstm", "//tensorflow/contrib/nn:nn_py", "//tensorflow/contrib/session_bundle:session_bundle_pip", + "//tensorflow/contrib/signal:signal_py", "//tensorflow/contrib/slim:slim", "//tensorflow/contrib/slim/python/slim/data:data_pip", "//tensorflow/contrib/slim/python/slim/nets:nets_pip", diff --git a/tensorflow/tools/pip_package/setup.py b/tensorflow/tools/pip_package/setup.py index 3ee99d5d315..f8982073c3a 100644 --- a/tensorflow/tools/pip_package/setup.py +++ b/tensorflow/tools/pip_package/setup.py @@ -29,7 +29,7 @@ from setuptools.dist import Distribution # This version string is semver compatible, but incompatible with pip. # For pip, we will remove all '-' characters from this string, and use the # result for pip. -_VERSION = '1.1.0-rc2' +_VERSION = '1.1.0' REQUIRED_PACKAGES = [ 'numpy >= 1.11.0', diff --git a/tensorflow/tools/quantization/quantize_graph.py b/tensorflow/tools/quantization/quantize_graph.py index d09349a79b9..a0cfc352d4f 100644 --- a/tensorflow/tools/quantization/quantize_graph.py +++ b/tensorflow/tools/quantization/quantize_graph.py @@ -453,7 +453,8 @@ class GraphRewriter(object): def round_nodes_recursively(self, current_node): """The entry point for simple rounding quantization.""" - if self.already_visited[current_node.name]: + if (current_node.name in self.already_visited + ) and self.already_visited[current_node.name]: return self.already_visited[current_node.name] = True for input_node_name in current_node.input: diff --git a/tensorflow/tools/tfprof/README.md b/tensorflow/tools/tfprof/README.md index c83cdd45b6c..540e179aaee 100644 --- a/tensorflow/tools/tfprof/README.md +++ b/tensorflow/tools/tfprof/README.md @@ -30,7 +30,7 @@ statistics. tfprof is part of TensorFlow core. Simply ```import tensorflow as tf```. -### Examine the shapes and sizes of all trainiable Variables. +### Examine the shapes and sizes of all trainable Variables. ```python # Print trainable variable parameter statistics to stdout. param_stats = tf.contrib.tfprof.model_analyzer.print_model_analysis( @@ -439,7 +439,7 @@ with gfile.Open(os.path.join(output_dir, "run_meta"), "w") as f: --op_log_path: tensorflow::tfprof::OpLog. A proto used to provide extra op information for ops. By giving a group of ops a type name, users can easily aggregate the -statistics for those ops without accidently missing or including extra ops. +statistics for those ops without accidentally missing or including extra ops. tfprof exposes the following Python API to add op information and logging. ```python diff --git a/third_party/gpus/crosstool/clang/bin/crosstool_wrapper_driver_is_not_gcc.tpl b/third_party/gpus/crosstool/clang/bin/crosstool_wrapper_driver_is_not_gcc.tpl index cab533b9e75..242439daf45 100755 --- a/third_party/gpus/crosstool/clang/bin/crosstool_wrapper_driver_is_not_gcc.tpl +++ b/third_party/gpus/crosstool/clang/bin/crosstool_wrapper_driver_is_not_gcc.tpl @@ -227,7 +227,7 @@ def InvokeNvcc(argv, log=False): # TODO(zhengxq): for some reason, 'gcc' needs this help to find 'as'. # Need to investigate and fix. - cmd = 'PATH=' + PREFIX_DIR + ' ' + cmd + cmd = 'PATH=' + PREFIX_DIR + ':$PATH ' + cmd if log: Log(cmd) return os.system(cmd) From 3a6db4eadd7e9fed214966e7a0bd2265ea2d0eaf Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Fri, 5 May 2017 09:11:35 -0800 Subject: [PATCH 08/27] Removing unnecessary lines from gitignore Change: 155210210 --- .gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index d8ecef1e1e7..da5d14a9b77 100644 --- a/.gitignore +++ b/.gitignore @@ -4,11 +4,8 @@ node_modules /.bazelrc /.tf_configure.bazelrc /bazel-* -/third_party/py/numpy/numpy_include /tools/python_bin_path.sh /tools/git/gen -/util/python/python_include -/util/python/python_lib /pip_test /_python_build *.pyc From 95cb6d0a3396b8274866f9692fc1231ae6edb7e6 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Fri, 5 May 2017 09:13:57 -0800 Subject: [PATCH 09/27] Go: Update generated wrapper functions for TensorFlow ops. Change: 155210529 --- tensorflow/go/op/wrappers.go | 157 ++++++++++++++++++++--------------- 1 file changed, 89 insertions(+), 68 deletions(-) diff --git a/tensorflow/go/op/wrappers.go b/tensorflow/go/op/wrappers.go index eb4789a1829..e57c197fa4b 100644 --- a/tensorflow/go/op/wrappers.go +++ b/tensorflow/go/op/wrappers.go @@ -5583,6 +5583,74 @@ func ReadFile(scope *Scope, filename tf.Output) (contents tf.Output) { return op.Output(0) } +// Store the input tensor in the state of the current session. +// +// Arguments: +// value: The tensor to be stored. +// +// Returns The handle for the tensor stored in the session state, represented +// as a ResourceHandle object. +func GetSessionHandleV2(scope *Scope, value tf.Output) (handle tf.Output) { + if scope.Err() != nil { + return + } + opspec := tf.OpSpec{ + Type: "GetSessionHandleV2", + Input: []tf.Input{ + value, + }, + } + op := scope.AddOperation(opspec) + return op.Output(0) +} + +// Adjust the hue of one or more images. +// +// `images` is a tensor of at least 3 dimensions. The last dimension is +// interpretted as channels, and must be three. +// +// The input image is considered in the RGB colorspace. Conceptually, the RGB +// colors are first mapped into HSV. A delta is then applied all the hue values, +// and then remapped back to RGB colorspace. +// +// Arguments: +// images: Images to adjust. At least 3-D. +// delta: A float delta to add to the hue. +// +// Returns The hue-adjusted image or images. +func AdjustHue(scope *Scope, images tf.Output, delta tf.Output) (output tf.Output) { + if scope.Err() != nil { + return + } + opspec := tf.OpSpec{ + Type: "AdjustHue", + Input: []tf.Input{ + images, delta, + }, + } + op := scope.AddOperation(opspec) + return op.Output(0) +} + +// Restore a Reader to its initial clean state. +// +// Arguments: +// reader_handle: Handle to a Reader. +// +// Returns the created operation. +func ReaderResetV2(scope *Scope, reader_handle tf.Output) (o *tf.Operation) { + if scope.Err() != nil { + return + } + opspec := tf.OpSpec{ + Type: "ReaderResetV2", + Input: []tf.Input{ + reader_handle, + }, + } + return scope.AddOperation(opspec) +} + // Computes softmax cross entropy cost and gradients to backpropagate. // // Unlike `SoftmaxCrossEntropyWithLogits`, this operation does not accept @@ -19039,6 +19107,27 @@ func Igamma(scope *Scope, a tf.Output, x tf.Output) (z tf.Output) { return op.Output(0) } +// Computes arctangent of `y/x` element-wise, respecting signs of the arguments. +// +// This is the angle \( \theta \in [-\pi, \pi] \) such that +// \[ x = r \cos(\theta) \] +// and +// \[ y = r \sin(\theta) \] +// where \(r = \sqrt(x^2 + y^2) \). +func Atan2(scope *Scope, y tf.Output, x tf.Output) (z tf.Output) { + if scope.Err() != nil { + return + } + opspec := tf.OpSpec{ + Type: "Atan2", + Input: []tf.Input{ + y, x, + }, + } + op := scope.AddOperation(opspec) + return op.Output(0) +} + // Compute the regularized incomplete beta integral \\(I_x(a, b)\\). // // The regularized incomplete beta integral is defined as: @@ -21627,71 +21716,3 @@ func SoftmaxCrossEntropyWithLogits(scope *Scope, features tf.Output, labels tf.O op := scope.AddOperation(opspec) return op.Output(0), op.Output(1) } - -// Store the input tensor in the state of the current session. -// -// Arguments: -// value: The tensor to be stored. -// -// Returns The handle for the tensor stored in the session state, represented -// as a ResourceHandle object. -func GetSessionHandleV2(scope *Scope, value tf.Output) (handle tf.Output) { - if scope.Err() != nil { - return - } - opspec := tf.OpSpec{ - Type: "GetSessionHandleV2", - Input: []tf.Input{ - value, - }, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - -// Adjust the hue of one or more images. -// -// `images` is a tensor of at least 3 dimensions. The last dimension is -// interpretted as channels, and must be three. -// -// The input image is considered in the RGB colorspace. Conceptually, the RGB -// colors are first mapped into HSV. A delta is then applied all the hue values, -// and then remapped back to RGB colorspace. -// -// Arguments: -// images: Images to adjust. At least 3-D. -// delta: A float delta to add to the hue. -// -// Returns The hue-adjusted image or images. -func AdjustHue(scope *Scope, images tf.Output, delta tf.Output) (output tf.Output) { - if scope.Err() != nil { - return - } - opspec := tf.OpSpec{ - Type: "AdjustHue", - Input: []tf.Input{ - images, delta, - }, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - -// Restore a Reader to its initial clean state. -// -// Arguments: -// reader_handle: Handle to a Reader. -// -// Returns the created operation. -func ReaderResetV2(scope *Scope, reader_handle tf.Output) (o *tf.Operation) { - if scope.Err() != nil { - return - } - opspec := tf.OpSpec{ - Type: "ReaderResetV2", - Input: []tf.Input{ - reader_handle, - }, - } - return scope.AddOperation(opspec) -} From f3f05c8fd6ab935a614337af033f413e262db301 Mon Sep 17 00:00:00 2001 From: Eric Liu Date: Fri, 5 May 2017 09:26:00 -0800 Subject: [PATCH 10/27] [XLA] Remove useless log message when dumping HLO GraphDef. This produces too much output that is not helpful. Change: 155212076 --- tensorflow/compiler/xla/service/hlo_tfgraph_builder.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tensorflow/compiler/xla/service/hlo_tfgraph_builder.cc b/tensorflow/compiler/xla/service/hlo_tfgraph_builder.cc index da07dea123a..2b14eca5d1b 100644 --- a/tensorflow/compiler/xla/service/hlo_tfgraph_builder.cc +++ b/tensorflow/compiler/xla/service/hlo_tfgraph_builder.cc @@ -68,9 +68,8 @@ void CleanNodeName(string* name) { } Status HloTfGraphBuilder::AddComputation(const HloComputation& computation) { - LOG(INFO) << "Adding computation " << computation.name(); + VLOG(2) << "Adding computation " << computation.name(); for (auto embedded : computation.MakeEmbeddedComputationsList()) { - LOG(INFO) << "Adding embedded computation " << embedded->name(); for (auto& instruction : embedded->instructions()) { TF_RETURN_IF_ERROR(AddInstruction(instruction.get())); } From ce1a5674362bf7ff42d323eb21667ceeee6c99b4 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Fri, 5 May 2017 09:48:11 -0800 Subject: [PATCH 11/27] Update ops-related pbtxt files. Change: 155214850 --- .../core/ops/compat/ops_history.v1.pbtxt | 25 +++++++++++++++++ tensorflow/core/ops/ops.pbtxt | 27 +++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/tensorflow/core/ops/compat/ops_history.v1.pbtxt b/tensorflow/core/ops/compat/ops_history.v1.pbtxt index 8856a0faaf4..bc40715accb 100644 --- a/tensorflow/core/ops/compat/ops_history.v1.pbtxt +++ b/tensorflow/core/ops/compat/ops_history.v1.pbtxt @@ -1716,6 +1716,31 @@ op { } } } +op { + name: "Atan2" + input_arg { + name: "y" + type_attr: "T" + } + input_arg { + name: "x" + type_attr: "T" + } + output_arg { + name: "z" + type_attr: "T" + } + attr { + name: "T" + type: "type" + allowed_values { + list { + type: DT_FLOAT + type: DT_DOUBLE + } + } + } +} op { name: "AudioSpectrogram" input_arg { diff --git a/tensorflow/core/ops/ops.pbtxt b/tensorflow/core/ops/ops.pbtxt index b452ab7ef5c..dd0a339609c 100644 --- a/tensorflow/core/ops/ops.pbtxt +++ b/tensorflow/core/ops/ops.pbtxt @@ -1904,6 +1904,33 @@ op { } summary: "Computes atan of x element-wise." } +op { + name: "Atan2" + input_arg { + name: "y" + type_attr: "T" + } + input_arg { + name: "x" + type_attr: "T" + } + output_arg { + name: "z" + type_attr: "T" + } + attr { + name: "T" + type: "type" + allowed_values { + list { + type: DT_FLOAT + type: DT_DOUBLE + } + } + } + summary: "Computes arctangent of `y/x` element-wise, respecting signs of the arguments." + description: "This is the angle \\( \\theta \\in [-\\pi, \\pi] \\) such that\n\\[ x = r \\cos(\\theta) \\]\nand\n\\[ y = r \\sin(\\theta) \\]\nwhere \\(r = \\sqrt(x^2 + y^2) \\)." +} op { name: "AudioSpectrogram" input_arg { From a827ef5727ffc64f4f3ad48eda01abd241909d13 Mon Sep 17 00:00:00 2001 From: Mustafa Ispir Date: Fri, 5 May 2017 10:07:37 -0800 Subject: [PATCH 12/27] Added cross compatibility to contrib feature columns: sparse_column_with_*, weighted_sparse_column, one_hot_column, embedding_column Change: 155217545 --- .../layers/python/layers/feature_column.py | 314 ++++++++++++++---- .../python/layers/feature_column_ops.py | 140 +------- .../python/layers/feature_column_ops_test.py | 51 ++- 3 files changed, 319 insertions(+), 186 deletions(-) diff --git a/tensorflow/contrib/layers/python/layers/feature_column.py b/tensorflow/contrib/layers/python/layers/feature_column.py index 04fe2370d1d..95a4b032b04 100644 --- a/tensorflow/contrib/layers/python/layers/feature_column.py +++ b/tensorflow/contrib/layers/python/layers/feature_column.py @@ -131,21 +131,27 @@ import math import six from tensorflow.contrib import lookup +from tensorflow.contrib.framework.python.framework import checkpoint_utils from tensorflow.contrib.framework.python.framework import experimental +from tensorflow.contrib.framework.python.ops import variables as contrib_variables +from tensorflow.contrib.layers.python.layers import embedding_ops from tensorflow.contrib.layers.python.layers import layers from tensorflow.contrib.layers.python.ops import bucketization_op from tensorflow.contrib.layers.python.ops import sparse_feature_cross_op from tensorflow.contrib.layers.python.ops import sparse_ops as contrib_sparse_ops from tensorflow.python.feature_column import feature_column as fc_core from tensorflow.python.framework import dtypes +from tensorflow.python.framework import ops from tensorflow.python.framework import sparse_tensor as sparse_tensor_py from tensorflow.python.framework import tensor_shape from tensorflow.python.ops import array_ops from tensorflow.python.ops import init_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import parsing_ops +from tensorflow.python.ops import resource_variable_ops from tensorflow.python.ops import sparse_ops from tensorflow.python.ops import string_ops +from tensorflow.python.ops import variables from tensorflow.python.platform import tf_logging as logging from tensorflow.python.util import deprecation @@ -291,11 +297,13 @@ class _FeatureColumn(object): # TODO(b/30410315): Support warm starting in all feature columns. -class _SparseColumn(_FeatureColumn, - collections.namedtuple("_SparseColumn", - ["column_name", "is_integerized", - "bucket_size", "lookup_config", - "combiner", "dtype"])): +class _SparseColumn( + _FeatureColumn, + fc_core._CategoricalColumn, # pylint: disable=protected-access + collections.namedtuple("_SparseColumn", [ + "column_name", "is_integerized", "bucket_size", "lookup_config", + "combiner", "dtype" + ])): """Represents a sparse feature column also known as categorical features. Instances of this class are immutable. A sparse column means features are @@ -426,9 +434,8 @@ class _SparseColumn(_FeatureColumn, initializer=init_ops.zeros_initializer(), combiner=self.combiner) - def _get_input_sparse_tensor(self, columns_to_tensors): - """Looks up the input tensor for transformation and sparsify it if dense.""" - input_tensor = columns_to_tensors[self.name] + def _get_input_sparse_tensor(self, input_tensor): + """sparsify input_tensor if dense.""" if not isinstance(input_tensor, sparse_tensor_py.SparseTensor): # To avoid making any assumptions about which values are to be ignored, # we set ignore_value to -1 for numeric tensors to avoid excluding valid @@ -455,18 +462,44 @@ class _SparseColumn(_FeatureColumn, format(self.name, other_column.name)) return compatible + @abc.abstractmethod + def _do_transform(self, input_tensor): + pass + + def insert_transformed_feature(self, columns_to_tensors): + """Handles sparse column to id conversion.""" + input_tensor = self._get_input_sparse_tensor(columns_to_tensors[self.name]) + columns_to_tensors[self] = self._do_transform(input_tensor) + + def _transform_feature(self, inputs): + input_tensor = self._get_input_sparse_tensor(inputs.get(self.name)) + return self._do_transform(input_tensor) + + @property + def _parse_example_config(self): + return self.config + + @property + def _num_buckets(self): + return self.length + + def _get_sparse_tensors(self, inputs, weight_collections=None, + trainable=None): + del weight_collections + del trainable + input_tensor = inputs.get(self) + return fc_core._CategoricalColumn.IdWeightPair( # pylint: disable=protected-access + self.id_tensor(input_tensor), self.weight_tensor(input_tensor)) + class _SparseColumnIntegerized(_SparseColumn): """See `sparse_column_with_integerized_feature`.""" - def insert_transformed_feature(self, columns_to_tensors): - """Handles sparse column to id conversion.""" - input_tensor = self._get_input_sparse_tensor(columns_to_tensors) - + def _do_transform(self, input_tensor): sparse_id_values = math_ops.mod(input_tensor.values, self.bucket_size, name="mod") - columns_to_tensors[self] = sparse_tensor_py.SparseTensor( - input_tensor.indices, sparse_id_values, input_tensor.dense_shape) + return sparse_tensor_py.SparseTensor(input_tensor.indices, sparse_id_values, + input_tensor.dense_shape) def sparse_column_with_integerized_feature(column_name, @@ -517,10 +550,7 @@ def sparse_column_with_integerized_feature(column_name, class _SparseColumnHashed(_SparseColumn): """See `sparse_column_with_hash_bucket`.""" - def insert_transformed_feature(self, columns_to_tensors): - """Handles sparse column to id conversion.""" - input_tensor = self._get_input_sparse_tensor(columns_to_tensors) - + def _do_transform(self, input_tensor): if self.dtype.is_integer: sparse_values = string_ops.as_string(input_tensor.values) else: @@ -528,8 +558,8 @@ class _SparseColumnHashed(_SparseColumn): sparse_id_values = string_ops.string_to_hash_bucket_fast( sparse_values, self.bucket_size, name="lookup") - columns_to_tensors[self] = sparse_tensor_py.SparseTensor( - input_tensor.indices, sparse_id_values, input_tensor.dense_shape) + return sparse_tensor_py.SparseTensor(input_tensor.indices, sparse_id_values, + input_tensor.dense_shape) def sparse_column_with_hash_bucket(column_name, @@ -572,16 +602,13 @@ def sparse_column_with_hash_bucket(column_name, class _SparseColumnKeys(_SparseColumn): """See `sparse_column_with_keys`.""" - def insert_transformed_feature(self, columns_to_tensors): - """Handles sparse column to id conversion.""" - input_tensor = self._get_input_sparse_tensor(columns_to_tensors) - + def _do_transform(self, input_tensor): table = lookup.index_table_from_tensor( mapping=tuple(self.lookup_config.keys), default_value=self.lookup_config.default_value, dtype=self.dtype, name="lookup") - columns_to_tensors[self] = table.lookup(input_tensor) + return table.lookup(input_tensor) def sparse_column_with_keys( @@ -621,9 +648,7 @@ def sparse_column_with_keys( class _SparseColumnVocabulary(_SparseColumn): """See `sparse_column_with_vocabulary_file`.""" - def insert_transformed_feature(self, columns_to_tensors): - """Handles sparse column to id conversion.""" - st = self._get_input_sparse_tensor(columns_to_tensors) + def _do_transform(self, st): if self.dtype.is_integer: sparse_string_values = string_ops.as_string(st.values) sparse_string_tensor = sparse_tensor_py.SparseTensor(st.indices, @@ -638,7 +663,7 @@ class _SparseColumnVocabulary(_SparseColumn): vocab_size=self.lookup_config.vocab_size, default_value=self.lookup_config.default_value, name=self.name + "_lookup") - columns_to_tensors[self] = table.lookup(sparse_string_tensor) + return table.lookup(sparse_string_tensor) def sparse_column_with_vocabulary_file(column_name, @@ -694,9 +719,12 @@ def sparse_column_with_vocabulary_file(column_name, dtype=dtype) -class _WeightedSparseColumn(_FeatureColumn, collections.namedtuple( - "_WeightedSparseColumn", - ["sparse_id_column", "weight_column_name", "dtype"])): +class _WeightedSparseColumn( + _FeatureColumn, + fc_core._CategoricalColumn, # pylint: disable=protected-access + collections.namedtuple("_WeightedSparseColumn", + ["sparse_id_column", "weight_column_name", + "dtype"])): """See `weighted_sparse_column`.""" def __new__(cls, sparse_id_column, weight_column_name, dtype): @@ -725,22 +753,6 @@ class _WeightedSparseColumn(_FeatureColumn, collections.namedtuple( """Returns a string which will be used as a key when we do sorting.""" return "{}".format(self) - def insert_transformed_feature(self, columns_to_tensors): - """Inserts a tuple with the id and weight tensors.""" - if self.sparse_id_column not in columns_to_tensors: - self.sparse_id_column.insert_transformed_feature(columns_to_tensors) - - weight_tensor = columns_to_tensors[self.weight_column_name] - if not isinstance(weight_tensor, sparse_tensor_py.SparseTensor): - # The weight tensor can be a regular Tensor. In such case, sparsify it. - weight_tensor = contrib_sparse_ops.dense_to_sparse_tensor(weight_tensor) - if not self.dtype.is_floating: - weight_tensor = math_ops.to_float(weight_tensor) - columns_to_tensors[self] = tuple([ - columns_to_tensors[self.sparse_id_column], - weight_tensor - ]) - def id_tensor(self, input_tensor): """Returns the id tensor from the given transformed input_tensor.""" return input_tensor[0] @@ -768,6 +780,43 @@ class _WeightedSparseColumn(_FeatureColumn, collections.namedtuple( initializer=init_ops.zeros_initializer(), combiner=self.sparse_id_column.combiner) + def _do_transform(self, id_tensor, weight_tensor): + if not isinstance(weight_tensor, sparse_tensor_py.SparseTensor): + # The weight tensor can be a regular Tensor. In such case, sparsify it. + weight_tensor = contrib_sparse_ops.dense_to_sparse_tensor(weight_tensor) + if not self.dtype.is_floating: + weight_tensor = math_ops.to_float(weight_tensor) + return tuple([id_tensor, weight_tensor]) + + def insert_transformed_feature(self, columns_to_tensors): + """Inserts a tuple with the id and weight tensors.""" + if self.sparse_id_column not in columns_to_tensors: + self.sparse_id_column.insert_transformed_feature(columns_to_tensors) + + weight_tensor = columns_to_tensors[self.weight_column_name] + columns_to_tensors[self] = self._do_transform( + columns_to_tensors[self.sparse_id_column], weight_tensor) + + def _transform_feature(self, inputs): + return self._do_transform( + inputs.get(self.sparse_id_column), inputs.get(self.weight_column_name)) + + @property + def _parse_example_config(self): + return self.config + + @property + def _num_buckets(self): + return self.length + + def _get_sparse_tensors(self, inputs, weight_collections=None, + trainable=None): + del weight_collections + del trainable + input_tensor = inputs.get(self) + return fc_core._CategoricalColumn.IdWeightPair( # pylint: disable=protected-access + self.id_tensor(input_tensor), self.weight_tensor(input_tensor)) + def weighted_sparse_column(sparse_id_column, weight_column_name, @@ -815,9 +864,10 @@ def weighted_sparse_column(sparse_id_column, return _WeightedSparseColumn(sparse_id_column, weight_column_name, dtype) -class _OneHotColumn(_FeatureColumn, - collections.namedtuple("_OneHotColumn", - ["sparse_id_column"])): +class _OneHotColumn( + _FeatureColumn, + fc_core._DenseColumn, # pylint: disable=protected-access + collections.namedtuple("_OneHotColumn", ["sparse_id_column"])): """Represents a one-hot column for use in deep networks. Args: @@ -897,12 +947,31 @@ class _OneHotColumn(_FeatureColumn, return math_ops.reduce_sum( one_hot_id_tensor, reduction_indices=[output_rank - 1]) + @property + def _variable_shape(self): + return tensor_shape.TensorShape((self.length)) -class _EmbeddingColumn(_FeatureColumn, collections.namedtuple( - "_EmbeddingColumn", - ["sparse_id_column", "dimension", "combiner", "initializer", - "ckpt_to_load_from", "tensor_name_in_ckpt", "shared_embedding_name", - "shared_vocab_size", "max_norm", "trainable"])): + def _get_dense_tensor(self, inputs, weight_collections=None, trainable=None): + del weight_collections + del trainable + return inputs.get(self) + + def _transform_feature(self, inputs): + return self._to_dnn_input_layer(inputs.get(self.sparse_id_column)) + + @property + def _parse_example_config(self): + return self.config + + +class _EmbeddingColumn( + _FeatureColumn, + fc_core._DenseColumn, # pylint: disable=protected-access + collections.namedtuple("_EmbeddingColumn", [ + "sparse_id_column", "dimension", "combiner", "initializer", + "ckpt_to_load_from", "tensor_name_in_ckpt", "shared_embedding_name", + "shared_vocab_size", "max_norm", "trainable" + ])): """Represents an embedding column. Args: @@ -1027,6 +1096,139 @@ class _EmbeddingColumn(_FeatureColumn, collections.namedtuple( raise ValueError("Column {} is not supported in linear models. " "Please use sparse_column.".format(self)) + @property + def _variable_shape(self): + return tensor_shape.TensorShape((self.dimension)) + + def _get_dense_tensor(self, inputs, weight_collections=None, trainable=None): + return _embeddings_from_arguments( + self, + self._deep_embedding_lookup_arguments(inputs.get(self)), + weight_collections, trainable) + + def _transform_feature(self, inputs): + return inputs.get(self.sparse_id_column) + + @property + def _parse_example_config(self): + return self.config + + +def _is_variable(v): + """Returns true if `v` is a variable.""" + return isinstance(v, (variables.Variable, + resource_variable_ops.ResourceVariable)) + + +def _embeddings_from_arguments(column, + args, + weight_collections, + trainable, + output_rank=2): + """Returns embeddings for a column based on the computed arguments. + + Args: + column: the column name. + args: the _DeepEmbeddingLookupArguments for this column. + weight_collections: collections to store weights in. + trainable: whether these embeddings should be trainable. + output_rank: the desired rank of the returned `Tensor`. Inner dimensions will + be combined to produce the desired rank. + + Returns: + the embeddings. + + Raises: + ValueError: if not possible to create. + """ + # pylint: disable=protected-access + input_tensor = layers._inner_flatten(args.input_tensor, output_rank) + weight_tensor = None + if args.weight_tensor is not None: + weight_tensor = layers._inner_flatten(args.weight_tensor, output_rank) + # pylint: enable=protected-access + + # This option is only enabled for scattered_embedding_column. + if args.hash_key: + embeddings = contrib_variables.model_variable( + name="weights", + shape=[args.vocab_size], + dtype=dtypes.float32, + initializer=args.initializer, + trainable=(trainable and args.trainable), + collections=weight_collections) + + return embedding_ops.scattered_embedding_lookup_sparse( + embeddings, + input_tensor, + args.dimension, + hash_key=args.hash_key, + combiner=args.combiner, + name="lookup") + + if args.shared_embedding_name is not None: + shared_embedding_collection_name = ( + "SHARED_EMBEDDING_COLLECTION_" + args.shared_embedding_name.upper()) + graph = ops.get_default_graph() + shared_embedding_collection = ( + graph.get_collection_ref(shared_embedding_collection_name)) + shape = [args.vocab_size, args.dimension] + if shared_embedding_collection: + if len(shared_embedding_collection) > 1: + raise ValueError( + "Collection %s can only contain one " + "(partitioned) variable." % shared_embedding_collection_name) + else: + embeddings = shared_embedding_collection[0] + if embeddings.get_shape() != shape: + raise ValueError( + "The embedding variable with name {} already " + "exists, but its shape does not match required " + "embedding shape here. Please make sure to use " + "different shared_embedding_name for different " + "shared embeddings.".format(args.shared_embedding_name)) + else: + embeddings = contrib_variables.model_variable( + name=args.shared_embedding_name, + shape=shape, + dtype=dtypes.float32, + initializer=args.initializer, + trainable=(trainable and args.trainable), + collections=weight_collections) + graph.add_to_collection(shared_embedding_collection_name, embeddings) + else: + embeddings = contrib_variables.model_variable( + name="weights", + shape=[args.vocab_size, args.dimension], + dtype=dtypes.float32, + initializer=args.initializer, + trainable=(trainable and args.trainable), + collections=weight_collections) + + if _is_variable(embeddings): + embeddings = [embeddings] + else: + embeddings = embeddings._get_variable_list() # pylint: disable=protected-access + # pylint: disable=protected-access + _maybe_restore_from_checkpoint(column._checkpoint_path(), embeddings) + return embedding_ops.safe_embedding_lookup_sparse( + embeddings, + input_tensor, + sparse_weights=weight_tensor, + combiner=args.combiner, + name=column.name + "weights", + max_norm=args.max_norm) + + +def _maybe_restore_from_checkpoint(checkpoint_path, variable): + if checkpoint_path is not None: + path, tensor_name = checkpoint_path + weights_to_restore = variable + if len(variable) == 1: + weights_to_restore = variable[0] + checkpoint_utils.init_from_checkpoint(path, + {tensor_name: weights_to_restore}) + def one_hot_column(sparse_id_column): """Creates an `_OneHotColumn` for a one-hot or multi-hot repr in a DNN. diff --git a/tensorflow/contrib/layers/python/layers/feature_column_ops.py b/tensorflow/contrib/layers/python/layers/feature_column_ops.py index 31aca87002a..d010ae6df14 100644 --- a/tensorflow/contrib/layers/python/layers/feature_column_ops.py +++ b/tensorflow/contrib/layers/python/layers/feature_column_ops.py @@ -20,7 +20,6 @@ from __future__ import print_function import functools -from tensorflow.contrib.framework.python.framework import checkpoint_utils from tensorflow.contrib.framework.python.framework import experimental from tensorflow.contrib.framework.python.ops import variables as contrib_variables from tensorflow.contrib.layers.python.layers import embedding_ops @@ -34,118 +33,12 @@ from tensorflow.python.ops import init_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import nn_ops from tensorflow.python.ops import parsing_ops -from tensorflow.python.ops import resource_variable_ops from tensorflow.python.ops import sparse_ops from tensorflow.python.ops import variable_scope -from tensorflow.python.ops import variables from tensorflow.python.platform import tf_logging as logging from tensorflow.python.util import nest -def _is_variable(v): - """Returns true if `v` is a variable.""" - return isinstance(v, (variables.Variable, - resource_variable_ops.ResourceVariable)) - - -def _embeddings_from_arguments(column, - args, - weight_collections, - trainable, - output_rank=2): - """Returns embeddings for a column based on the computed arguments. - - Args: - column: the column name. - args: the _DeepEmbeddingLookupArguments for this column. - weight_collections: collections to store weights in. - trainable: whether these embeddings should be trainable. - output_rank: the desired rank of the returned `Tensor`. Inner dimensions will - be combined to produce the desired rank. - - Returns: - the embeddings. - - Raises: - ValueError: if not possible to create. - """ - # pylint: disable=protected-access - input_tensor = layers._inner_flatten(args.input_tensor, output_rank) - weight_tensor = None - if args.weight_tensor is not None: - weight_tensor = layers._inner_flatten(args.weight_tensor, output_rank) - # pylint: enable=protected-access - - # This option is only enabled for scattered_embedding_column. - if args.hash_key: - embeddings = contrib_variables.model_variable( - name='weights', - shape=[args.vocab_size], - dtype=dtypes.float32, - initializer=args.initializer, - trainable=(trainable and args.trainable), - collections=weight_collections) - - return embedding_ops.scattered_embedding_lookup_sparse( - embeddings, input_tensor, args.dimension, - hash_key=args.hash_key, - combiner=args.combiner, name='lookup') - - if args.shared_embedding_name is not None: - shared_embedding_collection_name = ( - 'SHARED_EMBEDDING_COLLECTION_' + args.shared_embedding_name.upper()) - graph = ops.get_default_graph() - shared_embedding_collection = ( - graph.get_collection_ref(shared_embedding_collection_name)) - shape = [args.vocab_size, args.dimension] - if shared_embedding_collection: - if len(shared_embedding_collection) > 1: - raise ValueError('Collection %s can only contain one ' - '(partitioned) variable.' - % shared_embedding_collection_name) - else: - embeddings = shared_embedding_collection[0] - if embeddings.get_shape() != shape: - raise ValueError('The embedding variable with name {} already ' - 'exists, but its shape does not match required ' - 'embedding shape here. Please make sure to use ' - 'different shared_embedding_name for different ' - 'shared embeddings.'.format( - args.shared_embedding_name)) - else: - embeddings = contrib_variables.model_variable( - name=args.shared_embedding_name, - shape=shape, - dtype=dtypes.float32, - initializer=args.initializer, - trainable=(trainable and args.trainable), - collections=weight_collections) - graph.add_to_collection(shared_embedding_collection_name, embeddings) - else: - embeddings = contrib_variables.model_variable( - name='weights', - shape=[args.vocab_size, args.dimension], - dtype=dtypes.float32, - initializer=args.initializer, - trainable=(trainable and args.trainable), - collections=weight_collections) - - if _is_variable(embeddings): - embeddings = [embeddings] - else: - embeddings = embeddings._get_variable_list() # pylint: disable=protected-access - # pylint: disable=protected-access - _maybe_restore_from_checkpoint( - column._checkpoint_path(), embeddings) - return embedding_ops.safe_embedding_lookup_sparse( - embeddings, - input_tensor, - sparse_weights=weight_tensor, - combiner=args.combiner, - name=column.name + 'weights', - max_norm=args.max_norm) - - def _maybe_reshape_input_tensor(tensor, column_name, output_rank): """Reshape the input tensor by the following rule. @@ -232,12 +125,13 @@ def _input_from_feature_columns(columns_to_tensors, # pylint: disable=protected-access arguments = column._deep_embedding_lookup_arguments( transformed_tensor) - output_tensors.append(_embeddings_from_arguments( - column, - arguments, - weight_collections, - trainable, - output_rank=output_rank)) + output_tensors.append( + fc._embeddings_from_arguments( # pylint: disable=protected-access + column, + arguments, + weight_collections, + trainable, + output_rank=output_rank)) except NotImplementedError as ee: try: @@ -393,7 +287,7 @@ def _create_embedding_lookup(column, initializer=embedding_lookup_arguments.initializer, trainable=trainable, collections=weight_collections) - if _is_variable(variable): + if fc._is_variable(variable): # pylint: disable=protected-access variable = [variable] else: variable = variable._get_variable_list() # pylint: disable=protected-access @@ -406,16 +300,6 @@ def _create_embedding_lookup(column, return variable, predictions -def _maybe_restore_from_checkpoint(checkpoint_path, variable): - if checkpoint_path is not None: - path, tensor_name = checkpoint_path - weights_to_restore = variable - if len(variable) == 1: - weights_to_restore = variable[0] - checkpoint_utils.init_from_checkpoint(path, - {tensor_name: weights_to_restore}) - - def _create_joint_embedding_lookup(columns_to_tensors, embedding_lookup_arguments, num_outputs, @@ -451,7 +335,7 @@ def _create_joint_embedding_lookup(columns_to_tensors, initializer=init_ops.zeros_initializer(), trainable=trainable, collections=weight_collections) - if _is_variable(variable): + if fc._is_variable(variable): # pylint: disable=protected-access variable = [variable] else: variable = variable._get_variable_list() # pylint: disable=protected-access @@ -634,7 +518,7 @@ def weighted_sum_from_feature_columns(columns_to_tensors, predictions, shape=(-1, num_outputs))) column_to_variable[column] = variable _log_variable(variable) - _maybe_restore_from_checkpoint(column._checkpoint_path(), variable) + fc._maybe_restore_from_checkpoint(column._checkpoint_path(), variable) # pylint: disable=protected-access # pylint: enable=protected-access predictions_no_bias = math_ops.add_n(output_tensors) bias = contrib_variables.model_variable( @@ -827,10 +711,10 @@ def parse_feature_columns_from_sequence_examples( def _log_variable(variable): if isinstance(variable, list): for var in variable: - if _is_variable(variable): + if fc._is_variable(variable): # pylint: disable=protected-access logging.info('Created variable %s, with device=%s', var.name, var.device) - elif _is_variable(variable): + elif fc._is_variable(variable): # pylint: disable=protected-access logging.info('Created variable %s, with device=%s', variable.name, variable.device) diff --git a/tensorflow/contrib/layers/python/layers/feature_column_ops_test.py b/tensorflow/contrib/layers/python/layers/feature_column_ops_test.py index a09cc53571b..01239212664 100644 --- a/tensorflow/contrib/layers/python/layers/feature_column_ops_test.py +++ b/tensorflow/contrib/layers/python/layers/feature_column_ops_test.py @@ -597,12 +597,15 @@ class CreateInputLayersForDNNsTest(test.TestCase): "income": constant_op.constant([[20.3, 10], [110.3, 0.4], [-3.0, 30.4]]), } - output = feature_column_ops.input_from_feature_columns(features, [ - one_hot_column, embedding_column, real_valued_column]) + columns = [one_hot_column, embedding_column, real_valued_column] + output = feature_column_ops.input_from_feature_columns(features, columns) + output_core = fc_core.make_input_layer(features, columns) with self.test_session(): variables_lib.global_variables_initializer().run() lookup_ops.tables_initializer().run() self.assertAllEqual(output.eval().shape, [3, 2 + 4 + 10]) + # Verify cross compatibility: Core builder output should equal to contrib. + self.assertAllEqual(output.eval().shape, output_core.eval().shape) def testRealValuedColumn(self): real_valued = feature_column.real_valued_column("price") @@ -712,11 +715,14 @@ class CreateInputLayersForDNNsTest(test.TestCase): one_hot_column = feature_column.one_hot_column(weighted_ids_column) output = feature_column_ops.input_from_feature_columns(features, [one_hot_column]) + output_core = fc_core.make_input_layer(features, [one_hot_column]) with self.test_session(): variables_lib.global_variables_initializer().run() lookup_ops.tables_initializer().run() self.assertAllEqual([[0, 0, 10., 0], [0, 20., 0, 0], [30., 0, 40., 0]], output.eval()) + # Verify cross compatibility: Core builder output should equal to contrib. + self.assertAllEqual(output.eval(), output_core.eval()) def testOneHotColumnFromSparseColumnWithKeysSucceedsForDNN(self): ids_column = feature_column.sparse_column_with_keys( @@ -729,12 +735,15 @@ class CreateInputLayersForDNNsTest(test.TestCase): features = {"ids": ids_tensor} output = feature_column_ops.input_from_feature_columns(features, [one_hot_sparse]) + output_core = fc_core.make_input_layer(features, [one_hot_sparse]) with self.test_session(): variables_lib.global_variables_initializer().run() lookup_ops.tables_initializer().run() self.assertAllEqual([[0, 0, 1, 0], [0, 1, 0, 0], [1, 0, 0, 0]], output.eval()) + # Verify cross compatibility: Core builder output should equal to contrib. + self.assertAllEqual(output.eval(), output_core.eval()) def testOneHotColumnFromMultivalentSparseColumnWithKeysSucceedsForDNN(self): ids_column = feature_column.sparse_column_with_keys( @@ -747,12 +756,15 @@ class CreateInputLayersForDNNsTest(test.TestCase): features = {"ids": ids_tensor} output = feature_column_ops.input_from_feature_columns(features, [one_hot_sparse]) + output_core = fc_core.make_input_layer(features, [one_hot_sparse]) with self.test_session(): variables_lib.global_variables_initializer().run() lookup_ops.tables_initializer().run() self.assertAllEqual([[0, 0, 1, 0], [0, 1, 0, 0], [1, 0, 1, 0]], output.eval()) + # Verify cross compatibility: Core builder output should equal to contrib. + self.assertAllEqual(output.eval(), output_core.eval()) def testOneHotColumnFromSparseColumnWithIntegerizedFeaturePassesForDNN(self): ids_column = feature_column.sparse_column_with_integerized_feature( @@ -767,10 +779,13 @@ class CreateInputLayersForDNNsTest(test.TestCase): } output = feature_column_ops.input_from_feature_columns(features, [one_hot_sparse]) + output_core = fc_core.make_input_layer(features, [one_hot_sparse]) with self.test_session(): variables_lib.global_variables_initializer().run() self.assertAllEqual([[0, 0, 1, 0], [0, 1, 0, 0], [1, 0, 1, 0]], output.eval()) + # Verify cross compatibility: Core builder output should equal to contrib. + self.assertAllEqual(output.eval(), output_core.eval()) def testOneHotColumnFromSparseColumnWithHashBucketSucceedsForDNN(self): hashed_sparse = feature_column.sparse_column_with_hash_bucket("feat", 10) @@ -782,10 +797,13 @@ class CreateInputLayersForDNNsTest(test.TestCase): one_hot_sparse = feature_column.one_hot_column(hashed_sparse) output = feature_column_ops.input_from_feature_columns(features, [one_hot_sparse]) + output_core = fc_core.make_input_layer(features, [one_hot_sparse]) with self.test_session(): variables_lib.global_variables_initializer().run() lookup_ops.tables_initializer().run() self.assertAllEqual([3, 10], output.eval().shape) + # Verify cross compatibility: Core builder output should equal to contrib. + self.assertAllEqual(output.eval(), output_core.eval()) def testEmbeddingColumnSucceedsForDNN(self): hashed_sparse = feature_column.sparse_column_with_hash_bucket("wire", 10) @@ -797,9 +815,12 @@ class CreateInputLayersForDNNsTest(test.TestCase): embeded_sparse = feature_column.embedding_column(hashed_sparse, 10) output = feature_column_ops.input_from_feature_columns(features, [embeded_sparse]) + output_core = fc_core.make_input_layer(features, [embeded_sparse]) with self.test_session(): variables_lib.global_variables_initializer().run() self.assertAllEqual(output.eval().shape, [4, 10]) + # Verify cross compatibility: Core builder output should equal to contrib. + self.assertAllEqual(output.eval().shape, output_core.eval().shape) def testScatteredEmbeddingColumnSucceedsForDNN(self): wire_tensor = sparse_tensor.SparseTensor( @@ -838,12 +859,15 @@ class CreateInputLayersForDNNsTest(test.TestCase): initializer=init_ops.constant_initializer(init_value)) output = feature_column_ops.input_from_feature_columns(features, [embeded_sparse]) + output_core = fc_core.make_input_layer(features, [embeded_sparse]) with self.test_session(): variables_lib.global_variables_initializer().run() output_eval = output.eval() self.assertAllEqual(output_eval.shape, [2, 10]) self.assertAllClose(output_eval, np.tile(init_value, [2, 10])) + # Verify cross compatibility: Core builder output should equal to contrib. + self.assertAllEqual(output.eval(), output_core.eval()) def testEmbeddingColumnWithMultipleInitializersFails(self): hashed_sparse = feature_column.sparse_column_with_hash_bucket("wire", 10) @@ -889,10 +913,14 @@ class CreateInputLayersForDNNsTest(test.TestCase): embeded_sparse = feature_column.embedding_column(weighted_ids, 10) output = feature_column_ops.input_from_feature_columns(features, [embeded_sparse]) + output_core = fc_core.make_input_layer(features, [embeded_sparse]) + with self.test_session(): variables_lib.global_variables_initializer().run() lookup_ops.tables_initializer().run() self.assertAllEqual(output.eval().shape, [2, 10]) + # Verify cross compatibility: Core builder output should equal to contrib. + self.assertAllEqual(output.eval().shape, output_core.eval().shape) def testEmbeddingColumnWithIntegerWeightedSparseColumnSucceedsForDNN(self): """Same as the previous test, but with integer weights.""" @@ -1534,9 +1562,12 @@ class WeightedSumTest(test.TestCase): features = {"wire": wire_tensor} logits, _, _ = feature_column_ops.weighted_sum_from_feature_columns( features, [hashed_sparse], num_outputs=5) + logits_core = fc_core.make_linear_model(features, [hashed_sparse], units=5) with self.test_session(): variables_lib.global_variables_initializer().run() self.assertAllEqual(logits.eval().shape, [2, 5]) + # Verify cross compatibility: Core builder output should equal to contrib. + self.assertAllEqual(logits.eval(), logits_core.eval()) def testSparseIntColumn(self): """Tests a sparse column with int values.""" @@ -1549,9 +1580,12 @@ class WeightedSumTest(test.TestCase): features = {"wire": wire_tensor} logits, _, _ = feature_column_ops.weighted_sum_from_feature_columns( features, [hashed_sparse], num_outputs=5) + logits_core = fc_core.make_linear_model(features, [hashed_sparse], units=5) with self.test_session(): variables_lib.global_variables_initializer().run() self.assertAllEqual(logits.eval().shape, [2, 5]) + # Verify cross compatibility: Core builder output should equal to contrib. + self.assertAllEqual(logits.eval(), logits_core.eval()) def testSparseColumnWithDenseInputTensor(self): hashed_sparse = feature_column.sparse_column_with_hash_bucket("wire", 10) @@ -1560,9 +1594,12 @@ class WeightedSumTest(test.TestCase): features = {"wire": wire_tensor} logits, _, _ = feature_column_ops.weighted_sum_from_feature_columns( features, [hashed_sparse], num_outputs=5) + logits_core = fc_core.make_linear_model(features, [hashed_sparse], units=5) with self.test_session(): variables_lib.global_variables_initializer().run() self.assertAllEqual(logits.eval().shape, [2, 5]) + # Verify cross compatibility: Core builder output should equal to contrib. + self.assertAllEqual(logits.eval(), logits_core.eval()) def testWeightedSparseColumn(self): ids = feature_column.sparse_column_with_keys("ids", @@ -1579,10 +1616,13 @@ class WeightedSumTest(test.TestCase): features = {"ids": ids_tensor, "weights": weights_tensor} logits, _, _ = feature_column_ops.weighted_sum_from_feature_columns( features, [weighted_ids], num_outputs=5) + logits_core = fc_core.make_linear_model(features, [weighted_ids], units=5) with self.test_session(): variables_lib.global_variables_initializer().run() lookup_ops.tables_initializer().run() self.assertAllEqual(logits.eval().shape, [2, 5]) + # Verify cross compatibility: Core builder output should equal to contrib. + self.assertAllEqual(logits.eval(), logits_core.eval()) def testWeightedSparseColumnWithDenseInputTensor(self): ids = feature_column.sparse_column_with_keys( @@ -1594,11 +1634,14 @@ class WeightedSumTest(test.TestCase): features = {"ids": ids_tensor, "weights": weights_tensor} logits, _, _ = feature_column_ops.weighted_sum_from_feature_columns( features, [weighted_ids], num_outputs=5) + logits_core = fc_core.make_linear_model(features, [weighted_ids], units=5) with self.test_session(): variables_lib.global_variables_initializer().run() lookup_ops.tables_initializer().run() self.assertAllEqual(logits.eval().shape, [2, 5]) + # Verify cross compatibility: Core builder output should equal to contrib. + self.assertAllEqual(logits.eval(), logits_core.eval()) def testCrossedColumn(self): a = feature_column.sparse_column_with_hash_bucket( @@ -1649,6 +1692,8 @@ class WeightedSumTest(test.TestCase): output, column_to_variable, _ = ( feature_column_ops.weighted_sum_from_feature_columns( features, [movies], num_outputs=1)) + logits_core = fc_core.make_linear_model(features, [movies]) + with self.test_session() as sess: variables_lib.initialize_all_variables().run() lookup_ops.tables_initializer().run() @@ -1659,6 +1704,8 @@ class WeightedSumTest(test.TestCase): # score for first example = 0.3 (matrix) + 0.1 (head-on) = 0.4 # score for second example = 0.5 (winter sleep) self.assertAllClose(output.eval(), [[0.4], [0.5]]) + # Cross compatibility: Core builder output should equal to contrib. + self.assertAllEqual(output.eval().shape, logits_core.eval().shape) def testRealValuedColumnWithMultiDimensions(self): real_valued = feature_column.real_valued_column("price", 2) From 2311dfc8ec1cef44dddb37603211337f48708824 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Fri, 5 May 2017 10:08:29 -0800 Subject: [PATCH 13/27] Fix a bug in save_model_cli 'show'. Change: 155217646 --- tensorflow/python/tools/saved_model_cli.py | 9 +++++++-- tensorflow/python/tools/saved_model_cli_test.py | 10 ++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/tensorflow/python/tools/saved_model_cli.py b/tensorflow/python/tools/saved_model_cli.py index c9c56a50143..e19b1876814 100644 --- a/tensorflow/python/tools/saved_model_cli.py +++ b/tensorflow/python/tools/saved_model_cli.py @@ -504,7 +504,14 @@ def run(args): Args: args: A namespace parsed from command line. + + Raises: + AttributeError: An error when neither --inputs nor --input_exprs is passed + to run command. """ + if not args.inputs and not args.input_exprs: + raise AttributeError( + 'At least one of --inputs and --input_exprs must be required') tensor_key_feed_dict = load_inputs_from_input_arg_string( args.inputs, args.input_exprs) run_saved_model_with_feed_dict(args.dir, args.tag_set, args.signature_def, @@ -629,8 +636,6 @@ def create_parser(): def main(): parser = create_parser() args = parser.parse_args() - if not args.inputs and not args.input_exprs: - args.error('At least one of --inputs and --input_exprs is required') args.func(args) diff --git a/tensorflow/python/tools/saved_model_cli_test.py b/tensorflow/python/tools/saved_model_cli_test.py index 1c7a44b3ebd..8f79c888ebd 100644 --- a/tensorflow/python/tools/saved_model_cli_test.py +++ b/tensorflow/python/tools/saved_model_cli_test.py @@ -409,6 +409,16 @@ Method name is: tensorflow/serving/predict""" with self.assertRaises(RuntimeError): saved_model_cli.run(args) + def testRunCommandInputNotGivenError(self): + self.parser = saved_model_cli.create_parser() + base_path = test.test_src_dir_path(SAVED_MODEL_PATH) + args = self.parser.parse_args([ + 'run', '--dir', base_path, '--tag_set', 'serve', '--signature_def', + 'serving_default' + ]) + with self.assertRaises(AttributeError): + saved_model_cli.run(args) + def testRunCommandWithDebuggerEnabled(self): self.parser = saved_model_cli.create_parser() base_path = test.test_src_dir_path(SAVED_MODEL_PATH) From f3e4e98fdd988b8d6d4b4a014b6974144e73183a Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Fri, 5 May 2017 11:03:49 -0800 Subject: [PATCH 14/27] Add d3 v4 The old version will be deleted when the migration is completed. The new version can be referenced with the following build labels: - @org_d3js_v4 (for d3.js) - //tensorflow/tensorboard/components/tf_imports:d3v4.d.ts Change: 155224862 --- tensorflow/workspace.bzl | 333 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 331 insertions(+), 2 deletions(-) diff --git a/tensorflow/workspace.bzl b/tensorflow/workspace.bzl index 14fce6cf404..93300d9fb10 100644 --- a/tensorflow/workspace.bzl +++ b/tensorflow/workspace.bzl @@ -797,6 +797,27 @@ def tf_workspace(path_prefix="", tf_repo_name=""): }, ) + # TODO: Delete previous rule and rename this one org_d3js + filegroup_external( + name = "org_d3js_v4", + # no @license header + licenses = ["notice"], # BSD-3-Clause + sha256_urls_extract = { + "b5fac5b296bc196e6aa7b59f9e33986fc44d23d59a0e211705187be9e35b943d": [ + "http://bazel-mirror.storage.googleapis.com/github.com/d3/d3/releases/download/v4.8.0/d3.zip", + "https://github.com/d3/d3/releases/download/v4.8.0/d3.zip", + ], + }, + # TODO(jart): Use srcs=["d3.js"] instead of this once supported. + generated_rule_name = "all_files", + extra_build_file_content = "\n".join([ + "filegroup(", + " name = \"org_d3js_v4\",", + " srcs = [\"d3.js\"],", + ")", + ]), + ) + filegroup_external( name = "org_definitelytyped", licenses = ["notice"], # MIT @@ -806,8 +827,8 @@ def tf_workspace(path_prefix="", tf_repo_name=""): "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/ebc69904eb78f94030d5d517b42db20867f679c0/chai/chai.d.ts", ], "177293828c7a206bf2a7f725753d51396d38668311aa37c96445f91bbf8128a7": [ - "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/6e2f2280ef16ef277049d0ce8583af167d586c59/d3/d3.d.ts", - "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/6e2f2280ef16ef277049d0ce8583af167d586c59/d3/d3.d.ts", + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/6e2f2280ef16ef277049d0ce8583af167d586c59/d3/d3.d.ts", # v3 + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/6e2f2280ef16ef277049d0ce8583af167d586c59/d3/d3.d.ts", # v3 ], "e4cd3d5de0eb3bc7b1063b50d336764a0ac82a658b39b5cf90511f489ffdee60": [ "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/efd40e67ff323f7147651bdbef03c03ead7b1675/lodash/lodash.d.ts", @@ -828,6 +849,314 @@ def tf_workspace(path_prefix="", tf_repo_name=""): }, ) + filegroup_external( + name = "org_definitelytyped_types_d3_array", + licenses = ["notice"], # MIT + sha256_urls = { + "61e7abb7b1f01fbcb0cab8cf39003392f422566209edd681fbd070eaa84ca000": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-array/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-array/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_axis", + licenses = ["notice"], # MIT + sha256_urls = { + "95f75c8dcc89850b2e72581d96a7b5f46ea4ac852f828893f141f14a597421f9": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-axis/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-axis/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_brush", + licenses = ["notice"], # MIT + sha256_urls = { + "a2738e693ce8a8640c2d29001e77582c9c361fd23bda44db471629866b60ada7": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-brush/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-brush/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_chord", + licenses = ["notice"], # MIT + sha256_urls = { + "c54d24756eb6d744b31e538ad9bab3a75f6d54e2288b29cc72338d4a057d3e83": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-chord/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-chord/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_collection", + licenses = ["notice"], # MIT + sha256_urls = { + "f987667167b1d2970911247e325eb1c37ca0823646f81ccec837ae59039822f7": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-collection/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-collection/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_color", + licenses = ["notice"], # MIT + sha256_urls = { + "9580c81f38ddcce7be0ac9bd3d0d083adebc34e17441709f90b9e4dcd1c19a56": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-color/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-color/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_dispatch", + licenses = ["notice"], # MIT + sha256_urls = { + "169f80b4cceca8e2e9ed384d81a5db0624cc01a26451dfb5a7e0cec6ea9cfb06": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-dispatch/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-dispatch/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_drag", + licenses = ["notice"], # MIT + sha256_urls = { + "08d35d139dde58c2722be98d718d01204fd6167d310f09b379e832f3c741489d": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-drag/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-drag/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_dsv", + licenses = ["notice"], # MIT + sha256_urls = { + "62594d00cf9e4bb895339c8e56f64330e202a5eb2a0fa580a1f6e6336f2c93ce": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-dsv/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-dsv/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_ease", + licenses = ["notice"], # MIT + sha256_urls = { + "d1cf8f99b7bf758c2ba3c0a4ce553e151d4d9b4cf45a6e8bd0edec7ce90f725b": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-ease/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-ease/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_force", + licenses = ["notice"], # MIT + sha256_urls = { + "288421e2008668d2076a4684657dd3d29b992832ef02c552981eb94a91042553": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-force/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-force/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_format", + licenses = ["notice"], # MIT + sha256_urls = { + "b42cb17e580c1fd0b64d478f7bd80ca806efaefda24426a833cf1f30a7275bca": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-format/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-format/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_hierarchy", + licenses = ["notice"], # MIT + sha256_urls = { + "a5683f5835d8716c6b89c075235078438cfab5897023ed720bfa492e244e969e": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-hierarchy/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-hierarchy/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_interpolate", + licenses = ["notice"], # MIT + sha256_urls = { + "590a71b741323ac3139b333ec8b743e24717fdd5b32bcff48ee521162a9dfe1c": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-interpolate/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-interpolate/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_path", + licenses = ["notice"], # MIT + sha256_urls = { + "96f35ba041bcaa265e2b373ee675177410d44d31c980e4f7fbeefd4bcba15b00": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-path/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-path/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_polygon", + licenses = ["notice"], # MIT + sha256_urls = { + "ce453451e8105cac6a4f4a4263ca2142ebb4bf442e342f470a81da691f220fcb": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-polygon/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-polygon/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_quadtree", + licenses = ["notice"], # MIT + sha256_urls = { + "238e278f1be5d6985a19800800cffee80f81199f71d848e3bbc288d1791a6f90": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-quadtree/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-quadtree/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_queue", + licenses = ["notice"], # MIT + sha256_urls = { + "e6ae19aad83495475653578de64fb9d6bf9764eda6c84d70f7935ec84bcc482e": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-queue/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-queue/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_random", + licenses = ["notice"], # MIT + sha256_urls = { + "d31b92ed86c23ec0a4776f99fa81ff033c95b96c8304d8aa9baf3b94af779aa8": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-random/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-random/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_request", + licenses = ["notice"], # MIT + sha256_urls = { + "44bb7b07d977028e6567540a3303b06fc9b33fb0960bc75c520e0733c840d89f": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-request/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-request/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_scale", + licenses = ["notice"], # MIT + sha256_urls = { + "02ce7c644ba34bd1abb84da2e832f248b048b6a23812be4365bd837f186c9f1f": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-scale/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-scale/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_selection", + licenses = ["notice"], # MIT + sha256_urls = { + "699043ddb28dfa5e46d87bc6a24cfc6d604237f298259d3fb3c7066e05e8c86e": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-selection/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-selection/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_shape", + licenses = ["notice"], # MIT + sha256_urls = { + "62668a7aaaf6232762b544f9f89c0f557ca7cfb0cd343a358dda7ecbe26f5739": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-shape/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-shape/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_time", + licenses = ["notice"], # MIT + sha256_urls = { + "0502490ce682fd9265fb1d5d693ce6cd82e3b05e5f5ee3433731266ecb03d5fc": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-time/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-time/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_timer", + licenses = ["notice"], # MIT + sha256_urls = { + "6f191f9aea704aa64b1defa40dfdff1447a6e6bb815feff1660f894500a9c94d": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-timer/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-timer/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_transition", + licenses = ["notice"], # MIT + sha256_urls = { + "a0a7c0c9bfb5c7d6d9d22a8d16b4484b66d13f2ed226954037546cb3da4098ba": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-transition/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-transition/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_voronoi", + licenses = ["notice"], # MIT + sha256_urls = { + "c6bd5f229f915151d0ef678fe50b1aa6a62334ea0a8c6fc0effbac9f7032efc7": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-voronoi/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-voronoi/index.d.ts", + ], + }, + ) + + filegroup_external( + name = "org_definitelytyped_types_d3_zoom", + licenses = ["notice"], # MIT + sha256_urls = { + "a25dc17fbd304cf7a0e5e7bbb8339c930d464eb40c4d6e5f839ce9c0191f4110": [ + "http://bazel-mirror.storage.googleapis.com/raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-zoom/index.d.ts", + "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/1550dfd1b8e38d9bf104b3fd16ea9bf98a2b358e/types/d3-zoom/index.d.ts", + ], + }, + ) + filegroup_external( name = "org_threejs", # no @license header From 532919a3be3a03fda4a7abba7d9403d05d6e8a31 Mon Sep 17 00:00:00 2001 From: Justin Lebar Date: Fri, 5 May 2017 11:07:04 -0800 Subject: [PATCH 15/27] Use hlo_matchers in more tests. Change: 155225266 --- .../xla/service/hlo_rematerialization_test.cc | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tensorflow/compiler/xla/service/hlo_rematerialization_test.cc b/tensorflow/compiler/xla/service/hlo_rematerialization_test.cc index 82de1c835be..2a1d728bc84 100644 --- a/tensorflow/compiler/xla/service/hlo_rematerialization_test.cc +++ b/tensorflow/compiler/xla/service/hlo_rematerialization_test.cc @@ -28,11 +28,13 @@ limitations under the License. #include "tensorflow/compiler/xla/types.h" #include "tensorflow/compiler/xla/xla_data.pb.h" -namespace op = xla::testing::opcode_matchers; - namespace xla { namespace { +namespace op = xla::testing::opcode_matchers; + +using ::testing::_; + class HloRematerializationTest : public HloTestBase { protected: // Creates and returns a computation which can benefit from @@ -145,11 +147,9 @@ TEST_F(HloRematerializationTest, SingleComputation) { // Find and save the original broadcast instruction which should be // rematerialized. const HloInstruction* slice = computation->root_instruction(); - ASSERT_EQ(HloOpcode::kSlice, slice->opcode()); + ASSERT_THAT(slice, op::Slice(op::Concatenate(op::Broadcast(_), _))); const HloInstruction* concat = slice->operand(0); - ASSERT_EQ(HloOpcode::kConcatenate, concat->opcode()); const HloInstruction* bcast = concat->operand(0); - ASSERT_EQ(HloOpcode::kBroadcast, bcast->opcode()); SequentialHloOrdering::HloModuleSequence sequence; // Computation requires 16KB without rematerialization, but uses only 12KB @@ -165,8 +165,7 @@ TEST_F(HloRematerializationTest, SingleComputation) { // The broadcast should have been rematerialized. const HloInstruction* remat_bcast = concat->operand(0); - EXPECT_EQ(HloOpcode::kBroadcast, remat_bcast->opcode()); - EXPECT_NE(bcast, remat_bcast); + EXPECT_THAT(remat_bcast, op::Broadcast(::testing::Ne(bcast))); // The rematerialized broadcast should be immediate before the concat in the // sequence. From 18dcf0973bc660aa9e84f89c7d3a913f9893f01b Mon Sep 17 00:00:00 2001 From: Petros Mol Date: Fri, 5 May 2017 11:34:59 -0800 Subject: [PATCH 16/27] - Adds a tutorial for dense kernel methods. - Adds a README file to contrib/kernel_methods Change: 155228213 --- tensorflow/contrib/kernel_methods/README.md | 55 ++++ .../kernel_methods/g3doc/acc-vs-trn_time.png | Bin 0 -> 17992 bytes .../kernel_methods/g3doc/acc_vs_outdim.png | Bin 0 -> 19835 bytes .../kernel_methods/g3doc/kernel_mapping.jpg | Bin 0 -> 7330 bytes .../contrib/kernel_methods/g3doc/tutorial.md | 273 ++++++++++++++++++ 5 files changed, 328 insertions(+) create mode 100644 tensorflow/contrib/kernel_methods/README.md create mode 100644 tensorflow/contrib/kernel_methods/g3doc/acc-vs-trn_time.png create mode 100644 tensorflow/contrib/kernel_methods/g3doc/acc_vs_outdim.png create mode 100644 tensorflow/contrib/kernel_methods/g3doc/kernel_mapping.jpg create mode 100644 tensorflow/contrib/kernel_methods/g3doc/tutorial.md diff --git a/tensorflow/contrib/kernel_methods/README.md b/tensorflow/contrib/kernel_methods/README.md new file mode 100644 index 00000000000..1913800af0e --- /dev/null +++ b/tensorflow/contrib/kernel_methods/README.md @@ -0,0 +1,55 @@ +# TensorFlow contrib kernel_methods. + +This module contains operations and estimators that enable the use of primal +(explicit) kernel methods in TensorFlow. See also the [tutorial](https://www.tensorflow.org/code/tensorflow/contrib/kernel_methods/g3doc/tutorial.md) on how to use this module to improve the quality of +classification or regression tasks. + +## Kernel Mappers +Implement explicit kernel mapping Ops over tensors. Kernel mappers add +Tensor-In-Tensor-Out (TITO) Ops to the TensorFlow graph. They can be used in +conjunction with other layers or ML models. + +Sample usage: + +```python +kernel_mapper = tf.contrib.kernel_methods.SomeKernelMapper(...) +out_tensor = kernel_mapper.map(in_tensor) +... # code that consumes out_tensor. +``` + +Currently, there is a [RandomFourierFeatureMapper] +(https://www.tensorflow.org/code/tensorflow/contrib/kernel_methods/python/mappers/random_fourier_features.py) implemented that maps dense +input to dense output. + +## Kernel-based Estimators +tf.contrib.learn Estimators that use kernel mappers internally to discover +non-linearities in the data. These canned estimators map their input features +using kernel mapper Ops and then apply linear models to the mapped +features. Combining kernel mappers with linear models and different loss +functions leads to a variety of models: linear and non-linear SVMs, linear +regression (with and without kernels) and (multinomial) logistic regression +(with and without kernels). + +Currently there is a [KernelLinearClassifier] +(https://www.tensorflow.org/code/tensorflow/contrib/kernel_methods/python/kernel_estimators.py) implemented but more pre-packaged estimators +are on the way. + +Sample usage: + +```python +real_column_a = tf.contrib.layers.real_valued_column(name='real_column_a',...) +sparse_column_b = tf.contrib.layers.sparse_column_with_hash_bucket(...) +kernel_mappers = {real_column_a : [tf.contrib.kernel_methods.SomeKernelMapper(...)]} +optimizer = ... + +kernel_classifier = tf.contrib.kernel_methods.KernelLinearClassifier( + feature_columns=[real_column_a, sparse_column_b], + model_dir=..., + optimizer=optimizer, + kernel_mappers=kernel_mappers) + +# Construct input_fns +kernel_classifier.fit(...) +kernel_classifier.evaluate(...) +``` + diff --git a/tensorflow/contrib/kernel_methods/g3doc/acc-vs-trn_time.png b/tensorflow/contrib/kernel_methods/g3doc/acc-vs-trn_time.png new file mode 100644 index 0000000000000000000000000000000000000000..1028bb390179cd21dba0b41b53a0b1eff4e345a4 GIT binary patch literal 17992 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 Y?@T<71`Y$^^fctA;$4M2IRpRy2BB%ktpET3 literal 0 HcmV?d00001 diff --git a/tensorflow/contrib/kernel_methods/g3doc/kernel_mapping.jpg b/tensorflow/contrib/kernel_methods/g3doc/kernel_mapping.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fd69fac76ee4cd85b18f594c8026a3398552071d GIT binary patch literal 7330 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 literal 0 HcmV?d00001 diff --git a/tensorflow/contrib/kernel_methods/g3doc/tutorial.md b/tensorflow/contrib/kernel_methods/g3doc/tutorial.md new file mode 100644 index 00000000000..51000080a7f --- /dev/null +++ b/tensorflow/contrib/kernel_methods/g3doc/tutorial.md @@ -0,0 +1,273 @@ +# Improving classification using explicit kernel methods + +In this tutorial, we demonstrate how combining (explicit) kernel methods with +linear models can drastically increase the latters' quality of predictions +without significantly increasing training and inference times. Currently, +explicit kernel mappings are supported for dense features. Support for sparse +features is in the works. + +We will use [tf.contrib.learn](https://www.tensorflow.org/code/tensorflow/contrib/learn/python/learn) (TensorFlow's high-level Machine Learning API) Estimators for our ML models. +tf.contrib.learn API reduces the boilerplate code one needs to write for +configuring, training and evaluating models and will let us focus on the core +ideas. If you are not familiar with this API, [tf.contrib.learn Quickstart](https://www.tensorflow.org/get_started/tflearn) is a good place to start. We +will use MNIST, a widely-used dataset containing images of handwritten digits +(between 0 and 9). The tutorial consists of the following steps: + +* Load and prepare MNIST data for classification. +* Construct a simple linear model, train it and evaluate it on the eval data. +* Replace the linear model with a kernelized linear model, re-train and +re-evaluate. + +## Load and prepare MNIST data for classification +The first step is to prepare the data to be fed to the ML models. The following +utility command from tf.contrib.learn loads the MNIST dataset: + +```python +data = tf.contrib.learn.datasets.mnist.load_mnist() +``` +This loads the entire MNIST dataset (containing 70K samples) and splits it into +train, validation and test data with 55K, 5K and 10K samples respectively. Each +split contains one numpy array for images (with shape [sample_size, 784]) and +one for labels (with shape [sample_size, 1]). In this tutorial, we only use the +train and validation splits (to train and evaluate our models respectively). + +In order to feed data to a tf.contrib.learn Estimator, it is helpful to convert +it to Tensors. For this, we will use an `input function` which adds Ops to the +TensorFlow graph that, when executed, create mini-batches of Tensors to be used +downstream. For more background on input functions, check +[Building Input Functions with tf.contrib.learn](https://www.tensorflow.org/get_started/input_fn). In this example, we will use the `tf.train.shuffle_batch` Op which, +besides converting numpy arrays to Tensors, allows us to specify the batch_size +and whether to randomize the input every time the input_fn Ops are executed +(randomization typically expedites convergence during training). The full code +for loading and preparing the data is shown in the snippet below. In this +example, we use mini-batches of size 256 for training and the entire sample (5K +entries) for evaluation. Feel free to experiment with different batch sizes. + +```python +import numpy as np +import tensorflow as tf + +def get_input_fn(dataset_split, batch_size, capacity=10000, min_after_dequeue=3000): + + def _input_fn(): + images_batch, labels_batch = tf.train.shuffle_batch( + tensors=[dataset_split.images, dataset_split.labels.astype(np.int32)], + batch_size=batch_size, + capacity=capacity, + min_after_dequeue=min_after_dequeue, + enqueue_many=True, + num_threads=4) + features_map = {'images': images_batch} + return features_map, labels_batch + + return _input_fn + +data = tf.contrib.learn.datasets.mnist.load_mnist() + +train_input_fn = get_input_fn(data.train, batch_size=256) +eval_input_fn = get_input_fn(data.validation, batch_size=5000) + +``` + +## Training a simple linear model +We can now train a linear model over the MNIST dataset. We will use the [tf.contrib.learn.LinearClassifier](https://www.tensorflow.org/code/tensorflow/contrib/learn/python/learn/estimators/linear.py) estimator with 10 classes (representing the 10 +digits). The input features form a 784-dimensional (dense) vector which can be +specified as follows: + +```python +image_column = tf.contrib.layers.real_valued_column('images', dimension=784) +``` + +The full code for constructing, training and evaluating a LinearClassifier +estimator is shown below. + +```python +import time + +# Specify the feature(s) to be used by the estimator. +image_column = tf.contrib.layers.real_valued_column('images', dimension=784) +estimator = tf.contrib.learn.LinearClassifier(feature_columns=[image_column], n_classes=10) + +# Train. +start = time.time() +estimator.fit(input_fn=train_input_fn, steps=2000) +end = time.time() +print('Elapsed time: {} seconds'.format(end - start)) + +# Evaluate and report metrics. +eval_metrics = estimator.evaluate(input_fn=eval_input_fn, steps=1) +print(eval_metrics) +``` +On eval data, the loss (i.e., the value of the objective function being +minimized during training) lies between **0.25 and 0.30** (depending on the +parameters used) while the accuracy of the classifier is approximately **92.5%** +(training is randomized so the exact loss and accuracy will vary). Also, the +training time is around 25 seconds (this will also vary based on the machine you +run the code on). + +In addition to experimenting with the (training) batch size and the number of +training steps, there are a couple other parameters that can be tuned as well. +For instance, you can change the optimization method used to minimize the loss +by explicitly selecting another optimizer from the collection of +[available optimizers] +(https://www.tensorflow.org/code/tensorflow/python/training). +As an example, the following code constructs a LinearClassifer estimator that +uses the Follow-The-Regularized-Leader (FTRL) optimization strategy with a +specific learning rate and l2-regularization. + + +```python +optimizer = tf.train.FtrlOptimizer(learning_rate=5.0, l2_regularization_strength=1.0) +estimator = tf.contrib.learn.LinearClassifier( + feature_columns=[image_column], n_classes=10, optimizer=optimizer) +``` + +Regardless of the values of the parameters, the max accuracy a linear model can +achieve on this dataset caps at around **93%**. + +## Using explicit kernel mappings with the linear model. +The relatively high error (~7%) of the linear model over MNIST indicates that +the input data is not linearly separable. We will use explicit kernel mappings +to reduce the classification error. + +**Intuition:** The high-level idea is to use a non-linear map to transform the +input space to another feature space (of possibly higher dimension) where the +(transformed) features are (almost) linearly separable and then apply a linear +model on the mapped features. This is shown in the following figure: + +

+ +
+ +**Technical details overview:** In this example we will use **Random Fourier +Features** (introduced in the ["Random Features for Large-Scale Kernel Machines"] +(https://people.eecs.berkeley.edu/~brecht/papers/07.rah.rec.nips.pdf) paper by +Rahimi and Recht) to map the input data. Random Fourier Features map a vector +$$\mathbf{x} \in \mathbb{R}^d$$ to $$\mathbf{x'} \in \mathbb{R}^D$$ via the +following mapping: + +$$ +RFFM(\cdot): \mathbb{R}^d \to \mathbb{R}^D, \quad +RFFM(\mathbf{x}) = \cos(\mathbf{\Omega} \cdot \mathbf{x}+ \mathbf{b}) +$$ + +where $$\mathbf{\Omega} \in \mathbb{R}^{D \times d}$$, +$$\mathbf{x} \in \mathbb{R}^d,$$ $$\mathbf{b} \in \mathbb{R}^D$$ and cosine is +applied elementwise. + +In this example, the entries of $$\mathbf{\Omega}$$ and $$\mathbf{b}$$ are +sampled from distributions such that the mapping satisfies the following +property: + +$$ +RFFM(\mathbf{x})^T \cdot RFFM(\mathbf{y}) \approx +e^{-\frac{\|\mathbf{x} - \mathbf{y}\|^2}{2 \sigma^2}} +$$ + +The right-hand-side quantity of the expression above is known as the RBF (or +Gaussian) kernel function. This function is one of the most-widely used kernel +functions in Machine Learning and measures (implicitly) similarity in a +different (much higher dimensional) space than the original one. See +[Radial basis function kernel](https://en.wikipedia.org/wiki/Radial_basis_function_kernel) +for more details. + +**Kernel Classifier:** `tf.contrib.kernel_methods.KernelLinearClassifier` is a +pre-packaged `tf.contrib.learn` estimator that combines the power of explicit +kernel mappings with linear models. Its API is very similar to that of the +LinearClassifier with the additional ability to specify a list of explicit +kernel mappings to be apply to each feature used by the classifier. The +following code snippet demonstrates how to replace LinearClassifier with +KernelLinearClassifier. + + +```python +# Specify the feature(s) to be used by the estimator. This is identical to the +# code used for the LinearClassifier. +image_column = tf.contrib.layers.real_valued_column('images', dimension=784) +optimizer = tf.train.FtrlOptimizer( + learning_rate=50.0, l2_regularization_strength=0.001) + + +kernel_mapper = tf.contrib.kernel_methods.RandomFourierFeatureMapper( + input_dim=784, output_dim=2000, stddev=5.0, name='rffm') +kernel_mappers = {image_column: [kernel_mapper]} +estimator = tf.contrib.kernel_methods.KernelLinearClassifier( + n_classes=10, optimizer=optimizer, kernel_mappers=kernel_mappers) + +# Train. +start = time.time() +estimator.fit(input_fn=train_input_fn, steps=2000) +end = time.time() +print('Elapsed time: {} seconds'.format(end - start)) + +# Evaluate and report metrics. +eval_metrics = estimator.evaluate(input_fn=eval_input_fn, steps=1) +print(eval_metrics) +``` +The only additional parameter passed to `KernelLinearClassifier` is a dictionary +from feature_columns to a list of kernel mappings to be applied to the +corresponding feature column. In this example, the lines + +```python +kernel_mapper = tf.contrib.kernel_methods.RandomFourierFeatureMapper( + input_dim=784, output_dim=2000, stddev=5.0, name='rffm') +kernel_mappers = {image_column: [kernel_mapper]} +estimator = tf.contrib.kernel_methods.KernelLinearClassifier( + n_classes=10, optimizer=optimizer, kernel_mappers=kernel_mappers) +``` +instruct the classifier to first map the initial 784-dimensional images to +2000-dimensional vectors using random Fourier features and then learn a linear +model on the transformed vectors. Note that, besides the output dimension, there +is one more parameter (stddev) involved. This parameter is the standard +deviation ($$\sigma$$) of the approximated RBF kernel and controls the +similarity measure used in classification. This parameter is typically +determined via hyperparameter tuning. + +Running the code above yields a loss of approximately **0.10** while the +accuracy is increased to approximately **97%** on eval data (an increase of 4% +over the plain linear model). The training time hovers around 35 seconds. We can +increase the accuracy even more, by increasing the output dimension of the +mapping and tuning the standard deviation even more. + +**On the role of stddev:** The classification quality is very sensitive to the +value of the stddev parameter used to define the similarity measure between the +pairs of input features. The following table shows the accuracy of the +classifier on the eval data for different values of stddev (for all experiments +the output dimension was fixed to 3000). The optimal value is stddev=5.0. Notice +how too small or too high stddev values can dramatically decrease the accuracy +of the classification. + +stddev | eval accuracy +:----- | :------------ +1.0 | 0.1362 +2.0 | 0.4764 +4.0 | 0.9654 +5.0 | 0.9766 +8.0 | 0.9714 +16.0 | 0.8878 + +**On the role of the output dimension:** Intuitively, the larger the output +dimension of the mapping, the closer the inner product of two mapped vectors +approximates the kernel which typically translates to better classification +accuracy. Another way to think about this is that the output dimension equals +the number of weights of the linear model (the larger this dimension, the larger +the "degrees of freedom" of the model). However, after a certain threshold, +higher output dimensions increase the accuracy by very little (while still +increasing the training time). This is shown in the following 2 Figures which +depict the eval accuracy as a function of the output dimension and the training +time respectively. + +![image](./acc_vs_outdim.png) ![image](./acc-vs-trn_time.png) + + +## Explicit Kernel Mappings: summary and practical tips +* Explicit kernel mappings combine the predictive power of non-linear models +with the scalability of linear models. +* Random Fourier Features can be particularly effective for datasets with dense +features. +* The parameters of the kernel mapping are often data-dependent. Model quality +can be very sensitive to these parameters. Use hyperparameter tuning to find the +optimal values. +* If you have multiple numerical features, concatinate them into a single +multi-dimensional one and apply the kernel mapping to the concatenated vector. + From 116229a5e3590b432a0307b7e79bc6f96cbe34de Mon Sep 17 00:00:00 2001 From: Toby Boyd Date: Fri, 5 May 2017 11:59:30 -0800 Subject: [PATCH 17/27] Updated numbers after running benchmarks on updated ResNet model. Change: 155230686 --- tensorflow/docs_src/performance/benchmarks.md | 143 +++++++++--------- 1 file changed, 74 insertions(+), 69 deletions(-) diff --git a/tensorflow/docs_src/performance/benchmarks.md b/tensorflow/docs_src/performance/benchmarks.md index 19d37794ab8..6bbc98ac0d7 100644 --- a/tensorflow/docs_src/performance/benchmarks.md +++ b/tensorflow/docs_src/performance/benchmarks.md @@ -80,10 +80,12 @@ section. * **OS:** Ubuntu 16.04 LTS with tests run via Docker * **CUDA / cuDNN:** 8.0 / 5.1 * **TensorFlow GitHub hash:** b1e174e +* **Benchmark GitHub hash:** 9165a70 * **Build Command:** `bazel build -c opt --copt=-march="haswell" --config=cuda //tensorflow/tools/pip_package:build_pip_package` * **Disk:** Local SSD * **DataSet:** ImageNet +* **Test Date:** May 2017 Batch size and optimizer used for each model are listed in the table below. In addition to the batch sizes listed in the table, InceptionV3, ResNet-50, @@ -120,19 +122,19 @@ VGG16 | replicated (with NCCL) | n/a GPUs | InceptionV3 | ResNet-50 | ResNet-152 | Alexnet | VGG16 ---- | ----------- | --------- | ---------- | ------- | ----- - 1 | 142 | 238 | 95.6 | 2987 | 154 - 2 | 284 | 479 | 187 | 5658 | 295 - 4 | 569 | 948 | 374 | 10509 | 584 - 8 | 1131 | 1886 | 744 | 17822 | 1081 +1 | 142 | 219 | 91.8 | 2987 | 154 +2 | 284 | 422 | 181 | 5658 | 295 +4 | 569 | 852 | 356 | 10509 | 584 +8 | 1131 | 1734 | 716 | 17822 | 1081 **Training real data** GPUs | InceptionV3 | ResNet-50 | ResNet-152 | Alexnet | VGG16 ---- | ----------- | --------- | ---------- | ------- | ----- - 1 | 142 | 239 | 95.5 | 2890 | 154 - 2 | 278 | 468 | 187 | 4448 | 284 - 4 | 551 | 938 | 373 | 7105 | 534 - 8 | 1079 | 1802 | 721 | N/A | 898 +1 | 142 | 218 | 91.4 | 2890 | 154 +2 | 278 | 425 | 179 | 4448 | 284 +4 | 551 | 853 | 359 | 7105 | 534 +8 | 1079 | 1630 | 708 | N/A | 898 Training AlexNet with real data on 8 GPUs was excluded from the graph and table above due to it maxing out the input pipeline. @@ -145,19 +147,19 @@ The results below are all with a batch size of 32. GPUs | InceptionV3 | ResNet-50 | ResNet-152 | VGG16 ---- | ----------- | --------- | ---------- | ----- - 1 | 128 | 210 | 85.3 | 144 - 2 | 259 | 412 | 166 | 281 - 4 | 520 | 827 | 330 | 549 - 8 | 995 | 1623 | 643 | 820 +1 | 128 | 195 | 82.7 | 144 +2 | 259 | 368 | 160 | 281 +4 | 520 | 768 | 317 | 549 +8 | 995 | 1485 | 632 | 820 **Training real data** GPUs | InceptionV3 | ResNet-50 | ResNet-152 | VGG16 ---- | ----------- | --------- | ---------- | ----- - 1 | 130 | 208 | 85.0 | 144 - 2 | 257 | 403 | 163 | 253 - 4 | 507 | 814 | 325 | 457 - 8 | 966 | 1525 | 641 | 690 +1 | 130 | 193 | 82.4 | 144 +2 | 257 | 369 | 159 | 253 +4 | 507 | 760 | 317 | 457 +8 | 966 | 1410 | 609 | 690 ## Details for Google Compute Engine (NVIDIA® Tesla® K80) @@ -168,11 +170,12 @@ GPUs | InceptionV3 | ResNet-50 | ResNet-152 | VGG16 * **OS:** Ubuntu 16.04 LTS * **CUDA / cuDNN:** 8.0 / 5.1 * **TensorFlow GitHub hash:** b1e174e +* **Benchmark GitHub hash:** 9165a70 * **Build Command:** `bazel build -c opt --copt=-march="haswell" --config=cuda //tensorflow/tools/pip_package:build_pip_package` * **Disk:** 1.7 TB Shared SSD persistent disk (800 MB/s) * **DataSet:** ImageNet -* **Test Date:** April 2017 +* **Test Date:** May 2017 Batch size and optimizer used for each model are listed in the table below. In addition to the batch sizes listed in the table, InceptionV3 and ResNet-50 were @@ -198,19 +201,19 @@ The configuration used for each model was `variable_update` equal to GPUs | InceptionV3 | ResNet-50 | ResNet-152 | Alexnet | VGG16 ---- | ----------- | --------- | ---------- | ------- | ----- - 1 | 30.5 | 56.8 | 20.8 | 656 | 35.4 - 2 | 57.8 | 107 | 39.1 | 1209 | 64.8 - 4 | 116 | 212 | 77.2 | 2328 | 120 - 8 | 227 | 419 | 151 | 4640 | 234 +1 | 30.5 | 51.9 | 20.0 | 656 | 35.4 +2 | 57.8 | 99.0 | 38.2 | 1209 | 64.8 +4 | 116 | 195 | 75.8 | 2328 | 120 +8 | 227 | 387 | 148 | 4640 | 234 **Training real data** GPUs | InceptionV3 | ResNet-50 | ResNet-152 | Alexnet | VGG16 ---- | ----------- | --------- | ---------- | ------- | ----- - 1 | 30.6 | 56.7 | 20.7 | 639 | 34.2 - 2 | 58.4 | 107 | 39.0 | 1136 | 62.9 - 4 | 115 | 211 | 77.3 | 2067 | 118 - 8 | 225 | 422 | 151 | 4056 | 230 +1 | 30.6 | 51.2 | 20.0 | 639 | 34.2 +2 | 58.4 | 98.8 | 38.3 | 1136 | 62.9 +4 | 115 | 194 | 75.4 | 2067 | 118 +8 | 225 | 381 | 148 | 4056 | 230 ### Other Results @@ -218,19 +221,19 @@ GPUs | InceptionV3 | ResNet-50 | ResNet-152 | Alexnet | VGG16 GPUs | InceptionV3 (batch size 32) | ResNet-50 (batch size 32) ---- | --------------------------- | ------------------------- -1 | 29.3 | 53.9 -2 | 55.0 | 101 -4 | 109 | 200 -8 | 216 | 398 +1 | 29.3 | 49.5 +2 | 55.0 | 95.4 +4 | 109 | 183 +8 | 216 | 362 **Training real data** GPUs | InceptionV3 (batch size 32) | ResNet-50 (batch size 32) ---- | --------------------------- | ------------------------- - 1 | 29.5 | 53.6 - 2 | 55.4 | 102 - 4 | 110 | 201 - 8 | 216 | 387 +1 | 29.5 | 49.3 +2 | 55.4 | 95.3 +4 | 110 | 186 +8 | 216 | 359 ## Details for Amazon EC2 (NVIDIA® Tesla® K80) @@ -241,12 +244,13 @@ GPUs | InceptionV3 (batch size 32) | ResNet-50 (batch size 32) * **OS:** Ubuntu 16.04 LTS * **CUDA / cuDNN:** 8.0 / 5.1 * **TensorFlow GitHub hash:** b1e174e +* **Benchmark GitHub hash:** 9165a70 * **Build Command:** `bazel build -c opt --copt=-march="haswell" --config=cuda //tensorflow/tools/pip_package:build_pip_package` * **Disk:** 1TB Amazon EFS (burst 100 MiB/sec for 12 hours, continuous 50 MiB/sec) * **DataSet:** ImageNet -* **Test Date:** April 2017 +* **Test Date:** May 2017 Batch size and optimizer used for each model are listed in the table below. In addition to the batch sizes listed in the table, InceptionV3 and ResNet-50 were @@ -279,19 +283,19 @@ VGG16 | parameter_server | gpu GPUs | InceptionV3 | ResNet-50 | ResNet-152 | Alexnet | VGG16 ---- | ----------- | --------- | ---------- | ------- | ----- - 1 | 30.8 | 56.3 | 20.9 | 684 | 36.3 - 2 | 58.7 | 108 | 39.3 | 1244 | 69.4 - 4 | 117 | 217 | 79.1 | 2479 | 141 - 8 | 230 | 419 | 156 | 4853 | 260 +1 | 30.8 | 51.5 | 19.7 | 684 | 36.3 +2 | 58.7 | 98.0 | 37.6 | 1244 | 69.4 +4 | 117 | 195 | 74.9 | 2479 | 141 +8 | 230 | 384 | 149 | 4853 | 260 **Training real data** GPUs | InceptionV3 | ResNet-50 | ResNet-152 | Alexnet | VGG16 ---- | ----------- | --------- | ---------- | ------- | ----- - 1 | 30.5 | 56.0 | 20.6 | 674 | 36.3 - 2 | 59.0 | 107 | 39.0 | 1227 | 67.5 - 4 | 118 | 205 | 77.9 | 2201 | 136 - 8 | 228 | 405 | 152 | N/A | 242 +1 | 30.5 | 51.3 | 19.7 | 674 | 36.3 +2 | 59.0 | 94.9 | 38.2 | 1227 | 67.5 +4 | 118 | 188 | 75.2 | 2201 | 136 +8 | 228 | 373 | 149 | N/A | 242 Training AlexNet with real data on 8 GPUs was excluded from the graph and table above due to our EFS setup not providing enough throughput. @@ -302,19 +306,19 @@ above due to our EFS setup not providing enough throughput. GPUs | InceptionV3 (batch size 32) | ResNet-50 (batch size 32) ---- | --------------------------- | ------------------------- -1 | 29.9 | 53.5 -2 | 57.5 | 101 -4 | 114 | 202 -8 | 216 | 380 +1 | 29.9 | 49.0 +2 | 57.5 | 94.1 +4 | 114 | 184 +8 | 216 | 355 **Training real data** GPUs | InceptionV3 (batch size 32) | ResNet-50 (batch size 32) ---- | --------------------------- | ------------------------- -1 | 30.0 | 53.6 -2 | 57.5 | 102 -4 | 113 | 202 -8 | 212 | 379 +1 | 30.0 | 49.1 +2 | 57.5 | 95.1 +4 | 113 | 185 +8 | 212 | 353 ## Details for Amazon EC2 Distributed (NVIDIA® Tesla® K80) @@ -325,11 +329,12 @@ GPUs | InceptionV3 (batch size 32) | ResNet-50 (batch size 32) * **OS:** Ubuntu 16.04 LTS * **CUDA / cuDNN:** 8.0 / 5.1 * **TensorFlow GitHub hash:** b1e174e +* **Benchmark GitHub hash:** 9165a70 * **Build Command:** `bazel build -c opt --copt=-march="haswell" --config=cuda //tensorflow/tools/pip_package:build_pip_package` * **Disk:** 1.0 TB EFS (burst 100 MB/sec for 12 hours, continuous 50 MB/sec) * **DataSet:** ImageNet -* **Test Date:** April 2017 +* **Test Date:** May 2017 The batch size and optimizer used for the tests are listed in the table. In addition to the batch sizes listed in the table, InceptionV3 and ResNet-50 were @@ -343,11 +348,11 @@ Optimizer | sgd | sgd | sgd Configuration used for each model. -Model | variable_update | local_parameter_device ------------ | ---------------------- | ---------------------- -InceptionV3 | distributed_replicated | n/a -ResNet-50 | distributed_replicated | n/a -ResNet-152 | distributed_replicated | n/a +Model | variable_update | local_parameter_device | cross_replica_sync +----------- | ---------------------- | ---------------------- | ------------------ +InceptionV3 | distributed_replicated | n/a | True +ResNet-50 | distributed_replicated | n/a | True +ResNet-152 | distributed_replicated | n/a | True To simplify server setup, EC2 instances (p2.8xlarge) running worker servers also ran parameter servers. Equal numbers of parameter servers and work servers were @@ -371,11 +376,11 @@ used with the following exceptions: GPUs | InceptionV3 | ResNet-50 | ResNet-152 ---- | ----------- | --------- | ---------- -1 | 29.7 | 55.0 | 19.8 -8 | 229 | 410 | 150 -16 | 459 | 825 | 300 -32 | 902 | 1468 | 575 -64 | 1783 | 3051 | 1004 +1 | 29.7 | 52.4 | 19.4 +8 | 229 | 378 | 146 +16 | 459 | 751 | 291 +32 | 902 | 1388 | 565 +64 | 1783 | 2744 | 981 ### Other Results @@ -387,23 +392,23 @@ GPUs | InceptionV3 | ResNet-50 | ResNet-152 GPUs | InceptionV3 (batch size 32) | ResNet-50 (batch size 32) ---- | --------------------------- | ------------------------- -1 | 29.2 | 53.0 -8 | 219 | 363 -16 | 427 | 719 -32 | 820 | 1265 -64 | 1608 | 2623 - +1 | 29.2 | 48.4 +8 | 219 | 333 +16 | 427 | 667 +32 | 820 | 1180 +64 | 1608 | 2315 ## Methodology -This [script](https://github.com/tensorflow/benchmarks/tree/master/scripts/tf_cnn_benchmarks) +This +[script](https://github.com/tensorflow/benchmarks/tree/master/scripts/tf_cnn_benchmarks) was run on the various platforms to generate the above results. @{$performance_models$High-Performance Models} details techniques in the script along with examples of how to execute the script. In order to create results that are as repeatable as possible, each test was run 5 times and then the times were averaged together. GPUs are run in their default -state on the given platform. For NVIDIA® Tesla® K80 this means leaving on [GPU +state on the given platform. For NVIDIA® Tesla® K80 this means leaving on [GPU Boost](https://devblogs.nvidia.com/parallelforall/increase-performance-gpu-boost-k80-autoboost/). For each test, 10 warmup steps are done and then the next 100 steps are averaged. From 56b2b7ab193b6fedb3dee58e847bad9776f69a16 Mon Sep 17 00:00:00 2001 From: Alexandre Passos Date: Fri, 5 May 2017 12:50:51 -0800 Subject: [PATCH 18/27] Internal change. Change: 155236037 --- tensorflow/python/framework/function.py | 138 ++++++++++++++---------- 1 file changed, 84 insertions(+), 54 deletions(-) diff --git a/tensorflow/python/framework/function.py b/tensorflow/python/framework/function.py index 2a1389b91ff..ac8aee2c83d 100644 --- a/tensorflow/python/framework/function.py +++ b/tensorflow/python/framework/function.py @@ -113,18 +113,19 @@ def _add_op_node(op, func, input_dict): node_def = func.node_def[-1] for i in range(len(node_def.input)): if not node_def.input[i].startswith("^"): - assert node_def.input[i] in input_dict, ( - "%s missing from %s" % (node_def.input[i], input_dict.items())) + assert node_def.input[i] in input_dict, ("%s missing from %s" % + (node_def.input[i], + input_dict.items())) node_def.input[i] = input_dict[node_def.input[i]] -def _graph_to_function_def(graph, inputs, outputs, out_names=None): +def _graph_to_function_def(graph, operations, inputs, outputs, out_names=None): """Returns `graph` as a `FunctionDef` protocol buffer. This method creates a [`FunctionDef`]( https://www.tensorflow.org/code/tensorflow/core/framework/function.proto) - protocol buffer that contains all the ops present in the graph. The - graph effectively becomes the body of the function. + protocol buffer that contains all the ops in `operations`. The + operations become the body of the function. The arguments `inputs` and `outputs` will be listed as the inputs and outputs tensors of the function. They must be lists of @@ -132,6 +133,8 @@ def _graph_to_function_def(graph, inputs, outputs, out_names=None): Args: graph: Graph. + operations: the operations to put in the function. Must be a subset of + the operations in the graph. inputs: List of tensors. Inputs to the function. outputs: List of tensors. Outputs of the function. out_names: Optional list of string names for the outputs. @@ -145,12 +148,12 @@ def _graph_to_function_def(graph, inputs, outputs, out_names=None): func = function_pb2.FunctionDef() func.signature.name = "_" used_names = set() - func.signature.input_arg.extend([_tensor_to_argdef(i, used_names=used_names) - for i in inputs]) + func.signature.input_arg.extend( + [_tensor_to_argdef(i, used_names=used_names) for i in inputs]) if out_names is None: used_names = set() - func.signature.output_arg.extend([ - _tensor_to_argdef(o, used_names=used_names) for o in outputs]) + func.signature.output_arg.extend( + [_tensor_to_argdef(o, used_names=used_names) for o in outputs]) elif len(outputs) != len(out_names): raise ValueError( "Length of out_names (%d) does not match number of outputs (%d): %s" % @@ -159,12 +162,12 @@ def _graph_to_function_def(graph, inputs, outputs, out_names=None): raise ValueError( "Must not have duplicates in out_names: %s" % ", ".join(out_names)) else: - func.signature.output_arg.extend([ - _tensor_to_argdef(o, name=n) for o, n in zip(outputs, out_names)]) + func.signature.output_arg.extend( + [_tensor_to_argdef(o, name=n) for o, n in zip(outputs, out_names)]) func_arg_placeholders = set([i.name for i in inputs]) input_dict = _create_input_dict(graph, func_arg_placeholders) - for op in graph.get_operations(): + for op in operations: if _is_in_placeholders(op, func_arg_placeholders): continue _add_op_node(op, func, input_dict) @@ -295,17 +298,18 @@ class _FuncGraph(ops.Graph): self.extra_args = [] self.extra_vars = [] - def getvar(self, - getter, - name, - shape=None, - dtype=None, - initializer=None, - reuse=None, - trainable=True, - collections=None, # pylint: disable=redefined-outer-name - use_resource=None, - **kwargs): + def getvar( + self, + getter, + name, + shape=None, + dtype=None, + initializer=None, + reuse=None, + trainable=True, + collections=None, # pylint: disable=redefined-outer-name + use_resource=None, + **kwargs): """A custom variable getter.""" # Here, we switch the default graph to the outer graph and ask the # variable scope in which the function is defined to give us the @@ -538,20 +542,23 @@ class _DefinedFunction(object): # Build the FunctionDef self._definition = _graph_to_function_def( - temp_graph, inputs, outputs, out_names=self._out_names) + temp_graph, + temp_graph.get_operations(), + inputs, + outputs, + out_names=self._out_names) # Extra kwargs are treated as attrs on the function def. sig_pre_func_name = self._func_name or _get_func_name(self._func) - kwargs_attr = _parse_kwargs_as_attrs( - sig_pre_func_name, **self._extra_kwargs) + kwargs_attr = _parse_kwargs_as_attrs(sig_pre_func_name, + **self._extra_kwargs) for k in kwargs_attr: self._definition.attr[k].CopyFrom(kwargs_attr[k]) # Hash the definition and its dependencies. self._hash_str = self._create_hash_str( self._definition.signature.input_arg, - self._definition.signature.output_arg, - self._definition.node_def) + self._definition.signature.output_arg, self._definition.node_def) # Finally, we decide the function name to use. If not specified, # make up something which is almost certainly unique (but deterministic). @@ -658,8 +665,8 @@ def _from_definition(fdef, grad_func=None): # have access to such a callable here). func = None argnames = [arg.name for arg in fdef.signature.input_arg] - input_types = tuple(dtypes.as_dtype(arg.type) - for arg in fdef.signature.input_arg) + input_types = tuple( + dtypes.as_dtype(arg.type) for arg in fdef.signature.input_arg) func_name = fdef.signature.name # Note: FunctionDefs do not include python gradient functions, so if the # original _DefinedFunction included one it will not be reflected here. @@ -675,8 +682,7 @@ def _from_definition(fdef, grad_func=None): result._extra_inputs = [] result._hash_str = result._create_hash_str( result._definition.signature.input_arg, - result._definition.signature.output_arg, - result._definition.node_def) + result._definition.signature.output_arg, result._definition.node_def) # pylint: enable=protected-access return result @@ -696,7 +702,8 @@ def _from_library(lib): Raises: ValueError: `lib` is invalid """ - if not lib.function and not lib.gradient: return [] + if not lib.function and not lib.gradient: + return [] # function name -> FunctionDef proto funcs = {fdef.signature.name: fdef for fdef in lib.function} @@ -720,8 +727,9 @@ def _from_library(lib): grad_to_funcs[gdef.gradient_func].append(gdef.function_name) # Start with functions without gradients - ready = [fdef for fdef in lib.function - if func_to_grad[fdef.signature.name] is None] + ready = [ + fdef for fdef in lib.function if func_to_grad[fdef.signature.name] is None + ] if not ready: raise ValueError("FunctionDefLibrary contains cyclic gradient functions!\n" + str(lib)) @@ -733,7 +741,8 @@ def _from_library(lib): name = fdef.signature.name grad = initialized.get(func_to_grad[name]) - if func_to_grad[name]: assert grad + if func_to_grad[name]: + assert grad defined_func = _from_definition(fdef, grad_func=grad) initialized[name] = defined_func @@ -835,10 +844,15 @@ class _OverloadedFunction(object): name = self._func_name if name is not None: name = "_".join([name, key]) - defined = _DefinedFunction(self._func, self._argnames, input_types, name, - None, self._python_grad_func, - out_names=self._out_names, - **self._extra_kwargs) + defined = _DefinedFunction( + self._func, + self._argnames, + input_types, + name, + None, + self._python_grad_func, + out_names=self._out_names, + **self._extra_kwargs) _ = defined.name # Fully instantiate the function definition. if self._grad_func: # If _grad_func is given, it is another @@ -849,8 +863,8 @@ class _OverloadedFunction(object): for _ in defined.definition.signature.output_arg ] # pylint: disable=protected-access - defined._grad_func = self._grad_func.instantiate(input_types + - output_types) + defined._grad_func = self._grad_func.instantiate( + input_types + output_types) # pylint: enable=protected-access self._overload[key] = defined return defined @@ -981,22 +995,36 @@ class Defun(object): raise ValueError( "The function has fewer arguments than the number of specified " "input types.") - return _DefinedFunction(func, argnames, self._input_types, - self._func_name, self._grad_func, - self._python_grad_func, - out_names=self._out_names, **self._extra_kwargs) + return _DefinedFunction( + func, + argnames, + self._input_types, + self._func_name, + self._grad_func, + self._python_grad_func, + out_names=self._out_names, + **self._extra_kwargs) # 'func' expects no arguments and input types is an empty list. if min_args == 0 and max_args == 0: - return _DefinedFunction(func, [], [], self._func_name, self._grad_func, - self._python_grad_func, - out_names=self._out_names, **self._extra_kwargs) + return _DefinedFunction( + func, [], [], + self._func_name, + self._grad_func, + self._python_grad_func, + out_names=self._out_names, + **self._extra_kwargs) # Input types are unknown. It's an overloaded function and hence # its definition needs to be deferred until it's called. - return _OverloadedFunction(func, argnames, self._func_name, self._grad_func, - self._python_grad_func, - out_names=self._out_names, **self._extra_kwargs) + return _OverloadedFunction( + func, + argnames, + self._func_name, + self._grad_func, + self._python_grad_func, + out_names=self._out_names, + **self._extra_kwargs) class Declare(object): @@ -1039,8 +1067,10 @@ class Declare(object): names = [n for n, t in args] if len(names) != len(set(names)): raise ValueError("Expected names to all be unique: %s" % str(names)) - return [op_def_pb2.OpDef.ArgDef(type=t.as_datatype_enum, name=n) - for n, t in args] + return [ + op_def_pb2.OpDef.ArgDef(type=t.as_datatype_enum, name=n) + for n, t in args + ] self._sig.input_arg.extend(_to_argdef_list(inputs)) self._sig.output_arg.extend(_to_argdef_list(outputs)) From feb26a7224b8018a02af94fa28eaaafd4ddd2147 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Fri, 5 May 2017 13:03:57 -0800 Subject: [PATCH 19/27] Clean up TensorBoard build and fix sync process Change: 155237534 --- tensorflow/BUILD | 42 ++++ .../components/tf_audio_dashboard/BUILD | 63 ++++++ .../components/tf_audio_dashboard/demo/BUILD | 26 +++ .../tf_audio_dashboard/demo/data/BUILD | 17 ++ .../tensorboard/components/tf_backend/BUILD | 81 ++++++++ .../components/tf_backend_d3v4/BUILD | 45 +++++ .../components/tf_color_scale/BUILD | 65 +++++++ .../components/tf_color_scale/demo/BUILD | 26 +++ .../components/tf_color_scale_d3v4/BUILD | 72 +++++++ .../components/tf_dashboard_common/BUILD | 102 ++++++++++ .../components/tf_dashboard_common/demo/BUILD | 31 +++ .../components/tf_dashboard_common_d3v4/BUILD | 114 +++++++++++ .../tf_distribution_dashboard/BUILD | 63 ++++++ .../tf_distribution_dashboard/demo/BUILD | 26 +++ .../tf_distribution_dashboard/demo/data/BUILD | 17 ++ .../tensorboard/components/tf_globals/BUILD | 49 +++++ .../components/tf_globals_d3v4/BUILD | 16 ++ .../components/tf_graph_common/BUILD | 65 +++++++ .../components/tf_histogram_dashboard/BUILD | 62 ++++++ .../tf_histogram_dashboard/demo/BUILD | 26 +++ .../tf_histogram_dashboard/demo/data/BUILD | 17 ++ .../components/tf_image_dashboard/BUILD | 59 ++++++ .../components/tf_image_dashboard/demo/BUILD | 25 +++ .../tf_image_dashboard/demo/data/BUILD | 17 ++ .../tensorboard/components/tf_imports/BUILD | 120 ++++++++++++ .../components/tf_imports_d3v4/BUILD | 78 ++++++++ .../components/tf_scalar_dashboard/BUILD | 77 ++++++++ .../components/tf_scalar_dashboard/demo/BUILD | 26 +++ .../tf_scalar_dashboard/demo/data/BUILD | 17 ++ .../tensorboard/components/tf_storage/BUILD | 70 +++++++ .../components/tf_storage_d3v4/BUILD | 35 ++++ .../components/tf_text_dashboard/BUILD | 60 ++++++ .../components/tf_text_dashboard/demo/BUILD | 25 +++ .../tf_text_dashboard/demo/data/BUILD | 17 ++ .../components/vz_data_summary/BUILD | 91 +++++++++ .../vz_data_summary/BUILD.OPENSOURCE | 34 ---- .../components/vz_distribution_chart/BUILD | 69 +++++++ .../vz_distribution_chart/demo/BUILD | 24 +++ .../vz_distribution_chart_d3v4/BUILD | 66 +++++++ .../components/vz_histogram_timeseries/BUILD | 50 +++++ .../vz_histogram_timeseries/demo/BUILD | 25 +++ .../vz_histogram_timeseries_d3v4/BUILD | 63 ++++++ .../components/vz_line_chart/BUILD | 73 +++++++ .../components/vz_line_chart/demo/BUILD | 24 +++ .../components/vz_line_chart_d3v4/BUILD | 66 +++++++ .../tensorboard/components/vz_projector/BUILD | 180 ++++++++++++++++++ .../components/vz_projector/BUILD.OPENSOURCE | 19 -- .../components/vz_projector_d3v4/BUILD | 179 +++++++++++++++++ .../tensorboard/components/vz_sorting/BUILD | 50 +++++ .../components/vz_sorting/test/BUILD | 40 ++++ .../components/vz_sorting_d3v4/BUILD | 27 +++ tensorflow/tensorboard/defs.bzl | 20 ++ 52 files changed, 2698 insertions(+), 53 deletions(-) create mode 100644 tensorflow/tensorboard/components/tf_audio_dashboard/BUILD create mode 100644 tensorflow/tensorboard/components/tf_audio_dashboard/demo/BUILD create mode 100644 tensorflow/tensorboard/components/tf_audio_dashboard/demo/data/BUILD create mode 100644 tensorflow/tensorboard/components/tf_backend/BUILD create mode 100644 tensorflow/tensorboard/components/tf_backend_d3v4/BUILD create mode 100644 tensorflow/tensorboard/components/tf_color_scale/BUILD create mode 100644 tensorflow/tensorboard/components/tf_color_scale/demo/BUILD create mode 100644 tensorflow/tensorboard/components/tf_color_scale_d3v4/BUILD create mode 100644 tensorflow/tensorboard/components/tf_dashboard_common/BUILD create mode 100644 tensorflow/tensorboard/components/tf_dashboard_common/demo/BUILD create mode 100644 tensorflow/tensorboard/components/tf_dashboard_common_d3v4/BUILD create mode 100644 tensorflow/tensorboard/components/tf_distribution_dashboard/BUILD create mode 100644 tensorflow/tensorboard/components/tf_distribution_dashboard/demo/BUILD create mode 100644 tensorflow/tensorboard/components/tf_distribution_dashboard/demo/data/BUILD create mode 100644 tensorflow/tensorboard/components/tf_globals/BUILD create mode 100644 tensorflow/tensorboard/components/tf_globals_d3v4/BUILD create mode 100644 tensorflow/tensorboard/components/tf_graph_common/BUILD create mode 100644 tensorflow/tensorboard/components/tf_histogram_dashboard/BUILD create mode 100644 tensorflow/tensorboard/components/tf_histogram_dashboard/demo/BUILD create mode 100644 tensorflow/tensorboard/components/tf_histogram_dashboard/demo/data/BUILD create mode 100644 tensorflow/tensorboard/components/tf_image_dashboard/BUILD create mode 100644 tensorflow/tensorboard/components/tf_image_dashboard/demo/BUILD create mode 100644 tensorflow/tensorboard/components/tf_image_dashboard/demo/data/BUILD create mode 100644 tensorflow/tensorboard/components/tf_imports/BUILD create mode 100644 tensorflow/tensorboard/components/tf_imports_d3v4/BUILD create mode 100644 tensorflow/tensorboard/components/tf_scalar_dashboard/BUILD create mode 100644 tensorflow/tensorboard/components/tf_scalar_dashboard/demo/BUILD create mode 100644 tensorflow/tensorboard/components/tf_scalar_dashboard/demo/data/BUILD create mode 100644 tensorflow/tensorboard/components/tf_storage/BUILD create mode 100644 tensorflow/tensorboard/components/tf_storage_d3v4/BUILD create mode 100644 tensorflow/tensorboard/components/tf_text_dashboard/BUILD create mode 100644 tensorflow/tensorboard/components/tf_text_dashboard/demo/BUILD create mode 100644 tensorflow/tensorboard/components/tf_text_dashboard/demo/data/BUILD create mode 100644 tensorflow/tensorboard/components/vz_data_summary/BUILD delete mode 100644 tensorflow/tensorboard/components/vz_data_summary/BUILD.OPENSOURCE create mode 100644 tensorflow/tensorboard/components/vz_distribution_chart/BUILD create mode 100644 tensorflow/tensorboard/components/vz_distribution_chart/demo/BUILD create mode 100644 tensorflow/tensorboard/components/vz_distribution_chart_d3v4/BUILD create mode 100644 tensorflow/tensorboard/components/vz_histogram_timeseries/BUILD create mode 100644 tensorflow/tensorboard/components/vz_histogram_timeseries/demo/BUILD create mode 100644 tensorflow/tensorboard/components/vz_histogram_timeseries_d3v4/BUILD create mode 100644 tensorflow/tensorboard/components/vz_line_chart/BUILD create mode 100644 tensorflow/tensorboard/components/vz_line_chart/demo/BUILD create mode 100644 tensorflow/tensorboard/components/vz_line_chart_d3v4/BUILD create mode 100644 tensorflow/tensorboard/components/vz_projector/BUILD delete mode 100644 tensorflow/tensorboard/components/vz_projector/BUILD.OPENSOURCE create mode 100644 tensorflow/tensorboard/components/vz_projector_d3v4/BUILD create mode 100644 tensorflow/tensorboard/components/vz_sorting/BUILD create mode 100644 tensorflow/tensorboard/components/vz_sorting/test/BUILD create mode 100644 tensorflow/tensorboard/components/vz_sorting_d3v4/BUILD diff --git a/tensorflow/BUILD b/tensorflow/BUILD index a36a57314d6..de22a996ea9 100644 --- a/tensorflow/BUILD +++ b/tensorflow/BUILD @@ -319,6 +319,48 @@ filegroup( "//tensorflow/tensorboard/backend:all_files", "//tensorflow/tensorboard/backend/event_processing:all_files", "//tensorflow/tensorboard/components:all_files", + "//tensorflow/tensorboard/components/tf_audio_dashboard:all_files", + "//tensorflow/tensorboard/components/tf_audio_dashboard/demo:all_files", + "//tensorflow/tensorboard/components/tf_backend:all_files", + "//tensorflow/tensorboard/components/tf_backend_d3v4:all_files", + "//tensorflow/tensorboard/components/tf_color_scale:all_files", + "//tensorflow/tensorboard/components/tf_color_scale/demo:all_files", + "//tensorflow/tensorboard/components/tf_color_scale_d3v4:all_files", + "//tensorflow/tensorboard/components/tf_dashboard_common:all_files", + "//tensorflow/tensorboard/components/tf_dashboard_common/demo:all_files", + "//tensorflow/tensorboard/components/tf_dashboard_common_d3v4:all_files", + "//tensorflow/tensorboard/components/tf_distribution_dashboard:all_files", + "//tensorflow/tensorboard/components/tf_distribution_dashboard/demo:all_files", + "//tensorflow/tensorboard/components/tf_globals:all_files", + "//tensorflow/tensorboard/components/tf_globals_d3v4:all_files", + "//tensorflow/tensorboard/components/tf_graph_common:all_files", + "//tensorflow/tensorboard/components/tf_histogram_dashboard:all_files", + "//tensorflow/tensorboard/components/tf_histogram_dashboard/demo:all_files", + "//tensorflow/tensorboard/components/tf_image_dashboard:all_files", + "//tensorflow/tensorboard/components/tf_image_dashboard/demo:all_files", + "//tensorflow/tensorboard/components/tf_imports:all_files", + "//tensorflow/tensorboard/components/tf_imports_d3v4:all_files", + "//tensorflow/tensorboard/components/tf_scalar_dashboard:all_files", + "//tensorflow/tensorboard/components/tf_scalar_dashboard/demo:all_files", + "//tensorflow/tensorboard/components/tf_storage:all_files", + "//tensorflow/tensorboard/components/tf_storage_d3v4:all_files", + "//tensorflow/tensorboard/components/tf_text_dashboard:all_files", + "//tensorflow/tensorboard/components/tf_text_dashboard/demo:all_files", + "//tensorflow/tensorboard/components/vz_data_summary:all_files", + "//tensorflow/tensorboard/components/vz_distribution_chart:all_files", + "//tensorflow/tensorboard/components/vz_distribution_chart/demo:all_files", + "//tensorflow/tensorboard/components/vz_distribution_chart_d3v4:all_files", + "//tensorflow/tensorboard/components/vz_histogram_timeseries:all_files", + "//tensorflow/tensorboard/components/vz_histogram_timeseries/demo:all_files", + "//tensorflow/tensorboard/components/vz_histogram_timeseries_d3v4:all_files", + "//tensorflow/tensorboard/components/vz_line_chart:all_files", + "//tensorflow/tensorboard/components/vz_line_chart/demo:all_files", + "//tensorflow/tensorboard/components/vz_line_chart_d3v4:all_files", + "//tensorflow/tensorboard/components/vz_projector:all_files", + "//tensorflow/tensorboard/components/vz_projector_d3v4:all_files", + "//tensorflow/tensorboard/components/vz_sorting:all_files", + "//tensorflow/tensorboard/components/vz_sorting/test:all_files", + "//tensorflow/tensorboard/components/vz_sorting_d3v4:all_files", "//tensorflow/tensorboard/lib:all_files", "//tensorflow/tensorboard/plugins:all_files", "//tensorflow/tensorboard/plugins/projector:all_files", diff --git a/tensorflow/tensorboard/components/tf_audio_dashboard/BUILD b/tensorflow/tensorboard/components/tf_audio_dashboard/BUILD new file mode 100644 index 00000000000..004bece78ba --- /dev/null +++ b/tensorflow/tensorboard/components/tf_audio_dashboard/BUILD @@ -0,0 +1,63 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_ts_library") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_webcomponent_library") + +licenses(["notice"]) # Apache 2.0 + +webfiles( + name = "tf_audio_dashboard", + srcs = [ + "tf-audio-dashboard.html", + "tf-audio-grid.html", + "tf-audio-loader.html", + ], + path = "/tf-audio-dashboard", + deps = [ + "//tensorflow/tensorboard/components/tf_backend", + "//tensorflow/tensorboard/components/tf_dashboard_common", + "//tensorflow/tensorboard/components/tf_imports:lodash", + "@org_polymer", + "@org_polymer_paper_icon_button", + "@org_polymer_paper_slider", + "@org_polymer_paper_spinner", + "@org_polymer_paper_styles", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) + +################################################################################ +# MARKED FOR DELETION + +tensorboard_webcomponent_library( + name = "legacy", + srcs = [ + "tf-audio-dashboard.html", + "tf-audio-grid.html", + "tf-audio-loader.html", + ], + destdir = "tf-audio-dashboard", + deps = [ + "//tensorflow/tensorboard/components:tf_imports", + "//tensorflow/tensorboard/components/tf_backend:legacy", + "//tensorflow/tensorboard/components/tf_dashboard_common:legacy", + "//third_party/javascript/polymer/v1/paper-icon-button:lib", + "//third_party/javascript/polymer/v1/paper-styles:lib", + "//third_party/javascript/polymer/v1/polymer:lib", + ], +) + +# This is needed: components/BUILD seeks a legacy_ts rule in this package. +tensorboard_ts_library( + name = "legacy_ts", + srcs = [], + deps_mgmt = "off", + runtime = "nodejs", + deps = ["//tensorflow/tensorboard/components:common_deps"], +) diff --git a/tensorflow/tensorboard/components/tf_audio_dashboard/demo/BUILD b/tensorflow/tensorboard/components/tf_audio_dashboard/demo/BUILD new file mode 100644 index 00000000000..383ea8d1b65 --- /dev/null +++ b/tensorflow/tensorboard/components/tf_audio_dashboard/demo/BUILD @@ -0,0 +1,26 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") + +licenses(["notice"]) # Apache 2.0 + +# bazel run //third_party/tensorflow/tensorboard/components/tf_audio_dashboard/demo +webfiles( + name = "demo", + srcs = ["index.html"], + path = "/tf-audio-dashboard/demo", + deps = [ + "//tensorflow/tensorboard/components/tf_audio_dashboard", + "//tensorflow/tensorboard/components/tf_audio_dashboard/demo/data", + "//tensorflow/tensorboard/components/tf_imports:d3", + "@org_polymer_iron_demo_helpers", + "@org_polymer_paper_styles", + "@org_polymer_webcomponentsjs", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) diff --git a/tensorflow/tensorboard/components/tf_audio_dashboard/demo/data/BUILD b/tensorflow/tensorboard/components/tf_audio_dashboard/demo/data/BUILD new file mode 100644 index 00000000000..c3824a923dd --- /dev/null +++ b/tensorflow/tensorboard/components/tf_audio_dashboard/demo/data/BUILD @@ -0,0 +1,17 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") + +licenses(["notice"]) # Apache 2.0 + +webfiles( + name = "data", + srcs = glob(["*"]), + path = "/tf-audio-dashboard/demo/data", +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) diff --git a/tensorflow/tensorboard/components/tf_backend/BUILD b/tensorflow/tensorboard/components/tf_backend/BUILD new file mode 100644 index 00000000000..66fc429c605 --- /dev/null +++ b/tensorflow/tensorboard/components/tf_backend/BUILD @@ -0,0 +1,81 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_ts_library") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_typescript_genrule") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_webcomponent_library") + +licenses(["notice"]) # Apache 2.0 + +# TODO(dandelion): Add webfiles support for the test code. + +webfiles( + name = "tf_backend", + srcs = [ + "tf-backend.html", + ":ts", + ], + path = "/tf-backend", + deps = [ + "//tensorflow/tensorboard/components/tf_imports:d3", + "//tensorflow/tensorboard/components/tf_imports:lodash", + "//tensorflow/tensorboard/components/vz_sorting", + "@org_polymer", + ], +) + +tensorboard_typescript_genrule( + name = "ts", + srcs = [ + "backend.ts", + "behavior.ts", + "requestManager.ts", + "router.ts", + "urlPathHelpers.ts", + ], + typings = [ + "@org_definitelytyped//:d3.d.ts", + "@org_definitelytyped//:lodash.d.ts", + "//tensorflow/tensorboard/components/vz_sorting:ts_typings", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) + +################################################################################ +# MARKED FOR DELETION + +tensorboard_webcomponent_library( + name = "legacy", + srcs = [ + "tf-backend.html", + ":legacy_ts", + ], + visibility = ["//visibility:public"], + destdir = "tf-backend", + deps = [ + "//tensorflow/tensorboard/components:tf_imports", + "//third_party/javascript/polymer/v1/polymer:lib", + ], +) + +tensorboard_ts_library( + name = "legacy_ts", + srcs = [ + "backend.ts", + "behavior.ts", + "requestManager.ts", + "router.ts", + "urlPathHelpers.ts", + ], + deps_mgmt = "off", + runtime = "nodejs", + deps = [ + "//tensorflow/tensorboard/components:common_deps", + "//tensorflow/tensorboard/components/vz_sorting:legacy_ts", + ], +) diff --git a/tensorflow/tensorboard/components/tf_backend_d3v4/BUILD b/tensorflow/tensorboard/components/tf_backend_d3v4/BUILD new file mode 100644 index 00000000000..e54d0e222c9 --- /dev/null +++ b/tensorflow/tensorboard/components/tf_backend_d3v4/BUILD @@ -0,0 +1,45 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_ts_library") + +licenses(["notice"]) # Apache 2.0 + +tensorboard_ts_library( + name = "ts", + srcs = [ + "backend.ts", + "behavior.ts", + "requestManager.ts", + "router.ts", + "urlPathHelpers.ts", + ], + deps = [ + "//tensorflow/tensorboard/components/vz_sorting_d3v4:ts", + "//third_party/javascript/node_modules/typescript:es2015.promise", + "//third_party/javascript/typings/chai", + "//third_party/javascript/typings/d3_v4:bundle", + "//third_party/javascript/typings/lodash", + "//third_party/javascript/typings/mocha", + "//third_party/javascript/typings/polymer:polymer_without_externs", + "//third_party/javascript/typings/sinon", + ], +) + +# TODO(dandelion): Add runners for these tests +tensorboard_ts_library( + name = "tests", + srcs = [ + "backendTests.ts", + "behaviorTests.ts", + "requestManagerTests.ts", + ], + deps = [ + ":ts", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) diff --git a/tensorflow/tensorboard/components/tf_color_scale/BUILD b/tensorflow/tensorboard/components/tf_color_scale/BUILD new file mode 100644 index 00000000000..52102577b4f --- /dev/null +++ b/tensorflow/tensorboard/components/tf_color_scale/BUILD @@ -0,0 +1,65 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_ts_library") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_typescript_genrule") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_webcomponent_library") + +licenses(["notice"]) # Apache 2.0 + +# TODO(dandelion): Add webfiles support for the test code. + +webfiles( + name = "tf_color_scale", + srcs = [ + "tf-color-scale.html", + ":ts", + ], + path = "/tf-color-scale", + deps = [ + "//tensorflow/tensorboard/components/tf_imports:d3", + "@org_polymer", + ], +) + +tensorboard_typescript_genrule( + name = "ts", + srcs = [ + "colorScale.ts", + "palettes.ts", + ], + typings = ["@org_definitelytyped//:d3.d.ts"], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) + +################################################################################ +# MARKED FOR DELETION + +tensorboard_webcomponent_library( + name = "legacy", + srcs = [ + "tf-color-scale.html", + ":legacy_ts", + ], + destdir = "tf-color-scale", + deps = [ + "//tensorflow/tensorboard/components:tf_imports", + "//third_party/javascript/polymer/v1/polymer:lib", + ], +) + +tensorboard_ts_library( + name = "legacy_ts", + srcs = [ + "colorScale.ts", + "palettes.ts", + ], + deps_mgmt = "off", + runtime = "nodejs", + deps = ["//tensorflow/tensorboard/components:common_deps"], +) diff --git a/tensorflow/tensorboard/components/tf_color_scale/demo/BUILD b/tensorflow/tensorboard/components/tf_color_scale/demo/BUILD new file mode 100644 index 00000000000..00b8a033b8a --- /dev/null +++ b/tensorflow/tensorboard/components/tf_color_scale/demo/BUILD @@ -0,0 +1,26 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") + +licenses(["notice"]) # Apache 2.0 + +# bazel run //third_party/tensorflow/tensorboard/components/tf_color_scale/demo +webfiles( + name = "demo", + srcs = ["index.html"], + path = "/tf-color-scale/demo", + deps = [ + "//tensorflow/tensorboard/components/tf_color_scale", + "//tensorflow/tensorboard/components/tf_imports:d3", + "@org_polymer_iron_demo_helpers", + "@org_polymer_paper_button", + "@org_polymer_paper_styles", + "@org_polymer_webcomponentsjs", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) diff --git a/tensorflow/tensorboard/components/tf_color_scale_d3v4/BUILD b/tensorflow/tensorboard/components/tf_color_scale_d3v4/BUILD new file mode 100644 index 00000000000..fd7d394a366 --- /dev/null +++ b/tensorflow/tensorboard/components/tf_color_scale_d3v4/BUILD @@ -0,0 +1,72 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load( + "//tensorflow/tensorboard:defs.bzl", + "tensorboard_ts_development_sources", + "tensorboard_ts_devserver", + "tensorboard_ts_library", + "tensorboard_webcomponent_library", +) + +licenses(["notice"]) # Apache 2.0 + +# TODO(dandelion): Add runner for the test code. + +tensorboard_webcomponent_library( + name = "tf_color_scale", + srcs = ["tf-color-scale.html"], + ts_lib_deps = [":ts"], + deps = [ + "//third_party/javascript/polymer/v1/polymer:lib", + ], +) + +tensorboard_ts_library( + name = "ts", + srcs = [ + "colorScale.ts", + "palettes.ts", + ], + deps = ["//tensorflow/tensorboard/components:common_deps_d3v4"], +) + +tensorboard_ts_library( + name = "tests", + srcs = ["colorScaleTests.ts"], + deps = [ + ":ts", + "//tensorflow/tensorboard/components:common_deps_d3v4", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) + +tensorboard_webcomponent_library( + name = "demo", + srcs = ["demo.html"], + visibility = ["//visibility:public"], + deps = [ + ":tf_color_scale", + "//third_party/javascript/polymer/v1/iron-demo-helpers:lib", + "//third_party/javascript/polymer/v1/paper-button:lib", + "//third_party/javascript/polymer/v1/paper-styles:lib", + ], +) + +tensorboard_ts_devserver( + name = "devserver", + manifest = ":dev_sources", + serving_path = "/demo_out/bundle.js", + static_files = [":demo"], +) + +tensorboard_ts_development_sources( + name = "dev_sources", + deps = [ + ":ts", + ], +) diff --git a/tensorflow/tensorboard/components/tf_dashboard_common/BUILD b/tensorflow/tensorboard/components/tf_dashboard_common/BUILD new file mode 100644 index 00000000000..880e6bd7125 --- /dev/null +++ b/tensorflow/tensorboard/components/tf_dashboard_common/BUILD @@ -0,0 +1,102 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_ts_library") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_typescript_genrule") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_webcomponent_library") + +licenses(["notice"]) # Apache 2.0 + +webfiles( + name = "tf_dashboard_common", + srcs = glob(["*.html"]) + [ + ":ts", + ], + path = "/tf-dashboard-common", + deps = [ + "//tensorflow/tensorboard/components/tf_imports:lodash", + "//tensorflow/tensorboard/components/tf_imports:plottable", + "//tensorflow/tensorboard/components/tf_storage", + "//tensorflow/tensorboard/components/vz_sorting", + "@org_polymer", + "@org_polymer_iron_ajax", + "@org_polymer_iron_collapse", + "@org_polymer_iron_icons", + "@org_polymer_paper_button", + "@org_polymer_paper_checkbox", + "@org_polymer_paper_dialog", + "@org_polymer_paper_dropdown_menu", + "@org_polymer_paper_icon_button", + "@org_polymer_paper_input", + "@org_polymer_paper_item", + "@org_polymer_paper_menu", + "@org_polymer_paper_slider", + "@org_polymer_paper_spinner", + "@org_polymer_paper_styles", + "@org_polymer_paper_toggle_button", + ], +) + +tensorboard_typescript_genrule( + name = "ts", + srcs = [ + "categorizer.ts", + "dashboard-behavior.ts", + "reload-behavior.ts", + ], + typings = [ + "@org_definitelytyped//:d3.d.ts", + "//tensorflow/tensorboard/components/vz_sorting:ts_typings", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) + +################################################################################ +# MARKED FOR DELETION + +tensorboard_webcomponent_library( + name = "legacy", + srcs = glob(["*.html"]) + [":legacy_ts"], + destdir = "tf-dashboard-common", + deps = [ + "//tensorflow/tensorboard/components:tf_imports", + "//tensorflow/tensorboard/components/tf_storage:legacy", + "//tensorflow/tensorboard/components/vz_sorting:legacy", + "//third_party/javascript/polymer/v1/iron-ajax:lib", + "//third_party/javascript/polymer/v1/iron-collapse:lib", + "//third_party/javascript/polymer/v1/iron-icons:lib", + "//third_party/javascript/polymer/v1/paper-button:lib", + "//third_party/javascript/polymer/v1/paper-checkbox:lib", + "//third_party/javascript/polymer/v1/paper-dialog:lib", + "//third_party/javascript/polymer/v1/paper-dropdown-menu:lib", + "//third_party/javascript/polymer/v1/paper-icon-button:lib", + "//third_party/javascript/polymer/v1/paper-input:lib", + "//third_party/javascript/polymer/v1/paper-item:lib", + "//third_party/javascript/polymer/v1/paper-menu:lib", + "//third_party/javascript/polymer/v1/paper-slider:lib", + "//third_party/javascript/polymer/v1/paper-spinner:lib", + "//third_party/javascript/polymer/v1/paper-styles:lib", + "//third_party/javascript/polymer/v1/paper-toggle-button:lib", + "//third_party/javascript/polymer/v1/polymer:lib", + ], +) + +tensorboard_ts_library( + name = "legacy_ts", + srcs = [ + "categorizer.ts", + "dashboard-behavior.ts", + "reload-behavior.ts", + ], + deps_mgmt = "off", + runtime = "nodejs", + deps = [ + "//tensorflow/tensorboard/components:common_deps", + "//tensorflow/tensorboard/components/vz_sorting:legacy_ts", + ], +) diff --git a/tensorflow/tensorboard/components/tf_dashboard_common/demo/BUILD b/tensorflow/tensorboard/components/tf_dashboard_common/demo/BUILD new file mode 100644 index 00000000000..05cfe34e72c --- /dev/null +++ b/tensorflow/tensorboard/components/tf_dashboard_common/demo/BUILD @@ -0,0 +1,31 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") + +licenses(["notice"]) # Apache 2.0 + +# bazel run //third_party/tensorflow/tensorboard/components/tf_dashboard_common/demo +webfiles( + name = "demo", + srcs = [ + "tf-categorizer-demo.html", + "tf-collapsable-pane-demo.html", + "tf-multi-checkbox-demo.html", + "tf-regex-group-demo.html", + ], + path = "/tf-dashboard-common/demo", + deps = [ + "//tensorflow/tensorboard/components/tf_color_scale", + "//tensorflow/tensorboard/components/tf_dashboard_common", + "//tensorflow/tensorboard/components/tf_imports:d3", + "@org_polymer_iron_flex_layout", + "@org_polymer_paper_styles", + "@org_polymer_webcomponentsjs", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) diff --git a/tensorflow/tensorboard/components/tf_dashboard_common_d3v4/BUILD b/tensorflow/tensorboard/components/tf_dashboard_common_d3v4/BUILD new file mode 100644 index 00000000000..85f06dabb59 --- /dev/null +++ b/tensorflow/tensorboard/components/tf_dashboard_common_d3v4/BUILD @@ -0,0 +1,114 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load( + "//tensorflow/tensorboard:defs.bzl", + "tensorboard_ts_development_sources", + "tensorboard_ts_devserver", + "tensorboard_ts_library", + "tensorboard_webcomponent_library", +) + +licenses(["notice"]) # Apache 2.0 + +tensorboard_webcomponent_library( + name = "tf_dashboard_common", + srcs = [ + "dashboard-style.html", + "run-color-style.html", + "scrollbar-style.html", + "tensorboard-color.html", + "tf-categorizer.html", + "tf-collapsable-pane.html", + "tf-dashboard.html", + "tf-dashboard-layout.html", + "tf-downloader.html", + "tf-multi-checkbox.html", + "tf-no-data-warning.html", + "tf-option-selector.html", + "tf-panes-helper.html", + "tf-regex-group.html", + "tf-run-selector.html", + "tf-sidebar-helper.html", + ], + ts_lib_deps = [":ts"], + deps = [ + "//third_party/javascript/plottable/v3:lib", + "//third_party/javascript/polymer/v1/iron-ajax:lib", + "//third_party/javascript/polymer/v1/iron-collapse:lib", + "//third_party/javascript/polymer/v1/iron-icons:lib", + "//third_party/javascript/polymer/v1/paper-button:lib", + "//third_party/javascript/polymer/v1/paper-checkbox:lib", + "//third_party/javascript/polymer/v1/paper-dialog:lib", + "//third_party/javascript/polymer/v1/paper-dropdown-menu:lib", + "//third_party/javascript/polymer/v1/paper-icon-button:lib", + "//third_party/javascript/polymer/v1/paper-input:lib", + "//third_party/javascript/polymer/v1/paper-item:lib", + "//third_party/javascript/polymer/v1/paper-menu:lib", + "//third_party/javascript/polymer/v1/paper-slider:lib", + "//third_party/javascript/polymer/v1/paper-spinner:lib", + "//third_party/javascript/polymer/v1/paper-styles:lib", + "//third_party/javascript/polymer/v1/paper-toggle-button:lib", + "//third_party/javascript/polymer/v1/polymer:lib", + ], +) + +tensorboard_ts_library( + name = "ts", + srcs = [ + "dashboard-behavior.ts", + "reload-behavior.ts", + "tf-categorizer.ts", + "tf-multi-checkbox.ts", + "tf-regex-group.ts", + ], + deps = [ + "//tensorflow/tensorboard/components:common_deps_d3v4", + "//tensorflow/tensorboard/components/tf_storage_d3v4:ts", + "//tensorflow/tensorboard/components/vz_sorting_d3v4:ts", + ], +) + +tensorboard_ts_library( + name = "tests", + srcs = ["tf-categorizer-tests.ts"], + deps = [ + ":ts", + "//tensorflow/tensorboard/components:common_deps_d3v4", + ], +) + +tensorboard_webcomponent_library( + name = "demo", + srcs = [ + "tf-categorizer-demo.html", + "tf-collapsable-pane-demo.html", + "tf-multi-checkbox-demo.html", + "tf-regex-group-demo.html", + ], + deps = [ + ":tf_dashboard_common", + "//tensorflow/tensorboard/components/tf_color_scale_d3v4:tf_color_scale", + "//third_party/javascript/polymer/v1/iron-demo-helpers:lib", + "//third_party/javascript/polymer/v1/paper-styles:lib", + ], +) + +tensorboard_ts_devserver( + name = "devserver", + manifest = ":dev_sources", + serving_path = "/demo_out/bundle.js", + static_files = [":demo"], +) + +tensorboard_ts_development_sources( + name = "dev_sources", + deps = [ + ":ts", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) diff --git a/tensorflow/tensorboard/components/tf_distribution_dashboard/BUILD b/tensorflow/tensorboard/components/tf_distribution_dashboard/BUILD new file mode 100644 index 00000000000..e71bbdea2b1 --- /dev/null +++ b/tensorflow/tensorboard/components/tf_distribution_dashboard/BUILD @@ -0,0 +1,63 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_ts_library") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_webcomponent_library") + +licenses(["notice"]) # Apache 2.0 + +webfiles( + name = "tf_distribution_dashboard", + srcs = [ + "tf-distribution-dashboard.html", + ], + path = "/tf-distribution-dashboard", + deps = [ + "//tensorflow/tensorboard/components/tf_backend", + "//tensorflow/tensorboard/components/tf_color_scale", + "//tensorflow/tensorboard/components/tf_dashboard_common", + "//tensorflow/tensorboard/components/tf_imports:lodash", + "//tensorflow/tensorboard/components/vz_distribution_chart", + "@org_polymer", + "@org_polymer_iron_collapse", + "@org_polymer_paper_icon_button", + "@org_polymer_paper_styles", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) + +################################################################################ +# MARKED FOR DELETION + +tensorboard_webcomponent_library( + name = "legacy", + srcs = [ + "tf-distribution-dashboard.html", + ":legacy_ts", + ], + destdir = "tf-distribution-dashboard", + deps = [ + "//tensorflow/tensorboard/components:tf_imports", + "//tensorflow/tensorboard/components/tf_backend:legacy", + "//tensorflow/tensorboard/components/tf_dashboard_common:legacy", + "//tensorflow/tensorboard/components/vz_distribution_chart:legacy", + "//third_party/javascript/polymer/v1/iron-collapse:lib", + "//third_party/javascript/polymer/v1/paper-icon-button:lib", + "//third_party/javascript/polymer/v1/paper-styles:lib", + "//third_party/javascript/polymer/v1/polymer:lib", + ], +) + +# This is needed: components/BUILD seeks a legacy_ts rule in this package. +tensorboard_ts_library( + name = "legacy_ts", + srcs = [], + deps_mgmt = "off", + runtime = "nodejs", + deps = ["//tensorflow/tensorboard/components:common_deps"], +) diff --git a/tensorflow/tensorboard/components/tf_distribution_dashboard/demo/BUILD b/tensorflow/tensorboard/components/tf_distribution_dashboard/demo/BUILD new file mode 100644 index 00000000000..238937c0c25 --- /dev/null +++ b/tensorflow/tensorboard/components/tf_distribution_dashboard/demo/BUILD @@ -0,0 +1,26 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") + +licenses(["notice"]) # Apache 2.0 + +# bazel run //third_party/tensorflow/tensorboard/components/tf_distribution_dashboard/demo +webfiles( + name = "demo", + srcs = ["index.html"], + path = "/tf-distribution-dashboard/demo", + deps = [ + "//tensorflow/tensorboard/components/tf_distribution_dashboard", + "//tensorflow/tensorboard/components/tf_distribution_dashboard/demo/data", + "//tensorflow/tensorboard/components/tf_imports:d3", + "@org_polymer_iron_demo_helpers", + "@org_polymer_paper_styles", + "@org_polymer_webcomponentsjs", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) diff --git a/tensorflow/tensorboard/components/tf_distribution_dashboard/demo/data/BUILD b/tensorflow/tensorboard/components/tf_distribution_dashboard/demo/data/BUILD new file mode 100644 index 00000000000..589c1980e41 --- /dev/null +++ b/tensorflow/tensorboard/components/tf_distribution_dashboard/demo/data/BUILD @@ -0,0 +1,17 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") + +licenses(["notice"]) # Apache 2.0 + +webfiles( + name = "data", + srcs = glob(["*"]), + path = "/tf-distribution-dashboard/demo/data", +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) diff --git a/tensorflow/tensorboard/components/tf_globals/BUILD b/tensorflow/tensorboard/components/tf_globals/BUILD new file mode 100644 index 00000000000..2e5e4b05157 --- /dev/null +++ b/tensorflow/tensorboard/components/tf_globals/BUILD @@ -0,0 +1,49 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_ts_library") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_typescript_genrule") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_webcomponent_library") + +licenses(["notice"]) # Apache 2.0 + +# TODO(dandelion): Add webfiles support for the test code. + +webfiles( + name = "tf_globals", + srcs = [ + "tf-globals.html", + ":ts", + ], + path = "/tf-globals", +) + +tensorboard_typescript_genrule( + name = "ts", + srcs = ["globals.ts"], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) + +################################################################################ +# MARKED FOR DELETION + +tensorboard_webcomponent_library( + name = "legacy", + srcs = [ + "tf-globals.html", + ":legacy_ts", + ], + destdir = "tf-globals", +) + +tensorboard_ts_library( + name = "legacy_ts", + srcs = ["globals.ts"], + deps_mgmt = "off", + runtime = "nodejs", +) diff --git a/tensorflow/tensorboard/components/tf_globals_d3v4/BUILD b/tensorflow/tensorboard/components/tf_globals_d3v4/BUILD new file mode 100644 index 00000000000..202e72aaa67 --- /dev/null +++ b/tensorflow/tensorboard/components/tf_globals_d3v4/BUILD @@ -0,0 +1,16 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_ts_library") + +licenses(["notice"]) # Apache 2.0 + +tensorboard_ts_library( + name = "ts", + srcs = ["globals.ts"], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) diff --git a/tensorflow/tensorboard/components/tf_graph_common/BUILD b/tensorflow/tensorboard/components/tf_graph_common/BUILD new file mode 100644 index 00000000000..772abbbd31e --- /dev/null +++ b/tensorflow/tensorboard/components/tf_graph_common/BUILD @@ -0,0 +1,65 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_ts_library") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_typescript_genrule") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_webcomponent_library") + +licenses(["notice"]) # Apache 2.0 + +webfiles( + name = "tf_graph_common", + srcs = [ + "tf-graph-common.html", + ":ts", + ], + path = "/tf-graph-common", + deps = [ + "//tensorflow/tensorboard/components/tf_imports:d3", + "//tensorflow/tensorboard/components/tf_imports:dagre", + "//tensorflow/tensorboard/components/tf_imports:graphlib", + "//tensorflow/tensorboard/components/tf_imports:lodash", + "@org_polymer", + ], +) + +tensorboard_typescript_genrule( + name = "ts", + srcs = glob(["*.ts"]), + typings = [ + "@org_definitelytyped//:d3.d.ts", + "@org_definitelytyped//:lodash.d.ts", + "@org_definitelytyped//:polymer.d.ts", + "@org_definitelytyped//:webcomponents.js.d.ts", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) + +################################################################################ +# MARKED FOR DELETION + +tensorboard_webcomponent_library( + name = "legacy", + srcs = [ + "tf-graph-common.html", + ":legacy_ts", + ], + destdir = "tf-graph-common", + deps = [ + "//tensorflow/tensorboard/components:tf_imports", + "//third_party/javascript/polymer/v1/polymer:lib", + ], +) + +tensorboard_ts_library( + name = "legacy_ts", + srcs = glob(["*.ts"]), + deps_mgmt = "off", + runtime = "nodejs", + deps = ["//tensorflow/tensorboard/components:common_deps"], +) diff --git a/tensorflow/tensorboard/components/tf_histogram_dashboard/BUILD b/tensorflow/tensorboard/components/tf_histogram_dashboard/BUILD new file mode 100644 index 00000000000..c74eafa6582 --- /dev/null +++ b/tensorflow/tensorboard/components/tf_histogram_dashboard/BUILD @@ -0,0 +1,62 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_ts_library") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_webcomponent_library") + +licenses(["notice"]) # Apache 2.0 + +webfiles( + name = "tf_histogram_dashboard", + srcs = [ + "tf-histogram-dashboard.html", + ], + path = "/tf-histogram-dashboard", + deps = [ + "//tensorflow/tensorboard/components/tf_backend", + "//tensorflow/tensorboard/components/tf_color_scale", + "//tensorflow/tensorboard/components/tf_dashboard_common", + "//tensorflow/tensorboard/components/tf_imports:lodash", + "//tensorflow/tensorboard/components/vz_histogram_timeseries", + "@org_polymer", + "@org_polymer_iron_collapse", + "@org_polymer_paper_icon_button", + "@org_polymer_paper_styles", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) + +################################################################################ +# MARKED FOR DELETION + +tensorboard_webcomponent_library( + name = "legacy", + srcs = [ + "tf-histogram-dashboard.html", + ":legacy_ts", + ], + destdir = "tf-histogram-dashboard", + deps = [ + "//tensorflow/tensorboard/components:tf_imports", + "//tensorflow/tensorboard/components/tf_backend:legacy", + "//tensorflow/tensorboard/components/tf_dashboard_common:legacy", + "//tensorflow/tensorboard/components/vz_histogram_timeseries:legacy", + "//third_party/javascript/polymer/v1/iron-collapse:lib", + "//third_party/javascript/polymer/v1/paper-icon-button:lib", + "//third_party/javascript/polymer/v1/paper-styles:lib", + "//third_party/javascript/polymer/v1/polymer:lib", + ], +) + +# This is needed: components/BUILD seeks a legacy_ts rule in this package. +tensorboard_ts_library( + name = "legacy_ts", + srcs = [], + deps_mgmt = "off", + runtime = "nodejs", +) diff --git a/tensorflow/tensorboard/components/tf_histogram_dashboard/demo/BUILD b/tensorflow/tensorboard/components/tf_histogram_dashboard/demo/BUILD new file mode 100644 index 00000000000..8350084874b --- /dev/null +++ b/tensorflow/tensorboard/components/tf_histogram_dashboard/demo/BUILD @@ -0,0 +1,26 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") + +licenses(["notice"]) # Apache 2.0 + +# bazel run //third_party/tensorflow/tensorboard/components/tf_histogram_dashboard/demo +webfiles( + name = "demo", + srcs = ["index.html"], + path = "/tf-histogram-dashboard/demo", + deps = [ + "//tensorflow/tensorboard/components/tf_histogram_dashboard", + "//tensorflow/tensorboard/components/tf_histogram_dashboard/demo/data", + "//tensorflow/tensorboard/components/tf_imports:d3", + "@org_polymer_iron_demo_helpers", + "@org_polymer_paper_styles", + "@org_polymer_webcomponentsjs", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) diff --git a/tensorflow/tensorboard/components/tf_histogram_dashboard/demo/data/BUILD b/tensorflow/tensorboard/components/tf_histogram_dashboard/demo/data/BUILD new file mode 100644 index 00000000000..d396efab738 --- /dev/null +++ b/tensorflow/tensorboard/components/tf_histogram_dashboard/demo/data/BUILD @@ -0,0 +1,17 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") + +licenses(["notice"]) # Apache 2.0 + +webfiles( + name = "data", + srcs = glob(["*"]), + path = "/tf-histogram-dashboard/demo/data", +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) diff --git a/tensorflow/tensorboard/components/tf_image_dashboard/BUILD b/tensorflow/tensorboard/components/tf_image_dashboard/BUILD new file mode 100644 index 00000000000..b69fe6ba224 --- /dev/null +++ b/tensorflow/tensorboard/components/tf_image_dashboard/BUILD @@ -0,0 +1,59 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_ts_library") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_webcomponent_library") + +licenses(["notice"]) # Apache 2.0 + +webfiles( + name = "tf_image_dashboard", + srcs = [ + "tf-image-dashboard.html", + "tf-image-loader.html", + ], + path = "/tf-image-dashboard", + deps = [ + "//tensorflow/tensorboard/components/tf_backend", + "//tensorflow/tensorboard/components/tf_color_scale", + "//tensorflow/tensorboard/components/tf_dashboard_common", + "//tensorflow/tensorboard/components/tf_imports:d3", + "//tensorflow/tensorboard/components/tf_imports:lodash", + "@org_polymer", + "@org_polymer_paper_dialog", + "@org_polymer_paper_icon_button", + "@org_polymer_paper_slider", + "@org_polymer_paper_spinner", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) + +################################################################################ +# MARKED FOR DELETION + +tensorboard_webcomponent_library( + name = "legacy", + srcs = [ + "tf-image-dashboard.html", + "tf-image-loader.html", + ":legacy_ts", + ], + destdir = "tf-image-dashboard", + deps = [ + "//tensorflow/tensorboard/components/tf_backend:legacy", + "//tensorflow/tensorboard/components/tf_dashboard_common:legacy", + ], +) + +# This is needed: components/BUILD seeks a legacy_ts rule in this package. +tensorboard_ts_library( + name = "legacy_ts", + srcs = [], + deps_mgmt = "off", + runtime = "nodejs", +) diff --git a/tensorflow/tensorboard/components/tf_image_dashboard/demo/BUILD b/tensorflow/tensorboard/components/tf_image_dashboard/demo/BUILD new file mode 100644 index 00000000000..3a42342ca08 --- /dev/null +++ b/tensorflow/tensorboard/components/tf_image_dashboard/demo/BUILD @@ -0,0 +1,25 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") + +licenses(["notice"]) # Apache 2.0 + +# bazel run //third_party/tensorflow/tensorboard/components/tf_image_dashboard/demo +webfiles( + name = "demo", + srcs = ["index.html"], + path = "/tf-image-dashboard/demo", + deps = [ + "//tensorflow/tensorboard/components/tf_image_dashboard", + "//tensorflow/tensorboard/components/tf_image_dashboard/demo/data", + "@org_polymer_iron_demo_helpers", + "@org_polymer_paper_styles", + "@org_polymer_webcomponentsjs", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) diff --git a/tensorflow/tensorboard/components/tf_image_dashboard/demo/data/BUILD b/tensorflow/tensorboard/components/tf_image_dashboard/demo/data/BUILD new file mode 100644 index 00000000000..a613ac66c70 --- /dev/null +++ b/tensorflow/tensorboard/components/tf_image_dashboard/demo/data/BUILD @@ -0,0 +1,17 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") + +licenses(["notice"]) # Apache 2.0 + +webfiles( + name = "data", + srcs = glob(["*"]), + path = "/tf-image-dashboard/demo/data", +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) diff --git a/tensorflow/tensorboard/components/tf_imports/BUILD b/tensorflow/tensorboard/components/tf_imports/BUILD new file mode 100644 index 00000000000..b41a6bd4465 --- /dev/null +++ b/tensorflow/tensorboard/components/tf_imports/BUILD @@ -0,0 +1,120 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") + +licenses(["notice"]) # Apache 2.0 + +webfiles( + name = "d3", + srcs = [ + "d3.html", + "@org_d3js", + ], + path = "/tf-imports", +) + +webfiles( + name = "lodash", + srcs = [ + "lodash.html", + "@com_lodash", + ], + path = "/tf-imports", +) + +webfiles( + name = "graphlib", + srcs = [ + "graphlib.html", + "@io_github_cpettitt_graphlib", + ], + path = "/tf-imports", + deps = [":lodash"], +) + +webfiles( + name = "dagre", + srcs = [ + "dagre.html", + "@io_github_cpettitt_dagre", + ], + path = "/tf-imports", + deps = [ + ":graphlib", + ":lodash", + ], +) + +webfiles( + name = "plottable", + srcs = [ + "plottable.html", + "@com_palantir_plottable//:plottable.css", + "@com_palantir_plottable//:plottable.js", + ], + path = "/tf-imports", + deps = [":d3"], +) + +# Generate single TypeScript typings file for d3.js with no ES6 imports. +# +# The DefinitelyTyped definition of d3 v4 was written under the assumption that +# we want to use d3 in a modularized way. We don't want to do that because its +# import statements use NodeJS namespaces, and the Web Compiler only supports +# W3C, ECMA, and IETF standards. +genrule( + name = "d3v4_typings", + srcs = [ + # please maintain a reverse topological order + "@org_definitelytyped_types_d3_path//:index.d.ts", + "@org_definitelytyped_types_d3_time//:index.d.ts", + "@org_definitelytyped_types_d3_dsv//:index.d.ts", + "@org_definitelytyped_types_d3_color//:index.d.ts", + "@org_definitelytyped_types_d3_selection//:index.d.ts", + # d3-transition defines stuff in d3-selection wat? + # "@org_definitelytyped_types_d3_transition//:index.d.ts", + "@org_definitelytyped_types_d3_shape//:index.d.ts", + "@org_definitelytyped_types_d3_scale//:index.d.ts", + "@org_definitelytyped_types_d3_request//:index.d.ts", + "@org_definitelytyped_types_d3_interpolate//:index.d.ts", + "@org_definitelytyped_types_d3_drag//:index.d.ts", + "@org_definitelytyped_types_d3_brush//:index.d.ts", + "@org_definitelytyped_types_d3_axis//:index.d.ts", + "@org_definitelytyped_types_d3_zoom//:index.d.ts", + "@org_definitelytyped_types_d3_array//:index.d.ts", + "@org_definitelytyped_types_d3_chord//:index.d.ts", + "@org_definitelytyped_types_d3_collection//:index.d.ts", + "@org_definitelytyped_types_d3_dispatch//:index.d.ts", + "@org_definitelytyped_types_d3_ease//:index.d.ts", + "@org_definitelytyped_types_d3_force//:index.d.ts", + "@org_definitelytyped_types_d3_format//:index.d.ts", + "@org_definitelytyped_types_d3_hierarchy//:index.d.ts", + "@org_definitelytyped_types_d3_polygon//:index.d.ts", + "@org_definitelytyped_types_d3_quadtree//:index.d.ts", + "@org_definitelytyped_types_d3_queue//:index.d.ts", + "@org_definitelytyped_types_d3_random//:index.d.ts", + "@org_definitelytyped_types_d3_timer//:index.d.ts", + "@org_definitelytyped_types_d3_voronoi//:index.d.ts", + ], + outs = ["d3v4.d.ts"], + cmd = "\n".join([ + "(", + " echo 'declare namespace d3 {'", + " for f in $(SRCS); do", + " echo", + " echo /////////////////////////////////////////////", + " echo // $$f", + " echo /////////////////////////////////////////////", + " echo", + " sed '/^import /d' $$f", + " done", + " echo '}'", + ") >$@", + ]), +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) diff --git a/tensorflow/tensorboard/components/tf_imports_d3v4/BUILD b/tensorflow/tensorboard/components/tf_imports_d3v4/BUILD new file mode 100644 index 00000000000..23ecee759c0 --- /dev/null +++ b/tensorflow/tensorboard/components/tf_imports_d3v4/BUILD @@ -0,0 +1,78 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") + +licenses(["notice"]) # Apache 2.0 + +webfiles( + name = "d3", + srcs = [ + "d3.html", + "@org_d3js_v4", + ], + path = "/tf-imports-d3v4", +) + +webfiles( + name = "lodash", + srcs = [ + "lodash.html", + "@com_lodash", + ], + path = "/tf-imports-d3v4", +) + +webfiles( + name = "graphlib", + srcs = [ + "graphlib.html", + "@io_github_cpettitt_graphlib", + ], + path = "/tf-imports-d3v4", + deps = [":lodash"], +) + +webfiles( + name = "dagre", + srcs = [ + "dagre.html", + "@io_github_cpettitt_dagre", + ], + path = "/tf-imports-d3v4", + deps = [ + ":graphlib", + ":lodash", + ], +) + +webfiles( + name = "plottable", + srcs = [ + "plottable.html", + # TODO(jart): Replace when Plottable v3 is fixed. + "plottable.js", + "plottable.css", + # "//third_party/javascript/plottable/v3:plottable.css", + # "//third_party/javascript/plottable/v3:plottable.js", + ], + path = "/tf-imports-d3v4", + deps = [":d3"], +) + +genrule( + name = "TEMPORARY_fake_plottable_css", + outs = ["plottable.css"], + cmd = "echo >$@", +) + +genrule( + name = "TEMPORARY_fake_plottable_js", + outs = ["plottable.js"], + cmd = "echo >$@", +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) diff --git a/tensorflow/tensorboard/components/tf_scalar_dashboard/BUILD b/tensorflow/tensorboard/components/tf_scalar_dashboard/BUILD new file mode 100644 index 00000000000..436d0c262d4 --- /dev/null +++ b/tensorflow/tensorboard/components/tf_scalar_dashboard/BUILD @@ -0,0 +1,77 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_ts_library") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_webcomponent_library") + +licenses(["notice"]) # Apache 2.0 + +webfiles( + name = "tf_scalar_dashboard", + srcs = [ + "tf-scalar-dashboard.html", + "tf-smoothing-input.html", + ], + path = "/tf-scalar-dashboard", + deps = [ + "//tensorflow/tensorboard/components/tf_backend", + "//tensorflow/tensorboard/components/tf_color_scale", + "//tensorflow/tensorboard/components/tf_dashboard_common", + "//tensorflow/tensorboard/components/tf_imports:lodash", + "//tensorflow/tensorboard/components/vz_line_chart", + "@org_polymer", + "@org_polymer_iron_collapse", + "@org_polymer_paper_checkbox", + "@org_polymer_paper_dropdown_menu", + "@org_polymer_paper_icon_button", + "@org_polymer_paper_input", + "@org_polymer_paper_item", + "@org_polymer_paper_menu", + "@org_polymer_paper_slider", + "@org_polymer_paper_styles", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) + +################################################################################ +# MARKED FOR DELETION + +tensorboard_webcomponent_library( + name = "legacy", + srcs = [ + "tf-scalar-dashboard.html", + "tf-smoothing-input.html", + ], + destdir = "tf-scalar-dashboard", + deps = [ + "//tensorflow/tensorboard/components:tf_imports", + "//tensorflow/tensorboard/components/tf_backend:legacy", + "//tensorflow/tensorboard/components/tf_color_scale:legacy", + "//tensorflow/tensorboard/components/tf_dashboard_common:legacy", + "//tensorflow/tensorboard/components/vz_line_chart:legacy", + "//third_party/javascript/polymer/v1/iron-collapse:lib", + "//third_party/javascript/polymer/v1/paper-checkbox:lib", + "//third_party/javascript/polymer/v1/paper-dropdown-menu:lib", + "//third_party/javascript/polymer/v1/paper-icon-button:lib", + "//third_party/javascript/polymer/v1/paper-input:lib", + "//third_party/javascript/polymer/v1/paper-item:lib", + "//third_party/javascript/polymer/v1/paper-menu:lib", + "//third_party/javascript/polymer/v1/paper-slider:lib", + "//third_party/javascript/polymer/v1/paper-styles:lib", + "//third_party/javascript/polymer/v1/polymer:lib", + ], +) + +# This is needed: components/BUILD seeks a legacy_ts rule in this package. +tensorboard_ts_library( + name = "legacy_ts", + srcs = [], + deps_mgmt = "off", + runtime = "nodejs", + deps = ["//tensorflow/tensorboard/components:common_deps"], +) diff --git a/tensorflow/tensorboard/components/tf_scalar_dashboard/demo/BUILD b/tensorflow/tensorboard/components/tf_scalar_dashboard/demo/BUILD new file mode 100644 index 00000000000..218fda3fdb6 --- /dev/null +++ b/tensorflow/tensorboard/components/tf_scalar_dashboard/demo/BUILD @@ -0,0 +1,26 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") + +licenses(["notice"]) # Apache 2.0 + +# bazel run //third_party/tensorflow/tensorboard/components/tf_scalar_dashboard/demo +webfiles( + name = "demo", + srcs = ["index.html"], + path = "/tf-scalar-dashboard/demo", + deps = [ + "//tensorflow/tensorboard/components/tf_imports:d3", + "//tensorflow/tensorboard/components/tf_scalar_dashboard", + "//tensorflow/tensorboard/components/tf_scalar_dashboard/demo/data", + "@org_polymer_iron_demo_helpers", + "@org_polymer_paper_styles", + "@org_polymer_webcomponentsjs", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) diff --git a/tensorflow/tensorboard/components/tf_scalar_dashboard/demo/data/BUILD b/tensorflow/tensorboard/components/tf_scalar_dashboard/demo/data/BUILD new file mode 100644 index 00000000000..7f39d27f607 --- /dev/null +++ b/tensorflow/tensorboard/components/tf_scalar_dashboard/demo/data/BUILD @@ -0,0 +1,17 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") + +licenses(["notice"]) # Apache 2.0 + +webfiles( + name = "data", + srcs = glob(["*"]), + path = "/tf-scalar-dashboard/demo/data", +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) diff --git a/tensorflow/tensorboard/components/tf_storage/BUILD b/tensorflow/tensorboard/components/tf_storage/BUILD new file mode 100644 index 00000000000..e796340e032 --- /dev/null +++ b/tensorflow/tensorboard/components/tf_storage/BUILD @@ -0,0 +1,70 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_ts_library") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_typescript_genrule") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_webcomponent_library") + +licenses(["notice"]) # Apache 2.0 + +# TODO(dandelion): Add webfiles support for the test code. + +webfiles( + name = "tf_storage", + srcs = [ + "tf-storage.html", + ":ts", + ], + path = "/tf-storage", + deps = [ + "//tensorflow/tensorboard/components/tf_globals", + "//tensorflow/tensorboard/components/tf_imports:lodash", + "@org_polymer", + ], +) + +tensorboard_typescript_genrule( + name = "ts", + srcs = [ + "storage.ts", + ], + typings = [ + "@org_definitelytyped//:lodash.d.ts", + "//tensorflow/tensorboard/components/tf_globals:ts_typings", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) + +################################################################################ +# MARKED FOR DELETION + +tensorboard_webcomponent_library( + name = "legacy", + srcs = [ + "tf-storage.html", + ":legacy_ts", + ], + visibility = ["//visibility:public"], + destdir = "tf-storage", + deps = [ + "//tensorflow/tensorboard/components:tf_imports", + "//tensorflow/tensorboard/components/tf_globals:legacy", + "//third_party/javascript/polymer/v1/polymer:lib", + ], +) + +tensorboard_ts_library( + name = "legacy_ts", + srcs = ["storage.ts"], + deps_mgmt = "off", + runtime = "nodejs", + deps = [ + "//tensorflow/tensorboard/components:common_deps", + "//tensorflow/tensorboard/components/tf_globals:legacy_ts", + ], +) diff --git a/tensorflow/tensorboard/components/tf_storage_d3v4/BUILD b/tensorflow/tensorboard/components/tf_storage_d3v4/BUILD new file mode 100644 index 00000000000..877f0263195 --- /dev/null +++ b/tensorflow/tensorboard/components/tf_storage_d3v4/BUILD @@ -0,0 +1,35 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_ts_library") + +licenses(["notice"]) # Apache 2.0 + +# TODO(dandelion): Add test runner. + +tensorboard_ts_library( + name = "ts", + srcs = ["storage.ts"], + deps = [ + "//tensorflow/tensorboard/components/tf_globals_d3v4:ts", + "//third_party/javascript/lodash:lodash-module", + "//third_party/javascript/typings/lodash", + ], +) + +tensorboard_ts_library( + name = "tests", + srcs = ["storageTests.ts"], + deps = [ + ":ts", + "//tensorflow/tensorboard/components/tf_globals_d3v4:ts", + "//third_party/javascript/typings/chai", + "//third_party/javascript/typings/mocha", + "//third_party/javascript/typings/sinon", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) diff --git a/tensorflow/tensorboard/components/tf_text_dashboard/BUILD b/tensorflow/tensorboard/components/tf_text_dashboard/BUILD new file mode 100644 index 00000000000..71e16db6910 --- /dev/null +++ b/tensorflow/tensorboard/components/tf_text_dashboard/BUILD @@ -0,0 +1,60 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_ts_library") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_webcomponent_library") + +licenses(["notice"]) # Apache 2.0 + +webfiles( + name = "tf_text_dashboard", + srcs = [ + "tf-text-dashboard.html", + "tf-text-loader.html", + ], + path = "/tf-text-dashboard", + deps = [ + "//tensorflow/tensorboard/components/tf_backend", + "//tensorflow/tensorboard/components/tf_color_scale", + "//tensorflow/tensorboard/components/tf_dashboard_common", + "//tensorflow/tensorboard/components/tf_imports:d3", + "//tensorflow/tensorboard/components/tf_imports:lodash", + "@org_polymer", + "@org_polymer_paper_dialog", + "@org_polymer_paper_icon_button", + "@org_polymer_paper_material", + "@org_polymer_paper_slider", + "@org_polymer_paper_spinner", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) + +################################################################################ +# MARKED FOR DELETION + +tensorboard_webcomponent_library( + name = "legacy", + srcs = [ + "tf-text-dashboard.html", + "tf-text-loader.html", + ], + destdir = "tf-text-dashboard", + deps = [ + "//tensorflow/tensorboard/components/tf_backend:legacy", + "//tensorflow/tensorboard/components/tf_dashboard_common:legacy", + "//third_party/javascript/polymer/v1/paper-material:lib", + ], +) + +# This is needed: components/BUILD seeks a legacy_ts rule in this package. +tensorboard_ts_library( + name = "legacy_ts", + srcs = [], + deps_mgmt = "off", + runtime = "nodejs", +) diff --git a/tensorflow/tensorboard/components/tf_text_dashboard/demo/BUILD b/tensorflow/tensorboard/components/tf_text_dashboard/demo/BUILD new file mode 100644 index 00000000000..6cd6702e4b7 --- /dev/null +++ b/tensorflow/tensorboard/components/tf_text_dashboard/demo/BUILD @@ -0,0 +1,25 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") + +licenses(["notice"]) # Apache 2.0 + +# bazel run //third_party/tensorflow/tensorboard/components/tf_text_dashboard/demo +webfiles( + name = "demo", + srcs = ["index.html"], + path = "/tf-text-dashboard/demo", + deps = [ + "//tensorflow/tensorboard/components/tf_text_dashboard", + "//tensorflow/tensorboard/components/tf_text_dashboard/demo/data", + "@org_polymer_iron_demo_helpers", + "@org_polymer_paper_styles", + "@org_polymer_webcomponentsjs", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) diff --git a/tensorflow/tensorboard/components/tf_text_dashboard/demo/data/BUILD b/tensorflow/tensorboard/components/tf_text_dashboard/demo/data/BUILD new file mode 100644 index 00000000000..8adf661396c --- /dev/null +++ b/tensorflow/tensorboard/components/tf_text_dashboard/demo/data/BUILD @@ -0,0 +1,17 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") + +licenses(["notice"]) # Apache 2.0 + +webfiles( + name = "data", + srcs = glob(["*"]), + path = "/tf-text-dashboard/demo/data/plugin/text", +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) diff --git a/tensorflow/tensorboard/components/vz_data_summary/BUILD b/tensorflow/tensorboard/components/vz_data_summary/BUILD new file mode 100644 index 00000000000..a4ba0c089c9 --- /dev/null +++ b/tensorflow/tensorboard/components/vz_data_summary/BUILD @@ -0,0 +1,91 @@ +package(default_visibility = ["//visibility:public"]) + +load( + "//tensorflow/tensorboard:defs.bzl", + "tensorboard_ts_config", + "tensorboard_ts_declaration", + "tensorboard_ts_development_sources", + "tensorboard_ts_devserver", + "tensorboard_ts_library", + "tensorboard_webcomponent_library", +) + +licenses(["notice"]) # Apache 2.0 + +tensorboard_webcomponent_library( + name = "lib", + srcs = ["vz-data-summary.html"], + ts_lib_deps = [":ts_lib"], + destdir = "vz-data-summary", + deps = [ + "//learning/vis/vz_elements:common", + "//third_party/javascript/d3/v3:lib", + "//third_party/javascript/polymer/v1/iron-demo-helpers:lib", + "//third_party/javascript/polymer/v1/iron-resizable-behavior:lib", + "//third_party/javascript/polymer/v1/polymer:lib", + ], +) + +tensorboard_ts_library( + name = "ts_lib", + srcs = ["vz-data-summary.ts"], + externs_list = [":externs"], + deps = [ + ":typings", + "//third_party/javascript/typings/polymer:polymer_without_externs", + ], +) + +tensorboard_ts_declaration( + name = "typings", + srcs = ["typings.d.ts"], +) + +# This build rule is used to run the demo. +tensorboard_ts_devserver( + name = "dev_server", + manifest = ":dev_sources", + serving_path = "/demo_lib_out/vz-data-summary/vz-data-summary.js", + static_files = [":demo_lib"], + deps = [":tsconfig"], +) + +tensorboard_webcomponent_library( + name = "demo_lib", + srcs = ["demo.html"], + destdir = "vz-data-summary", + deps = [ + ":lib", + "//third_party/javascript/d3/v3:lib", + "//third_party/javascript/polymer/v1/iron-demo-helpers:lib", + "//third_party/javascript/polymer/v1/iron-resizable-behavior:lib", + "//third_party/javascript/polymer/v1/polymer:lib", + ], +) + +tensorboard_ts_library( + name = "demo_ts_lib", + srcs = ["demo.ts"], + externs_list = [":externs"], + deps = [ + ":ts_lib", + "//third_party/javascript/typings/d3", + ], +) + +tensorboard_ts_development_sources( + name = "dev_sources", + deps = [":demo_ts_lib"], +) + +tensorboard_ts_config( + name = "tsconfig", + deps = [":ts_lib"], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], + visibility = ["//tensorflow:__subpackages__"], +) diff --git a/tensorflow/tensorboard/components/vz_data_summary/BUILD.OPENSOURCE b/tensorflow/tensorboard/components/vz_data_summary/BUILD.OPENSOURCE deleted file mode 100644 index 9743d70d947..00000000000 --- a/tensorflow/tensorboard/components/vz_data_summary/BUILD.OPENSOURCE +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2016 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the 'License'); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an 'AS IS' BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================= - -# Description: -# Package for the data-summary vz-element. -package(default_visibility = ["//tensorflow:internal"]) - -licenses(["notice"]) # Apache 2.0 - -exports_files(["LICENSE"]) - -filegroup( - name = "all_files", - srcs = glob( - ["**/*"], - exclude = [ - "**/METADATA", - "**/OWNERS", - ], - ), - visibility = ["//tensorflow:__subpackages__"], -) diff --git a/tensorflow/tensorboard/components/vz_distribution_chart/BUILD b/tensorflow/tensorboard/components/vz_distribution_chart/BUILD new file mode 100644 index 00000000000..5ce98b1d7c4 --- /dev/null +++ b/tensorflow/tensorboard/components/vz_distribution_chart/BUILD @@ -0,0 +1,69 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_ts_library") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_typescript_genrule") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_webcomponent_library") + +licenses(["notice"]) # Apache 2.0 + +webfiles( + name = "vz_distribution_chart", + srcs = [ + "vz-distribution-chart.html", + ":ts", + ], + path = "/vz-distribution-chart", + deps = [ + "//tensorflow/tensorboard/components/tf_imports:lodash", + "//tensorflow/tensorboard/components/tf_imports:plottable", + "//tensorflow/tensorboard/components/vz_line_chart", + "@org_polymer", + ], +) + +tensorboard_typescript_genrule( + name = "ts", + srcs = ["vz-distribution-chart.ts"], + typings = [ + "@org_definitelytyped//:d3.d.ts", + "@com_palantir_plottable//:plottable.d.ts", + "@org_definitelytyped//:lodash.d.ts", + "//tensorflow/tensorboard/components/vz_line_chart:ts_typings", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) + +################################################################################ +# MARKED FOR DELETION + +tensorboard_webcomponent_library( + name = "legacy", + srcs = [ + "vz-distribution-chart.html", + ":legacy_ts", + ], + visibility = ["//visibility:public"], + destdir = "vz-distribution-chart", + deps = [ + "//tensorflow/tensorboard/components:tf_imports", + "//tensorflow/tensorboard/components/vz_sorting:legacy", + "//third_party/javascript/polymer/v1/polymer:lib", + ], +) + +tensorboard_ts_library( + name = "legacy_ts", + srcs = ["vz-distribution-chart.ts"], + deps_mgmt = "off", + runtime = "nodejs", + deps = [ + "//tensorflow/tensorboard/components:common_deps", + "//tensorflow/tensorboard/components/vz_line_chart:legacy_ts", + ], +) diff --git a/tensorflow/tensorboard/components/vz_distribution_chart/demo/BUILD b/tensorflow/tensorboard/components/vz_distribution_chart/demo/BUILD new file mode 100644 index 00000000000..77f05aa2d4c --- /dev/null +++ b/tensorflow/tensorboard/components/vz_distribution_chart/demo/BUILD @@ -0,0 +1,24 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") + +licenses(["notice"]) # Apache 2.0 + +# bazel run //third_party/tensorflow/tensorboard/components/vz_distribution_chart/demo +webfiles( + name = "demo", + srcs = ["index.html"], + path = "/vz-distribution-chart/demo", + deps = [ + "//tensorflow/tensorboard/components/vz_distribution_chart", + "@org_polymer_iron_demo_helpers", + "@org_polymer_paper_styles", + "@org_polymer_webcomponentsjs", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) diff --git a/tensorflow/tensorboard/components/vz_distribution_chart_d3v4/BUILD b/tensorflow/tensorboard/components/vz_distribution_chart_d3v4/BUILD new file mode 100644 index 00000000000..384fc6f44c0 --- /dev/null +++ b/tensorflow/tensorboard/components/vz_distribution_chart_d3v4/BUILD @@ -0,0 +1,66 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load( + "//tensorflow/tensorboard:defs.bzl", + "tensorboard_ts_development_sources", + "tensorboard_ts_devserver", + "tensorboard_ts_library", + "tensorboard_webcomponent_library", +) + +licenses(["notice"]) # Apache 2.0 + +tensorboard_ts_library( + name = "ts", + srcs = ["vz-distribution-chart.ts"], + deps = [ + "//tensorflow/tensorboard/components:common_deps_d3v4", + "//tensorflow/tensorboard/components/vz_line_chart_d3v4:ts", + "//third_party/javascript/lodash:lodash-module", + "//third_party/javascript/plottable/v3:bundle", + ], +) + +tensorboard_webcomponent_library( + name = "vz_distribution_chart", + srcs = [ + "demo.html", + "vz-distribution-chart.html", + ], + ts_lib_deps = [":ts"], + visibility = ["//visibility:public"], + deps = [ + "//tensorflow/tensorboard/components/vz_sorting:legacy", + "//third_party/javascript/plottable/v3:lib", + "//third_party/javascript/polymer/v1/polymer:lib", + ], +) + +tensorboard_webcomponent_library( + name = "demo", + srcs = ["demo.html"], + visibility = ["//visibility:public"], + deps = [ + ":vz_distribution_chart", + "//third_party/javascript/polymer/v1/iron-demo-helpers:lib", + "//third_party/javascript/polymer/v1/paper-styles:lib", + ], +) + +tensorboard_ts_devserver( + name = "devserver", + manifest = ":dev_sources", + serving_path = "/demo_out/bundle.js", + static_files = [":demo"], +) + +tensorboard_ts_development_sources( + name = "dev_sources", + deps = [":ts"], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) diff --git a/tensorflow/tensorboard/components/vz_histogram_timeseries/BUILD b/tensorflow/tensorboard/components/vz_histogram_timeseries/BUILD new file mode 100644 index 00000000000..31032a6b230 --- /dev/null +++ b/tensorflow/tensorboard/components/vz_histogram_timeseries/BUILD @@ -0,0 +1,50 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_ts_library") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_webcomponent_library") + +licenses(["notice"]) # Apache 2.0 + +webfiles( + name = "vz_histogram_timeseries", + srcs = [ + "vz-histogram-timeseries.html", + ], + path = "/vz-histogram-timeseries", + deps = [ + "//tensorflow/tensorboard/components/tf_imports:d3", + "@org_polymer", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) + +################################################################################ +# MARKED FOR DELETION + +tensorboard_webcomponent_library( + name = "legacy", + srcs = [ + "index.html", + "vz-histogram-timeseries.html", + ":legacy_ts", + ], + visibility = ["//visibility:public"], + destdir = "vz-histogram-timeseries", + deps = [ + "//tensorflow/tensorboard/components:tf_imports", + "//third_party/javascript/polymer/v1/polymer:lib", + ], +) + +# This is needed: components/BUILD seeks a legacy_ts rule in this package. +tensorboard_ts_library( + name = "legacy_ts", + deps_mgmt = "off", + runtime = "nodejs", +) diff --git a/tensorflow/tensorboard/components/vz_histogram_timeseries/demo/BUILD b/tensorflow/tensorboard/components/vz_histogram_timeseries/demo/BUILD new file mode 100644 index 00000000000..894de95be65 --- /dev/null +++ b/tensorflow/tensorboard/components/vz_histogram_timeseries/demo/BUILD @@ -0,0 +1,25 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") + +licenses(["notice"]) # Apache 2.0 + +# bazel run //third_party/tensorflow/tensorboard/components/vz_histogram_timeseries/demo +webfiles( + name = "demo", + srcs = ["index.html"], + path = "/vz-histogram-timeseries/demo", + deps = [ + "//tensorflow/tensorboard/components/vz_histogram_timeseries", + "@org_polymer_iron_demo_helpers", + "@org_polymer_paper_button", + "@org_polymer_paper_styles", + "@org_polymer_webcomponentsjs", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) diff --git a/tensorflow/tensorboard/components/vz_histogram_timeseries_d3v4/BUILD b/tensorflow/tensorboard/components/vz_histogram_timeseries_d3v4/BUILD new file mode 100644 index 00000000000..02c0640742b --- /dev/null +++ b/tensorflow/tensorboard/components/vz_histogram_timeseries_d3v4/BUILD @@ -0,0 +1,63 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_ts_library") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_webcomponent_library") + +licenses(["notice"]) # Apache 2.0 + +webfiles( + name = "vz_histogram_timeseries", + srcs = [ + "vz-histogram-timeseries.html", + ], + path = "/vz-histogram-timeseries", + deps = [ + "//tensorflow/tensorboard/components/tf_imports_d3v4:d3", + "@org_polymer", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) + +# bazel run //third_party/tensorflow/tensorboard/components/vz_histogram_timeseries/demo +webfiles( + name = "demo", + srcs = ["demo.html"], + path = "/vz-histogram-timeseries", + deps = [ + ":vz_histogram_timeseries", + "@org_polymer_iron_demo_helpers", + "@org_polymer_paper_button", + "@org_polymer_paper_styles", + "@org_polymer_webcomponentsjs", + ], +) + +################################################################################ +# MARKED FOR DELETION + +tensorboard_webcomponent_library( + name = "legacy", + srcs = [ + "vz-histogram-timeseries.html", + ":legacy_ts", + ], + visibility = ["//visibility:public"], + destdir = "vz-histogram-timeseries", + deps = [ + "//tensorflow/tensorboard/components:tf_imports", + "//third_party/javascript/polymer/v1/polymer:lib", + ], +) + +# This is needed: components/BUILD seeks a legacy_ts rule in this package. +tensorboard_ts_library( + name = "legacy_ts", + deps_mgmt = "off", + runtime = "nodejs", +) diff --git a/tensorflow/tensorboard/components/vz_line_chart/BUILD b/tensorflow/tensorboard/components/vz_line_chart/BUILD new file mode 100644 index 00000000000..7b13abd7214 --- /dev/null +++ b/tensorflow/tensorboard/components/vz_line_chart/BUILD @@ -0,0 +1,73 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_ts_library") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_typescript_genrule") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_webcomponent_library") + +licenses(["notice"]) # Apache 2.0 + +webfiles( + name = "vz_line_chart", + srcs = [ + "vz-line-chart.html", + ":ts", + ], + path = "/vz-line-chart", + deps = [ + "//tensorflow/tensorboard/components/tf_imports:lodash", + "//tensorflow/tensorboard/components/tf_imports:plottable", + "@org_polymer", + ], +) + +tensorboard_typescript_genrule( + name = "ts", + srcs = [ + "dragZoomInteraction.ts", + "vz-chart-helpers.ts", + "vz-line-chart.ts", + ], + typings = [ + "@org_definitelytyped//:d3.d.ts", + "@com_palantir_plottable//:plottable.d.ts", + "@org_definitelytyped//:lodash.d.ts", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) + +################################################################################ +# MARKED FOR DELETION + +tensorboard_webcomponent_library( + name = "legacy", + srcs = [ + "index.html", + "vz-line-chart.html", + ":legacy_ts", + ], + visibility = ["//visibility:public"], + destdir = "vz-line-chart", + deps = [ + "//tensorflow/tensorboard/components:tf_imports", + "//tensorflow/tensorboard/components/vz_sorting:legacy", + "//third_party/javascript/polymer/v1/polymer:lib", + ], +) + +tensorboard_ts_library( + name = "legacy_ts", + srcs = [ + "dragZoomInteraction.ts", + "vz-chart-helpers.ts", + "vz-line-chart.ts", + ], + deps_mgmt = "off", + runtime = "nodejs", + deps = ["//tensorflow/tensorboard/components:common_deps"], +) diff --git a/tensorflow/tensorboard/components/vz_line_chart/demo/BUILD b/tensorflow/tensorboard/components/vz_line_chart/demo/BUILD new file mode 100644 index 00000000000..84699b67b6b --- /dev/null +++ b/tensorflow/tensorboard/components/vz_line_chart/demo/BUILD @@ -0,0 +1,24 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") + +licenses(["notice"]) # Apache 2.0 + +# bazel run //third_party/tensorflow/tensorboard/components/vz_line_chart/demo +webfiles( + name = "demo", + srcs = ["index.html"], + path = "/vz-line-chart/demo", + deps = [ + "//tensorflow/tensorboard/components/vz_line_chart", + "@org_polymer_iron_demo_helpers", + "@org_polymer_paper_styles", + "@org_polymer_webcomponentsjs", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) diff --git a/tensorflow/tensorboard/components/vz_line_chart_d3v4/BUILD b/tensorflow/tensorboard/components/vz_line_chart_d3v4/BUILD new file mode 100644 index 00000000000..fd460b3608f --- /dev/null +++ b/tensorflow/tensorboard/components/vz_line_chart_d3v4/BUILD @@ -0,0 +1,66 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load( + "//tensorflow/tensorboard:defs.bzl", + "tensorboard_ts_development_sources", + "tensorboard_ts_devserver", + "tensorboard_ts_library", + "tensorboard_webcomponent_library", +) + +licenses(["notice"]) # Apache 2.0 + +tensorboard_ts_library( + name = "ts", + srcs = [ + "dragZoomInteraction.ts", + "vz-chart-helpers.ts", + "vz-line-chart.ts", + ], + deps = [ + "//tensorflow/tensorboard/components:common_deps_d3v4", + "//third_party/javascript/lodash:lodash-module", + "//third_party/javascript/plottable/v3:bundle", + ], +) + +tensorboard_webcomponent_library( + name = "vz_line_chart", + srcs = ["vz-line-chart.html"], + ts_lib_deps = [":ts"], + visibility = ["//visibility:public"], + deps = [ + "//tensorflow/tensorboard/components/vz_sorting:legacy", + "//third_party/javascript/plottable/v3:lib", + "//third_party/javascript/polymer/v1/polymer:lib", + ], +) + +tensorboard_webcomponent_library( + name = "demo", + srcs = ["demo.html"], + visibility = ["//visibility:public"], + deps = [ + ":vz_line_chart", + "//third_party/javascript/polymer/v1/iron-demo-helpers:lib", + "//third_party/javascript/polymer/v1/paper-styles:lib", + ], +) + +tensorboard_ts_devserver( + name = "devserver", + manifest = ":dev_sources", + serving_path = "/demo_out/bundle.js", + static_files = [":demo"], +) + +tensorboard_ts_development_sources( + name = "dev_sources", + deps = [":ts"], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) diff --git a/tensorflow/tensorboard/components/vz_projector/BUILD b/tensorflow/tensorboard/components/vz_projector/BUILD new file mode 100644 index 00000000000..0ea94b9a22a --- /dev/null +++ b/tensorflow/tensorboard/components/vz_projector/BUILD @@ -0,0 +1,180 @@ +package(default_visibility = [":projector_group"]) + +load( + "//tensorflow/tensorboard:defs.bzl", + "tensorboard_karma_web_test_suite", + "tensorboard_ts_config", + "tensorboard_ts_declaration", + "tensorboard_ts_development_sources", + "tensorboard_ts_library", + "tensorboard_webcomponent_library", +) + +licenses(["notice"]) # Apache 2.0 + +filegroup( + name = "all_files", + srcs = glob( + ["**/*"], + exclude = [ + "**/METADATA", + "**/OWNERS", + ], + ), + visibility = ["//tensorflow:__subpackages__"], +) + +# Visibility group for all clients of projector. +package_group( + name = "projector_group", + packages = [ + "//apps/labs/towerbridge/...", + "//experimental/bigpicture/projector/...", + "//java/com/google/apps/labs/towerbridge/...", + "//learning/vis/projector/...", + "//tensorflow/tensorboard/...", + ], +) + +tensorboard_ts_declaration( + name = "external", + srcs = ["external.d.ts"], +) + +tensorboard_ts_library( + name = "ts_lib", + srcs = glob( + ["*.ts"], + exclude = [ + "*.d.ts", + "*_test.ts", + "bh_tsne.ts", + "sptree.ts", + ], + ), + runtime_deps = [ + "//third_party/javascript/d3/v3:d3", + "//third_party/javascript/numericjs", + "//third_party/javascript/threejs/r77:threejs", + "//third_party/javascript/threejs/r77/examples/js/controls:orbitcontrols", + "//third_party/javascript/weblas", + ], + deps = [ + ":external", + ":tsne_ts_lib", + "//third_party/javascript/node_modules/typescript:es2015.promise", + "//third_party/javascript/typings/d3", + "//third_party/javascript/typings/polymer:polymer_without_externs", + "//third_party/javascript/typings/threejs:three", + "//third_party/javascript/typings/webcomponents_js", + ], +) + +tensorboard_ts_library( + name = "tsne_ts_lib", + srcs = [ + "bh_tsne.ts", + "sptree.ts", + ], +) + +_PROJECTOR_LIB_DEPS = [ + "//third_party/javascript/polymer/v1/iron-collapse:lib", + "//third_party/javascript/polymer/v1/iron-icons:lib", + "//third_party/javascript/polymer/v1/paper-button:lib", + "//third_party/javascript/polymer/v1/paper-checkbox:lib", + "//third_party/javascript/polymer/v1/paper-dialog:lib", + "//third_party/javascript/polymer/v1/paper-dialog-scrollable:lib", + "//third_party/javascript/polymer/v1/paper-dropdown-menu:lib", + "//third_party/javascript/polymer/v1/paper-icon-button:lib", + "//third_party/javascript/polymer/v1/paper-input:lib", + "//third_party/javascript/polymer/v1/paper-item:lib", + "//third_party/javascript/polymer/v1/paper-listbox:lib", + "//third_party/javascript/polymer/v1/paper-slider:lib", + "//third_party/javascript/polymer/v1/paper-spinner:lib", + "//third_party/javascript/polymer/v1/paper-toast:lib", + "//third_party/javascript/polymer/v1/paper-toggle-button:lib", + "//third_party/javascript/polymer/v1/paper-tooltip:lib", + "//third_party/javascript/polymer/v1/polymer:lib", +] + +_PROJECTOR_DESTDIR = "vz-projector" + +_PROJECTOR_LIB_TS_LIB_DEPS = [ + ":ts_lib", + ":tsne_ts_lib", +] + +# Standalone embedding projector demos should depend on this target. We +# exclude the HTML file for the dashboard itself. Demos do not need that +# HTML file. This was introduced because standalone demos as of today +# have an additional Closure pass that uses a compilation configuration +# stricter than that of TensorBoard. +tensorboard_webcomponent_library( + name = "lib", + srcs = glob( + ["*.html"], + exclude = ["vz-projector-dashboard.html"], + ), + ts_lib_deps = _PROJECTOR_LIB_TS_LIB_DEPS, + destdir = _PROJECTOR_DESTDIR, + deps = _PROJECTOR_LIB_DEPS, +) + +# TensorBoard, however, should depend on this target, which includes +# the HTML file for the dashboard. +tensorboard_webcomponent_library( + name = "lib_for_tensorboard", + srcs = glob(["*.html"]), + ts_lib_deps = _PROJECTOR_LIB_TS_LIB_DEPS, + destdir = _PROJECTOR_DESTDIR, + deps = _PROJECTOR_LIB_DEPS, +) + +### Tests ### + +tensorboard_ts_library( + name = "ts_test", + testonly = 1, + srcs = glob(["*_test.ts"]), + runtime_deps = [ + "//third_party/javascript/polymer/v1/polymer:lib_all_js", + ], + deps = [ + ":ts_lib", + ":tsne_ts_lib", + "//third_party/javascript/typings/chai", + "//third_party/javascript/typings/jasmine:jasmine_without_externs", + "//third_party/javascript/typings/mocha", + ], +) + +tensorboard_ts_development_sources( + name = "dev_sources_for_test", + testonly = 1, + runtime_deps = [ + "//third_party/javascript/chai", + "//third_party/javascript/mocha", + ], + deps = [ + ":ts_test", + ], +) + +# To run locally, run :all_tests_local +tensorboard_karma_web_test_suite( + name = "all_tests", + size = "medium", + browsers = ["//testing/web/browsers:chrome-linux"], + manifest = ":dev_sources_for_test", +) + +# Generate a TypeScript IDE project by running this target. +tensorboard_ts_config( + name = "tsconfig", + deps = [ + ":ts_lib", + ":ts_test", + ":tsne_ts_lib", + ], +) diff --git a/tensorflow/tensorboard/components/vz_projector/BUILD.OPENSOURCE b/tensorflow/tensorboard/components/vz_projector/BUILD.OPENSOURCE deleted file mode 100644 index 8c222be10e9..00000000000 --- a/tensorflow/tensorboard/components/vz_projector/BUILD.OPENSOURCE +++ /dev/null @@ -1,19 +0,0 @@ -# Description: -# Package for the Embedding Projector component. -package(default_visibility = ["//tensorflow:internal"]) - -licenses(["notice"]) # Apache 2.0 - -exports_files(["LICENSE"]) - -filegroup( - name = "all_files", - srcs = glob( - ["**/*"], - exclude = [ - "**/METADATA", - "**/OWNERS", - ], - ), - visibility = ["//tensorflow:__subpackages__"], -) diff --git a/tensorflow/tensorboard/components/vz_projector_d3v4/BUILD b/tensorflow/tensorboard/components/vz_projector_d3v4/BUILD new file mode 100644 index 00000000000..d9703d080d3 --- /dev/null +++ b/tensorflow/tensorboard/components/vz_projector_d3v4/BUILD @@ -0,0 +1,179 @@ +package(default_visibility = [":projector_group"]) + +load( + "//tensorflow/tensorboard:defs.bzl", + "tensorboard_karma_web_test_suite", + "tensorboard_ts_config", + "tensorboard_ts_declaration", + "tensorboard_ts_development_sources", + "tensorboard_ts_library", + "tensorboard_webcomponent_library", +) + +licenses(["notice"]) # Apache 2.0 + +filegroup( + name = "all_files", + srcs = glob( + ["**"], + exclude = [ + "OWNERS", + "tsconfig.json", + ], + ), + visibility = ["//tensorflow:__subpackages__"], +) + +# Visibility group for all clients of projector. +package_group( + name = "projector_group", + packages = [ + "//apps/labs/towerbridge/...", + "//experimental/bigpicture/projector/...", + "//java/com/google/apps/labs/towerbridge/...", + "//learning/vis/projector/...", + "//tensorflow/tensorboard/...", + ], +) + +tensorboard_ts_declaration( + name = "external", + srcs = ["external.d.ts"], +) + +tensorboard_ts_library( + name = "ts_lib", + srcs = glob( + ["*.ts"], + exclude = [ + "*.d.ts", + "*_test.ts", + "bh_tsne.ts", + "sptree.ts", + ], + ), + runtime_deps = [ + "//third_party/javascript/numericjs", + "//third_party/javascript/threejs/r77:threejs", + "//third_party/javascript/threejs/r77/examples/js/controls:orbitcontrols", + "//third_party/javascript/weblas", + ], + deps = [ + ":external", + ":tsne_ts_lib", + "//third_party/javascript/node_modules/typescript:es2015.promise", + "//third_party/javascript/typings/d3_v4:bundle", + "//third_party/javascript/typings/polymer:polymer_without_externs", + "//third_party/javascript/typings/threejs:three", + "//third_party/javascript/typings/webcomponents_js", + ], +) + +tensorboard_ts_library( + name = "tsne_ts_lib", + srcs = [ + "bh_tsne.ts", + "sptree.ts", + ], +) + +_PROJECTOR_LIB_DEPS = [ + "//third_party/javascript/polymer/v1/iron-collapse:lib", + "//third_party/javascript/polymer/v1/iron-icons:lib", + "//third_party/javascript/polymer/v1/paper-button:lib", + "//third_party/javascript/polymer/v1/paper-checkbox:lib", + "//third_party/javascript/polymer/v1/paper-dialog:lib", + "//third_party/javascript/polymer/v1/paper-dialog-scrollable:lib", + "//third_party/javascript/polymer/v1/paper-dropdown-menu:lib", + "//third_party/javascript/polymer/v1/paper-icon-button:lib", + "//third_party/javascript/polymer/v1/paper-input:lib", + "//third_party/javascript/polymer/v1/paper-item:lib", + "//third_party/javascript/polymer/v1/paper-listbox:lib", + "//third_party/javascript/polymer/v1/paper-slider:lib", + "//third_party/javascript/polymer/v1/paper-spinner:lib", + "//third_party/javascript/polymer/v1/paper-toast:lib", + "//third_party/javascript/polymer/v1/paper-toggle-button:lib", + "//third_party/javascript/polymer/v1/paper-tooltip:lib", + "//third_party/javascript/polymer/v1/polymer:lib", +] + +_PROJECTOR_DESTDIR = "vz-projector" + +_PROJECTOR_LIB_TS_LIB_DEPS = [ + ":ts_lib", + ":tsne_ts_lib", +] + +# Standalone embedding projector demos should depend on this target. We +# exclude the HTML file for the dashboard itself. Demos do not need that +# HTML file. This was introduced because standalone demos as of today +# have an additional Closure pass that uses a compilation configuration +# stricter than that of TensorBoard. +tensorboard_webcomponent_library( + name = "lib", + srcs = glob( + ["*.html"], + exclude = ["vz-projector-dashboard.html"], + ), + ts_lib_deps = _PROJECTOR_LIB_TS_LIB_DEPS, + destdir = _PROJECTOR_DESTDIR, + deps = _PROJECTOR_LIB_DEPS, +) + +# TensorBoard, however, should depend on this target, which includes +# the HTML file for the dashboard. +tensorboard_webcomponent_library( + name = "lib_for_tensorboard", + srcs = glob(["*.html"]), + ts_lib_deps = _PROJECTOR_LIB_TS_LIB_DEPS, + destdir = _PROJECTOR_DESTDIR, + deps = _PROJECTOR_LIB_DEPS, +) + +### Tests ### + +tensorboard_ts_library( + name = "ts_test", + testonly = 1, + srcs = glob(["*_test.ts"]), + runtime_deps = [ + "//third_party/javascript/polymer/v1/polymer:lib_all_js", + ], + deps = [ + ":ts_lib", + ":tsne_ts_lib", + "//third_party/javascript/typings/chai", + "//third_party/javascript/typings/jasmine:jasmine_without_externs", + "//third_party/javascript/typings/mocha", + ], +) + +tensorboard_ts_development_sources( + name = "dev_sources_for_test", + testonly = 1, + runtime_deps = [ + "//third_party/javascript/chai", + "//third_party/javascript/mocha", + ], + deps = [ + ":ts_test", + ], +) + +# To run locally, run :all_tests_local +tensorboard_karma_web_test_suite( + name = "all_tests", + size = "medium", + browsers = ["//testing/web/browsers:chrome-linux"], + manifest = ":dev_sources_for_test", +) + +# Generate a TypeScript IDE project by running this target. +tensorboard_ts_config( + name = "tsconfig", + deps = [ + ":ts_lib", + ":ts_test", + ":tsne_ts_lib", + ], +) diff --git a/tensorflow/tensorboard/components/vz_sorting/BUILD b/tensorflow/tensorboard/components/vz_sorting/BUILD new file mode 100644 index 00000000000..8efedb3639c --- /dev/null +++ b/tensorflow/tensorboard/components/vz_sorting/BUILD @@ -0,0 +1,50 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("@io_bazel_rules_closure//closure:defs.bzl", "webfiles") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_ts_library") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_typescript_genrule") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_webcomponent_library") + +licenses(["notice"]) # Apache 2.0 + +webfiles( + name = "vz_sorting", + srcs = [ + "vz-sorting.html", + ":ts", + ], + path = "/vz-sorting", + visibility = ["//visibility:public"], +) + +tensorboard_typescript_genrule( + name = "ts", + srcs = ["sorting.ts"], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) + +################################################################################ +# MARKED FOR DELETION + +tensorboard_webcomponent_library( + name = "legacy", + srcs = [ + "vz-sorting.html", + ":legacy_ts", + ], + visibility = ["//visibility:public"], + destdir = "vz-sorting", +) + +tensorboard_ts_library( + name = "legacy_ts", + srcs = ["sorting.ts"], + deps_mgmt = "off", + runtime = "nodejs", + deps = ["//tensorflow/tensorboard/components:common_deps"], +) diff --git a/tensorflow/tensorboard/components/vz_sorting/test/BUILD b/tensorflow/tensorboard/components/vz_sorting/test/BUILD new file mode 100644 index 00000000000..d1cf5a596ad --- /dev/null +++ b/tensorflow/tensorboard/components/vz_sorting/test/BUILD @@ -0,0 +1,40 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_ts_library") +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_wct_test_suite") + +licenses(["notice"]) # Apache 2.0 + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) + +################################################################################ +# MARKED FOR DELETION + +tensorboard_wct_test_suite( + name = "legacy_test", + size = "medium", + srcs = [ + "index.html", + ":legacy_ts", + ], + deps = [ + "//tensorflow/tensorboard/components/vz_sorting:legacy", + "//third_party/javascript/polymer/v1/webcomponentsjs:lib", + ], +) + +tensorboard_ts_library( + name = "legacy_ts", + testonly = 1, + srcs = ["sortingTests.ts"], + deps_mgmt = "off", + runtime = "nodejs", + deps = [ + "//tensorflow/tensorboard/components:common_deps", + "//tensorflow/tensorboard/components/vz_sorting:legacy_ts", + ], +) diff --git a/tensorflow/tensorboard/components/vz_sorting_d3v4/BUILD b/tensorflow/tensorboard/components/vz_sorting_d3v4/BUILD new file mode 100644 index 00000000000..6e6ce525b47 --- /dev/null +++ b/tensorflow/tensorboard/components/vz_sorting_d3v4/BUILD @@ -0,0 +1,27 @@ +package(default_visibility = ["//tensorflow:internal"]) + +load("//tensorflow/tensorboard:defs.bzl", "tensorboard_ts_library") + +licenses(["notice"]) # Apache 2.0 + +tensorboard_ts_library( + name = "ts", + srcs = ["sorting.ts"], +) + +tensorboard_ts_library( + name = "tests", + srcs = ["sortingTests.ts"], + deps = [ + ":ts", + "//third_party/javascript/typings/chai", + "//third_party/javascript/typings/mocha", + "//third_party/javascript/typings/sinon", + ], +) + +filegroup( + name = "all_files", + srcs = glob(["**"]), + tags = ["notsan"], +) diff --git a/tensorflow/tensorboard/defs.bzl b/tensorflow/tensorboard/defs.bzl index 7bb5f961c97..5d88baa5be3 100644 --- a/tensorflow/tensorboard/defs.bzl +++ b/tensorflow/tensorboard/defs.bzl @@ -60,6 +60,26 @@ def tensorboard_typescript_genrule(name, srcs, typings=[], **kwargs): **kwargs ) +def tensorboard_karma_web_test_suite(**kwargs): + """Rules referencing this will be deleted from the codebase soon.""" + pass + +def tensorboard_ts_config(**kwargs): + """Rules referencing this will be deleted from the codebase soon.""" + pass + +def tensorboard_ts_declaration(**kwargs): + """Rules referencing this will be deleted from the codebase soon.""" + pass + +def tensorboard_ts_development_sources(**kwargs): + """Rules referencing this will be deleted from the codebase soon.""" + pass + +def tensorboard_ts_devserver(**kwargs): + """Rules referencing this will be deleted from the codebase soon.""" + pass + def tensorboard_ts_library(**kwargs): """Rules referencing this will be deleted from the codebase soon.""" pass From 3cffa5fd4fcb2b2ef1fc244c1cf11dda507896cf Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Fri, 5 May 2017 13:53:38 -0800 Subject: [PATCH 20/27] Modify make_export_strategy to work with core Estimator. Change: 155243616 --- .../learn/python/learn/experiment_test.py | 83 ++++++++++++++++--- .../learn/utils/saved_model_export_utils.py | 34 ++++++-- 2 files changed, 96 insertions(+), 21 deletions(-) diff --git a/tensorflow/contrib/learn/python/learn/experiment_test.py b/tensorflow/contrib/learn/python/learn/experiment_test.py index 9ecfc732998..17feeb27362 100644 --- a/tensorflow/contrib/learn/python/learn/experiment_test.py +++ b/tensorflow/contrib/learn/python/learn/experiment_test.py @@ -22,6 +22,7 @@ import os import tempfile import time +from tensorflow.contrib.learn.python.learn import estimator as estimator_lib from tensorflow.contrib.learn.python.learn import evaluable from tensorflow.contrib.learn.python.learn import experiment from tensorflow.contrib.learn.python.learn import run_config @@ -38,6 +39,7 @@ from tensorflow.python.training import saver from tensorflow.python.training import server_lib from tensorflow.python.training import session_run_hook from tensorflow.python.util import compat +from tensorflow.python.util import tf_inspect class SheepCounter(object): @@ -119,6 +121,15 @@ class TestBaseEstimator(object): compat.as_bytes(export_dir_base), compat.as_bytes('bogus_timestamp')) +def _check_method_supports_args(method, kwargs): + """Checks that the given method supports the given args.""" + supported_args = tuple(tf_inspect.getargspec(method).args) + for kwarg in kwargs: + if kwarg not in supported_args: + raise ValueError( + 'Argument `{}` is not supported in method {}.'.format(kwarg, method)) + + class TestEstimator( TestBaseEstimator, evaluable.Evaluable, trainable.Trainable): @@ -126,9 +137,12 @@ class TestEstimator( super(TestEstimator, self).__init__(config, max_evals, eval_dict) tf_logging.info('Create Estimator') + def evaluate(self, **kwargs): + _check_method_supports_args(evaluable.Evaluable.evaluate, kwargs) + return super(TestEstimator, self).evaluate(**kwargs) + def fit(self, **kwargs): - if 'hooks' in kwargs: - raise ValueError('`hooks` is defined in core Estimator') + _check_method_supports_args(trainable.Trainable.fit, kwargs) if 'monitors' in kwargs: self.monitors = kwargs['monitors'] return super(TestEstimator, self).train(**kwargs) @@ -136,6 +150,13 @@ class TestEstimator( def train(self, **kwargs): raise ValueError('`train` is not defined in Estimator.') + def export_savedmodel( + self, export_dir_base, serving_input_fn, **kwargs): + _check_method_supports_args( + estimator_lib.Estimator.export_savedmodel, kwargs) + return super(TestEstimator, self).export_savedmodel( + export_dir_base, serving_input_fn, **kwargs) + class TestCoreEstimator(TestBaseEstimator, core_estimator.Estimator): @@ -144,17 +165,22 @@ class TestCoreEstimator(TestBaseEstimator, core_estimator.Estimator): tf_logging.info('Create Core Estimator') def evaluate(self, **kwargs): - if 'eval_metrics' in kwargs: - raise ValueError('`eval_metrics` is not defined in core Estimator') + _check_method_supports_args(core_estimator.Estimator.evaluate, kwargs) return super(TestCoreEstimator, self).evaluate(**kwargs) def train(self, **kwargs): - if 'monitors' in kwargs: - raise ValueError('`monitors` is not defined in core Estimator') + _check_method_supports_args(core_estimator.Estimator.train, kwargs) if 'hooks' in kwargs: self.monitors = kwargs['hooks'] return super(TestCoreEstimator, self).train(**kwargs) + def export_savedmodel( + self, export_dir_base, serving_input_receiver_fn, **kwargs): + _check_method_supports_args( + core_estimator.Estimator.export_savedmodel, kwargs) + return super(TestCoreEstimator, self).export_savedmodel( + export_dir_base, serving_input_receiver_fn, **kwargs) + class _NoopHook(session_run_hook.SessionRunHook): pass @@ -184,6 +210,23 @@ class ExperimentTest(test.TestCase): eval_input_fn='eval_input', eval_metrics='eval_metrics') + def test_default_output_alternative_key_core_estimator(self): + est = TestCoreEstimator() + export_strategy = saved_model_export_utils.make_export_strategy( + est, + default_output_alternative_key='export_key', + exports_to_keep=None) + ex = experiment.Experiment( + est, + train_input_fn='train_input', + eval_input_fn='eval_input', + train_steps=100, + eval_steps=100, + export_strategies=export_strategy) + with self.assertRaisesRegexp( + ValueError, 'default_output_alternative_key is not supported'): + ex.train_and_evaluate() + def test_train(self): for est in self._estimators_for_tests(): eval_metrics = 'eval_metrics' if not isinstance( @@ -508,7 +551,9 @@ class ExperimentTest(test.TestCase): eval_metrics = 'eval_metrics' if not isinstance( est, core_estimator.Estimator) else None export_strategy_1 = saved_model_export_utils.make_export_strategy( - est, 'export_input_1', exports_to_keep=None) + est, + None if isinstance(est, core_estimator.Estimator) else 'export_1', + exports_to_keep=None) ex = experiment.Experiment( est, @@ -531,9 +576,13 @@ class ExperimentTest(test.TestCase): # After reset with list, the count should increase with the number of # items. export_strategy_2 = saved_model_export_utils.make_export_strategy( - est, 'export_input_2', exports_to_keep=None) + est, + None if isinstance(est, core_estimator.Estimator) else 'export_2', + exports_to_keep=None) export_strategy_3 = saved_model_export_utils.make_export_strategy( - est, 'export_input_3', exports_to_keep=None) + est, + None if isinstance(est, core_estimator.Estimator) else 'export_3', + exports_to_keep=None) old_es = ex.reset_export_strategies( [export_strategy_2, export_strategy_3]) @@ -547,7 +596,9 @@ class ExperimentTest(test.TestCase): est, core_estimator.Estimator) else None noop_hook = _NoopHook() export_strategy = saved_model_export_utils.make_export_strategy( - est, 'export_input', exports_to_keep=None) + est, + None if isinstance(est, core_estimator.Estimator) else 'export_input', + exports_to_keep=None) ex = experiment.Experiment( est, train_input_fn='train_input', @@ -625,7 +676,9 @@ class ExperimentTest(test.TestCase): est, core_estimator.Estimator) else None noop_hook = _NoopHook() export_strategy = saved_model_export_utils.make_export_strategy( - est, 'export_input', exports_to_keep=None) + est, + None if isinstance(est, core_estimator.Estimator) else 'export_input', + exports_to_keep=None) ex = experiment.Experiment( est, train_input_fn='train_input', @@ -646,7 +699,9 @@ class ExperimentTest(test.TestCase): eval_metrics = 'eval_metrics' if not isinstance( est, core_estimator.Estimator) else None export_strategy = saved_model_export_utils.make_export_strategy( - est, 'export_input', exports_to_keep=None) + est, + None if isinstance(est, core_estimator.Estimator) else 'export_input', + exports_to_keep=None) ex = experiment.Experiment( est, train_input_fn='train_input', @@ -796,7 +851,9 @@ class ExperimentTest(test.TestCase): def test_test(self): for est in self._estimators_for_tests(): exp_strategy = saved_model_export_utils.make_export_strategy( - est, 'export_input', exports_to_keep=None) + est, + None if isinstance(est, core_estimator.Estimator) else 'export_input', + exports_to_keep=None) ex = experiment.Experiment( est, train_input_fn='train_input', diff --git a/tensorflow/contrib/learn/python/learn/utils/saved_model_export_utils.py b/tensorflow/contrib/learn/python/learn/utils/saved_model_export_utils.py index 7ad3779314b..fa314e69c7a 100644 --- a/tensorflow/contrib/learn/python/learn/utils/saved_model_export_utils.py +++ b/tensorflow/contrib/learn/python/learn/utils/saved_model_export_utils.py @@ -42,6 +42,7 @@ from tensorflow.contrib.learn.python.learn.estimators import constants from tensorflow.contrib.learn.python.learn.estimators import prediction_key from tensorflow.contrib.learn.python.learn.utils import gc from tensorflow.contrib.learn.python.learn.utils import input_fn_utils +from tensorflow.python.estimator import estimator as core_estimator from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors_impl from tensorflow.python.platform import gfile @@ -352,7 +353,8 @@ def make_export_strategy(serving_input_fn, `InputFnOps`. default_output_alternative_key: the name of the head to serve when an incoming serving request does not explicitly request a specific head. - Not needed for single-headed models. + Must be `None` if the estimator inherits from ${tf.estimator.Estimator} + or for single-headed models. assets_extra: A dict specifying how to populate the assets.extra directory within the exported SavedModel. Each key should give the destination path (including the filename) relative to the assets.extra directory. @@ -384,14 +386,30 @@ def make_export_strategy(serving_input_fn, Returns: The string path to the exported directory. + + Raises: + ValueError: If `estimator` is a ${tf.estimator.Estimator} instance + and `default_output_alternative_key` was specified. """ - export_result = estimator.export_savedmodel( - export_dir_base, - serving_input_fn, - default_output_alternative_key=default_output_alternative_key, - assets_extra=assets_extra, - as_text=as_text, - checkpoint_path=checkpoint_path) + if isinstance(estimator, core_estimator.Estimator): + if default_output_alternative_key is not None: + raise ValueError( + 'default_output_alternative_key is not supported in core ' + 'Estimator. Given: {}'.format(default_output_alternative_key)) + export_result = estimator.export_savedmodel( + export_dir_base, + serving_input_fn, + assets_extra=assets_extra, + as_text=as_text, + checkpoint_path=checkpoint_path) + else: + export_result = estimator.export_savedmodel( + export_dir_base, + serving_input_fn, + default_output_alternative_key=default_output_alternative_key, + assets_extra=assets_extra, + as_text=as_text, + checkpoint_path=checkpoint_path) garbage_collect_exports(export_dir_base, exports_to_keep) return export_result From e436ecd251b0bdb6c645ba32ad33219bcbf6004e Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Fri, 5 May 2017 14:07:33 -0800 Subject: [PATCH 21/27] Set inline