Хорошо, чтобы использовать разные вычисления для разных срезов партии во время обучения? - PullRequest
0 голосов
/ 07 февраля 2020

Я пытаюсь создать модель, которая предсказывает следующую карту, которая будет сыграна в карточной игре. В игре есть несколько карт, в которые можно играть только в начале игры, и другие карты, в которые можно играть на протяжении всей игры. Моя первоначальная попытка состояла в том, чтобы создать одну большую net, но во время оценки она иногда работает плохо и предсказывает не открывающие карты в начале и наоборот.

Чтобы смягчить эту проблему, я хочу разделить каждый пакет на две: один для открывающих карт и один для не открывающих карт и обрабатывать их через пользовательские полностью связанные слои с различными входами каждый. Вот где это становится сложным: я хочу делать это динамически во время обучения, а не в качестве этапа предварительной обработки. Это как две разные сети в одной. Первый вопрос: это хорошая идея? Есть ли фундаментальные проблемы с разделением партии и применением различных преобразований к каждому срезу во время тренировки? Это как-то нарушает основные принципы градиентного потока? Я подозреваю, что это так ... Так как две разные сети создают разные градиенты, я подозреваю, что веса перед разделением тянутся в двух направлениях.

    #this condition determines whether the card is played as an opener card
    opener_card_batch_indices = tf.equal(target_player_cards[:, 0], 6)
    nonopener_cards_batch_indices = tf.logical_not(tf.equal(target_player_cards[:, 0], 6))


    #find the batch indices that have opener cards
    opener_card_batch_indices_i = tf.where(opener_card_batch_indices)
    nonopener_card_item_batch_indices_i = tf.where(nonopener_cards_batch_indices)


    opener_card_input_layer = merge(
        [
            target_player_embedding,
            //some variables
        ], mode='concat', axis=1)
    opener_card_input_layer = tf.boolean_mask(opener_card_input_layer, opener_card_batch_indices)

    nonopener_card_input_layer = merge(
        [
            target_player_embedding,
            ///OTHER variables than opener cards
        ], mode='concat', axis=1)
    nonopener_card_input_layer = tf.boolean_mask(nonopener_card_input_layer, nonopener_cards_batch_indices)


    opener_card_output = batch_normalization(fully_connected(opener_card_input_layer, 8, bias=False,
                                                activation='relu',
                                                regularizer="L2"))
    nonopener_card_output = batch_normalization(fully_connected(nonopener_card_input_layer, 64, bias=False,
                                                 activation='relu',
                                                 regularizer="L2"))


    opener_card_logits = fully_connected(opener_card_output, total_num_cards, activation='linear')
    nonopener_card_logits = fully_connected(nonopener_card_output, total_num_cards, activation='linear')

    opener_card_logits_scattered = tf.scatter_nd(opener_card_item_batch_indices_i, opener_card_logits, (n, total_num_cards))
    nonopener_card_logits_scattered = tf.scatter_nd(nonopener_card_item_batch_indices_i, nonopener_card_logits, (n, total_num_cards))

    #put everything back in the original order
    opener_nonopener_card_logits_scattered = tf.stack([opener_card_logits_scattered, nonopener_card_logits_scattered], axis=2)
    logits = tf.reduce_sum(opener_nonopener_card_logits_scattered, axis=2)


    is_training = tflearn.get_training_mode()
    inference_output = tf.nn.softmax(logits)
    net = tf.cond(is_training, lambda: logits, lambda: inference_output)
    return regression_custom(net, optimizer='adam', to_one_hot=True,
                             n_classes=total_num_cards,
                             shuffle_batches=True,
                             learning_rate=learning_rate,
                             loss=self.class_weighted_sm_ce_loss,
                             name='target', metric=self.weighted_accuracy)
...