Keras-实现具有多个输出的自定义损失功能

时间:2019-11-21 17:02:39

标签: python tensorflow keras loss-function

我正在尝试复制(较小版本的)AlphaGo Zero系统。但是,在网络模型中,我遇到了问题。我应该实现的损失函数如下:

enter image description here

位置:

  • z 是网络的两个首部之一的标签(介于-1和1之间的实际值),而 v 是该网络预测的值。< / li>
  • pi 是所有动作的分布概率的标签, p 是网络预测的所有动作的分布概率。
  • c 是L2正则化参数。

我将表示有效的通道列表(代表游戏状态)和一个数组( pi p 的大小)传递给网络(通过输入1(如果有效,则放置0)。

如您所见,损失函数使用目标预测和网络预测进行计算。但是经过大量搜索之后,实现我的自定义损失函数时,即使我有两个“ y_true”和两个“ y_pred”,也只能作为参数y_truey_pred传递。我尝试使用索引获取这些值,但是我很确定它不起作用。

网络和自定义损失函数的建模在下面的代码中:

def custom_loss(y_true, y_pred):

    # I am pretty sure this does not work

    output_prob_dist = y_pred[0]
    output_value = y_pred[1] 
    label_prob_dist = y_true[0]
    label_value = y_pred[1]

    mse_loss = K.mean(K.square(label_value - output_value), axis=-1)
    cross_entropy_loss = K.dot(K.transpose(label_prob_dist), output_prob_dist)

    return mse_loss - cross_entropy_loss

def define_model():
    """Neural Network model implementation using Keras + Tensorflow."""
    state_channels = Input(shape = (5,5,6), name='States_Channels_Input')
    valid_actions_dist = Input(shape = (32,), name='Valid_Actions_Input')

    conv = Conv2D(filters=10, kernel_size=2, kernel_regularizer=regularizers.l2(0.0001), activation='relu', name='Conv_Layer')(state_channels)
    pool = MaxPooling2D(pool_size=(2, 2), name='Pooling_Layer')(conv)
    flat = Flatten(name='Flatten_Layer')(pool)

    # Merge of the flattened channels (after pooling) and the valid action
    # distribution. Used only as input in the probability distribution head.
    merge = concatenate([flat, valid_actions_dist])

    #Probability distribution over actions
    hidden_fc_prob_dist_1 = Dense(100, kernel_regularizer=regularizers.l2(0.0001), activation='relu', name='FC_Prob_1')(merge)
    hidden_fc_prob_dist_2 = Dense(100, kernel_regularizer=regularizers.l2(0.0001), activation='relu', name='FC_Prob_2')(hidden_fc_prob_dist_1)
    output_prob_dist = Dense(32, kernel_regularizer=regularizers.l2(0.0001), activation='softmax', name='Output_Dist')(hidden_fc_prob_dist_2)

    #Value of a state
    hidden_fc_value_1 = Dense(100, kernel_regularizer=regularizers.l2(0.0001), activation='relu', name='FC_Value_1')(flat)
    hidden_fc_value_2 = Dense(100, kernel_regularizer=regularizers.l2(0.0001), activation='relu', name='FC_Value_2')(hidden_fc_value_1)
    output_value = Dense(1, kernel_regularizer=regularizers.l2(0.0001), activation='tanh', name='Output_Value')(hidden_fc_value_2)

    model = Model(inputs=[state_channels, valid_actions_dist], outputs=[output_prob_dist, output_value])

    model.compile(loss=custom_loss, optimizer='adam', metrics=['accuracy'])

    return model



# In the main method
model = define_model()
# ...
# MCTS routine to collect the data for the network input
# ...

x_train = [channels_input, valid_actions_dist_input]
y_train = [dist_probs_label, who_won_label]

model.fit(x_train, y_train, epochs=10)

简而言之,我的问题是:如何正确实现使用网络输出和网络标签值的自定义损失函数?

1 个答案:

答案 0 :(得分:0)

我检查了他们的git,并且发生了很多事情;如方程式所示,最终损失是三种不同损失的组合,并且三个网络正在使这种最终损失最小化。他们的损失代码如下:

    # train ops
    policy_cost = tf.reduce_mean(
    tf.nn.softmax_cross_entropy_with_logits_v2(
        logits=logits, labels=tf.stop_gradient(labels['pi_tensor'])))

    value_cost = params['value_cost_weight'] * tf.reduce_mean(
    tf.square(value_output - labels['value_tensor']))

   reg_vars = [v for v in tf.trainable_variables()
            if 'bias' not in v.name and 'beta' not in v.name]
   l2_cost = params['l2_strength'] * \
   tf.add_n([tf.nn.l2_loss(v) for v in reg_vars])

   combined_cost = policy_cost + value_cost + l2_cost

您可以参考this并进行相应的更改。