【问题标题】:Setting Keras Variables in Generator在生成器中设置 Keras 变量
【发布时间】:2019-09-03 01:25:00
【问题描述】:

我想在生成器中设置我的 LSTM 隐藏状态。但是,状态集只在生成器之外起作用:

K.set_value(model.layers[0].states[0], np.random.randn(batch_size,num_outs)) # this works

def gen_data():
    x = np.zeros((batch_size, num_steps, num_input))
    y = np.zeros((batch_size, num_steps, num_output))
    while True:
        for i in range(batch_size):
            K.set_value(model.layers[0].states[0], np.random.randn(batch_size,num_outs)) # error
            x[i, :, :] = X_train[gen_data.current_idx]
            y[i, :, :] = Y_train[gen_data.current_idx]
            gen_data.current_idx += 1
        yield x, y
gen_data.current_idx = 0

fit_generator函数中调用生成器:

model.fit_generator(gen_data(), len(X_train)//batch_size, 1, validation_data=None)

这是我打印状态时的结果:

print(model.layers[0].states[0])
<tf.Variable 'lstm/Variable:0' shape=(1, 2) dtype=float32>

这是生成器中出现的错误:

ValueError: Tensor("Placeholder_1:0", shape=(1, 2), dtype=float32) must be from the same graph as Tensor("lstm/Variable:0", shape=(), dtype=resource)

我做错了什么?

【问题讨论】:

  • 根据 keras 文档,fit_generator 函数“用 Python 生成器(或序列实例)逐批生成的数据训练模型”,所以你需要一个 Python @ 987654321@这里。
  • @KacperFloriański 我没有写下我的完整生成器,但现在我已经编辑了它

标签: python tensorflow keras lstm


【解决方案1】:

生成器是多线程的,因此生成器内部使用的图形将在与创建图形的线程不同的线程中运行。因此访问模型表单生成器将访问不同的图形。一个简单(但不好)的解决方案是通过设置workers=0 来强制生成器在与创建图形的线程相同的线程中运行。

model.fit_generator(gen_data(), len(X_train)//batch_size, 1, validation_data=None, workers=0))

调试代码:

def gen_data():
    print ("-->",tf.get_default_graph())
    while True:
        for i in range(1):
            yield (np.random.randn(batch_size, num_steps, num_input), 
            np.random.randn(batch_size, num_steps, 8))

model = get_model()
print (tf.get_default_graph())
model.fit_generator(gen_data(), 8, 1)
print (tf.get_default_graph())

输出

<tensorflow.python.framework.ops.Graph object at 0x1228a5e80>
--><tensorflow.python.framework.ops.Graph object at 0x14388e5c0>
Epoch 1/1 
8/8 [==============================] - 4s 465ms/step - loss: 1.0198 - acc: 0.1575
<tensorflow.python.framework.ops.Graph object at 0x1228a5e80>

您可以看到图形对象不同。制作workers=0 将强制生成器运行单线程。

使用

model.fit_generator(gen_data(), 8, 1, workers=0)

结果

<tensorflow.python.framework.ops.Graph object at 0x1228a5e80>
--> <tensorflow.python.framework.ops.Graph object at 0x1228a5e80>
Epoch 1/1
8/8 [==============================] - 4s 466ms/step - loss: 1.0373 - acc: 0.0975
<tensorflow.python.framework.ops.Graph object at 0x1228a5e80>

同一个单线程生成器可以访问同一个图。

但是,要启用多线程生成器,一种优雅的方法是将图形保存到创建图形的主进程中的变量中,并将其传递给生成器,生成器使用传递的图形作为默认图形。

【讨论】:

  • @MerklT 它之前对我有用,因为在我的机器上,生成器在同一个线程中运行。我已经更新了答案以强制它使用相同的线程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-11
  • 2018-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-17
相关资源
最近更新 更多