复数计算误差随着矩阵大小的增加而增加

Complex number computational error grows as the size of matrix increase

如果我有两个小的复数矩阵,即使我手动执行复数乘法也很好(将复数分解为实部和虚部并分别进行乘法)。

import numpy as np
a_shape = (3,10)
b_shape = (10,3)

# Generating the first complex matrix a
np.random.seed(0)
a_real = np.random.randn(a_shape[0], a_shape[1])
np.random.seed(1)
a_imag = np.random.randn(a_shape[0], a_shape[1])
a = a_real + a_imag*1j

# Generating the second complex matrix b
np.random.seed(2)
b_real = np.random.randn(b_shape[0], b_shape[1])
np.random.seed(3)
b_imag = np.random.randn(b_shape[0], b_shape[1])
b = b_real + b_imag*1j

# 1st approach to do complex multiplication
output1 = np.dot(a,b)
# Manaul complex multiplication
output_real = np.dot(a.real,b.real) - np.dot(a.imag,b.imag)
np.array_equal(output1.real, output_real) # the results are the same

>>> True

但是如果我的矩阵比较大,np.(a,b)和手动相乘得到的结果是不一样的

a_shape = (3,500)
b_shape = (500,3)

# Generating the first complex matrix a
np.random.seed(0)
a_real = np.random.randn(a_shape[0], a_shape[1])
np.random.seed(1)
a_imag = np.random.randn(a_shape[0], a_shape[1])
a = a_real + a_imag*1j

# Generating the second complex matrix b
np.random.seed(2)
b_real = np.random.randn(b_shape[0], b_shape[1])
np.random.seed(3)
b_imag = np.random.randn(b_shape[0], b_shape[1])
b = b_real + b_imag*1j

# 1st approach to do complex multiplication
output1 = np.dot(a,b)
# 2nd approach to do complex multiplication
output_real = np.dot(a.real,b.real) - np.dot(a.imag,b.imag)
np.array_equal(output1.real, output_real)
>>> False

我问这个是因为我需要在 pytorch 中做一些复数乘法。 pytorch 本身不支持复数,所以我需要为真实和图像组件手动完成。

然后结果比使用 np.dot(a,b) 略有偏差 这个问题有什么解决办法吗?

两次计算的差异

output1.real - output_real
>>>array([[-3.55271368e-15, -2.48689958e-14,  1.06581410e-14],
       [-1.06581410e-14, -5.32907052e-15, -7.10542736e-15],
       [ 0.00000000e+00, -2.84217094e-14, -7.10542736e-15]])

你没有说差异有多小,但我怀疑你所看到的与复数无关,而是与浮点运算的性质有关。

特别是浮点加法是不结合的,也就是说我们不一定有

(a + b) + c = a + (b + c)

这将解释您所看到的,因为您正在做的是比较

Sum{ Ra[i]*Rb[i] - Ia[i]*Ib[i]}

Sum{ Ra[i]*Rb[i]} - Sum{ Ia[i]*Ib[i]}

(其中 Ra[i] 是 a[i] 等的实部)

要证明这是问题所在,有一件事是将数字的实部和复数部分限制为十六分之一的整数。有了这样的数字——只要你不添加一个离谱的数字(许多数十亿)——双精度浮点运算将是精确的,所以你应该得到相同的结果。例如,在 C 语言中,您可以通过生成一堆介于 -16 和 16 之间的随机整数,然后将每个整数除以(双精度)数字 16.0 来生成此类数字,以获得 -1 和 1 之间的双精度数字,这是一个整体十六分之一的数目。