#python #tensorflow #data-preprocessing
Вопрос:
Я пытаюсь создать функцию синтаксического анализа, которая считывает пару (изображение, метка) из TFRecord. Когда метка является int64, все работает хорошо, однако, когда я пытаюсь сохранить метку в виде строки и преобразовать ее в int в функции синтаксического анализатора, все ломается. Я все еще новичок в фреймворке, поэтому в моей реализации ниже используется eager .numpy(), который не работает, когда я применяю .map к tf.data .Dataset.
Некоторая справочная информация: у меня есть иерархии в моем наборе данных, очень похожие на этот пример, где я использовал «dog» и «labrador» для представления этого. Я хотел бы разрешить обучать данные, которые могут классифицировать категориальные изображения (кошка, собака), а также обучать модели, которые могут классифицировать более конкретные типы (бульдог, лабрадор) из тех же помеченных данных, которые обычно имеют метки наиболее конкретного типа для этого на изображении.
Это то, что я пытался сделать:
#!/usr/bin/env python3
import tensorflow as tf
import functools
# example: this model classifies dogs and cats. this map translates a specific dog type to the "dog" label,
# and the same for cats. all other labels would go to the negative class "neg".
example_label_map = {
"bulldog": "dog",
"labrador": "dog",
"persian cat": "cat",
"cow": "neg",
}
# map the N classes to an int of 0..N-1
labels_to_class_int = {
"neg": 0, # negative class
"dog": 1,
"cat": 2,
}
def parse_tfrec_function(example, labels_map):
"""
labels is a map of labels to class numbers. e.g. "bulldog" -> 1, "labrador" -> 1, "persian cat" -> 2, ...
"""
image_feature_description = {
"image": tf.io.FixedLenFeature([], tf.string),
"label": tf.io.FixedLenFeature([], tf.string)
}
features = tf.io.parse_single_example(example, image_feature_description)
image = tf.io.parse_tensor(features["image"], tf.uint8)
# *** the following fails. how can this be done efficiently (lazy)?
label = features["label"].numpy().decode('utf-8')
class_num = labels_map[label]
return image, class_num
tfrec_file = ['/path/to/dataset.tfrec']
dataset = tf.data.TFRecordDataset(tfrec_file)
labels_map = {}
for k, v in example_label_map.items():
labels_map[k] = labels_to_class_int[v]
print(labels_map)
parser_fn = functools.partial(parse_tfrec_function, labels_map=labels_map)
parset_dataset = dataset.map(parser_fn)
Причина сбоя, поскольку он пытается быстро запустить:
AttributeError: 'Tensor' object has no attribute 'numpy'
Как правильно это сделать? Сохранение номеров классов в TFRecord потребовало бы создания разных TFRecords с практически одинаковыми данными, если бы я хотел обучить сеть, которая более специфична для различения определенного подмножества классов.
Как можно эффективно преобразовать строку метки в номер класса, учитывая сопоставление, которое выполняется как шаг предварительной обработки (.map для tf.data.Набор данных)?
Спасибо!
Комментарии:
1. Привет, ты смог это решить?
2. @VivekPayasi, Нет. Я обошел это, создав несколько наборов данных, каждый с нужным подмножеством. С тем объемом данных, который мне был нужен для обучения, мне это сошло с рук.
Ответ №1:
IIUC вопрос на самом деле заключается в переназначении строки на int в режиме графика. Я думаю, что должно быть возможно выполнить это переназначение string->int с использованием tf.case.
Пример:
import tensorflow.compat.v1 as tf
tf.disable_eager_execution()
def remap_string_to_int(tensor: tf.Tensor) -> tf.Tensor:
pred_fn_pairs = [
(tf.equal(tensor, 'neg'), lambda: 0),
(tf.equal(tensor, 'dog'), lambda: 1),
(tf.equal(tensor, 'cat'), lambda: 2),
]
return tf.case(pred_fn_pairs)
with tf.Session() as sess:
label_tensor = tf.placeholder(tf.string, [])
label_int_tensor = remap_string_to_int(label_tensor)
print("int-value is: ",
sess.run(label_int_tensor, feed_dict={label_tensor: 'dog'}))
С принтами:
>>> int-value is: 1