Tensorflow - не предусмотрены градиенты ни для одной переменной.

Я экспериментирую с кодом на Jupyter и продолжаю здесь застревать. На самом деле все работает нормально, если я удалю строку, начинающуюся с "optimizer = ...", и все ссылки на эту строку. Но если я вставлю эту строчку в код, выдает ошибку.

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

Обратите внимание, что есть 5, 4, 3 и 2 единицы во входном слое, в 2 скрытых слоях и в выходных слоях.

КОД:

tf.reset_default_graph()

num_units_in_layers = [5,4,3,2]

X = tf.placeholder(shape=[5, 3], dtype=tf.float32)
Y = tf.placeholder(shape=[2, 3], dtype=tf.float32)
parameters = initialize_layer_parameters(num_units_in_layers)
init = tf.global_variables_initializer() 

my_sess = tf.Session()
my_sess.run(init)
ZL = forward_propagation_with_relu(X, num_units_in_layers, parameters, my_sess)
#my_sess.run(parameters)  # Do I need to run this? Or is it obsolete?

cost = compute_cost(ZL, Y, my_sess, parameters, batch_size=3, lambd=0.05)
optimizer =  tf.train.AdamOptimizer(learning_rate = 0.001).minimize(cost)
_ , minibatch_cost = my_sess.run([optimizer, cost], 
                                 feed_dict={X: minibatch_X, 
                                            Y: minibatch_Y})

print(minibatch_cost)
my_sess.close()

ОШИБКА:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-321-135b9fc18268> in <module>()
     16 cost = compute_cost(ZL, Y, my_sess, parameters, 3, 0.05)
     17 
---> 18 optimizer =  tf.train.AdamOptimizer(learning_rate = 0.001).minimize(cost)
     19 _ , minibatch_cost = my_sess.run([optimizer, cost], 
     20                                  feed_dict={X: minibatch_X, 

~/.local/lib/python3.5/site-packages/tensorflow/python/training/optimizer.py in minimize(self, loss, global_step, var_list, gate_gradients, aggregation_method, colocate_gradients_with_ops, name, grad_loss)
    362           "No gradients provided for any variable, check your graph for ops"
    363           " that do not support gradients, between variables %s and loss %s." %
--> 364           ([str(v) for _, v in grads_and_vars], loss))
    365 
    366     return self.apply_gradients(grads_and_vars, global_step=global_step,

ValueError: No gradients provided for any variable, check your graph for ops that do not support gradients, between variables ["<tf.Variable 'weights/W1:0' shape=(4, 5) dtype=float32_ref>", "<tf.Variable 'biases/b1:0' shape=(4, 1) dtype=float32_ref>", "<tf.Variable 'weights/W2:0' shape=(3, 4) dtype=float32_ref>", "<tf.Variable 'biases/b2:0' shape=(3, 1) dtype=float32_ref>", "<tf.Variable 'weights/W3:0' shape=(2, 3) dtype=float32_ref>", "<tf.Variable 'biases/b3:0' shape=(2, 1) dtype=float32_ref>"] and loss Tensor("Add_3:0", shape=(), dtype=float32).

Обратите внимание, что если я бегу

print(tf.trainable_variables())

прямо перед строкой "optimizer = ..." я действительно вижу там свои обучаемые переменные.

hts/W1:0' shape=(4, 5) dtype=float32_ref>, <tf.Variable 'biases/b1:0' shape=(4, 1) dtype=float32_ref>, <tf.Variable 'weights/W2:0' shape=(3, 4) dtype=float32_ref>, <tf.Variable 'biases/b2:0' shape=(3, 1) dtype=float32_ref>, <tf.Variable 'weights/W3:0' shape=(2, 3) dtype=float32_ref>, <tf.Variable 'biases/b3:0' shape=(2, 1) dtype=float32_ref>]

Кто-нибудь знает, в чем может быть проблема?

РЕДАКТИРОВАНИЕ И ДОБАВЛЕНИЕ ДОПОЛНИТЕЛЬНОЙ ИНФОРМАЦИИ: Если вы хотите увидеть, как я создаю и инициализирую свои параметры, вот код. Может, с этой частью что-то не так, но я не понимаю, что ...

def get_nn_parameter(variable_scope, variable_name, dim1, dim2):
  with tf.variable_scope(variable_scope, reuse=tf.AUTO_REUSE):
    v = tf.get_variable(variable_name, 
                        [dim1, dim2], 
                        trainable=True, 
                        initializer = tf.contrib.layers.xavier_initializer())
  return v


def initialize_layer_parameters(num_units_in_layers):
    parameters = {}
    L = len(num_units_in_layers)

    for i in range (1, L):
        temp_weight = get_nn_parameter("weights",
                                       "W"+str(i), 
                                       num_units_in_layers[i], 
                                       num_units_in_layers[i-1])
        parameters.update({"W" + str(i) : temp_weight})  
        temp_bias = get_nn_parameter("biases",
                                     "b"+str(i), 
                                     num_units_in_layers[i], 
                                     1)
        parameters.update({"b" + str(i) : temp_bias})  

    return parameters
#

ДОБАВЛЕНИЕ

У меня все заработало. Вместо того, чтобы писать отдельный ответ, я добавляю сюда правильную версию своего кода.

(Ответ Дэвида ниже очень помог.)

Я просто удалил параметр my_sess as в моей функции compute_cost. (Раньше я не мог заставить его работать, но, похоже, это вообще не нужно.) И я также переупорядочил операторы в моей основной функции, чтобы вызывать вещи в правильном порядке.

Вот рабочая версия моей функции стоимости и то, как я ее называю:

def compute_cost(ZL, Y, parameters, mb_size, lambd):

    logits = tf.transpose(ZL)
    labels = tf.transpose(Y)

    cost_unregularized = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits = logits, labels = labels))

    #Since the dict parameters includes both W and b, it needs to be divided with 2 to find L
    L = len(parameters) // 2

    list_sum_weights = []

    for i in range (0, L):
        list_sum_weights.append(tf.nn.l2_loss(parameters.get("W"+str(i+1))))

    regularization_effect = tf.multiply((lambd / mb_size), tf.add_n(list_sum_weights))
    cost = tf.add(cost_unregularized, regularization_effect)

    return cost

А вот основная функция, в которой я вызываю функцию compute_cost (..):

tf.reset_default_graph()

num_units_in_layers = [5,4,3,2]

X = tf.placeholder(shape=[5, 3], dtype=tf.float32)
Y = tf.placeholder(shape=[2, 3], dtype=tf.float32)
parameters = initialize_layer_parameters(num_units_in_layers)

my_sess = tf.Session()
ZL = forward_propagation_with_relu(X, num_units_in_layers, parameters)

cost = compute_cost(ZL, Y, parameters, 3, 0.05)
optimizer =  tf.train.AdamOptimizer(learning_rate = 0.001).minimize(cost)
init = tf.global_variables_initializer() 

my_sess.run(init)
_ , minibatch_cost = my_sess.run([optimizer, cost], 
                                 feed_dict={X: [[-1.,4.,-7.],[2.,6.,2.],[3.,3.,9.],[8.,4.,4.],[5.,3.,5.]], 
                                            Y: [[0.6, 0., 0.3], [0.4, 0., 0.7]]})


print(minibatch_cost)

my_sess.close()

person edn    schedule 15.03.2018    source источник


Ответы (1)


Я на 99,9% уверен, что вы неправильно создаете функцию затрат.

cost = compute_cost(ZL, Y, my_sess, parameters, batch_size=3, lambd=0.05)

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

Позже вы передаете результат compute_cost в ваш минимизатор.

Это распространенное заблуждение о тензорном потоке.

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

Выполните рефакторинг вашего кода, чтобы строго следовать этой передовой практике:

(1) Создайте функцию build_graph(), в эту функцию должны быть помещены все ваши математические операции. Вы должны определить свою функцию затрат и все уровни сети. Верните optimize.minimize() тренировочную операцию (и любые другие OP, которые вы, возможно, захотите вернуть, например, точность).

(2) Теперь создайте сеанс.

(3) После этого не создавайте больше операций или переменных тензорного потока, если вам кажется, что вы делаете что-то не так.

(4) Вызвать программу sessions.run на своем train_op и передать данные заполнителя через feed_dict.

Вот простой пример того, как структурировать код:

https://github.com/aymericdamien/TensorFlow-Examples/blob/master/notebooks/3_NeuralNetworks/neural_network_raw.ipynb

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

person David Parks    schedule 15.03.2018
comment
Дэвид, спасибо за ответ. У меня было несколько вопросов, основанных на вашем ответе, но я не смог уместить его в окне комментариев, поэтому я поставил его выше как отдельный ответ. Если у вас есть возможность посмотреть ... Заранее спасибо! - person edn; 15.03.2018
comment
Как вы думаете, можете ли вы помочь мне с тремя вопросами? 1) Вы имеете в виду, что я никогда не должен передавать свой сеанс тензорного потока в качестве параметра функции какой-либо функции? 2) Моя дилемма в том, что я не мог прочитать веса в функции compute_cost. Я мог использовать их только с my_sess.run (.. weight ..), иначе я все время получал ошибки. (См. Ниже, как я его использовал.) 3) Также .. Разве моя функция не возвращает тензор ниже? - person edn; 15.03.2018
comment
Привет @edn, переместите, пожалуйста, свой ответ на вопрос. Вы всегда можете отредактировать вопрос после того, как он был задан (приятно, чтобы четко указать, что вы добавляете дополнение), но это совершенно неправильная форма при переполнении стека для публикации вопроса в качестве ответа (также это снижает вероятность того, что другие люди прыгнут с ответами, так как это будет выглядеть как хорошо заданный вопрос). Вы должны сделать это и удалить опубликованный ответ, чтобы исправить его. - person David Parks; 15.03.2018
comment
Что касается кода, который вы разместили, он мне кажется правильным. Вы сталкиваетесь с тем же сообщением об ошибке? Насколько я могу судить, ваша функция стоимости выглядит так, как будто она построена правильно. Попробуйте выполнить отладку, вызвав tf.gradients(tf.get_collection(GraphKeys.TRAINABLE_VARIABLES)), чтобы убедиться, что вы можете создавать градиенты для переменных. Если нет, попробуйте получить эту коллекцию переменных и вызвать tf.gradients для каждой переменной, чтобы узнать, какая из них вызывает проблему. Как только вы узнаете, какой именно, я отправлю еще один вопрос, напрямую указав проблемную переменную, и мы сможем ее понять. - person David Parks; 15.03.2018
comment
Также рекомендуется создать сеанс непосредственно перед этой строкой my_sess.run(init). Хотя это ничего не изменит в вашем текущем коде, скорее всего, это убережет вас от мелких, но типичных ошибок в будущем. Практическое правило: не создавать OP после открытия сеанса. - person David Parks; 15.03.2018
comment
Спасибо за внимание. Я переместил правильную версию своего кода в качестве дополнения к моему вопросу выше. Надеюсь, теперь формат выглядит правильным. Я также пробовал использовать ваши (Дэвида) советы, и, похоже, они работают. Когда я запускаю: print (tf.gradients (cost, tf.get_collection (tf.GraphKeys.TRAINABLE_VARIABLES))) Это дает: [‹tf.Tensor 'gradient_1 / AddN_2: 0' shape = (4, 5) dtype = float32› , ‹Tf.Tensor 'gradient_1 / Add_grad / Reshape_1: 0' shape = (4, 1) dtype = float32›, ..... Но интересно видеть, что он не дает их имен как W1, b1 и т. Д. I по заданным размерам матрицы можно понять, какой вес какой - person edn; 16.03.2018
comment
Еще одна лучшая практика - использовать свойство name=... ваших тензоров, чтобы вам не приходилось так много работать наугад во время отладки. Отладка тензорного потока - это не прогулка по парку. :) Я не понимаю, как можно успешно вызвать tf.gradients, но все равно получить эту ошибку в оптимизаторе. Попробуйте воспользоваться функцией оптимизаторов tf.apply_gradients. Когда вы звоните minimize, это фактически просто звонки tf.gradients и optimizer.apply_gradients для вас. Я надеюсь, что в процессе у вас что-то всплывет. - person David Parks; 16.03.2018
comment
Возможно, я вызвал недоразумение. Я действительно решил проблему, и теперь она работает. Я отредактировал свою первую запись выше и поместил рабочую версию своего кода внизу своей записи. И вызов tf.gradients (...) также работает. С другой стороны, я на самом деле даю имена своим тензорам (веса и смещения). Пожалуйста, проверьте функцию initialize_layer_parameters (...) в приведенном выше коде. Или вы имеете в виду другое, когда говорите, что я должен дать имя своим тензорам? По поводу вашего комментария об отладке кода tenorflow .. Ну, с этим я не могу согласиться .. :) - person edn; 16.03.2018
comment
Любая идея, в чем может быть проблема, здесь ? - person Stefan Falk; 20.04.2020