我想创建多个矩阵,这些矩阵的对角线为零且对称。此形式的维度为n的矩阵需要完全指定n *(n-1)/ 2个参数。 这些参数将在以后学习...
在numpy中,我可以使用numpy.triu_indices来计算这些三角形,以从主要对角线上方的第一个对角线开始获取上三角矩阵的索引,然后按提供的参数将其填充,如以下代码片段所示:
import numpy as np
R = np.array([[1,2,1,1,2,1], [1,1,1,1,1,1]])
s = R.shape[1]
M = R.shape[0]
iu_r, iu_c = np.triu_indices(s,1)
Q = np.zeros((M,s,s),dtype=float)
Q[:,iu_r,iu_c] = R
Q = Q + np.transpose(Q,(0,2,1))
输出:
[[[0. 1. 2. 1.]
[1. 0. 1. 2.]
[2. 1. 0. 1.]
[1. 2. 1. 0.]]
[[0. 1. 1. 1.]
[1. 0. 1. 1.]
[1. 1. 0. 1.]
[1. 1. 1. 0.]]]
但是显然,不能像
那样直接将其转换为张量流。import tensorflow as tf
import numpy as np
M = 2
s = 4
iu_r, iu_c = np.triu_indices(s,1)
rates = tf.get_variable(shape=(M,s*(s-1)/2), name="R", dtype=float)
Q = tf.get_variable(shape=(M,s,s), dtype=float, initializer=tf.initializers.zeros, name="Q")
Q = Q[:,iu_r,iu_c].assign(rates)
失败
TypeError: Tensors in list passed to 'values' of 'Pack' Op have types [int32, int64, int64] that don't all match.
从张量流中的矢量张量定义矩阵张量的正确方法是什么?
编辑:
我当前的解决方案是使用tensorflow提供的scatter_nd函数进行嵌入,因为它适合像fill_triangular一样不需要分配冗余变量的需求。但是,索引与numpy生成的索引不兼容。目前,对以下示例进行了硬编码:
import tensorflow as tf
import numpy as np
M = 2
s = 4
iu_r, iu_c = np.triu_indices(s,1)
rates = tf.get_variable(shape=(M,s*(s-1)/2), name="R", dtype=float)
iupper = [[[0,0,1],[0,0,2],[0,0,3],[0,1,2],[0,1,3],[0,2,3]],[[1,0,1],[1,0,2],[1,0,3],[1,1,2],[1,1,3],[1,2,3]]]
Q = tf.scatter_nd(iupper,rates,shape=(M,s,s), name="rate_matrix")
翻译
获得的索引应该没问题。iu_r, iu_c = np.triu_indices(s,1)
但是也许有人对此有一个更优雅的解决方案?
答案 0 :(得分:0)
显然您需要类似convert_to_tensor的东西。
此函数将各种类型的Python对象转换为Tensor对象。它接受Tensor对象,numpy数组,Python列表和Python标量。
注意:TensorFlow操作会自动将NumPy ndarrays转换为Tensors。
答案 1 :(得分:0)
我不清楚这部分的工作原理:
import numpy as np
R = np.array([[1,2,1,1,2,1], [1,1,1,1,1,1]])
s = R.shape[1]
M = R.shape[0]
iu_r, iu_c = np.triu_indices(s,1)
Q = np.zeros((M,s,s),dtype=float)
Q[:,iu_r,iu_c] = R
Q = Q + np.transpose(Q,(0,2,1))
因为这将错误地失败。 您可以使用以下更简单的代码:
import numpy as np
R = [1,2,1,1,2,1]
N = 4
Q = np.zeros((N,N),dtype=float)
for i in range(0,N):
for j in range(0,N):
if (i<j):
Q[i][j] = R.pop(0)
Q
为:
[[0. 1. 2. 1.]
[0. 0. 1. 2.]
[0. 0. 0. 1.]
[0. 0. 0. 0.]]
<class 'numpy.ndarray'>
要获得对称Q,只需使用以下命令:Q = Q + np.transpose(Q)
以后无论您使用哪种锯齿形汇率,都可以像这样转换成张量:
import tensorflow as tf
data_tf = tf.convert_to_tensor(Q, np.float32)
sess = tf.InteractiveSession()
print(data_tf.eval())
sess.close()
答案 2 :(得分:0)
其他答案建议使用convert_to_tensor函数,将numpy数组转换为TensorFlow张量。
这确实可以为您提供具有对角线为零对称的所需属性的矩阵。但是,一旦开始训练,这些属性就可能不再适用,因为通常不能保证重量更新会保持此属性不变。
如果在整个训练过程中确实需要使矩阵对称且对角线为零,则可以执行以下操作:
import tensorflow as tf
from tensorflow.contrib.distributions import fill_triangular
M = 2 # batch size
s = 4 # matrix size
rates = tf.get_variable(shape=(M,s*(s+1)/2), name="R", dtype=float)
# Q will be triangular (with a non-zero diagonal!)
Q = fill_triangular(rates)
# set the diagonal of Q to zero.
Q = tf.linalg.set_diag(Q,tf.zeros((M,s)))
# make Q symmetric
Q = Q + tf.transpose(Q,[0,2,1])
这是一项测试,即使在训练后,也可以验证矩阵是否具有所需的属性:
import numpy as np
# define some arbitrary loss function
Q_target = tf.constant(np.random.normal(size=(1,s,s)).astype(np.float32))
loss = tf.nn.l2_loss(Q-Q_target)
# a single training step (which will update the matrices)
train_step = tf.train.GradientDescentOptimizer(learning_rate=0.1).minimize(loss)
sess = tf.Session()
sess.run(tf.global_variables_initializer())
# this is Q before training
print(sess.run(Q))
#[[[ 0. -0.564 0.318 -0.446]
# [-0.564 0. -0.028 0.2 ]
# [ 0.318 -0.028 0. 0.369]
# [-0.446 0.2 0.369 0. ]]
#
# [[ 0. 0.412 0.216 0.063]
# [ 0.412 0. 0.221 -0.336]
# [ 0.216 0.221 0. -0.653]
# [ 0.063 -0.336 -0.653 0. ]]]
# this is Q after training
sess.run(train_step)
print(sess.run(Q))
#[[[ 0. -0.548 0.235 -0.284]
# [-0.548 0. -0.055 0.074]
# [ 0.235 -0.055 0. 0.25 ]
# [-0.284 0.074 0.25 0. ]]
#
# [[ 0. 0.233 0.153 0.123]
# [ 0.233 0. 0.144 -0.354]
# [ 0.153 0.144 0. -0.568]
# [ 0.123 -0.354 -0.568 0. ]]]