Определить функцию потерь в кератах с помощью itertools

Я хочу определить функцию потерь, которая представляет расстояние между выходными точками скрытого слоя. Во-первых, я написал это без керас

import numpy as np
import itertools
pts = np.array([
    [10,10,10],
    [10,11,20],
    [20,11,30],
    [20,10,10],
    [10,10,20],
    ])
diff = list(itertools.combinations(pts, 2))

ptdiff = lambda (p1,p2): (np.sqrt(np.sum((p1 - p2) ** 2)))
diffs = map(ptdiff, diff)
np.mean(diffs)

Я получаю результат. И я пытаюсь эту функцию потери в керасе, z вывод скрытого слоя, который представляет собой матрицу

определить функцию потерь

def vae_loss(z):
    z_diff = list(itertools.combinations(z,2))
    ptdiff = lambda (p1,p2): (np.sqrt(np.sum((p1 - p2) ** 2)))
    z_diffs = map(ptdiff, z_diff)
    loss = K.mean(z_diffs)
    return loss

Но это показывает TypeError: 'Tensor' object is not iterable.Мне просто интересно, как я могу решить эту проблему.

1 ответ

Решение

Основываясь на этом очень полезном вопросе, вы можете использовать свойства вещания Keras. Я предполагаю, что здесь вы запускаете Keras на сервере TensorFlow. Из документов TF о вещании:

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

Воспроизводимый пример вашего кода:

import numpy as np
import itertools

# Generate 100 random points in a 5-D space
n_dim = 5
matrix = np.random.rand(1000, 5)

# List all possible combinations
combinations = list(itertools.combinations(matrix.tolist(), 2))

def mse(tup):
    """MSE between first and second element of a tuple of lists"""
    return np.mean((np.array(tup[0]) - np.array(tup[1]))**2)

avg_mse = np.mean([mse(c) for c in combinations])
print('Average mse: {:.3f}'.format(avg_mse))

Это возвращает, в моем случае, Average mse: 0.162

Основываясь на приведенном выше вопросе, вы можете построить свою функцию потерь следующим образом:

import keras.backend as K

# Wrap our random matrix into a tensor
tensor = K.constant(value=matrix)

def loss_function(x):
    x_ = K.expand_dims(tensor, axis=0)
    x__ = K.expand_dims(tensor, axis=1)

    # Compute mse for all combinations, making use of broadcasting
    z = K.mean(K.square(x_ - x__), axis=-1)

    # Return average mse
    return(K.mean(z))

with K.get_session() as sess:
    print('Average mse: {:.3f}'.format(loss_function(tensor).eval()))

Который возвращается за мной Average mse: 0.162,

Обратите внимание, что эта реализация не точно повторяет поведение из вашего примера. Разница в том, что все комбинации строк с самим собой также рассматриваются (не в случае с itertools.combinations) и комбинации рассматриваются дважды: mse((row1, row2)) а также mse((row2, row1)) оба будут рассчитаны, что опять-таки не так с вашим itertools код. Как видно из моего примера, для матриц с большим количеством строк это не должно иметь большого значения.

Другие вопросы по тегам