假设我有三个维度为A_1
的矩阵A_2
,A_3
和mxn
,其中m
和n
很大。这些矩阵严格包含正数。
我想构造一个尺寸为check
的矩阵mx1
,使得对于每个i=1,...,m
:
check(i)=1
,如果存在 j,k
,这样
A_1(i,1)+A_2(j,1)+A_3(k,1)<=quantile(A_1(i,2:end)+A_2(j,2:end)+A_3(k,3:end), 0.95)
在我的情况下,m
大(m=10^5
)和n=500
。因此,我希望您能帮助您找到一种有效的方法。
下面我重现一个示例。我强加了m
比实际小,并报告了我构建check
的不完整且可能效率不高的尝试。
clear
rng default
m=4;
n=500;
A_1=betarnd(1,2,m,n);
A_2=betarnd(1,2,m,n);
A_3=betarnd(1,2,m,n);
check=zeros(m,1);
for i=1:m
for j=1:m
for k=1:m
if A_1(i,1)+A_2(j,1)+A_3(k,1)<=quantile(A_1(i,2:end)+A_2(j,2:end)+A_3(k,2:end), 0.95)
check(i)=1;
STOP TO LOOP OVER j AND k, MOVE TO THE NEXT i (INCOMPLETE!)
else
KEEP SEARCHING FOR j,k SUCH THAT THE CONDITION IS SATISFIED (INCOMPLETE!)
end
end
end
end
答案 0 :(得分:4)
给定标量x
和向量v
,表达式x <=quantile (v, .95)
可以写成sum( x > v) < Q
,其中Q = .95 * numel(v)
*。
还可以在循环之前对A_1
进行拆分,以避免额外的索引编制。
此外,可以去除最内层的循环,从而有利于向量化。
Af_1 = A_1(:,1);
Af_2 = A_2(:,1);
Af_3 = A_3(:,1);
As_1 = A_1(:,2:end);
As_2 = A_2(:,2:end);
As_3 = A_3(:,2:end);
Q = .95 * (n -1);
for i=1:m
for j=1:m
if any (sum (Af_1(i) + Af_2(j) + Af_3 > As_1(i,:) + As_2(j,:) + As_3, 2) < Q)
check(i) = 1;
break;
end
end
end
通过重新排列不等式和预计算中涉及的表达式,可以实现更多优化:
lhs = A_3(:,1) - A_3(:,2:end);
lhsi = A_1(:,1) - A_1(:,2:end);
rhsj = A_2(:,2:end) - A_2(:,1);
Q = .95 * (n - 1);
for i=1:m
LHS = lhs + lhsi(i,:);
for j=1:m
if any (sum (LHS > rhsj(j,:), 2) < Q)
check(i) = 1;
break;
end
end
end
答案 1 :(得分:0)
选项1:
由于所有数字均为正数,因此您可以进行一些优化。只有将A1
添加到混合中,才能使95%更高-如果在右侧找到j
的最大95%的k
和A2+A3
,前两个元素的总和,您可以简单地为每个i
取。
maxDif = -inf;
for j = 1 : m
for k = 1 : m
newDif = quantile(A_2..., 0.95) - A_2(j,1)-A_3(k,1);
maxDif = max(newDif, maxDif);
end
end
即使速度太慢,也可以先获取maxDifA2
和maxDifA3
,然后估计maxDif
将用于那些特定的j
和k
值并进行计算。
现在,对于某些数字,您将得到maxDif > A_1
,那么check
为1。对于某些数字,您将得到maxDif + quantile(A1, 0.95) < A_1
,这里check
为0(如果您通过分别计算A2和A3来估算maxDif
,则不正确!)。不幸的是,对于某些(大多数?)而言,您将获得介于两者之间的值,这对您完全没有帮助。然后剩下的就是选项2(它也更简单):
选项2:
如果您可以在右侧保存求和A_2+A_3
,则可以节省一些时间,因为对于每个不同的i
都会重复该计算,但是这需要大量内存。但是quantile
还是更昂贵的操作,因此您不会节省很多时间。类似于
for j = 1 : m
for k = 1 : m
A23R(j,k,:) = A2(j,:)+A3(k,:); % Unlikely to fit in memory.
end
end
然后,您可以使用A23R执行循环,并避免对每个i
重复该总和。