我想通过将矢量连接到自身n次来从矢量创建矩阵。因此,如果我的向量是mx1
,那么我的矩阵将是mxn
,并且矩阵的每列将等于向量。
以下哪项是最好/最正确的方式,或者有更好的方式我不知道?
matrix = repmat(vector, 1, n);
matrix = vector * ones(1, n);
由于
答案 0 :(得分:4)
以下是使用timeit
不同矢量大小和重复因子的基准测试。要显示的结果是Windows上的Matlab R2015b。
首先为每个考虑的方法定义一个函数:
%// repmat approach
function matrix = f_repmat(vector, n)
matrix = repmat(vector, 1, n);
%// multiply approach
function matrix = f_multiply(vector, n)
matrix = vector * ones(1, n);
%// indexing approach
function matrix = f_indexing(vector,n)
matrix = vector(:,ones(1,n));
然后生成不同大小的向量,并使用不同的重复因子:
M = round(logspace(2,4,15)); %// vector sizes
N = round(logspace(2,3,15)); %// repetition factors
time_repmat = NaN(numel(M), numel(N)); %// preallocate results
time_multiply = NaN(numel(M), numel(N));
time_indexing = NaN(numel(M), numel(N));
for ind_m = 1:numel(M);
for ind_n = 1:numel(N);
vector = (1:M(ind_m)).';
n = N(ind_n);
time_repmat(ind_m, ind_n) = timeit(@() f_repmat(vector, n)); %// measure time
time_multiply(ind_m, ind_n) = timeit(@() f_multiply(vector, n));
time_indexing(ind_m, ind_n) = timeit(@() f_indexing(vector, n));
end
end
结果绘制在以下两个图中,使用repmat
作为参考:
figure
imagesc(time_multiply./time_repmat)
set(gca, 'xtick',1:2:numel(N), 'xticklabels',N(1:2:end))
set(gca, 'ytick',1:2:numel(M), 'yticklabels',M(1:2:end))
title('Time of multiply / time of repmat')
axis image
colorbar
figure
imagesc(time_indexing./time_repmat)
set(gca, 'xtick',1:2:numel(N), 'xticklabels',N(1:2:end))
set(gca, 'ytick',1:2:numel(M), 'yticklabels',M(1:2:end))
title('Time of indexing / time of repmat')
axis image
colorbar
或许更好的比较表明,对于每个测试的矢量大小和重复因子,三种方法中哪一种最快:
figure
times = cat(3, time_repmat, time_multiply, time_indexing);
[~, fastest] = min(times, [], 3);
imagesc(fastest)
set(gca, 'xtick',1:2:numel(N), 'xticklabels',N(1:2:end))
set(gca, 'ytick',1:2:numel(M), 'yticklabels',M(1:2:end))
title('1: repmat is fastest; 2: multiply is; 3: indexing is')
axis image
colorbar
可以从数字中得出一些结论:
repmat
repmat
。对于较大的矢量大小或重复因子值,它往往更快,而对于较小的值则较慢。答案 1 :(得分:2)
如果它们为您提供所需的输出,则这两种方法都是正确的。
但是,根据您声明向量的方式,如果您使用repmat
,则ones
可能会发现错误的结果。例如,举个例子
>> v = 1:10;
>> m = v * ones(1, n)
Error using *
Inner matrix dimensions must agree.
>> m = repmat(v, 1, n)
m =
Columns 1 through 22
1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2
Columns 23 through 44
3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4
Columns 45 through 50
5 6 7 8 9 10
ones
提供错误,告知您没有做正确的事,但repmat
却没有。虽然此示例适用于repmat
和ones
>> v = (1:10).';
>> m = v * ones(1, n)
m =
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
4 4 4 4 4
5 5 5 5 5
6 6 6 6 6
7 7 7 7 7
8 8 8 8 8
9 9 9 9 9
10 10 10 10 10
>> m = repmat(v, 1, n)
m =
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
4 4 4 4 4
5 5 5 5 5
6 6 6 6 6
7 7 7 7 7
8 8 8 8 8
9 9 9 9 9
10 10 10 10 10
答案 2 :(得分:2)
两者都是正确的,但repmat
是多维矩阵复制的更通用的解决方案,因此必然比其他解决方案慢。将两个向量相乘的特定“自制”解决方案可能更快。选择而不是乘法可能更快,即vector(:,ones(n,1))
而不是vector*ones(1,n)
。
编辑:
在命令窗口中键入open repmat
。如您所见,它不是内置函数。您可以看到它还使用ones
(选择)来复制矩阵。但是,由于它是一种更通用的解决方案(对于标量和多维矩阵以及多个方向的副本),您将发现不必要的if
语句和其他不必要的代码,从而有效地降低了速度。
编辑:
对于非常大的向量,使用ones
的乘法向量变得更慢。明确的获胜者使用ones
进行选择,即vector(:,ones(n,1))
(由于它使用相同的策略,因此应始终比repmat
更快。)
答案 3 :(得分:2)
您也可以这样做 -
vector(:,ones(1,n))
但是,如果我必须选择,repmat
将成为我的首选方法,因为它完全是出于此目的。此外,根据您将如何使用此复制数组,您可以完全避免使用bsxfun
创建它,该Comparing BSXFUN and REPMAT
在其输入数组上进行动态复制,并在输入上应用某些操作。这是一个比较 - @covers
annotation在大多数情况下bsxfun
显示优于repmat
。
为了表现,让我们测试一下这些。这是一个基准代码 -
%// Inputs
vector = rand(1000,1);
n = 1000;
%// Warm up tic/toc.
for iter = 1:50000
tic(); elapsed = toc();
end
disp(' ------- With REPMAT -------')
tic,
for iter = 1:200
A = repmat(vector, 1, n);
end
toc, clear A
disp(' ------- With vector(:,ones(1,n)) -------')
tic,
for iter = 1:200
A = vector(:,ones(1,n));
end
toc, clear A
disp(' ------- With vector * ones(1, n) -------')
tic,
for iter = 1:200
A = vector * ones(1, n);
end
toc
运行时结果 -
------- With REPMAT -------
Elapsed time is 1.241546 seconds.
------- With vector(:,ones(1,n)) -------
Elapsed time is 1.212566 seconds.
------- With vector * ones(1, n) -------
Elapsed time is 3.023552 seconds.