Наборы данных Tensorflow со строковыми входами не сохраняют тип данных - PullRequest
2 голосов
/ 10 апреля 2020

Весь воспроизводимый код , приведенный ниже, запускается в Google Colab с TF 2.2.0-rc2.

Адаптация простого примера из документации для создания набора данных из простой список Python:

import numpy as np
import tensorflow as tf
tf.__version__
# '2.2.0-rc2'
np.version.version
# '1.18.2'

dataset1 = tf.data.Dataset.from_tensor_slices([1, 2, 3]) 
for element in dataset1: 
  print(element) 
  print(type(element.numpy()))

мы получаем результат

tf.Tensor(1, shape=(), dtype=int32)
<class 'numpy.int32'>
tf.Tensor(2, shape=(), dtype=int32)
<class 'numpy.int32'>
tf.Tensor(3, shape=(), dtype=int32)
<class 'numpy.int32'>

, где все типы данных int32, как и ожидалось.

Но изменив это простой пример подачи списка строк вместо целых чисел:

dataset2 = tf.data.Dataset.from_tensor_slices(['1', '2', '3']) 
for element in dataset2: 
  print(element) 
  print(type(element.numpy()))

дает результат

tf.Tensor(b'1', shape=(), dtype=string)
<class 'bytes'>
tf.Tensor(b'2', shape=(), dtype=string)
<class 'bytes'>
tf.Tensor(b'3', shape=(), dtype=string)
<class 'bytes'>

, где, к удивлению, и несмотря на то, что сами тензоры имеют значение dtype=string, их оценки имеют тип bytes.

Это поведение не ограничивается методом .from_tensor_slices; Вот ситуация с .list_files (следующий фрагмент работает прямо в блокноте fre sh Colab):

disc_data = tf.data.Dataset.list_files('sample_data/*.csv') # 4 csv files
for element in disc_data: 
  print(element) 
  print(type(element.numpy()))

результат:

tf.Tensor(b'sample_data/california_housing_test.csv', shape=(), dtype=string)
<class 'bytes'>
tf.Tensor(b'sample_data/mnist_train_small.csv', shape=(), dtype=string)
<class 'bytes'>
tf.Tensor(b'sample_data/california_housing_train.csv', shape=(), dtype=string)
<class 'bytes'>
tf.Tensor(b'sample_data/mnist_test.csv', shape=(), dtype=string)
<class 'bytes'>

, где снова имена файлов в вычисленных тензорах возвращаются как bytes вместо string, несмотря на то, что сами тензоры имеют значение dtype=string.

Аналогичное поведение наблюдается и с * Метод 1041 * (здесь не показан).

Окончательная демонстрация: как показано в методике .as_numpy_iterator 1045 * Документация , следующее условие равенства оценивается как True:

dataset3 = tf.data.Dataset.from_tensor_slices({'a': ([1, 2], [3, 4]), 
                                               'b': [5, 6]}) 

list(dataset3.as_numpy_iterator()) == [{'a': (1, 3), 'b': 5}, 
                                       {'a': (2, 4), 'b': 6}] 
# True

, но если мы изменим элементы b на строки, условие равенства теперь неожиданно оценивается как False!

dataset4 = tf.data.Dataset.from_tensor_slices({'a': ([1, 2], [3, 4]), 
                                               'b': ['5', '6']})   # change elements of b to strings

list(dataset4.as_numpy_iterator()) == [{'a': (1, 3), 'b': '5'},   # here
                                       {'a': (2, 4), 'b': '6'}]   # also
# False

, вероятно, из-за различных типов данных, поскольку Сами ценности, очевидно, идентичны.


Я не наткнулся на это поведение в результате экспериментов с академиками c; Я пытаюсь передать свои данные в наборы данных TF, используя пользовательские функции, которые считывают пары файлов с диска в форме

f = ['filename1', 'filename2']

, и эти пользовательские функции прекрасно работают сами по себе, но отображаются через наборы данных TF

RuntimeError: not a string

, который после этого копания кажется, по крайней мере, необъяснимым, если возвращаемые типы данных действительно bytes, а не string.

Итак, это ошибка (как кажется), или я что-то здесь упускаю?

1 Ответ

2 голосов
/ 10 апреля 2020

Это известное поведение:

От: https://github.com/tensorflow/tensorflow/issues/5552#issuecomment -260455136

TensorFlow преобразует str в байты в большинстве мест, включая sess.run и это вряд ли изменится. Пользователь может свободно конвертировать обратно, но, к сожалению, это слишком большое изменение, чтобы добавить юникод dtype в ядро. Закрытие, поскольку пока не исправит.

Я думаю, что ничего не изменилось с TensorFlow 2.x - все еще есть места, в которых строки преобразуются в байты, и вы должны позаботиться об этом вручную.

Из проблемы , которую вы открыли сами, может показаться, что они рассматривают предмет как проблему Numpy, а не самого Tensorflow.

...