如何使用numpy或scipy优化非常大的数组构造

时间:2019-06-14 08:16:15

标签: python numpy optimization scipy large-data

我正在使用python 64位处理非常大的数据集,需要一些帮助来优化我的插值代码。

我习惯于使用numpy来避免循环,但是这里有2个循环,我找不到避免的方法。

主要问题还在于,当我使用numpy时,我需要计算的数组大小会导致内存错误,因此我切换到了scipy稀疏数组,该方法可以工作,但需要太多时间来计算两个左循环...

我尝试使用numpy.fromfunction迭代地构建矩阵,但由于数组太大而无法运行。

我已经阅读了很多有关构建大型阵列的文章,但是与我要构建的阵列相比,被询问的阵列过于简单,因此解决方案在这里不起作用。

我无法减小数据集的大小,因为它是我已经用10x10的图块平铺的点云。

这是我的插值代码:

z_int = ss.dok_matrix((x_int.shape))

n,p = x_obs.shape
m = y_obs.shape[0]
a1 = ss.coo_matrix( (n, 3), dtype=np.int64 )
a2 = ss.coo_matrix( (3, 3), dtype=np.int64 )
a3 = ss.dok_matrix( (n, m))
a4 = ss.coo_matrix( (3, n), dtype=np.int64)

b = ss.vstack((z_obs, ss.coo_matrix( (3, 1), dtype=np.int64 ))).tocoo()

a1 = ss.hstack((ss.coo_matrix(np.ones((n,p))), ss.coo_matrix(x_obs), ss.coo_matrix(y_obs)))

shape_a3 = a3.shape[0]

for l in np.arange(0, shape_a3):
    for c in np.arange(0, shape_a3) :
        if l == c:
            a3[l, c] = rho
        else:
            a3[l, c] = phi(x_obs[l] - x_obs[c], y_obs[l] - y_obs[c])


a4 = a1.transpose()

a12 = ss.vstack((a1, a2))
a34 = ss.vstack((a3, a4))
a = ss.hstack((a12, a34)).tocoo()


x = spsolve(a, b)


for i in np.arange(0, z_int.shape[0]):
    for j in np.arange(0, z_int.shape[0]):
        z_int[i, j] = x[0] + x[1] * x_int[i, j] + x[2] * y_int[i, j] + np.sum(x[3:] * phi(x_int[i, j] - x_obs, y_int[i, j] - y_obs).T)


return z_int.todense()

其中dist()是一个计算距离的函数,而phi是以下内容:

return dist(dx, dy) ** 2 * np.log(dist(dx, dy))

我需要使代码运行得更快,并且我知道它可能写得很差,但是我想学习如何编写更优化的东西来提高我的编码技能。

1 个答案:

答案 0 :(得分:0)

该代码很难遵循,并且可以理解为很慢。稀疏矩阵上的迭代甚至比密集阵列上的迭代还要慢。我几乎希望您从使用密集数组的小型工作示例开始,然后再担心使其不适用于大型案例。我不会尝试全面修复或加快速度,只是会四处乱窜。

第一个a1创建对您没有任何作用(浪费时间除外)。 Python不是一种编译语言,您可以在一开始就定义变量的类型。第二次分配后的a1是一个稀疏矩阵,因为这是hstack创建的,而不是因为先前的coo分配。

a1 = ss.coo_matrix( (n, 3), dtype=np.int64 )
...
a1 = ss.hstack((ss.coo_matrix(np.ones((n,p))), ss.coo_matrix(x_obs), ss.coo_matrix(y_obs)))

dokzint初始化为a3矩阵是正确的,因为您需要重复填写值。但是我喜欢看到这种初始化更接近循环,而不是回到顶部。我本可以使用lil而不是dok,但是我不确定这是否更快。

for l in np.arange(0, shape_a3):
    for c in np.arange(0, shape_a3) :
        if l == c:
            a3[l, c] = rho
        else:
            a3[l, c] = phi(x_obs[l] - x_obs[c], y_obs[l] - y_obs[c])

l==c测试确定主对角线。有几种制作对角矩阵的方法。但是好像您正在设置a3的所有元素。如果是这样,为什么要使用较慢的稀疏方法?

什么是phi,它需要标量输入吗? x_obs[:,None]-x_obs应该直接给出(n,n)数组。

spsolve产生什么? x,稀疏或密集。通过在z_int循环中使用,它看起来像一维密集阵列。似乎您正在设置z_int的所有值。

如果phi采用(n,n)个数组,我认为

x[0] + x[1] * x_int[i, j] + x[2] * y_int[i, j] + np.sum(x[3:] * phi(x_int[i, j] - x_obs, y_int[i, j] - y_obs).T)

x[0] + x[1] * x_int + x[2] * y_int +  np.sum(x[3:]) * phi(x_int-x_obs, y_int-y_obs).T)