如何在 MATLAB 中以分量方式将向量和矩阵相乘?

How to component wise multiply a vector and a matrix in MATLAB?

我想计算以下表达式:

a_2 = c_k2 * (b - t_k2)

其中 t_k2 是大小为 K1 x K2 的列向量,b 的大小为 K1 x 1c_k2 是常数 (1 x 1)。但是我有 K2 个 t 向量。我知道我可以这样做:

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

但我想知道是否有一种切割方法可以在 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 中的条目。

也许这是不可能的...

我不确定 c_k_vec 从哪里来,但是可以很容易地通过 .* 为每个元素完成向量乘法,所以如果您解决了 (b-t_k2) 部分,则乘以.*

常量应该非常简单

您几乎回答了您的问题(再次 :))。您当然可以在 b 上使用 repmat 将列向量水平复制 K2 次以使维度一致。但是,如果要实现矢量化输出矩阵的计算,c 矩阵存在一些小问题,因为维度当前不兼容。

如果我对你的问题理解正确,输出的每一行都应该乘以 c 的对应行。在那种情况下,它只是在 c 上 运行ning 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 一样多的列,然后我们将通过复制将这个中间结果乘以正确的 cc 向量以在形状上与中间结果匹配。 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_k2ra_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 与我用 repmatbsxfun 计算的结果之间进行元素减法,它表示最大的元素在两个矩阵之间的差异是 0....因此,我们可以看到源和任何一种替代方法之间没有差异。