我正在寻找最节省内存的方法来计算复杂numpy ndarray的绝对平方值
arr = np.empty((250000, 150), dtype='complex128') # common size
Run Code Online (Sandbox Code Playgroud)
我还没有找到一个完全可以做到的ufunc np.abs()**2.
由于该大小和类型的数组占用大约半GB,我正在寻找一种主要的内存效率方式.
我也希望它是可移植的,所以理想情况下是ufuncs的一些组合.
到目前为止,我的理解是,这应该是最好的
result = np.abs(arr)
result **= 2
Run Code Online (Sandbox Code Playgroud)
它将不必要地计算(**0.5)**2,但应该**2就地计算.总的来说,峰值内存要求只是原始数组大小+结果数组大小,应该是1.5*原始数组大小,因为结果是真实的.
如果我想摆脱无用的**2电话,我必须做这样的事情
result = arr.real**2
result += arr.imag**2
Run Code Online (Sandbox Code Playgroud)
但如果我没有记错,这意味着我将不得不为分配内存都实部和虚部的计算,因此峰值内存使用量是2.0*原始数组的大小.这些arr.real属性还返回一个非连续的数组(但这个问题不太重要).
有什么我想念的吗?有没有更好的方法来做到这一点?
编辑1:我很抱歉没有说清楚,我不想覆盖arr,所以我不能用它作为出来.
我正在尝试将 csv 转换为 numpy 数组。在 numpy 数组中,我用 NaN 替换了几个元素。然后,我想在 numpy 数组中找到 NaN 元素的索引。代码是:
import pandas as pd
import matplotlib.pyplot as plyt
import numpy as np
filename = 'wether.csv'
df = pd.read_csv(filename,header = None )
list = df.values.tolist()
labels = list[0]
wether_list = list[1:]
year = []
month = []
day = []
max_temp = []
for i in wether_list:
year.append(i[1])
month.append(i[2])
day.append(i[3])
max_temp.append(i[5])
mid = len(max_temp) // 2
temps = np.array(max_temp[mid:])
temps[np.where(np.array(temps) == -99.9)] = np.nan
plyt.plot(temps,marker = '.',color = …Run Code Online (Sandbox Code Playgroud) 如果类型正确,提供输入数组作为numpy中的ufunc的可选输出参数通常是安全的吗?例如,我已经验证以下工作:
>>> import numpy as np
>>> arr = np.array([1.2, 3.4, 4.5])
>>> np.floor(arr, arr)
array([ 1., 3., 4.])
Run Code Online (Sandbox Code Playgroud)
数组类型必须与输出兼容或与输出相同(它是一个浮点数numpy.floor()),否则会发生这种情况:
>>> arr2 = np.array([1, 3, 4], dtype = np.uint8)
>>> np.floor(arr2, arr2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: ufunc 'floor' output (typecode 'e') could not be coerced to provided output parameter (typecode 'B') according to the casting rule ''same_kind''
Run Code Online (Sandbox Code Playgroud)
因此,给定一个正确类型的数组,通常可以安全地应用ufuncs吗?或者是floor()一个例外情况?文档没有说清楚,以下两个线程也没有与问题相关:
编辑:
作为第一顺序猜测,我认为它基于http://docs.scipy.org/doc/numpy/user/c-info.ufunc-tutorial.html上的教程,经常但并不总是安全的.在计算过程中使用输出数组作为中间结果的临时持有者似乎没有任何限制.虽然类似于floor()也ciel() …
我已经阅读了很多"避免与numpy循环".所以,我试过了.我正在使用此代码(简化版).一些辅助数据:
In[1]: import numpy as np
resolution = 1000 # this parameter varies
tim = np.linspace(-np.pi, np.pi, resolution)
prec = np.arange(1, resolution + 1)
prec = 2 * prec - 1
values = np.zeros_like(tim)
Run Code Online (Sandbox Code Playgroud)
我的第一个实现是for循环:
In[2]: for i, ti in enumerate(tim):
values[i] = np.sum(np.sin(prec * ti))
Run Code Online (Sandbox Code Playgroud)
然后,我摆脱了显式for循环,并实现了这一点:
In[3]: values = np.sum(np.sin(tim[:, np.newaxis] * prec), axis=1)
Run Code Online (Sandbox Code Playgroud)
对于小型阵列来说,这个解决方案更快,但是当我扩大规模时,我有这样的时间依赖:

我缺少什么或是正常行为?如果不是,在哪里挖?
编辑:根据评论,这里有一些额外的信息.用IPython中的测量的时间%timeit和%%timeit,在新内核进行每一次运行.我的笔记本电脑是acer aspire v7-482pg(i7,8GB).我正在使用:
运行 Numpy 1.19.2 版,与通过计算已经展平的数组的平均值相比,我在累积数组每个单独轴的平均值方面获得了更好的性能。
shape = (10000,32,32,3)
mat = np.random.random(shape)
Run Code Online (Sandbox Code Playgroud)
# Call this Method A.
%%timeit
mat_means = mat.mean(axis=0).mean(axis=0).mean(axis=0)
Run Code Online (Sandbox Code Playgroud)
14.6 ms ± 167 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
mat_reshaped = mat.reshape(-1,3)
Run Code Online (Sandbox Code Playgroud)
# Call this Method B
%%timeit
mat_means = mat_reshaped.mean(axis=0)
Run Code Online (Sandbox Code Playgroud)
135 ms ± 227 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
这很奇怪,因为多次执行平均值具有与重构阵列上的相同的错误访问模式(可能甚至更糟)。我们也以这种方式进行更多的操作。作为完整性检查,我将数组转换为 FORTRAN 顺序:
mat_reshaped_fortran = mat.reshape(-1,3, order='F')
Run Code Online (Sandbox Code Playgroud)
%%timeit
mat_means = mat_reshaped_fortran.mean(axis=0)
Run Code Online (Sandbox Code Playgroud)
12.2 ms ± 85.9 …
关于此答案,是否存在一种快速方法来计算具有不等数量元素的组的数组的中值?
例如:
data = [1.00, 1.05, 1.30, 1.20, 1.06, 1.54, 1.33, 1.87, 1.67, ... ]
index = [0, 0, 1, 1, 1, 1, 2, 3, 3, ... ]
Run Code Online (Sandbox Code Playgroud)
然后,我想计算数量和每组中位数之间的差(例如,组的中位数0为1.025,则第一个结果为1.00 - 1.025 = -0.025)。因此,对于上面的数组,结果将显示为:
result = [-0.025, 0.025, 0.05, -0.05, -0.19, 0.29, 0.00, 0.10, -0.10, ...]
Run Code Online (Sandbox Code Playgroud)
既然np.median.reduceat还不存在,还有另一种快速的方法来实现这一目标吗?我的数组将包含数百万行,因此速度至关重要!
可以假定索引是连续且有序的(如果不是,则很容易对其进行转换)。
import numpy as np
np.random.seed(0)
rows = 10000
cols = 500
ngroup = 100
# Create random data and groups …Run Code Online (Sandbox Code Playgroud) (版本 1.13+)中有一个positive函数numpy,它似乎什么都不做:
In [1]: import numpy as np
In [2]: A = np.array([0, 1, -1, 1j, -1j, 1+1j, 1-1j, -1+1j, -1-1j, np.inf, -np.inf])
In [3]: A == np.positive(A)
Out[3]:
array([ True, True, True, True, True, True, True, True, True,
True, True])
Run Code Online (Sandbox Code Playgroud)
文档说: Returned array or scalar: `y = +x`
这个函数的用例是什么?
我正在研究cs231n,我很难理解这个索引是如何工作的.鉴于
x = [[0,4,1], [3,2,4]]
dW = np.zeros(5,6)
dout = [[[ 1.19034710e-01 -4.65005990e-01 8.93743168e-01 -9.78047129e-01
-8.88672957e-01 -4.66605091e-01]
[ -1.38617461e-03 -2.64569728e-01 -3.83712733e-01 -2.61360826e-01
8.07072009e-01 -5.47607277e-01]
[ -3.97087458e-01 -4.25187949e-02 2.57931759e-01 7.49565950e-01
1.37707667e+00 1.77392240e+00]]
[[ -1.20692745e+00 -8.28111550e-01 6.53041092e-01 -2.31247762e+00
-1.72370321e+00 2.44308033e+00]
[ -1.45191870e+00 -3.49328154e-01 6.15445782e-01 -2.84190582e-01
4.85997687e-02 4.81590106e-01]
[ -1.14828583e+00 -9.69055406e-01 -1.00773809e+00 3.63553835e-01
-1.28078363e+00 -2.54448436e+00]]]
Run Code Online (Sandbox Code Playgroud)
他们做的操作是
np.add.at(dW, x, dout)
x是二维数组.索引如何在这里工作?我浏览了np.ufunc.at文档,但他们有一个简单的例子,有1d数组和常量:
np.add.at(a, [0, 1, 2, 2], 1)
Run Code Online (Sandbox Code Playgroud) 我想知道是否有更有效/Pythonic 的方法来添加多个 numpy 数组(2D)而不是:
def sum_multiple_arrays(list_of_arrays):
a = np.zeros(shape=list_of_arrays[0].shape) #initialize array of 0s
for array in list_of_arrays:
a += array
return a
Run Code Online (Sandbox Code Playgroud)
Ps:我知道, np.add()但它只适用于 2 个数组。
我试图在两个3D阵列上播放">"的简单操作.一个具有另一个维度(m,1,n)(1,m,n).如果我改变第三维(n)的值,我会天真地期望计算的速度将缩放为n.
然而,当我尝试明确地测量它时,我发现当将n从1增加到2时,计算时间增加约10倍,之后缩放是线性的.
当从n = 1到n = 2时,为什么计算时间会急剧增加?我假设它是numpy中的内存管理工件,但我正在寻找更具体的内容.
代码附在下面,附带结果图.
import numpy as np
import time
import matplotlib.pyplot as plt
def compute_time(n):
x, y = (np.random.uniform(size=(1, 1000, n)),
np.random.uniform(size=(1000, 1, n)))
t = time.time()
x > y
return time.time() - t
a = [
[
n, np.asarray([compute_time(n)
for _ in range(100)]).mean()
]
for n in range(1, 30, 1)
]
a = np.asarray(a)
plt.plot(a[:, 0], a[:, 1])
plt.xlabel('n')
plt.ylabel('time(ms)')
plt.show()
Run Code Online (Sandbox Code Playgroud)
广播操作的时间图
numpy ×10
numpy-ufunc ×10
python ×8
performance ×3
broadcasting ×1
for-loop ×1
in-place ×1
matrix ×1
median ×1
optimization ×1
pandas ×1
python-3.x ×1