градиент тензорного потока - получение всех значений наночастиц - PullRequest
0 голосов
/ 24 января 2019

Я использую Python 3 с Anaconda и TenSerflow 1.12 с нетерпением Eval.

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

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

Это код:

def matrix_row_wise_norm(matrix):
    import tensorflow as tf
    tensor = tf.expand_dims(matrix, -1)

    tensor = tf.transpose(tensor, [0, 2, 1]) - tf.transpose(tensor, [2, 0, 1])
    norm = tf.norm(tensor, axis=2)
    return norm

В функции потерь я использую

def loss(y_true, p_pred):
    with tf.GradientTape() as t:
    t.watch(y_pred)
        distance_matrix = matrix_row_wise_norm(y_pred)
        grad = t.gradient(distance_matrix, y_pred)

И все грады nan с.Я проверил, что y_pred состоит из допустимых значений - и это так.Я попытался создать градиент y_pred * 2 относительно себя и получил допустимые значения градиента.

Что мне здесь не хватает?Проблематично ли индексирование при создании матрицы расстояний?


edit:

dtype для y_pred и loss равен tf.float32

edit: обнаружил открытый отчет об ошибках в tf - может ли это быть проблемой?


edit:

Когда я изменяю ось нормы на 0 или 1, я получаю допустимые значения, и ничто не идет к nan.Операция, которую я получаю, используя норму с axis=2, представляет собой попарное расстояние между парами строк в матрице. Я подозревал, что это может быть связано с расстоянием 0 между строкой, так что я обрезал значения с минимальным значением:1e-7 без удачи.

Спасибо

1 Ответ

0 голосов
/ 27 января 2019

Кажется, что tf.norm страдает от числовой нестабильности, как объяснено здесь

Они также предлагают использовать норму l2, которая является более числовой стабильной, поэтому я попробовал это, также получив значения nan, благодаря 0 градиентам. Так что я использовал их вместе с градиентным отсечением, пока все хорошо, функция потерь работает и может сходиться.

def last_attempt (y_true, y_pred): импортировать тензор потока как тф импортировать numpy как np

loss = tf.zeros(1)

for i in range(y_pred.shape[0]):
    dist = tf.gather(y_pred, [i], axis=0)
    y = y_true.numpy().squeeze()
    norm = tf.map_fn(tf.nn.l2_loss, dist-y_pred)

    d = norm.numpy()
    d[np.where(y != y[i])] = 0.0
    max_pos = tf.gather(norm, np.argmax(d))

    d = norm.numpy()
    d[np.where(y == y[i])] = np.inf
    min_neg = tf.gather(norm, np.argmin(d))

    loss += tf.clip_by_value(max_pos - min_neg + tf.constant(1, dtype=tf.float32),
                             1e-8, 1e1)

return loss

Существует много возможностей для оптимизации этой функции, вот ссылка на мой другой ТАК вопрос - работа над этим.

Спасибо всем

...