我正在尝试研究一些旧教程,发现将所有内容保留在Keras中令人兴奋。但是,用Tensorflow编写时,我遇到了一件非常简单的事情。这是本教程中的tf代理代码。
tf.reset_default_graph()
weights = tf.Variable(tf.ones([num_bandits]))
chosen_action = tf.argmax(weights,0)
reward_holder = tf.placeholder(shape=[1],dtype=tf.float32)
action_holder = tf.placeholder(shape=[1],dtype=tf.int32)
responsible_weight = tf.slice(weights,action_holder,[1])
loss = -(tf.log(responsible_weight)*reward_holder)
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001)
update = optimizer.minimize(loss)
这是一个简单的多臂匪徒。 到目前为止,我试图将代理转换为Keras的工作是
size = 4
weights = K.variable(K.ones(shape=(size), dtype='float32'))
best_action = Lambda(lambda x: K.cast(K.argmax(x), dtype=K.floatx()))(weights)
reward = Input(shape=(1,), dtype='float32')
action = Input(shape=(1,), dtype='int32')
responsible_weight = K.slice(weights, action[-1], [1])
custom_loss = -(K.log(responsible_weight) * reward)
opti = SGD(lr=0.001)
model = Model(inputs=[reward, action], outputs=best_action)
model.compile(optimizer=opti, loss=custom_loss)
挑战似乎是输入张量必须来自输入层(至少与其他练习无关)。
有人可以在这里看到明显的错误吗?当我到达model = Model()行时,attributeError告诉我
'NoneType' object has no attribute '_inbound_nodes'
我的“输出”已经包装在Lambda函数中,该函数部分地处理了Keras Tensor部分(如潜在的重复操作所建议)。只是为了好玩,我添加了另一层并乘以另一线程所建议的值,但这并没有改变错误。
答案 0 :(得分:0)
在强制将输入(通常为x_train)和输出(通常为y_train)作为已知数据传递的意义上,Keras与tensorflow有所不同。
Keras中的损失必须一定是一个具有地面真实值和预测(输出)值的函数:function(y_true, y_pred)
。
通过查看您的代码,损失似乎是crossentropy,其中 p (y_true)为reward
和 q (y_pred )为responsible_weight
。
因此,我们可以像reward
是输出(y_train或y_true)而action_holder
是输入(x_train)那样重新制作它。
def loss(y_true,y_pred):
return - K.log(y_pred)*y_true
此外,action_holder
只是单行权重,这与Embedding
层大小为1且词汇量为num_bandits
的想法非常吻合。
也就是说,我们可以开始建模:
#because of the log, let's also add a non negative constraint to the weights
from keras.constraints import NonNeg
input_action = Input((1,))
responsible_weight = Embedding(num_bandits,
1,
name='weights',
embeddings_initializer='ones',
embeddings_constraint=NonNeg())(input_action)
model = Model(input_action, responsible_weight)
model.compile(optimizer=anyOptimizer, loss=loss)
要进行培训,请使用:
model.fit(data_for_action_holder, data_for_reward, ...)
输入和输出数据的形状都必须为(examples, 1)
关于最佳动作或选择的动作,它根本不参与培训。要获得它,您将需要获取嵌入权重并获得其最大值:
weights = model.get_layer('weights').get_weights()[0].max()
关于对数为零的风险,您可以稍微更改损失函数以避免零预测:
def loss(y_true, y_pred):
return - K.log(y_pred + K.epsilon())*(y_true + K.epsilon())