Repository: tensorflow/tensor2tensor

Issue:
TF 1.6 will break some layers because name_scope's constructor args changed
I just tried to use tensor2tensor with TF 1.6, which causes an exception `TypeError: unhashable type 'list'`

This is caused in the usage of `tf.name_scope`, which has now wants arguments like `tf.name_scope(name, default_name=default_name, values=values)` (whereas before no `default_name` argument existed). T2T calls name scope as `tf.name_scope(name, [list of values])`. To fix, T2T should instead call it using named arguments i.e `tf.name_scope(name, values=[list of values])`

as a temp workaround, i've been patching `name_scope` (instead of patching each individual layer in T2T)

```python
import tensorflow as tf

# have to monkey patch bc tensor2tensor doesn't work with tf 1.6 :(
# because name_scope wants arguments as tf.name_scope(name, default_name, values)
# whereas before it was tf.name_scope(name, values)
class PatchedNameScope(tf.name_scope):
    
    def __init__(self, name, values=None, default_name=None):
        super().__init__(name, values=values, default_name=default_name)
        
    
tf.name_scope = PatchedNameScope
```



Discussion:

Resolving patch:
diff --git a/tensor2tensor/data_generators/imagenet.py b/tensor2tensor/data_generators/imagenet.py
--- a/tensor2tensor/data_generators/imagenet.py
+++ b/tensor2tensor/data_generators/imagenet.py
@@ -235,7 +235,7 @@ def distorted_bounding_box_crop(image,
   Returns:
     (cropped image `Tensor`, distorted bbox `Tensor`).
   """
-  with tf.name_scope(scope, "distorted_bounding_box_crop", [image, bbox]):
+  with tf.name_scope(scope, default_name="distorted_bounding_box_crop", values=[image, bbox]):
     # Each bounding box has shape [1, num_boxes, box coords] and
     # the coordinates are ordered [ymin, xmin, ymax, xmax].
 
diff --git a/tensor2tensor/layers/common_layers.py b/tensor2tensor/layers/common_layers.py
--- a/tensor2tensor/layers/common_layers.py
+++ b/tensor2tensor/layers/common_layers.py
@@ -76,7 +76,7 @@ def comma_separated_string_to_integer_list(s):
 
 def saturating_sigmoid(x):
   """Saturating sigmoid: 1.2 * sigmoid(x) - 0.1 cut to [0, 1]."""
-  with tf.name_scope("saturating_sigmoid", [x]):
+  with tf.name_scope("saturating_sigmoid", values=[x]):
     y = tf.sigmoid(x)
     return tf.minimum(1.0, tf.maximum(0.0, 1.2 * y - 0.1))
 
@@ -173,7 +173,7 @@ def shakeshake(xs, equal_grad=False):
 
 def convert_rgb_to_real(x):
   """Conversion of pixel values to real numbers."""
-  with tf.name_scope("rgb_to_real", [x]):
+  with tf.name_scope("rgb_to_real", values=[x]):
     x = tf.to_float(x)
     # Use the formula (value/128) - 1 to convert each channel value into a
     # real number in the range -1 to 1.
@@ -794,7 +794,7 @@ def subseparable_conv_block(inputs, filters, dilation_rates_and_kernel_sizes,
 
 def pool(inputs, window_size, pooling_type, padding, strides=(1, 1)):
   """Pooling (supports "LEFT")."""
-  with tf.name_scope("pool", [inputs]):
+  with tf.name_scope("pool", values=[inputs]):
     static_shape = inputs.get_shape()
     if not static_shape or len(static_shape) != 4:
       raise ValueError("Inputs to conv must have statically known rank 4.")
@@ -949,7 +949,7 @@ def simple_attention(target, source, bias=None):
   Returns:
     a `Tensor` with same shape as `target`
   """
-  with tf.name_scope("simple_attention", [target, source]):
+  with tf.name_scope("simple_attention", values=[target, source]):
     target_shape = shape_list(target)
     source_shape = shape_list(source)
     target = tf.reshape(
@@ -1515,7 +1515,7 @@ def pad_to_same_length(x, y, final_length_divisible_by=1, axis=1):
   """Pad tensors x and y on axis 1 so that they have the same length."""
   if axis not in [1, 2]:
     raise ValueError("Only axis=1 and axis=2 supported for now.")
-  with tf.name_scope("pad_to_same_length", [x, y]):
+  with tf.name_scope("pad_to_same_length", values=[x, y]):
     x_length = shape_list(x)[axis]
     y_length = shape_list(y)[axis]
     max_length = tf.maximum(x_length, y_length)
@@ -1550,7 +1550,7 @@ def padding_list(length_diff, arg):
 
 def pad_with_zeros(logits, labels):
   """Pad labels on the length dimension to match logits length."""
-  with tf.name_scope("pad_with_zeros", [logits, labels]):
+  with tf.name_scope("pad_with_zeros", values=[logits, labels]):
     logits, labels = pad_to_same_length(logits, labels)
     if len(labels.shape.as_list()) == 3:  # 2-d labels.
       logits, labels = pad_to_same_length(logits, labels, axis=2)
@@ -1644,7 +1644,7 @@ def padded_cross_entropy(logits,
         reduce_sum=reduce_sum)
   confidence = 1.0 - label_smoothing
   vocab_size = shape_list(logits)[-1]
-  with tf.name_scope("padded_cross_entropy", [logits, labels]):
+  with tf.name_scope("padded_cross_entropy", values=[logits, labels]):
     if len(logits.get_shape().as_list()) == 2:
       # Deal with the case where we did not insert extra dimensions due to
       # TPU issues.  No pad-to-same-length happens in this case.
@@ -1678,7 +1678,7 @@ def smoothing_cross_entropy(logits,
   Returns:
 
   """
-  with tf.name_scope("smoothing_cross_entropy", [logits, labels]):
+  with tf.name_scope("smoothing_cross_entropy", values=[logits, labels]):
     # Low confidence is given to all non-true labels, uniformly.
     low_confidence = (1.0 - confidence) / tf.to_float(vocab_size - 1)
     # Normalizing constant is the best cross-entropy value with soft targets.
@@ -1725,7 +1725,7 @@ def global_pool_1d(inputs, pooling_type="MAX", mask=None):
     output: A tensor of dimensions batch_size x input_dims
       dimension containing the sequences of transformed vectors.
   """
-  with tf.name_scope("global_pool", [inputs]):
+  with tf.name_scope("global_pool", values=[inputs]):
     if mask is not None:
       mask = tf.expand_dims(mask, axis=2)
       inputs = tf.multiply(inputs, mask)
@@ -1762,7 +1762,7 @@ def running_global_pool_1d(inputs, pooling_type="MAX"):
       dimension containing the running 'totals'.
   """
   del pooling_type
-  with tf.name_scope("running_global_pool", [inputs]):
+  with tf.name_scope("running_global_pool", values=[inputs]):
     scan_fct = tf.maximum
     # Permute inputs so seq_length is first.
     elems = tf.transpose(inputs, [1, 0, 2])
@@ -2118,7 +2118,7 @@ def padded_cross_entropy_factored(factored_logits,
   a = factored_logits.a
   b = factored_logits.b
   confidence = 1.0 - label_smoothing
-  with tf.name_scope("padded_cross_entropy_factored", [a, b, labels]):
+  with tf.name_scope("padded_cross_entropy_factored", values=[a, b, labels]):
     labels_flat = tf.reshape(labels, [-1])
     a_flat = tf.reshape(a, [-1, shape_list(b)[1]])
     xent = smoothing_cross_entropy_factored(a_flat, b, labels_flat,
diff --git a/tensor2tensor/layers/modalities.py b/tensor2tensor/layers/modalities.py
--- a/tensor2tensor/layers/modalities.py
+++ b/tensor2tensor/layers/modalities.py
@@ -168,7 +168,7 @@ class CTCSymbolModality(SymbolModality):
 
   def loss(self, logits, targets):
     """Compute the CTC loss."""
-    with tf.name_scope("ctc_loss", [logits, targets]):
+    with tf.name_scope("ctc_loss", values=[logits, targets]):
       # For CTC we assume targets are 1d, [batch, length, 1, 1] here.
       targets_shape = targets.get_shape().as_list()
       assert len(targets_shape) == 4


Test patch: