我想计算以下表达式:
a_2 = c_k2 * (b - t_k2)
其中t_k2是大小K1 x K2的列向量,b是大小K1 x 1,c_k2是常数(1 x 1)。但是我有这些t向量的K2。我知道我可以这样做:
t % (K1 x K2)
b % (K1 x 1)
a_k2 % (K1 x K2)
c % (K2 x 1)
for k2=1:K2
t_k2 = t(:,k2); % K1 x 1
c_k2 = c(k2);
a_k2(:,k2) = c_k2 * (b - t_k2); % K1 x 1
end
但是我想知道是否有使用cleaver的方法将其编写为MATLAB中的一行(避免所有索引和循环,并希望加快速度)。那可能吗?
我最初的想法可能是将b复制到大小为" K1 x K2"的矩阵中。假定可以做到,用B表示。然后我们可以计算B-t,并且每个条目都有(b - t_k2)。假设我们甚至可以做到这一点,我唯一的想法就是将每个常量c_k复制到具有该数量的向量中,如c_k_vec = [c_k, ... c_k]所示,然后对这些矩阵进行元素明智的乘法。显然,B应该:
B = repmat(b, [1,K2]);
和
B - t
完成了部分任务...但我不清楚如何在一行中没有循环的情况下生成列为c_k_vec = [c_k, ... c_k]的矩阵。这个想法是向量c与B-t的每一列匹配,我们希望将B-t的每一列乘以向量x中的项。
也许这是不可能的...
bsxfun是您的朋友
您几乎回答了您的问题(再次:))。您当然可以在b上使用repmat来水平复制列向量K2多次,以使尺寸一致。但是,c矩阵存在一个小问题,因为如果要实现矢量化输出矩阵的计算,则尺寸当前不兼容。
如果我正确理解了您的问题,则应将输出的每一行乘以c的相应行。在这种情况下,这只是在c上运行repmat的另一种情况,但重复此向量K1次。
具体而言,您可以执行以下操作:
a_k2 = repmat(c.', K1, 1) .* (repmat(b, 1, K2) - t);
请注意,我必须转置c,因为您说它是K2 x 1矢量。为了确保大小匹配,我对其进行了转置,使其变为1 x K2,并且repmat'ing将复制此矩阵以使其成为K1 x K2以与中间结果匹配。
但是,这看起来有点不雅致。我鼓励您利用bsxfun,它可以在后台进行复制:
a_k2 = bsxfun(@times, c.', bsxfun(@minus, b, t));
首先要做的是将b复制到与t一样多的列,然后通过复制c向量在形状上匹配,将中间结果乘以正确的c值。中间结果。 bsxfun的优点在于您无需知道需要多少次repmat。 bsxfun为您找到答案。
为了显示这三个语句是等效的,让我们生成一些样本数据,并运行您的for循环,然后运行我上面编写的两段代码:
%// Data setup
rng(123);
K1 = 10;
K2 = 12;
t = rand(K1, K2);
b = rand(K1, 1);
c = rand(K2, 1);
%// Your code
for k2=1:K2
t_k2 = t(:,k2); % K1 x 1
c_k2 = c(k2); %// Note - typo here
a_k2(:,k2) = c_k2 * (b - t_k2); % K1 x 1
end
%// Using repmat
a_k2r = repmat(c.', K1, 1) .* (repmat(b, 1, K2) - t);
%// Using bsxfun
a_k2b = bsxfun(@times, c.', bsxfun(@minus, b, t));
a_2k是您的代码生成的,而,a_k2b是我建议的两段代码的输出。如果我们全部显示它们,则会得到:
>> a_k2
a_k2 =
Columns 1 through 7
0.1527 0.0905 0.1628 0.7042 0.2768 0.0623 0.1011
-0.0574 -0.0840 -0.3855 -0.1957 0.0905 -0.0491 -0.1620
0.0480 -0.0235 -0.2595 -0.1198 -0.0244 -0.0246 -0.1424
-0.0229 0.0741 -0.0547 0.0228 0.1035 -0.0020 -0.0663
0.1334 0.0812 0.1078 0.4122 0.0350 0.0444 0.0255
0.4098 0.0396 0.3969 0.5813 0.7211 0.0539 0.3857
-0.5287 0.0121 -0.0626 -0.1462 -0.2218 -0.0127 -0.2168
-0.0881 0.0626 0.2019 -0.2849 -0.4143 -0.0093 0.1374
0.2384 0.0444 0.3083 -0.1188 0.2827 -0.0054 0.2625
0.0016 -0.0221 -0.1421 -0.0931 -0.2149 -0.0092 -0.0763
Columns 8 through 12
0.1656 0.2643 0.1098 0.0366 0.1747
-0.1386 -0.2183 -0.4315 -0.0428 -0.0435
-0.0685 -0.1180 -0.0347 0.0174 0.0360
-0.0416 0.0591 -0.1329 0.0363 -0.0918
0.1812 -0.0105 0.1691 0.0541 0.1672
0.0796 0.0640 0.1599 0.0301 0.1280
-0.0612 -0.0450 0.0583 -0.0550 -0.0953
0.0829 0.2347 0.0906 0.0010 0.0127
0.1338 0.2263 0.3101 -0.0044 0.2388
-0.0616 -0.0017 0.0279 0.0009 -0.1763
>> a_k2b
a_k2b =
Columns 1 through 7
0.1527 0.0905 0.1628 0.7042 0.2768 0.0623 0.1011
-0.0574 -0.0840 -0.3855 -0.1957 0.0905 -0.0491 -0.1620
0.0480 -0.0235 -0.2595 -0.1198 -0.0244 -0.0246 -0.1424
-0.0229 0.0741 -0.0547 0.0228 0.1035 -0.0020 -0.0663
0.1334 0.0812 0.1078 0.4122 0.0350 0.0444 0.0255
0.4098 0.0396 0.3969 0.5813 0.7211 0.0539 0.3857
-0.5287 0.0121 -0.0626 -0.1462 -0.2218 -0.0127 -0.2168
-0.0881 0.0626 0.2019 -0.2849 -0.4143 -0.0093 0.1374
0.2384 0.0444 0.3083 -0.1188 0.2827 -0.0054 0.2625
0.0016 -0.0221 -0.1421 -0.0931 -0.2149 -0.0092 -0.0763
Columns 8 through 12
0.1656 0.2643 0.1098 0.0366 0.1747
-0.1386 -0.2183 -0.4315 -0.0428 -0.0435
-0.0685 -0.1180 -0.0347 0.0174 0.0360
-0.0416 0.0591 -0.1329 0.0363 -0.0918
0.1812 -0.0105 0.1691 0.0541 0.1672
0.0796 0.0640 0.1599 0.0301 0.1280
-0.0612 -0.0450 0.0583 -0.0550 -0.0953
0.0829 0.2347 0.0906 0.0010 0.0127
0.1338 0.2263 0.3101 -0.0044 0.2388
-0.0616 -0.0017 0.0279 0.0009 -0.1763
>> a_k2r
a_k2r =
Columns 1 through 7
0.1527 0.0905 0.1628 0.7042 0.2768 0.0623 0.1011
-0.0574 -0.0840 -0.3855 -0.1957 0.0905 -0.0491 -0.1620
0.0480 -0.0235 -0.2595 -0.1198 -0.0244 -0.0246 -0.1424
-0.0229 0.0741 -0.0547 0.0228 0.1035 -0.0020 -0.0663
0.1334 0.0812 0.1078 0.4122 0.0350 0.0444 0.0255
0.4098 0.0396 0.3969 0.5813 0.7211 0.0539 0.3857
-0.5287 0.0121 -0.0626 -0.1462 -0.2218 -0.0127 -0.2168
-0.0881 0.0626 0.2019 -0.2849 -0.4143 -0.0093 0.1374
0.2384 0.0444 0.3083 -0.1188 0.2827 -0.0054 0.2625
0.0016 -0.0221 -0.1421 -0.0931 -0.2149 -0.0092 -0.0763
Columns 8 through 12
0.1656 0.2643 0.1098 0.0366 0.1747
-0.1386 -0.2183 -0.4315 -0.0428 -0.0435
-0.0685 -0.1180 -0.0347 0.0174 0.0360
-0.0416 0.0591 -0.1329 0.0363 -0.0918
0.1812 -0.0105 0.1691 0.0541 0.1672
0.0796 0.0640 0.1599 0.0301 0.1280
-0.0612 -0.0450 0.0583 -0.0550 -0.0953
0.0829 0.2347 0.0906 0.0010 0.0127
0.1338 0.2263 0.3101 -0.0044 0.2388
-0.0616 -0.0017 0.0279 0.0009 -0.1763
...为了获得一些好处,让我们比较原始矩阵(您的代码)与其中每个矩阵之间的绝对差,并找出最大偏差:
>> format long g
>> max_diff1 = max(abs(a_k2(:) - a_k2r(:)))
max_diff1 =
0
>> max_diff2 = max(abs(a_k2(:) - a_k2b(:)))
max_diff2 =
0
如您所见,如果我们在计算a_2k与我用repmat和bsxfun生成的结果之间进行元素明智的减法,则表示两个矩阵之差的最大元素为0。因此,我们可以看到来源与两种替代方法之间没有区别。
我不是唯一使用ones(N, 1)*或*ones(1, N)而不是repmat的旧计时器,对吗?
@ user3528438-我也曾经这样做过...在了解repmat之前...然后我只是坚持使用repmat ...但是通过ones(1,N)或ones(N,1)复制索引肯定是有效的 !
我不确定c_k_vec的来源,但是通过。*可以很容易地对每个元素进行向量乘法,因此,如果您解决了(b-t_k2)部分,则将常数与。*相乘应该非常简单
不,不是,因为不是按元素的乘法。 这个想法是,向量c与B-t的每一列匹配,我们希望将B-t的每一列乘以向量x中的项。
输出是K1 x K2大小的矩阵,而c_k向量是K2 x 1矩阵。 在调用.*之前,需要对c_k进行附加的repmat调用。