Пользовательский градиент Tensorflow с разными размерами ввода и вывода - PullRequest
0 голосов
/ 29 августа 2018

Я пытаюсь определить новый оп и градиент для Tensorflow. Я нашел следующую ссылку: https://gist.github.com/harpone/3453185b41d8d985356cbe5e57d67342

Работает нормально, пока входное измерение равно выходному измерению. Я хочу отправить 2 параметра размера (1,) и получить опцию размера N = (65536,) для каждого и градиент того же размера N = (65536,) для каждого.

мой ввод: x (1,), y (1,)

вывод:

op N=(65536,)

grad of x: N=(65536,)

grad of y: N=(65536,)

или ввод пар (2,) выходной градус N = (65536,2)

на тренировке я буду использовать redu_sum, поэтому получу 2 числа (в качестве параметров) и градиентный спуск должен работать правильно.

Но это не работает, и я получаю следующее сообщение:

Traceback (most recent call last):
  File "tfTmp.py", line 97, in <module>
    gr = tf.gradients(z, [x,y])
  File "/home/user/.local/lib/python2.7/site-packages/tensorflow/python/ops/gradients_impl.py", line 532, in gradients
    gate_gradients, aggregation_method, stop_gradients)
  File "/home/user/.local/lib/python2.7/site-packages/tensorflow/python/ops/gradients_impl.py", line 734, in _GradientsHelper
    (op.name, i, t_in.shape, in_grad.shape))
ValueError: Incompatible shapes between op input and calculated input gradient.  Forward operation: myOp.  Input index: 0. Original input shape: (1,).  Calculated input gradient shape: (65536,)

Мой код:

import...
def my_op(x,y):
    op_output=getOutput(x,y) # size of N=(65536,)
    return op_output

def callGrad(op,grad):
    x = op.input[0]
    y = op.input[1]
    Gx=calculateGradx(x,y); # size of N=(65536,);
    Gy=calculateGrady(x,y); # size of N=(65536,);

    return Gx,Gy

def pyfunc(func,inp,Tout,stateful=True,name=None,grad=None)
    rnd_name = 'PyFuncGrad' + str(np.random.randint(0, 1E+8))

    tf.RegisterGradient(rnd_name)(grad)
    g= tf.get_default_graph()
    with g.gradient_override_map({"PyFuc": rnd_name});
        return tf.py_func(func, inp, Tout, stateful=stateful, name=name)

from tensorflow.python.framework import ops

def tf_ops(x,y, name=None)
    with ops.name_scope(name, "myOp", [x,y]) as name:
        z = py_func(my_op,

[x,y],[tf.float32],name=name,grad=callGrad);
            return z[0];

with tf.Session() as sess:
    N=1; # for N=65536 it works but I want only one parameter
    x=tf.constant(np.ones(N)); 
    y=tf.constant(np.ones(N));

    z=tf_op(x,y);
    gr=tf.gradients(z,[x,y]);

    init = tf.global_variables_initializer();
    sess.run(init)

    print(x.eval(), y.eval(),z.eval(), gr[0].eval(), gr[1].eval())

Важное замечание: я не хочу делать Reduce_sum в градиенте, потому что я буду использовать автоматическую разность, поэтому я хочу получить следующую функцию стоимости: сумма ((реф-OP (х, у)) ^ 2) * * тысяча двадцать-один

градиент -2 * сумма ((ref-OP (x, y)) * dOp / dx)), -2 * сумма ((ref-OP (x, y)) * dOp / dy))

поэтому dOp / dx должно быть таким же, как Op, т.е. N = (65536,)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...