使用numpy方法修改(keras / tensorflow)张量

zwe*_*wep 5 python numpy keras tensorflow

我要执行特定操作。即从一个矩阵:

A = np.array([[1,2],
            [3,4]])
Run Code Online (Sandbox Code Playgroud)

到以下

B = np.array([[1, 0, 0, 2, 0, 0],
              [0, 1, 0, 0, 2, 0],
              [0, 0, 1, 0, 0, 2],
              [3, 0, 0, 4, 0, 0],
              [0, 3, 0, 0, 4, 0],
              [0, 0, 3, 0, 0, 4]])
Run Code Online (Sandbox Code Playgroud)

换句话说:将每个条目乘以单位矩阵并保持相同的顺序。现在,我使用以下代码通过使用numpy来完成此操作。这里NM是起始矩阵的维数,并且单位矩阵的维数。

l_slice = 3
n_slice = 2
A = np.reshape(np.arange(1, 1+N ** 2), (N, N))
B = np.array([i * np.eye(M) for i in A.flatten()])
C = B.reshape(N, N, M, M).reshape(N, N * M, M).transpose([0, 2, 1]).reshape((N * M, N * M))
Run Code Online (Sandbox Code Playgroud)

在哪里C有我想要的属性。

但是现在我想在Keras / Tensorflow中进行此修改,其中矩阵A是我的一层的结果。

但是,我不确定我是否能够正确创建矩阵B。尤其是当涉及批次时,我认为我将以某种方式弄乱问题的范围。拥有更多Keras / Tensorflow经验的人能否评论这种“重塑”,以及他/她如何在Keras / Tensorflow中看到这种情况?

jde*_*esa 2

以下是使用 TensorFlow 实现此目的的一种方法:

import tensorflow as tf

data = tf.placeholder(tf.float32, [None, None])
n = tf.placeholder(tf.int32, [])
eye = tf.eye(n)
mult = data[:, tf.newaxis, :, tf.newaxis] * eye[tf.newaxis, :, tf.newaxis, :]
result = tf.reshape(mult, n * tf.shape(data))
with tf.Session() as sess:
    a = sess.run(result, feed_dict={data: [[1, 2], [3, 4]], n: 3})
    print(a)
Run Code Online (Sandbox Code Playgroud)

输出:

import tensorflow as tf

data = tf.placeholder(tf.float32, [None, None])
n = tf.placeholder(tf.int32, [])
eye = tf.eye(n)
mult = data[:, tf.newaxis, :, tf.newaxis] * eye[tf.newaxis, :, tf.newaxis, :]
result = tf.reshape(mult, n * tf.shape(data))
with tf.Session() as sess:
    a = sess.run(result, feed_dict={data: [[1, 2], [3, 4]], n: 3})
    print(a)
Run Code Online (Sandbox Code Playgroud)

顺便说一句,您可以在 NumPy 中执行基本相同的操作,这应该比您当前的解决方案更快:

import numpy as np

data = np.array([[1, 2], [3, 4]])
n = 3
eye = np.eye(n)
mult = data[:, np.newaxis, :, np.newaxis] * eye[np.newaxis, :, np.newaxis, :]
result = np.reshape(mult, (n * data.shape[0], n * data.shape[1]))
print(result)
# The output is the same as above
Run Code Online (Sandbox Code Playgroud)

编辑:

我会尝试给出一些关于为什么/如何工作的直觉,如果太长,抱歉。这并不难,但我认为解释起来有点棘手。也许更容易看出下面的乘法是如何工作的

import numpy as np

data = np.array([[1, 2], [3, 4]])
n = 3
eye = np.eye(n)
mult1 = data[:, :, np.newaxis, np.newaxis] * eye[np.newaxis, np.newaxis, :, :]
Run Code Online (Sandbox Code Playgroud)

现在,mult1是一种“矩阵的矩阵”。如果我给出两个索引,我将得到原始索引中相应元素的对角矩阵:

print(mult1[0, 0])
# [[1. 0. 0.]
#  [0. 1. 0.]
#  [0. 0. 1.]]
Run Code Online (Sandbox Code Playgroud)

所以你可以说这个矩阵可以像这样可视化:

| 1 0 0 |  | 2 0 0 |
| 0 1 0 |  | 0 2 0 |
| 0 0 1 |  | 0 0 2 |

| 3 0 0 |  | 4 0 0 |
| 0 3 0 |  | 0 4 0 |
| 0 0 3 |  | 0 0 4 |
Run Code Online (Sandbox Code Playgroud)

然而,这是欺骗性的,因为如果你尝试将其重塑为最终形状,结果将不是正确的:

print(np.reshape(mult1, (n * data.shape[0], n * data.shape[1])))
# [[1. 0. 0. 0. 1. 0.]
#  [0. 0. 1. 2. 0. 0.]
#  [0. 2. 0. 0. 0. 2.]
#  [3. 0. 0. 0. 3. 0.]
#  [0. 0. 3. 4. 0. 0.]
#  [0. 4. 0. 0. 0. 4.]]
Run Code Online (Sandbox Code Playgroud)

原因是重塑(概念上)首先“展平”数组,然后给出新的形状。但本例中的展平数组并不是您所需要的:

print(mult1.ravel())
# [1. 0. 0. 0. 1. 0. 0. 0. 1. 2. 0. 0. 0. 2. 0. ...
Run Code Online (Sandbox Code Playgroud)

你看,它首先遍历第一个子矩阵,然后是第二个子矩阵,依此类推。你想要的是它首先遍历第一个子矩阵的第一行,然后是第二个子矩阵的第一行,然后是第一个子矩阵的第二行,等等。所以基本上你想要这样的东西:

  • 1取前两个子矩阵(带有和 的子矩阵2
    • 获取所有第一行 ([1, 0, 0][2, 0, 0])。
      • 取其中第一个 ( [1, 0, 0])
        • 取其每个元素(100)。

然后继续剩下的部分。因此,如果您考虑一下,我们首先遍历轴 0(“矩阵的矩阵”的行),然后遍历 2(每个子矩阵的行),然后遍历 1(“矩阵的矩阵”的列),最后遍历 3(子矩阵的列) )。所以我们可以重新排列轴来做到这一点:

mult2 = mult1.transpose((0, 2, 1, 3))
print(np.reshape(mult2, (n * data.shape[0], n * data.shape[1])))
# [[1. 0. 0. 2. 0. 0.]
#  [0. 1. 0. 0. 2. 0.]
#  [0. 0. 1. 0. 0. 2.]
#  [3. 0. 0. 4. 0. 0.]
#  [0. 3. 0. 0. 4. 0.]
#  [0. 0. 3. 0. 0. 4.]]
Run Code Online (Sandbox Code Playgroud)

它有效!因此,在我发布的解决方案中,为了避免转置,我只是进行乘法,因此轴的顺序正是这样的:

mult = data[
        :,           # Matrix-of-matrices rows
        np.newaxis,  # Submatrix rows
        :,           # Matrix-of-matrices columns
        np.newaxis   # Submatrix columns
    ] * eye[
        np.newaxis,  # Matrix-of-matrices rows
        :,           # Submatrix rows
        np.newaxis,  # Matrix-of-matrices columns
        :            # Submatrix columns
    ]
Run Code Online (Sandbox Code Playgroud)

我希望这能让它稍微清楚一些。老实说,特别是在这种情况下,我可以很快找到解决方案,因为不久前我必须解决类似的问题,我猜你最终会对这些事情建立起直觉。