【问题标题】:Tensorflow: how to retain file names in tf.data.Dataset from_generator?Tensorflow:如何在 tf.data.Dataset from_generator 中保留文件名?
【发布时间】:2021-07-08 09:02:54
【问题描述】:

我正在努力解决以下问题。我正在使用 from_generator 方法创建一个 tf.data.Dataset。它工作得很好,但在预测之后,我想调查哪些样本被错误分类以及为什么。为此,我需要按照它们被提供给模型的相同顺序来检索文件名。我该怎么做?

def make_dataset(directory):
    """ Makes a dataset from generator. """

    def generator():
        files = list_files_in_directory(directory)
        random.Random(42).shuffle(files)
        print(f'Files in {directory}: {len(files)}')

        for fn in files:
            X, y = read_file(fn)
            yield X, [y]   # here I lose info about fn

    def get_shapes():
        X, _ = next(generator())
        return tf.TensorShape(X.shape), tf.TensorShape(1)

    return (
        tf.data.Dataset
            .from_generator(
                generator,
                output_types=(tf.float64, tf.uint8),
                output_shapes=get_shapes())
            .batch(128, drop_remainder=True)
            .prefetch(256))

model.fit(make_dataset(directory_train))
y_pred = model.predict(make_dataset(directory_test))

# here: what is the most elegant way to retain the input filenames for y_pred ?

附:由于文件是在“惰性”模式下读取的,因此需要生成器中的 shuffle 以确保输入数据的随机性。

【问题讨论】:

  • 您能分享一下您的实际用例吗?我认为可能有更优雅的解决方案

标签: python tensorflow dataset generator lazy-evaluation


【解决方案1】:

一种可能性是让您的生成器返回文件名,并将其作为调试输入传递给您的模型。

端到端示例。

让我们训练一个简单的线性回归,这是模型的定义:

model = tf.keras.models.Sequential([tf.keras.layers.Dense(1,input_shape=(1,))])
model.compile(loss='mse', optimizer='sgd')

让我们生成一些数据

现在,让我们生成一些随机数据,并将每个样本关联到一个虚拟文件名

# generating some random data
filenames = np.array([[f"{s}.txt"] for s in string.ascii_lowercase])
X = np.random.uniform(size=(26, 1))
y = np.random.uniform(size=(26, 1))
data = np.concatenate((filenames, X, y), axis=1)

让我们看一下数据的第一个元素:

>>> data[0]
array(['a.txt', '0.36798830850651043', '0.5976948635618315'], dtype='<U32')

训练模型

我们用我们的数据训练模型。为简单起见,让我们使用我们的数组Xy

model.fit(X,y)

创建调试生成器和调试模型

所以,我们想要的是在我们的模型中创建一个调试输入,它只是用来接收我们的文件名,并直接输出它而无需任何转换。为此,我们使用 Functionnal API 将现有模型包装到我们的调试模型中:

debug_input = tf.keras.Input(shape=(), dtype=tf.string)
debug_model = tf.keras.Model([debug_input, model.input], [debug_input, model.output])

现在,我们需要创建一个数据集生成器,它将生成一个元组 (filename, feature) 来提供我们的调试模型:

def debug_gen(data):
    # shuffling data
    np.random.shuffle(data)
    for filename, feature, label in data:
        yield (filename, feature), label


debug_ds = tf.data.Dataset.from_generator(
    lambda: debug_gen(data),
    output_types=((tf.string, tf.float64), tf.float64),
    output_shapes=((tf.TensorShape(()), tf.TensorShape(())), tf.TensorShape(())),
).batch(1)

现在,如果我们在生成器中的一项上调用predict,我们应该得到文件名作为输出,以及预测:

>>> debug_model.predict(debug_ds.take(1))
[array([b'a.txt'], dtype=object), array([[-0.7604195]], dtype=float32)]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-29
    • 2018-06-26
    • 1970-01-01
    • 1970-01-01
    • 2011-08-16
    • 2017-08-25
    • 1970-01-01
    相关资源
    最近更新 更多