Как получить Mean & Std из нескольких сохраненных массивов с помощью элементарной операции - PullRequest
0 голосов
/ 03 января 2019

У меня есть папка с 1000 сжатых файлов (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)

1 Ответ

0 голосов
/ 03 января 2019

Во-первых, если у вас есть (ssh) доступ к машине с большим объемом памяти, это проще всего.Может быть, вы даже можете обойтись без одного.885 * 854 * (1000 симуляций) * (4 байта на float32) = 2,8 ГБ, поэтому, если вы выполняете 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))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...