Я пытаюсь создать модель, которая предсказывает следующую карту, которая будет сыграна в карточной игре. В игре есть несколько карт, в которые можно играть только в начале игры, и другие карты, в которые можно играть на протяжении всей игры. Моя первоначальная попытка состояла в том, чтобы создать одну большую 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)