简体   繁体   English

如何在 tf.data.Dataset 生成器中使用 tf.keras 模型?

[英]How to use a tf.keras model in a tf.data.Dataset generator?

I would like to use a pre-trained Keras model as part of my data processing to generate training data for a second Keras model.我想使用预训练的 Keras 模型作为数据处理的一部分,为第二个 Keras 模型生成训练数据。 Ideally, I would like to do this by calling the first model in the data generator for the second model.理想情况下,我想通过为第二个模型调用数据生成器中的第一个模型来做到这一点。

I am using tensorflow 1.15.我正在使用 tensorflow 1.15。

A simple example of what I'm trying to do is as follows:我正在尝试做的一个简单示例如下:

import numpy as np
import tensorflow as tf
from tensorflow_core.python.keras import Sequential
from tensorflow_core.python.keras.layers import Dense

batch_size = 4
data_size = 16

model_generator = Sequential([Dense(data_size)])
model_generator.compile(optimizer='adam', loss='mae')
model_generator.build((batch_size, data_size))
sess = tf.keras.backend.get_session()

def generator():
    while True:
        data = np.random.random((batch_size, data_size))
        targets = tf.random.uniform((batch_size, 1))
        data = model_generator(data, training=False)
        data = data.eval(session=sess)
        yield (data, targets)

model_train = Sequential([Dense(data_size)])
model_train.compile(optimizer='adam', loss='mae')
model_train.build((batch_size, data_size))

output_types = (tf.float64, tf.float64)
output_shapes = (tf.TensorShape((batch_size, data_size)), tf.TensorShape((batch_size, 1)))
dataset = tf.data.Dataset.from_generator(
    generator,
    output_types=output_types,
    output_shapes=output_shapes,
)

if next(generator()) is not None:
    print("Generator works outside of model.fit()!")

model_train.fit(
    dataset,
    epochs=2,
    steps_per_epoch=2
)

The snippet above produces the following error message when .fit() is called.:调用 .fit() 时,上面的代码段会产生以下错误消息。:

2020-01-28 17:35:56.705549: W tensorflow/core/framework/op_kernel.cc:1639] Invalid argument: ValueError: Tensor("dense/kernel/Read/ReadVariableOp:0", shape=(16, 16), dtype=float32) must be from the same graph as Tensor("sequential/dense/Cast:0", shape=(4, 16), dtype=float32).
Traceback (most recent call last):

The code will run normally if the generator does not call the model_generator model.如果生成器不调用model_generator模型,代码将正常运行。 For example:例如:

def generator():
    while True:
        data = np.random.random((batch_size, data_size))
        targets = np.random.random((batch_size, 1))
        yield (data, targets)

I believe that the fit call creates its own tensorflow graph which does not include the nodes needed for model_generator .我相信 fit 调用会创建自己的张量流图,其中不包括model_generator所需的节点。 Is there any way to use one model in the generator used for training another model like this?有没有办法在生成器中使用一个模型来训练另一个这样的模型? If so, how can I modify the above example to achieve this?如果是这样,我该如何修改上面的例子来实现这一点?

I don't think it's possible to have the graph connected between a tf.Dataset and a Keras model.我认为在tf.Datasettf.Dataset模型之间连接图是tf.Dataset Instead, what you need to do is find some way of creating a single model out of the two.相反,您需要做的是找到某种方法从两者中创建一个模型。

If the model_generator can be used directly as an input to your model_train , then the easiest way I can think of to do this is to create a Sequential model containing both models.如果model_generator可以直接用作model_train的输入,那么我能想到的最简单的方法是创建一个包含两个模型的序列模型。 Here's a simple example based on your snippet above.这是一个基于您上面的代码段的简单示例。 In this example, only model_train will be backpropogated through.在这个例子中,只有model_train会被反向传播。

import numpy as np
import tensorflow as tf
from tensorflow_core.python.keras import Sequential, Model
from tensorflow_core.python.keras.layers import Dense, Input

batch_size = 4
data_size = 16

def generator():
    while True:
        data = np.random.random((batch_size, data_size))
        targets = np.random.random((batch_size, 1))
        yield (data, targets)

model_generator = Sequential([Dense(data_size)])

# Freeze weights in your generator so they don't get updated
for layer in model_generator.layers:
    layer.trainable = False

model_train = Sequential([Dense(data_size)])

# Create a model to train which calls both model_generator and model_train
model_fit = Sequential([model_generator, model_train])
model_fit.compile(optimizer='adam', loss='mae')
model_fit.build((batch_size, data_size))
model_fit.summary()

output_types = (tf.float64, tf.float64)
output_shapes = (tf.TensorShape((batch_size, data_size)),
                 tf.TensorShape((batch_size, 1)))
dataset = tf.data.Dataset.from_generator(
    generator,
    output_types=output_types,
    output_shapes=output_shapes,
)

model_fit.fit(
    dataset,
    epochs=2,
    steps_per_epoch=2
)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM