一系列 numpy 操作似乎依赖于 numpy 数组初始化

Series of numpy operations seem to depend on numpy arrays initialization

我正在用 numpy 数组向量化一系列操作。在这样做的过程中,我在不同的代码执行中得到了不同的结果。我正在使用 numpy.random.randn 来获取我需要的形状的 numpy 数组,并测试我的操作是否按照我希望的方式进行。我有时会得到想要的结果,有时却得不到,即使是同一系列的操作。

理论上,第一行big_result应该等于result_1,而第二行等于result_2。有时会发生这种情况。其他时候第一行是正确的,而第二行不是。而其他时候,两者都是错误的。

这是重现问题的代码(我添加了一些我亲手得到的种子,其中有错误发生,有的则没有):

import numpy as np

np.random.seed(2) # First row of big_result corresponds to result_1, the rest is wrong
np.random.seed(3) # First row of big_result corresponds to result_1, the rest is wrong
np.random.seed(4) # Both rows of big_result are ok

# My two vectors
a = np.random.randn(1000, 8)
b = np.random.randn(500, 8)

# Operation vector
c = np.random.randn(3, 6, 8)

# Matrix with both a, b
big_A = np.full((2, 1000, 8), np.nan)
big_A[0, :, :] = a
big_A[1, :500, :] = b

# Broadcasting used to enable the use of c with big_A
big_C = np.broadcast_to(c, (2, 3, 6, 8)).reshape((3, 6, 2, 8))

# First result (for a)
result_1 = np.linalg.norm(a[:, np.newaxis] - c[:, np.newaxis, :], axis=-1)
result_1 = np.min(result_1[np.newaxis], axis=(-1, 1)) # Shape: (1, 1000)

# Second result (for b)
result_2 = np.linalg.norm(b[:, np.newaxis] - c[:, np.newaxis, :], axis=-1)
result_2 = np.min(result_2[np.newaxis], axis=(-1, 1)) # Shape: (1, 500)

# I mask out this operation to avoid meddling of NaN values
arr_with_nan = big_A[np.newaxis] - big_C[:, :, :, np.newaxis]
arr_with_nan = np.ma.array(arr_with_nan, mask=np.isnan(arr_with_nan))

# Result for both a and b 
big_result = np.linalg.norm(arr_with_nan, axis=-1)
big_result = np.min(big_result[np.newaxis], axis=2)
big_result = np.min(big_result, axis=1)[0] # Shape: (2, 1000), where (1,) -> result_1; (2,) -> result_2

一些评论

ab 对应于 axis=1 中维度可能不同的 numpy 数组。这就是为什么我将它们附加到一个大的 numpy 矩阵 big_Anp.nan 中以填充值。另外,我的“操作向量”c 正在广播到形状 (2, 3, 6, 8) 以便它可以用于 big_A 内的 ab .这个广播不允许我立即操作big_Cbig_A,所以我不得不将big_C重塑为(3, 6, 2, 8)

我猜我正在处理一个舍入错误。我试过用 .astype(np.float32 or np.float64) 投射所有内容,但它不起作用。如果我随后执行我的代码,它就会失败。如何确保我的代码独立于 ab 中的初始值工作?

编辑:我忘了添加我的确切问题。

broadcast_to 后不要重塑。如果必须转置,或使用 big_C[:,:,None,:] 制作 (2,3,1,6,8)