python - 如何将字符串映射到 int(类号)作为 tf.data.Dataset .map() 的一部分以在 Tensorflow 中进行预处理?
问题描述
我正在尝试创建一个从 TFRecord 读取(图像、标签)对的解析器函数。当标签是 int64 时,一切正常,但是当我尝试将标签保存为字符串并在解析器函数中将其转换为 int 时,事情就中断了。我还是这个框架的新手,所以我下面的实现使用了急切的 .numpy(),当我将 .map 应用于 tf.data.Dataset 时它不起作用。
一些背景:我的数据集中有层次结构,就像在这个例子中我使用“狗”和“拉布拉多”来表示它一样。我想允许训练可以对分类图像(猫、狗)进行分类的数据,并训练可以从相同的标记数据中对更具体的类型(斗牛犬、拉布拉多犬)进行分类的模型,这些数据通常具有最特定类型的标签在图像上。
这就是我试图做的:
#!/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 中需要使用几乎相同的数据制作不同的 TFRecord。
给定作为预处理步骤运行的映射(.map for tf.data.Dataset),如何将标签字符串有效地转换为类号?
谢谢!
解决方案
IIUC 的问题实际上是在图形模式下将字符串重新映射为 int。我认为应该可以使用tf.case执行这个 string->int 重新映射。
一个例子:
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
推荐阅读
- python - 如何通过另一个循环循环字典?
- php - 如何通过自己的加密值更新每一行
- django - 如何找到 acme 挑战响应?
- ios - 如何更改 Mac Catalyst 窗口场景中的窗口标题?
- intern - 我如何针对 Edge Chromium 运行 Intern?
- gatsby - Gatsby 为图像构建缺少的路径前缀
- python - Python urllib +基本服务器无法在macos上连接
- c# - Prism:项目默认xml命名空间必须是msbuild xml命名空间
- ios - Swift - 当收到奇数或偶数作为乘积的答案时更改 UIImageView
- angular - 我在使用 InAppBrowser browser.onloadstart ') 时遇到问题。订阅,使用 de ionic