#python #keras #conv-neural-network
#python #keras #conv-нейронная сеть
Вопрос:
Мне нужно использовать эту функцию потерь для CNN. list_distance и list_residual являются тензорами вывода из скрытых слоев, которые важны для вычисления потерь, но когда я выполняю код, он возвращает мне эту ошибку
Ошибка типа: объекты тензора могут повторяться только при активном выполнении. Для перебора этого тензора используйте tf.map_fn.
Есть ли другой способ перебора тензоров без использования структуры x в X или преобразования ее в массив numpy или с использованием серверной функции keras?
def DBL(y_true, y_pred, list_distances, list_residual, l=0.65):
prob_dist = []
Li = []
# mean of the images power spectrum
S = np.sum([np.power(np.abs(fp.fft2(residual)), 2)
for residual in list_residual], axis=0) / K.shape(list_residual)[0]
# log-ratio between the geometric and arithmetic of S
R = np.log10((scistats.gmean(S) / np.mean(S)))
for c_i, dis_i in enumerate(list_distances):
prob_dist.append([
np.exp(-dis_i) / sum([np.exp(-dis_j) if c_j != c_i else 0 for c_j, dis_j in enumerate(list_distances)])
])
for count, _ in enumerate(prob_dist):
Li.append(
-1 * np.log10(sum([p_j for c_j, p_j in enumerate(prob_dist[count])
if y_pred[count] == 1 and count != c_j])))
L0 = np.sum(Li)
return L0 - l * R
Комментарии:
1. Включите режим нетерпеливого выполнения Tensorflow, как указывает ошибка
2. Возможно ли сконструировать функцию другим способом, используя серверную функцию вместо режима ожидания?
3. Почему вы хотите, чтобы это было вместо простого
tf.enable_eager_execution()
в начале вашего скрипта? Но да, проверьтеmap_fn
, поскольку ошибка указывает еще раз.4. Использование
tf.enable_eager_execution
в скрипте — плохая практика …. он предназначен для использования при заклинивании в интерпретаторе python.
Ответ №1:
Вам нужно определить пользовательскую функцию для ввода в tf.map_fn()
— Tensorflow dox
Функции Mapper отображают (как ни странно) существующий объект (тензор) в новый, используя функцию, которую вы определяете.
Они применяют пользовательскую функцию к каждому элементу объекта без всякой возни с for
циклами.
Например (непроверенный код, может не запускаться — на моем телефоне atm):
def custom(a):
b = a 1
return b
original = np.array([2,2,2])
mapped = tf.map_fn(custom, original)
# mapped == [3, 3, 3] ... hopefully
Все примеры Tensorflow используют lambda
функции, поэтому вам может потребоваться определить свои функции таким образом, если вышеуказанное не работает. Пример Tensorflow:
elems = np.array([1, 2, 3, 4, 5, 6])
squares = map_fn(lambda x: x * x, elems)
# squares == [1, 4, 9, 16, 25, 36]
Редактировать:
Кроме того, функции map намного проще распараллеливать, чем для циклов — предполагается, что каждый элемент объекта обрабатывается уникально, поэтому вы можете увидеть повышение производительности, используя их.
Редактировать 2:
Для части «уменьшить сумму, но не по этому индексу» я бы настоятельно рекомендовал вам начать оглядываться на матричные операции… Как уже упоминалось, map
функции работают поэлементно — они не знают о других элементах. reduce
Функция — это то, что вы хотите, но даже они сложны, когда вы пытаетесь выполнить суммы «не по этому индексу»… также tensorflow построен вокруг matrix ops… Не парадигма MapReduce.
Что-то в этом роде может помочь:
sess = tf.Session()
var = np.ones([3, 3, 3]) * 5
zero_identity = tf.linalg.set_diag(
var, tf.zeros(var.shape[0:-1], dtype=tf.float64)
)
exp_one = tf.exp(var)
exp_two = tf.exp(zero_identity)
summed = tf.reduce_sum(exp_two, axis = [0,1])
final = exp_one / summed
print("input matrix: n", var, "n")
print("Identities of the matrix to Zero: n", zero_identity.eval(session=sess), "n")
print("Exponential Values numerator: n", exp_one.eval(session=sess), "n")
print("Exponential Values to Sum: n", exp_two.eval(session=sess), "n")
print("Summed values for zero identity matrixn ... along axis [0,1]: n", summed.eval(session=sess), "n")
print("Output:n", final.eval(session=sess), "n")
Комментарии:
1. возможно ли реализовать с помощью map_fn подобный код для c_i, dis_i в enumerate(list_distances): prob_dist.append([np.exp(-dis_i) / sum([np.exp(-dis_j), если c_j != c_i, иначе 0 для c_j, dis_j в enumerate(list_distances)]) ])
2. Я бы посоветовал вам начать думать в терминах матричных операций. Как упоминалось в моем редактировании, функции отображения работают поэлементно
3. Этот ответ у меня не сработал. Я выполняю пользовательскую функцию потерь, поэтому мне нужно использовать map_fn как для y_true, так и для y_pred вместе. И когда они являются символическими, то есть заполнителями без жестко заданного размера пакета и без режима нетерпеливого выполнения, я даже не могу сложить y_true и y_pred вместе, чтобы передать в map_fn. Я получаю ошибку OperatorNotAllowedInGraphError.