numpy/tensorflow 中不同形状矩阵的矢量化乘法
Vectorizing multiplication of matrices with different shapes in numpy/tensorflow
我有一个 4x4 输入矩阵,我想将每个 2x2 切片乘以存储在 3x3 权重矩阵中的权重。请参阅附件图片以获取示例:
在图像中,4x4 输入矩阵的彩色部分与 3x3 权重矩阵的相同彩色部分相乘,并存储在 4x4 输出矩阵中。当切片重叠时,输出取重叠的总和(例如蓝色+红色)。
我正在尝试在 Tensorflow 2.0 中使用 eager tensors(可以将其视为 numpy 数组)执行此操作。这是我为执行此操作而编写的内容,它会产生预期的输出。
inputm = np.ones([4,4]) # initialize 4x4 input matrix
weightm = np.ones([3,3]) # initialize 3x3 weight matrix
outputm = np.zeros([4,4]) # initialize blank 4x4 output matrix
# iterate through each weight
for i in range(weightm.shape[0]):
for j in range(weightm.shape[1]):
outputm[i:i+2, j:j+2] += weightm[i,j] * inputm[i:i+2, j:j+2]
但是,我不认为这是有效的,因为我正在一个接一个地迭代权重矩阵,当我需要在 500x500 的大矩阵上执行此操作时,这将非常慢。我很难找到一种向量化此操作的方法,可能会将权重矩阵平铺为与输入矩阵相同的形状并执行单个矩阵乘法。我也考虑过展平矩阵,但我仍然无法找到更有效地做到这一点的方法。
任何建议将不胜感激。提前致谢!
好吧,我想我有一个解决方案,但这涉及同时使用 numpy 操作(例如 np.repeat
)和 TensorFlow 2.0 操作(即 tf.segment_sum
)。并且警告你这不是世界上最清晰优雅的解决方案,但它是我能想到的最优雅的解决方案。就这样吧。
你的问题的罪魁祸首是这个权重矩阵。如果您将此权重矩阵操纵为 4x4 矩阵(每个位置的权重总和正确),您将得到一个很好的权重矩阵,您可以对输入进行逐元素乘法。这就是我的解决方案。请注意,这是为 4x4 问题设计的,您应该能够相对轻松地将其扩展到 500x500 矩阵。
import numpy as np
import tensorflow as tf
a = np.array([[1,2,3,4],[4,3,2,1],[1,2,3,4],[4,3,2,1]])
w = np.array([[5,4,3],[3,4,5],[5,4,3]])
# We make weights to a 6x6 matrix by repeating 2 times on both axis
w_rep = np.repeat(w,2,axis=0)
w_rep = np.repeat(w_rep,2,axis=1)
# Let's now jump in to tensorflow
tf_a = tf.constant(a)
tf_w = tf.constant(w_rep)
tf_segments = tf.constant([0,1,1,2,2,3])
# This is the most tricky bit, here we use the segment_sum to achieve what we need
# You can use segment_sum to get the sum of segments on the very first dimension of a matrix.
# So you need to do that to the input matrix twice. One on the original and the other on the transpose.
tf_w2 = tf.math.segment_sum(tf_w, tf_segments)
tf_w2 = tf.transpose(tf_w2)
tf_w2 = tf.math.segment_sum(tf_w2, tf_segments)
tf_w2 = tf.transpose(tf_w2)
print(tf_w2*a)
PS:我将尝试在以后的编辑中加入说明这里发生的事情的插图。但我估计这需要一些时间。
在意识到@thushv89 的把戏后,我意识到您可以通过将权重矩阵与一个矩阵进行卷积来获得相同的结果:
import numpy as np
from scipy.signal import convolve2d
a = np.ones([4,4]) # initialize 4x4 input matrix
w = np.ones([3,3]) # initialize 3x3 weight matrix
b = np.multiply(a, convolve2d(w, np.ones((2,2))))
print(b)
我有一个 4x4 输入矩阵,我想将每个 2x2 切片乘以存储在 3x3 权重矩阵中的权重。请参阅附件图片以获取示例:
在图像中,4x4 输入矩阵的彩色部分与 3x3 权重矩阵的相同彩色部分相乘,并存储在 4x4 输出矩阵中。当切片重叠时,输出取重叠的总和(例如蓝色+红色)。
我正在尝试在 Tensorflow 2.0 中使用 eager tensors(可以将其视为 numpy 数组)执行此操作。这是我为执行此操作而编写的内容,它会产生预期的输出。
inputm = np.ones([4,4]) # initialize 4x4 input matrix
weightm = np.ones([3,3]) # initialize 3x3 weight matrix
outputm = np.zeros([4,4]) # initialize blank 4x4 output matrix
# iterate through each weight
for i in range(weightm.shape[0]):
for j in range(weightm.shape[1]):
outputm[i:i+2, j:j+2] += weightm[i,j] * inputm[i:i+2, j:j+2]
但是,我不认为这是有效的,因为我正在一个接一个地迭代权重矩阵,当我需要在 500x500 的大矩阵上执行此操作时,这将非常慢。我很难找到一种向量化此操作的方法,可能会将权重矩阵平铺为与输入矩阵相同的形状并执行单个矩阵乘法。我也考虑过展平矩阵,但我仍然无法找到更有效地做到这一点的方法。
任何建议将不胜感激。提前致谢!
好吧,我想我有一个解决方案,但这涉及同时使用 numpy 操作(例如 np.repeat
)和 TensorFlow 2.0 操作(即 tf.segment_sum
)。并且警告你这不是世界上最清晰优雅的解决方案,但它是我能想到的最优雅的解决方案。就这样吧。
你的问题的罪魁祸首是这个权重矩阵。如果您将此权重矩阵操纵为 4x4 矩阵(每个位置的权重总和正确),您将得到一个很好的权重矩阵,您可以对输入进行逐元素乘法。这就是我的解决方案。请注意,这是为 4x4 问题设计的,您应该能够相对轻松地将其扩展到 500x500 矩阵。
import numpy as np
import tensorflow as tf
a = np.array([[1,2,3,4],[4,3,2,1],[1,2,3,4],[4,3,2,1]])
w = np.array([[5,4,3],[3,4,5],[5,4,3]])
# We make weights to a 6x6 matrix by repeating 2 times on both axis
w_rep = np.repeat(w,2,axis=0)
w_rep = np.repeat(w_rep,2,axis=1)
# Let's now jump in to tensorflow
tf_a = tf.constant(a)
tf_w = tf.constant(w_rep)
tf_segments = tf.constant([0,1,1,2,2,3])
# This is the most tricky bit, here we use the segment_sum to achieve what we need
# You can use segment_sum to get the sum of segments on the very first dimension of a matrix.
# So you need to do that to the input matrix twice. One on the original and the other on the transpose.
tf_w2 = tf.math.segment_sum(tf_w, tf_segments)
tf_w2 = tf.transpose(tf_w2)
tf_w2 = tf.math.segment_sum(tf_w2, tf_segments)
tf_w2 = tf.transpose(tf_w2)
print(tf_w2*a)
PS:我将尝试在以后的编辑中加入说明这里发生的事情的插图。但我估计这需要一些时间。
在意识到@thushv89 的把戏后,我意识到您可以通过将权重矩阵与一个矩阵进行卷积来获得相同的结果:
import numpy as np
from scipy.signal import convolve2d
a = np.ones([4,4]) # initialize 4x4 input matrix
w = np.ones([3,3]) # initialize 3x3 weight matrix
b = np.multiply(a, convolve2d(w, np.ones((2,2))))
print(b)