在 TensorFlow 中定义 cost/loss 函数
Defining a cost/loss function in TensorFlow
我正在研究一个图形网络问题,我想在其中利用 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
之间 link 的机会,如果 link 则为 A_ij = 1
,否则为 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 returns 一个值,并将它与学习率相乘可以提高分数,但是我的 tfZ 向量只返回 nans,我显然做错了什么,如果有人能发现我是什么做错了,不胜感激
只需更改此:
D = tf.sqrt(r - 2*tf.matmul(tfZ, tf.transpose(tfZ)) + tf.transpose(r) + 1e-8) # adding a small constant.
因为距离在对角线上有零点,当值为零时无法计算sqrt的梯度
我正在研究一个图形网络问题,我想在其中利用 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
之间 link 的机会,如果 link 则为 A_ij = 1
,否则为 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 returns 一个值,并将它与学习率相乘可以提高分数,但是我的 tfZ 向量只返回 nans,我显然做错了什么,如果有人能发现我是什么做错了,不胜感激
只需更改此:
D = tf.sqrt(r - 2*tf.matmul(tfZ, tf.transpose(tfZ)) + tf.transpose(r) + 1e-8) # adding a small constant.
因为距离在对角线上有零点,当值为零时无法计算sqrt的梯度