Это может помочь проанализировать как выход read_data_sets.py и выход операции parse_example в вашем model.py
Что read_data_sets производит
read_data_sets, как Вы отмечаете, создает Numpy массивы для каждого изображения. Они имеют форму [28, 28, 1] для каналов с шириной x ширины (изображения монохромные), а в вашем первоначальном вызове read_data_sets вы указываете, что вам нужны данные изображения в виде массивов uint8. Когда вы вызываете tostring в массив uint8 numpy, информация о форме отбрасывается, и поскольку каждый uint8 является одиночным байтом, вы заканчиваете байтовой строкой длиной 784 с одной записью для каждого пикселя в исходном массиве 28x28x1 numpy в ряду строк заказ. Затем он сохраняется как bytes_list
в результате tf.train.Example
.
Для отображения каждой записи на карте функций под ключом features
имеется список байтов с ровно одной записью. Эта запись представляет собой строку длиной 784, где каждый «символ» в строке представляет собой значение между 0-255, представляющим значение монохромного пикселя для точки в исходном изображении 28x28. Ниже приведен пример экземпляра tf.train.Example
как напечатано на Python:
features {
feature {
key: "features"
value {
bytes_list {
value: "\000\000\257..."
}
}
}
feature {
key: "labels"
value {
int64_list {
value: 10
}
}
}
}
Что parse_example ожидает и возвращает
tf.parse_example принимает вектор tf.string
объектов в качестве входных данных. Эти объекты сериализуются tf.train.Example
объектов. В вашем коде util.read_examples
производит именно это.
Другой аргумент tf.parse_example
- это схема примеров. Как упоминалось ранее, запись features
в вашем примере представляет собой tf.string
, как определено выше. Для справки ваш код имеет:
def parse_examples(examples):
feature_map = {
'labels': tf.FixedLenFeature(
shape=[], dtype=tf.int64, default_value=[-1]),
'features': tf.FixedLenFeature(
shape=[], dtype=tf.string),
}
return tf.parse_example(examples, features=feature_map)
Интересующая вещь, связанная с полученным вами сообщением об ошибке, является параметром формы.Этот параметр формы указывает форму одного экземпляра, в этом случае, указав, что shape=[]
вы говорите, что каждое изображение является строкой ранга 0, то есть простой-старой строкой (т. Е. Не вектором , а не матрица и т. д.). Это требует, чтобы bytes_list
имели ровно один элемент. Это именно то, что вы храните в каждом поле features
вашего tf.train.Example
.
Несмотря на то, shape
свойства относится к форме одного экземпляра, выход tf.parse_example
для features
поля будет вся партии примеров. Это может быть немного запутанным. Поэтому, в то время как каждый отдельный пример имеет одну строку (shape=[]
), партия представляет собой вектор строк (shape=[batch_size]
).
Используя изображение
Имея данные изображения в строке не очень полезно; нам нужно преобразовать его в числовые данные. Оп TensorFlow сделать это tf.decode_raw (Джереми Lewi explained почему tf.string_to_number
не будет работать здесь):
image_bytes = tf.decode_raw(parsed['features'], out_type=tf.uint8)
image_data = tf.cast(image_bytes, tf.float32)
(не забудьте установить out_type=tf.uint8
поскольку это тип данных, который был выход в read_data_sets
). Как правило, вы хотите, чтобы результат был равен tf.float32
. Иногда это даже полезно, чтобы изменить тензор, чтобы восстановить исходные формы, например,
# New shape is [batch_size, height, width, channels]. We use
# -1 as the first dimension in case batches are variable size.
image_data = tf.reshape(image_data, [-1, 28, 28, 1])
(NB: Вы, вероятно, не нужно, чтобы в вашем коде).
В качестве альтернативы, вы можете сохранить данные как tf.float32, вызвав read_data_sets
с dtype=tf.float32
(по умолчанию). Затем вы можете построить свой tf.train.Example
как explained Джереми Льюи, который также дал код для анализа таких примеров. Однако в этом случае формы будут разными. Форма каждого экземпляра (как указано в форме в FixedLenFeature) теперь равна IMAGE_PIXELS
, а форма записи features
на выходе tf.parsed_example
равна [batch_size, IMAGE_PIXELS]
.
Компромисс между uint8
и float32
, конечно же, заключается в том, что данные на диске будут в четыре раза больше для последнего, но вы избегаете дополнительного броска, необходимого для первого. В случае MNIST, где данных не так много, добавленная ясность непосредственного использования данных с плавающей точкой, вероятно, стоит дополнительного места.
Сторона примечания: TFRecord формат файла tf.Example не требуется Google Cloud ML. Любой действительный способ чтения данных в TensorFlow будет работать. См. Https://www.tensorflow.org/versions/r0.11/how_tos/reading_data/index.html. Тем не менее, чтение файлов (по сравнению с подачей, см. Ссылку) может быть более эффективным. И кодирование файлов TFRecord tf.Example - это хорошо поддерживаемый и удобный способ кодирования нескольких полей/функций на запись (например, изображение + метка) на диске. – rhaertel80