2016-11-22 4 views
0

実際のベクトルを2進化するために、以下のカスタム操作をグラデーションで作成しました。 (このコードはhttps://gist.github.com/harpone/3453185b41d8d985356cbe5e57d67342からインスピレーションを受けている)Tensorflow:2つのネットワークで同時に使用されるカスタム操作では、ナノが生成されます

def py_func(func, inp, Tout, stateful=True, name=None, grad=None): 

    # Need to generate a unique name to avoid duplicates: 
    rnd_name = name+'PyFuncGrad' + str(np.random.randint(0, 1E+8)) 

    tf.RegisterGradient(rnd_name)(grad) # see _MyBinarizerGrad for grad example 
    g = tf.get_default_graph() 
    with g.gradient_override_map({"PyFunc": rnd_name}): 
     return tf.py_func(func, inp, Tout, stateful=stateful, name=name) 

def mycustombinarizer(x): 
    if _test_: 
     return x>0.5 
    sess_ = tf.Session() 
    probs = tf.constant(x) 
    probs = tf.reshape(probs,[-1]) 
    probs = tf.pack([1-probs, probs], axis=1) 
    probs = tf.log(probs/(1-probs)) 
    indexes = tf.multinomial(probs, 1) 
    indexes = tf.cast(tf.reshape(indexes, list(x.shape)),tf.float32) 
    with sess_.as_default(): 
     binary_x = indexes.eval() 
    return binary_x 

def binarizer(x, name=None): 
    with ops.name_scope(name, "Binarizer", [x]) as name: 
     sqr_x = py_func(mycustombinarizer, 
         [x], 
         [tf.float32], 
         name=name, 
         grad=_MyBinarizerGrad) # <-- here's the call to the gradient 
     return tf.reshape(sqr_x[0], tf.shape(x)) 

def _MyBinarizerGrad(op, grad): 
    return grad 

この操作を使用してちょうど1のネットワークがある場合、これは完全に正常に動作します。しかし、同じネットワークの2つのコピーを作成し、このバイナリ演算を使用して結合コスト(cost_net1 + cost_net2)を最適化しようとすると、数回繰り返した後にナノコストが生成されます。

def network_(x, netname): 
    with tf.variable_scope(netname): 
     x = someoperation(x) 
     ... 
     ret_tensor = binarizer(x,netname) 

ypred1 = network_(input,'net1') 
ypred2 = network_(input,'net2') 
cost = costfn(ypred1,ytrue)+costfn(ypred2,ytrue) 

誰でも私のカスタム機能の実装に間違いがありますか教えてください。セッションでmycustombinarizerのindexes.eval()を評価するのが問題なのですか、それともname_scope/variable_scopeに問題があるのでしょうか、まったく問題ですか?私はここで立ち往生している。

答えて

0

グラフの作成、セッションの開始、実行はpy_func内でうまくサポートされているとは思わない。この場合、すべてのものを削除し、ストレートアップテンソルフローコードを使用すれば、すべてがうまくいくはずです。

+0

私はカスタムグラデーションを定義するためにpyfuncを書きました。このコードをテンソルフローコードでカスタムのグラデーションを得るために変換するにはどうすればいいですか? –

+0

パブリックAPIでこれがうまくサポートされているとは思いません。 –

2

これは多分お試しください。

@function.Defun() 
def BinarizerGrad(unused_x, dy): 
    # Backprop dy directly. 
    return dy 

@function.Defun(grad_func=BinarizerGrad) 
def Binarizer(x): 
    # your whatever forward function here. 
    return tf.floor(x + tf.random_uniform(tf.shape(x))) 

g = tf.Graph() 
with g.as_default(): 
    x = tf.placeholder(tf.float32) 
    y = Binarizer(x) 
    dy = tf.placeholder(tf.float32) 
    dx = tf.gradients(y, x, grad_ys=dy) 

with tf.Session(graph=g) as sess: 
    x_val = np.array([[1, 2, 3], [0.5, 0.3, 0.2]]) 
    dy_val = np.array([[1, 0, 1], [0., 0.1, 0.9]]) 
    for v in sess.run([x, y, dx], feed_dict={x : x_val, dy: dy_val}): 
    print v 
関連する問題