Весь воспроизводимый код , приведенный ниже, запускается в 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
.
Итак, это ошибка (как кажется), или я что-то здесь упускаю?