转置矩阵的每一行并将结果向量乘以其他矩阵的更快方法?
Faster way to transpose each row of a matrix and multiply the resulting vector by some other matrix?
我有一个尺寸为 N_rows x N_cols
的输入矩阵 X
。我还有一个稀疏的三对角矩阵 M
,它是大小为 N_rows x N_rows
的正方形。这些创建如下:
N_rows = 3;
N_cols = 6;
X = rand(N_rows,N_cols);
mm = 10*ones(N_cols,1); % Subdiagonal elements
dd = 20*ones(N_cols,1); % Main diagonal elements
pp = 30*ones(N_cols,1); % Superdiagonal elements
M = spdiags([mm dd pp],-1:1,N_cols,N_cols);
看起来像下面这样:
>> X
X =
0.4018 0.1233 0.4173 0.9448 0.3377 0.1112
0.0760 0.1839 0.0497 0.4909 0.9001 0.7803
0.2399 0.2400 0.9027 0.4893 0.3692 0.3897
full(M)
ans =
2 3 0 0 0 0
1 2 3 0 0 0
0 1 2 3 0 0
0 0 1 2 3 0
0 0 0 1 2 3
0 0 0 0 1 2
我想取 X
的每一行,并与 M
进行矩阵乘法,然后将获得的行重新组合在一起以获得输出 Y
。目前,我通过以下方式成功实现了这一目标:
Y = (M*X.').';
上面的示例是针对 X
的 3x6 矩阵,但实际上我需要对尺寸为 500 x 500 的矩阵执行此操作,大约 10000 次,探查器说此操作在我的较大代码中的瓶颈。有没有更快的方法来做这个逐行矩阵乘法?
在我的系统上,执行以下操作 10000 次大约需要 20 秒:
N_rows = 500;
N_cols = 500;
X = rand(N_rows,N_cols);
mm = 10*ones(N_cols,1); % Subdiagonal elements
dd = 20*ones(N_cols,1); % Main diagonal elements
pp = 30*ones(N_cols,1); % Superdiagonal elements
M = spdiags([mm dd pp],-1:1,N_cols,N_cols);
tic
for k = 1:10000
Y = (M*X.').';
end
toc
Elapsed time is 18.632922 seconds.
您可以使用 X*M.'
而不是 (M*X.').';
。这在我的计算机上节省了大约 35% 的时间。
这可以解释为因为转置(或排列维度)意味着重新排列矩阵的内部(线性顺序)表示中的元素,这需要时间。
另一种选择是使用 conv2
:
Y = conv2(X, [30 20 10], 'same');
解释:
有一个三对角矩阵,每条对角线上的所有元素都相同:
M =
2 3 0 0 0 0
1 2 3 0 0 0
0 1 2 3 0 0
0 0 1 2 3 0
0 0 0 1 2 3
0 0 0 0 1 2
假设您要将矩阵乘以向量:
V = [11 ;12 ;13 ;14 ;15 ;16];
R = M * V;
向量 R
的每个元素由 M
的每一行的乘积之和计算得出 V
:
R(1):
2 3 0 0 0 0
11 12 13 14 15 16
R(2):
1 2 3 0 0 0
11 12 13 14 15 16
R(3):
0 1 2 3 0 0
11 12 13 14 15 16
R(4):
0 0 1 2 3 0
11 12 13 14 15 16
R(5):
0 0 0 1 2 3
11 12 13 14 15 16
R(6):
0 0 0 0 1 2
11 12 13 14 15 16
等于[1 2 3]
的滑动window乘以M
的每一行。基本上卷积应用滑动 window 但首先它反转 window 的方向所以我们需要以相反的顺序提供滑动 window 以获得正确的结果。因此,我使用 Y = conv2(X, [30 20 10], 'same');
而不是 Y = conv2(X, [10 20 30], 'same');
。
我有一个尺寸为 N_rows x N_cols
的输入矩阵 X
。我还有一个稀疏的三对角矩阵 M
,它是大小为 N_rows x N_rows
的正方形。这些创建如下:
N_rows = 3;
N_cols = 6;
X = rand(N_rows,N_cols);
mm = 10*ones(N_cols,1); % Subdiagonal elements
dd = 20*ones(N_cols,1); % Main diagonal elements
pp = 30*ones(N_cols,1); % Superdiagonal elements
M = spdiags([mm dd pp],-1:1,N_cols,N_cols);
看起来像下面这样:
>> X
X =
0.4018 0.1233 0.4173 0.9448 0.3377 0.1112
0.0760 0.1839 0.0497 0.4909 0.9001 0.7803
0.2399 0.2400 0.9027 0.4893 0.3692 0.3897
full(M)
ans =
2 3 0 0 0 0
1 2 3 0 0 0
0 1 2 3 0 0
0 0 1 2 3 0
0 0 0 1 2 3
0 0 0 0 1 2
我想取 X
的每一行,并与 M
进行矩阵乘法,然后将获得的行重新组合在一起以获得输出 Y
。目前,我通过以下方式成功实现了这一目标:
Y = (M*X.').';
上面的示例是针对 X
的 3x6 矩阵,但实际上我需要对尺寸为 500 x 500 的矩阵执行此操作,大约 10000 次,探查器说此操作在我的较大代码中的瓶颈。有没有更快的方法来做这个逐行矩阵乘法?
在我的系统上,执行以下操作 10000 次大约需要 20 秒:
N_rows = 500;
N_cols = 500;
X = rand(N_rows,N_cols);
mm = 10*ones(N_cols,1); % Subdiagonal elements
dd = 20*ones(N_cols,1); % Main diagonal elements
pp = 30*ones(N_cols,1); % Superdiagonal elements
M = spdiags([mm dd pp],-1:1,N_cols,N_cols);
tic
for k = 1:10000
Y = (M*X.').';
end
toc
Elapsed time is 18.632922 seconds.
您可以使用 X*M.'
而不是 (M*X.').';
。这在我的计算机上节省了大约 35% 的时间。
这可以解释为因为转置(或排列维度)意味着重新排列矩阵的内部(线性顺序)表示中的元素,这需要时间。
另一种选择是使用 conv2
:
Y = conv2(X, [30 20 10], 'same');
解释:
有一个三对角矩阵,每条对角线上的所有元素都相同:
M =
2 3 0 0 0 0
1 2 3 0 0 0
0 1 2 3 0 0
0 0 1 2 3 0
0 0 0 1 2 3
0 0 0 0 1 2
假设您要将矩阵乘以向量:
V = [11 ;12 ;13 ;14 ;15 ;16];
R = M * V;
向量 R
的每个元素由 M
的每一行的乘积之和计算得出 V
:
R(1):
2 3 0 0 0 0
11 12 13 14 15 16
R(2):
1 2 3 0 0 0
11 12 13 14 15 16
R(3):
0 1 2 3 0 0
11 12 13 14 15 16
R(4):
0 0 1 2 3 0
11 12 13 14 15 16
R(5):
0 0 0 1 2 3
11 12 13 14 15 16
R(6):
0 0 0 0 1 2
11 12 13 14 15 16
等于[1 2 3]
的滑动window乘以M
的每一行。基本上卷积应用滑动 window 但首先它反转 window 的方向所以我们需要以相反的顺序提供滑动 window 以获得正确的结果。因此,我使用 Y = conv2(X, [30 20 10], 'same');
而不是 Y = conv2(X, [10 20 30], 'same');
。