Python 一系列numpy操作似乎依赖于numpy阵列初始化

Python 一系列numpy操作似乎依赖于numpy阵列初始化,python,numpy,array-broadcasting,Python,Numpy,Array Broadcasting,我正在用numpy数组对一系列操作进行矢量化。通过这样做,我在不同的代码执行中得到了不同的结果。我正在使用numpy.random.randn获取所需形状的numpy数组,并测试我的操作是否按照我的要求执行。我有时会得到想要的结果,有时却得不到,即使是同一系列的操作 理论上,big_result的第一行应等于result_1,而第二行应等于result_2。这种情况有时会发生。其他时候,第一行是正确的,而第二行不是。其他时候,两者都是错误的 这是重现问题的代码(我添加了一些手动获得的种子,其中发

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

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

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

一些评论
a
b
对应于小数组,其在
轴=1中的尺寸可能会有所不同。这就是为什么我要用
np.nan
将它们添加到一个大的numpy矩阵
big_a
,以填充值。另外,我的“操作向量”
c
正在广播到形状
(2,3,6,8)
,以便它可以用于
a
b
内部
大a
。这个广播不允许我立即操作
big_C
big_A
,所以我不得不将
big_C
重新调整为
(3,6,2,8)

我猜我正在处理一个舍入错误。我尝试过使用
.astype(np.float32或np.float64)
强制转换所有内容,但它不起作用。如果我随后执行代码,它将失败。如何确保我的代码独立于
a
b
中的初始值工作


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

广播到
后不要重塑。如果必须转置,或者使用
big_C[:,:,None,:]
来生成一个(2,3,1,6,8)

当试图使这样的代码正常工作时,我更喜欢使用小的定义数组,例如
np.arange(24)。重塑(2,3,4)
而不是
随机的
数组。然后,我可以显示整个阵列,并更容易地检查错误。大阵列很适合进行定时测试和检查内存错误;它们不适合比较可能具有较小浮点差异的方法。请不要在
广播到
重塑
。如果你必须转置,或者使用
c[:,:,None,:]
来做一个(3,6,1,8)@hpaulj按照你的建议,我删除了
广播后重塑
并将
大c[:,:,:,np.newaxis]
改为
大c[,:,np.newaxis,:]
,这迫使我将
大a[np.newaxis]
改为
[:,np.newaxis,:,np.newaxis]
。这解决了问题。我做了一个1000次迭代的for循环,它们都测试了
True
比较
大的结果
行与
结果1
结果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