我想在生成器中设置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)
我在做什么错了?
答案 0 :(得分: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>
具有访问同一图形的相同单线程生成器。
但是,要启用多线程生成器,一种优雅的方法是将图形保存到创建图形的主过程中的变量中,并将其传递给使用传递的图形作为默认图形的生成器。