我的数据集是一个Numpy数组,维度为(N, W, H, C),其中N是图像数量,H和W分别是高度和宽度,C是通道数。
我知道有很多工具可用,但我希望仅使用Numpy来标准化这些图像。
我的计划是计算整个数据集中每个通道的均值和标准差,然后减去均值并除以标准差。
假设数据集中有两张图像,且这两张图像的第一个通道看起来像这样:
x=array([[[3., 4.], [5., 6.]], [[1., 2.], [3., 4.]]])
计算均值:
numpy.mean(x[:,:,:,0])= 3.5
计算标准差:
numpy.std(x[:,:,:,0])= 1.5
标准化第一个通道:
x[:,:,:,0] = (x[:,:,:,0] - 3.5) / 1.5
这是正确的吗?
谢谢!
回答:
看起来不错,但NumPy有一些功能可以让它变得更简洁。我假设你想单独标准化每个通道。
首先,请注意x
有一个mean
方法,所以我们可以写x[..., 0].mean()
而不是np.mean(x[:, :, :, 0])
。此外,mean
方法接受关键字参数axis
,我们可以这样使用:
means = x.mean(axis=(0, 1, 2)) # 在N,H,W轴上取均值means.shape # => 将会计算为(C,)
然后我们可以从整个数据集中减去均值,如下所示:
centered = x - x.mean(axis=(0,1,2), keepdims=True)
请注意,这里我们必须使用keepdims
。
还有一个x.std
方法,工作方式相同,所以我们可以在一行内完成整个标准化过程:
z = (x - x.mean(axis=(0,1,2), keepdims=True)) / x.std(axis=(0,1,2), keepdims=True)
请查看numpy.ndarray.mean和np.ndarray.std的文档以获取更多信息。np.ndarray.method
方法是你调用x.method
时使用的,而不是使用np.method(x)
。
编辑:后来我了解到,当然还有一个scipy.stats.zscore
。我不确定这是否是沿每个通道计算z分数的更可读的方式,但有些人可能更喜欢它:
z = zscore(x.reshape(-1, 3)).reshape(x.shape)
Scipy函数只能在一个轴上操作,所以我们必须先重塑为NHW x C
矩阵,然后再重塑回来。