将向量的张量嵌入矩阵的张量

时间:2018-12-13 20:59:13

标签: python-3.x numpy tensorflow

我想创建多个矩阵,这些矩阵的对角线为零且对称。此形式的维度为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)

但是也许有人对此有一个更优雅的解决方案?

3 个答案:

答案 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.   ]]]