'Builds a feed-forward part of the net given features as input.
The network topology is already defined in the constructor, so multiple
calls to BuildForward build multiple networks whose parameters are all
shared. It is the source of the input features and the use of the output
that distinguishes each network.
Args:
feature_endpoints: tensors with input features to the network
return_average: whether to use moving averages as model parameters
Returns:
logits: output of the final layer before computing softmax'

def _BuildNetwork(self, feature_endpoints, return_average=False):

    assert (len(feature_endpoints) == self._feature_size)
    embeddings = []
    for i in range(self._feature_size):
        embeddings.append(self._AddEmbedding(feature_endpoints[i], self._num_features[i], self._num_feature_ids[i], self._embedding_sizes[i], i, return_average=return_average))
    last_layer = tf.concat(embeddings, 1)
    last_layer_size = self.embedding_size
    for (i, hidden_layer_size) in enumerate(self._hidden_layer_sizes):
        weights = self._AddParam([last_layer_size, hidden_layer_size], tf.float32, ('weights_%d' % i), self._ReluWeightInitializer(), return_average=return_average)
        bias = self._AddParam([hidden_layer_size], tf.float32, ('bias_%d' % i), self._relu_bias_init, return_average=return_average)
        last_layer = tf.nn.relu_layer(last_layer, weights, bias, name=('layer_%d' % i))
        last_layer_size = hidden_layer_size
    softmax_weight = self._AddParam([last_layer_size, self._num_actions], tf.float32, 'softmax_weight', tf.random_normal_initializer(stddev=self._softmax_init, seed=self._seed), return_average=return_average)
    softmax_bias = self._AddParam([self._num_actions], tf.float32, 'softmax_bias', tf.zeros_initializer(), return_average=return_average)
    logits = tf.nn.xw_plus_b(last_layer, softmax_weight, softmax_bias, name='logits')
    return {'logits': logits}
