Repository: keras-team/keras

Issue:
keras.backend.function() broken in 2.2.0 for string inputs with TF backend
The following code works on Keras 2.1.6 using TensorFlow 1.9.0-rc0, but it fails when upgrading to Keras 2.2.0:

```python
import tensorflow as tf
import numpy as np
from keras.backend import function

x = tf.placeholder(shape=[None], dtype=tf.string)
f = tf.substr(x, 2, 3)
func = function(inputs=[x], outputs=[f])

some_strings = np.array([b"abcdefg", b"012345689"])
print(func([some_strings]))
```

Excepted output is:

```
[array([b'cde', b'234'], dtype=object)]
```

But here is the exception I get instead with Keras 2.2.0:

```pycon
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/ageron/.virtualenvs/ml/lib/python3.5/site-packages/keras/backend/tensorflow_backend.py", line 2661, in __call__
    return self._call(inputs)
  File "/home/ageron/.virtualenvs/ml/lib/python3.5/site-packages/keras/backend/tensorflow_backend.py", line 2614, in _call
    dtype=tensor.dtype.base_dtype.name))
  File "/home/ageron/.virtualenvs/ml/lib/python3.5/site-packages/numpy/core/numeric.py", line 492, in asarray
    return array(a, dtype, copy=False, order=order)
TypeError: data type "string" not understood
```

Running on Ubuntu 16.4, Python 3.5.2, and using the following library versions:
```pycon
>>> import tensorflow as tf
>>> tf.__version__
'1.9.0-rc0'
>>> import numpy as np
>>> np.__version__
'1.14.3'
>>> import keras
Using TensorFlow backend.
>>> keras.__version__
'2.2.0'
```

This issue may be related to #10372.



Discussion:
The problem comes from this call:

```python
np.asarray(value, dtype=tensor.dtype.base_dtype.name)
```

This is because `tensor.dtype.base_dtype.name` is equal to `"string"`, and NumPy does not support that type. Perhaps a simple fix could be to map `"string"` to `"object"`?


Resolving patch:
diff --git a/keras/backend/tensorflow_backend.py b/keras/backend/tensorflow_backend.py
--- a/keras/backend/tensorflow_backend.py
+++ b/keras/backend/tensorflow_backend.py
@@ -2611,12 +2611,12 @@ def _call(self, inputs):
                 # `callable_fn` only supports exact matches.
                 array_vals.append(
                     np.asarray(value,
-                               dtype=tensor.dtype.base_dtype.name))
+                               dtype=tf.as_dtype(tensor.dtype).as_numpy_dtype))
         if self.feed_dict:
             for key in sorted(self.feed_dict.keys()):
                 array_vals.append(
                     np.asarray(self.feed_dict[key],
-                               dtype=key.dtype.base_dtype.name))
+                               dtype=tf.as_dtype(key.dtype).as_numpy_dtype))
 
         # Refresh callable if anything has changed.
         if (self._callable_fn is None or


Test patch:
diff --git a/tests/keras/backend/backend_test.py b/tests/keras/backend/backend_test.py
--- a/tests/keras/backend/backend_test.py
+++ b/tests/keras/backend/backend_test.py
@@ -530,6 +530,16 @@ def test_function_tf_feed_dict(self):
         assert output == [21.]
         assert KTF.get_session().run(fetches=[x, y]) == [30., 40.]
 
+    def test_function_tf_string_input(self):
+        # Test functions with string inputs.
+
+        x_placeholder = KTF.placeholder(shape=(), dtype="string")
+        x_identity = KTF.identity(x_placeholder)
+
+        f = KTF.function(inputs=[x_placeholder], outputs=[x_identity])
+        output = f([b'test'])
+        assert output == [b'test']
+
     def test_rnn(self):
         # implement a simple RNN
         num_samples = 4