如何使用逐元素操作获取多个 numpy 保存数组的均值和标准差
How to get Mean & Std of multiple numpy saved arrays using element-wise operation
我有一个包含 1000 个代表数据模拟结果的 numpy 压缩文件 (npz) 的文件夹。每个文件有两个数组 a
和 b
,具有相同的维度、形状和数据类型。作为最终输出,我想要的是 a
、b
和 c
(我在下面的示例中创建)的逐元素均值和标准差数组,同时考虑到所有模拟即:
mean_a = np.mean(a1,a2,a3,...a1000)
std_a = np.std(a1,a2,a3...a1000)
等
我已经设法获得了平均值,但没有使用直接的逐元素操作。我最挣扎的是得了性病。我试图将所有数组附加到列表中,但我遇到了内存错误的问题。知道我该如何进行吗?看看下面我到目前为止所取得的成就。提前致谢!!
import glob
import numpy as np
import os
simulation_runs = 10
simulation_range = np.arange(simulation_runs)
npFiles = [npFile for npFile in glob.iglob(os.path.join(outDir, "sc0*.npz"))]
a_accum = np.empty([885, 854], dtype=np.float32)
b_accum = np.empty([885, 854], dtype=np.float32)
c_accum = np.empty([885, 854], dtype=np.float32)
for run, i in enumerate(npFiles):
npData = np.load(i)
a = npData['scc']
b = npData['bcc']
c = a+b
a_accum = a + a_accum
b_accum = b + b_accum
c_accum = c + b_accum
aMean = a_accum/len(simulation_range)
bMean= b_accum/len(simulation_range)
cMean = c_accum/len(simulation_range)
首先,如果您可以 (ssh) 访问具有更多内存的机器,那是最简单的。也许你甚至可以没有一个。 885*854*(1000 次模拟)*(每个 float32 4 字节)= 2.8 GiB,所以如果你分别执行 a、b 和 c,你应该在一台合理的机器上有足够的内存。在那种情况下,只需将它们放入一个数组中,然后使用 np.mean 和 np.std:
a = np.zeros((1000,885,854), dtype=np.float32)
for run, i in enumerate(npFiles):
a[i]=np.load(run)['scc']
amean = a.mean(axis=0)
astd = a.std(axis=0)
对于 b 和 c 也类似。
否则,最优雅的选择是以易于延迟加载的格式保存数据。 dask
是专门为此设计的,但可能需要一些时间来学习(尽管 运行 很长一段时间可能是值得的)。您还可以将它存储在 netcat 文件中,并使用 xarray
作为 dask
的一种前端,也许这样甚至更方便。
如果你只需要平均值,标准差,你可以手动完成。 std 的公式是
std = sqrt(mean(abs(x - x.mean())**2))
既然你已经有了办法,那么这个过程将与你已经做过的非常相似:(未经测试)
import numpy as np
import os
simulation_runs = 10
simulation_range = np.arange(simulation_runs)
npFiles = [npFile for npFile in glob.iglob(os.path.join(outDir, "sc0*.npz"))]
a_accum = np.empty([885, 854], dtype=np.float32)
b_accum = np.empty([885, 854], dtype=np.float32)
c_accum = np.empty([885, 854], dtype=np.float32)
for run, i in enumerate(npFiles):
npData = np.load(i)
a = npData['scc']
b = npData['bcc']
c = a+b
a_accum = a + a_accum
b_accum = b + b_accum
c_accum = c + b_accum
aMean = a_accum/len(simulation_range)
bMean= b_accum/len(simulation_range)
cMean = c_accum/len(simulation_range)
a_sumsq = np.empty([885, 854], dtype=np.float32)
b_sumsq = np.empty([885, 854], dtype=np.float32)
c_sumsq = np.empty([885, 854], dtype=np.float32)
for run, i in enumerate(npFiles):
npData = np.load(i)
a = npData['scc']
b = npData['bcc']
c = a+b
a_sumsq += (a-aMean)**2
b_sumsq += (b-bMean)**2
c_sumsq += (c-cMean)**2
a_std = np.sqrt(a_sumsq/(len(npFiles)-1)) # The -1 is to get an unbiased estimator
b_std = np.sqrt(b_sumsq/(len(npFiles)-1))
c_std = np.sqrt(c_sumsq/(len(npFiles)-1))
我有一个包含 1000 个代表数据模拟结果的 numpy 压缩文件 (npz) 的文件夹。每个文件有两个数组 a
和 b
,具有相同的维度、形状和数据类型。作为最终输出,我想要的是 a
、b
和 c
(我在下面的示例中创建)的逐元素均值和标准差数组,同时考虑到所有模拟即:
mean_a = np.mean(a1,a2,a3,...a1000)
std_a = np.std(a1,a2,a3...a1000)
等
我已经设法获得了平均值,但没有使用直接的逐元素操作。我最挣扎的是得了性病。我试图将所有数组附加到列表中,但我遇到了内存错误的问题。知道我该如何进行吗?看看下面我到目前为止所取得的成就。提前致谢!!
import glob
import numpy as np
import os
simulation_runs = 10
simulation_range = np.arange(simulation_runs)
npFiles = [npFile for npFile in glob.iglob(os.path.join(outDir, "sc0*.npz"))]
a_accum = np.empty([885, 854], dtype=np.float32)
b_accum = np.empty([885, 854], dtype=np.float32)
c_accum = np.empty([885, 854], dtype=np.float32)
for run, i in enumerate(npFiles):
npData = np.load(i)
a = npData['scc']
b = npData['bcc']
c = a+b
a_accum = a + a_accum
b_accum = b + b_accum
c_accum = c + b_accum
aMean = a_accum/len(simulation_range)
bMean= b_accum/len(simulation_range)
cMean = c_accum/len(simulation_range)
首先,如果您可以 (ssh) 访问具有更多内存的机器,那是最简单的。也许你甚至可以没有一个。 885*854*(1000 次模拟)*(每个 float32 4 字节)= 2.8 GiB,所以如果你分别执行 a、b 和 c,你应该在一台合理的机器上有足够的内存。在那种情况下,只需将它们放入一个数组中,然后使用 np.mean 和 np.std:
a = np.zeros((1000,885,854), dtype=np.float32)
for run, i in enumerate(npFiles):
a[i]=np.load(run)['scc']
amean = a.mean(axis=0)
astd = a.std(axis=0)
对于 b 和 c 也类似。
否则,最优雅的选择是以易于延迟加载的格式保存数据。 dask
是专门为此设计的,但可能需要一些时间来学习(尽管 运行 很长一段时间可能是值得的)。您还可以将它存储在 netcat 文件中,并使用 xarray
作为 dask
的一种前端,也许这样甚至更方便。
如果你只需要平均值,标准差,你可以手动完成。 std 的公式是
std = sqrt(mean(abs(x - x.mean())**2))
既然你已经有了办法,那么这个过程将与你已经做过的非常相似:(未经测试)
import numpy as np
import os
simulation_runs = 10
simulation_range = np.arange(simulation_runs)
npFiles = [npFile for npFile in glob.iglob(os.path.join(outDir, "sc0*.npz"))]
a_accum = np.empty([885, 854], dtype=np.float32)
b_accum = np.empty([885, 854], dtype=np.float32)
c_accum = np.empty([885, 854], dtype=np.float32)
for run, i in enumerate(npFiles):
npData = np.load(i)
a = npData['scc']
b = npData['bcc']
c = a+b
a_accum = a + a_accum
b_accum = b + b_accum
c_accum = c + b_accum
aMean = a_accum/len(simulation_range)
bMean= b_accum/len(simulation_range)
cMean = c_accum/len(simulation_range)
a_sumsq = np.empty([885, 854], dtype=np.float32)
b_sumsq = np.empty([885, 854], dtype=np.float32)
c_sumsq = np.empty([885, 854], dtype=np.float32)
for run, i in enumerate(npFiles):
npData = np.load(i)
a = npData['scc']
b = npData['bcc']
c = a+b
a_sumsq += (a-aMean)**2
b_sumsq += (b-bMean)**2
c_sumsq += (c-cMean)**2
a_std = np.sqrt(a_sumsq/(len(npFiles)-1)) # The -1 is to get an unbiased estimator
b_std = np.sqrt(b_sumsq/(len(npFiles)-1))
c_std = np.sqrt(c_sumsq/(len(npFiles)-1))