我必须将矩阵A
(100x8000),B
(8000x27)和C
(27x1)相乘。
由于矩阵B
和C
是恒定的,而A
是可变的,因此我更喜欢将其计算为:ABC = np.dot(A, np.dot(B, C))
。但是,我想知道,就准确性而言,在数字上可能比np.dot(np.dot(a, B), C)
更糟。
可能重要的是:矩阵A
和B
包含8000个分别(分别)100个和27个相关特征的样本。
乘法是否有数字个最优顺序(就准确性而言)?如果可以,我该如何确定?
可以假设A
和B
矩阵都是非负矩阵。
而且:
C = np.linalg.solve(cov(B, k), X)
其中X
是27x1矩阵,其中包含27个(可能是相关的)未知分布的随机变量,cov = lambda X, k: np.dot(X.T, X) + k * np.eye(X.shape[1])
,而k
是使表达式最小化的非负常数:
sum((X[i, 0] - np.dot(np.dot(B[:, [i]].T, drop(B, i)),
np.linalg.solve(cov(drop(B, i), k),
np.delete(X, i, axis=0))) **2
for i in range(27))
drop()
函数定义为lambda X, i: np.delete(X, i, axis=1)
。
可以假设np.cov(B.T, B)
是X
的协方差矩阵,它遵循多元高斯分布。
答案 0 :(得分:4)
目前(对于一组特定的矩阵),我最好的想法是执行以下数值实验:
np.float64
,np.float32
,甚至np.float16
)答案 1 :(得分:2)
建议使用导致浮点累积误差最小的公式。
(AB)C
:(AB)
的每个元素都是A
中每一行与B
中每一列的点积。对于B
中的每一列,找到最大元素与最小元素的比率,然后找到那些每个列比率的最大值。将此称为B_ratio
。A(BC)
:让T = (BC)
产生8000x1矩阵。 A(BC)
的每个元素都是A
中每一行与T
中每一[one]列的点积。对于T
中的每个[one]列,找到max元素与min元素的比率。将此称为T_ratio
。假设A
中值的分布均匀,则无论哪个上面的解决方案都具有较小的绝对比率,数值上的稳定性更高。也就是说,如果fabs(B_ratio) < fabs(T_ratio)
那么(AB)C
会更好。
合理性:将大小相加时会累积错误-较小数字的低位会“丢失”。通过将因素保持在较小的绝对分布范围内,损失单个小术语的贡献的可能性就会降低。
添加IEEE 754浮点数z = x + y
时,可能会出现以下情况之一:
z.exponent == max(x.exponent, y.exponent) && z.mantissa != max(x,y).mantissa
,这意味着尾数之和不带进位。没有引入错误。z.exponent == max(x.exponent, y.exponent)+1
,这意味着尾数加进位。最低的精度损失,导致引入了2^-(z.exponent - MANTISSA_BITS)
的错误。z == max(x, y)
表示x或y增大2 ^ MANTISSA_BITS,导致其他输入的总损耗(甚至低于噪声阈值)。< / li>
为保持数值稳定性,您可以通过以下方式使累积误差最小化:首先对数字进行排序,然后从最小到最大进行累积。这样可以避免上述情况3经常发生,尽管它仍然可能发生。
What Every Computer Scientist Should Know About Floating-Point Arithmetic
答案 2 :(得分:0)
三个矩阵相乘总是不会比两个相乘慢吗?
您实际上只有两个选择:(AB)C
和A(BC)
。从BC = const
开始,您可以拥有形状为T = BC
的常数8000x1
,然后将AT
乘以而不用重新计算T
。
答案 3 :(得分:0)
嗯,我认为不同的乘法顺序在速度上没有区别。计算次数应该相同。 另外,我看不到像其他矩阵计算(例如,通过数组的迭代顺序)那样的缓存的可能改进。
唯一的问题是,如果np.dot(B,C)
确实不会改变,并且您需要多次计算的结果,则可以将它们放在一个额外的矩阵中。