假设我有一个形状为(1,2,3,3)
的四维数组:
test = np.array([[[[11,27,33],[45,58,96],[77,85,93]],[[55,27,39],[46,51,62],[73,86,98]]]])
什么是标准化/计算2D子集的z分数的最有效方法?例如,test[0][0]
如下所示:
array([[11, 27, 33],
[45, 58, 96],
[77, 85, 93]])
这里有2个维度,但我想计算两个维度的平均值和标准差,并使用这些值来标准化这两个维度中的每个值。
我可以像这样手动完成:
(test[0][0] - np.mean(test[0][0])) / np.std(test[0][0])
正确地给出了:
array([[-1.61593336, -1.06970236, -0.86486574],
[-0.45519249, -0.01137981, 1.2859188 ],
[ 0.63726949, 0.91038499, 1.18350049]])
然而,这需要我迭代4D阵列的前2个维度,考虑到我的实际数据的大小,这将花费太长时间
我看到scipy
有一个zscore
函数,但一次只能在一维中运行:scipy.stats.zscore(test, axis=3)
并且无法找到标准化的简单实现穿过2D数组
答案 0 :(得分:1)
方法#1:您可以使用np.mean
和np.std
在axis=(2,3)
的多个轴(在本例中为最后两个轴)上使用keepdims=1
和(test - test.mean(axis=(2,3),keepdims=1)) / test.std(axis=(2,3),keepdims=1)
并保持它们的数量与std
相同,以便后面的减法和除法运算可以播放。
因此,矢量化实现将是 -
m = (test - test.mean(axis=(2,3),keepdims=1))
s = np.sqrt((np.abs(m)**2).mean(axis=(2,3),keepdims=1))
out = m/s
方法#2:使用numexpr
定义的替代方法可以重复使用平均值 -
import numexpr as ne
d0,d1 = test.shape[-2:]
m = (test - test.mean(axis=(2,3),keepdims=1))
m1 = m.reshape(-1,d0*d1)
s = np.sqrt(ne.evaluate('sum(abs(m1)**2,1)')/(d0*d1))
out = m/s[:,None,None]
方法#3:对于较大的数据集,您可能希望使用division by s
模块来非常有效地执行这些求和/平均操作 -
1.0/s
根据this post
,我们可以将这些m
替换为vars:
OsType: redhat
OsVersion: '7_2'
tasks:
- debug: 'msg="{{ ami_{{OsType}}_{{ OsVersion }} }}"'
,然后将其与fatal: [localhost]: FAILED! => {
"failed": true,
"msg": "template error while templating string: expected token 'end of print statement', got '{'. String: {{ ami_{{ OsType }}_{{ OsVersion }} }}"
}
相乘,以进一步提升效果。这适用于所有上述三种方法。
答案 1 :(得分:0)
要在numpy中进行规范化,只需进行广播匹配。
def normalize_nchw(inp):
EPS = 1e-6
means = np.mean(inp, axis=(2,3)).expand_dims(-1).expand_dims(-1)
inp -= means
vars = EPS + np.mean(inp*inp, axis=(2,3)).expand_dims(-1).expand_dims(-1)
inp *= (1./np.sqrt(vars))
旁注:如果你是为CNN做这件事,最好的办法是使用批量规范化,这种规范化已经内置到很多框架中。