代码之家  ›  专栏  ›  技术社区  ›  NicolaiF

在TensorFlow中定义成本/损失函数

  •  1
  • NicolaiF  · 技术社区  · 6 年前

    我正在研究一个图形网络问题,我想利用TensorFlow的强大功能。

    但是,我在正确实现TensorFlow中的成本函数时遇到了困难。

    我的成本函数如下所示:

    sum_i>j A_ij*log(pi_ij)+(1-A_ij)*log(1-pi_ij)
    

    哪里: pi_ij = sigmoid(-|z_i-z_j|+beta)

    ||是欧几里得距离, pi_ij 表示在 i j A_ij = 1 如果link和0(在简单邻接矩阵中)都是大小相同的矩阵。我已经使用python和一个简单的SGD方法手动解决了这个优化问题。我计算成本函数如下:

    import tensorflow as tf
    import numpy as np
    import scipy.sparse.csgraph as csg
    from scipy.spatial import distance
    
    Y = np.array([[0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 1., 1., 0., 1., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 1., 0.],
       [0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 1., 0.],
       [0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 1., 0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 1.],
       [0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],
       [1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 0., 1.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],
       [0., 0., 0., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 1.],
       [0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 0., 0., 0., 0., 0.],
       [0., 0., 0., 1., 1., 0., 0., 0., 0., 0., 1., 1., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 1., 0., 1., 0., 0., 1., 0., 0., 0.]])
    
    # removing all non linked entries
    temp = Y[~np.all(Y == 0, axis=1)]
    temp = temp[:,~np.all(Y == 0, axis=1)]
    Y = temp
    
    n = np.shape(Y)[0]
    k = 2
    
    # finding shortest path and cmdscaling
    D = csg.shortest_path(Y, directed=True)
    Z = cmdscale(D)[0][:,0:k]
    Z = Z - Z.mean(axis=0, keepdims=True)
    
    # calculating cost
    euclideanZ = distance.cdist(Z, Z, 'euclidean')
    sigmoid = lambda x: 1 / (1 + np.exp(-x))
    vectorSigmoid = np.vectorize(sigmoid)
    pi = vectorSigmoid(euclideanZ)
    
    cost = np.sum(Y*np.log(pi)+(1-Y)*np.log(1-pi))
    

    我如何在TensorFlow中定义这样的损失函数?有可能吗?如能在正确的方向上提供任何帮助或推动,我们将不胜感激。

    编辑

    我在张量流中得到了这个:

    tfY = tf.placeholder(shape=(15, 15), dtype=tf.float32)
    
    with tf.variable_scope('test'):
        shape = [] # Shape [] means that we're using a scalar variable
        B = tf.Variable(tf.zeros(shape))
        tfZ = tf.Variable(tf.zeros(shape=(15,2)))
    
    def loss():
        r = tf.reduce_sum(tfZ*tfZ, 1)
        r = tf.reshape(r, [-1, 1])
        D = tf.sqrt(r - 2*tf.matmul(tfZ, tf.transpose(tfZ)) + tf.transpose(r))
        return tf.reduce_sum(tfY*tf.log(tf.sigmoid(D+B))+(1-tfY)*tf.log(1-tf.sigmoid(D+B)))
    
    LOSS = loss()
    GRADIENT = tf.gradients(LOSS, [B, tfZ])
    
    sess = tf.Session()
    sess.run(tf.global_variables_initializer())
    
    tot_loss = sess.run(LOSS, feed_dict={tfZ: Z,
                                         tfY: Y})
    
    print(tot_loss)
    
    loss_grad = sess.run(GRADIENT, feed_dict={tfZ: Z,
                                         tfY: Y})
    
    print(loss_grad)
    

    打印以下内容:

    -487.9079
    [-152.56271, array([[nan, nan],
           [nan, nan],
           [nan, nan],
           [nan, nan],
           [nan, nan],
           [nan, nan],
           [nan, nan],
           [nan, nan],
           [nan, nan],
           [nan, nan],
           [nan, nan],
           [nan, nan],
           [nan, nan],
           [nan, nan],
           [nan, nan]], dtype=float32)]
    

    我的beta返回一个值,将其与学习率相乘可以提高分数,但我的tfZ向量只返回nan,显然我做错了什么,如果有人能发现我做错了什么,我将不胜感激。

    1 回复  |  直到 6 年前
        1
  •  1
  •   LI Xuhong    6 年前

    只需更改以下内容:

    D = tf.sqrt(r - 2*tf.matmul(tfZ, tf.transpose(tfZ)) + tf.transpose(r) + 1e-8)  # adding a small constant.
    

    因为距离在对角线上有零,当值为零时,无法计算sqrt的梯度。