移位值 np.apply_along_axis returns 不一致的结果

Shifting values with np.apply_along_axis returns inconsistent results

TL;DR: np.apply_along_axis 适用于形状为 (1561, 338) 的特定数组,它是另一个形状为 (351225, 338) 的数组的子集,但它失败了。

我正在尝试应用以下功能:

def add_min(a):
    return a + abs(a.min()) if a.min() < 0 else a

x_train 的形状为 (1561, 15, 15, 338) (n * height * width * channels) 并且我需要将所有值都转换为正数才能记录规范化我的数据。出于显而易见的原因,我想按频道执行此操作。

现在,如果我重塑 x_train:x_train = x_train.reshape(-1, 338) 并获得形状 (351225, 338) 我应该能够执行:

x_train = np.apply_along_axis(add_min, 0, x_train)

然而...

之前:

x_train.min()
>> -2147483648

之后:

x_train.min()
>> -2147370103

换句话说,它不起作用。另一方面,如果我只保留中心像素:

# Keep the center value of axes (1, 2)
x_train = x_train[:, x_train.shape[1]//2, x_train.shape[2]//2, :]
x_train.shape
>> (1561, 338)

x_train.min()
>> -32768  # strange coincidence that this location in the image has a much smaller value range 

x_train = np.apply_along_axis(add_min, 0, x_train)
x_train.min()
>> 0

我认为这与较大的负值有关,因为如果我 select 在 2 个中心轴(即 1 和 8)而不是中间 (7, 7) 中的随机索引,我再次分别在 np.apply_along_axis 之前和之后获得 -2147483648 和 -2147369934 的 x_train.min()

那我做错了什么?有没有更好的方法可以实现我的目标?

如果问题是“随机的”,int32 上的溢出是一个很好的猜测。但是使用 apply_along_axis 可能会使诊断问题变得更加困难,因为它将您的函数包装在一个(晦涩的)迭代中。使用整个数组计算来诊断事物应该更容易。

制作一个混合了 min 个值的适度数组:

In [77]: A = np.random.randint(-50,1000,(4,8))
In [78]: A
Out[78]: 
array([[151, 531, 765, 379,  89, 499, 818, 848],
       [873, -12, -45, 900, 416, 838, 603, 849],
       [540,   0,   1, 589, 297, 566, 688, 556],
       [ 53, 170, 461, -16,  -6, 480, 321, 392]])

你的函数:

In [79]: np.apply_along_axis(add_min, 0, A)
Out[79]: 
array([[151, 543, 810, 395,  95, 499, 818, 848],
       [873,   0,   0, 916, 422, 838, 603, 849],
       [540,  12,  46, 605, 303, 566, 688, 556],
       [ 53, 182, 506,   0,   0, 480, 321, 392]])

让我们创建一个等效的全数组。首先找到规格为axismin

In [80]: am = np.min(A, axis=0, keepdims=True)
In [81]: am
Out[81]: array([[ 53, -12, -45, -16,  -6, 480, 321, 392]])

现在创建一个模仿您的函数的移位数组(没有仅适用于标量的 if):

In [82]: shift=np.abs(am)
In [83]: shift[am>=0]=0
In [84]: shift
Out[84]: array([[ 0, 12, 45, 16,  6,  0,  0,  0]])
In [85]: A+shift
Out[85]: 
array([[151, 543, 810, 395,  95, 499, 818, 848],
       [873,   0,   0, 916, 422, 838, 603, 849],
       [540,  12,  46, 605, 303, 566, 688, 556],
       [ 53, 182, 506,   0,   0, 480, 321, 392]])

还有其他方法可以实现这种转变,但适用相同的基本思想,使用 am<0 确定哪些列得到转变。

这样也会更快。