сумма по списку тензоров в tensorflow

у меня есть глубокая нейронная сеть, где веса между слоями хранятся в списке.

layers[j].weights Я хочу включить штраф хребта в мою функцию затрат. Мне нужно использовать что-то вроде tf.nn.l2_loss(layers[j].weights**2 for j in range(self.n_layers)) т. е. квадратная сумма всех Весов.

в частности, веса определяются как:

>>> avs.layers
[<neural_network.Layer object at 0x10a4b2a90>, <neural_network.Layer object at 0x10ac85080>, <neural_network.Layer object at 0x10b0f3278>, <neural_network.Layer object at 0x10b0eacf8>, <neural_network.Layer object at 0x10b145588>, <neural_network.Layer object at 0x10b165048>, <neural_network.Layer object at 0x10b155ba8>]
>>>
>>> avs.layers[0].weights
<tensorflow.python.ops.variables.Variable object at 0x10b026748>
>>> 

как я могу это сделать в tensorflow ?

2 ответов


стандартный способ суммировать список тензоров-использовать tf.add_n() операция, которая принимает список тензоров (каждый из которых имеет одинаковый размер и форму) и производит один тензор, содержащий сумму.

для конкретной проблемы, которая у вас есть, я предполагаю, что каждый layers[j].weights может иметь различный размер. Поэтому вам нужно будет уменьшить каждый элемент до скаляра перед суммированием, например, используя tf.nn.l2_loss()


на tf.nn.l2_loss() функция возвращает значение с 0 габариты.

но приятно не нужно вручную применять это к каждому тензору веса, поэтому сохранение тензоров веса в списке-один из способов решения проблемы (как отметил @mrry).

но вместо того, чтобы писать это каждый раз, что вы могли бы сделать, это использовать следующую функцию

def l2_loss_sum(list_o_tensors):
    return tf.add_n([tf.nn.l2_loss(t) for t in list_o_tensors])

в вашем случае это будет выглядеть так:

total_loss = l2_loss_sum([layers[j].weights for j in range(self.n_layers)])

и tf.nn.l2_loss() неявно применяет операция возведения в квадрат значений, а также умножение всех квадратов значений на 1/2, так что вы использовали что-то вроде tf.nn.l2_loss(layers[j].weights**2 for j in range(self.n_layers)) вы на самом деле будете поднимать Весы до 4-й степени. В результате ваша производная от этого Терма будет странной: она не отменит 1/2 до 1 (но неявно удвоит ваш β), и веса будут кубическими.