问题 我想从我的主管的未发表的论文中实现一个算法,作为其中的一部分,我需要使用本文中给出的一些规则来构造协方差矩阵C.我来自Matlab,想借此机会最终学习Python,因此我的问题是:我如何以最有效(快速)的方式在Python中做到这一点(包括numpy,scipy)?
子问题1:
还有更好的方法吗?
子问题2
我相当确信子问题1是不容易的,但我不知道子问题2.我可能也应该说我处理的矩阵可能是2 * 10 ^ 4 x 2 * 10 ^ 4.
谢谢!
修改 我不想给出实际的协方差矩阵,但是由于人们想要一个例子,我们想要构建一个称为“布朗桥”的随机过程的协方差矩阵。它的结构由:
给出cov(Xs,Xt)= min {s,t} - st
让我们说 s,t∈{1,...,100} 。你会如何建造它?
答案 0 :(得分:9)
首先,对于未来可能会遇到此问题的其他人:如果您确实有数据且想要估计协方差矩阵,正如几个人所指出的那样,请使用np.cov
或类似的东西。
但是,您的问题是如何在给定一些预定义规则的情况下构建大型矩阵。为了澄清评论中的一些混淆:你的问题似乎不是关于估计协方差矩阵,而是关于指定一个。换句话说,如果给定一些预先定义的规则,你就会问如何构建一个大型数组。
哪种方式最有效取决于您正在做的细节。在这种情况下,大多数性能技巧都将涉及在您预先形成的计算中利用对称性。 (例如,一行是否相同?)
如果不确切知道自己在做什么,很难说出具体内容。因此,我将重点关注如何做这类事情。 (注意:我刚注意到你的编辑。我稍后会包含一个布朗桥的例子......)
最基本的情况是输出数组中的常量行或列。使用切片语法创建数组并将值赋值给列或行很容易:
import numpy as np
num_vars = 10**4
cov = np.zeros((num_vars, num_vars), dtype=float)
设置整个列/行:
# Third column will be all 9's
cov[:,2] = 9
# Second row will be all 1's (will overwrite the 9 in col3)
cov[1,:] = 1
您还可以将数组分配给列/行:
# 5th row will have random values
cov[4,:] = np.random.random(num_vars)
# 6th row will have a simple geometric sequence
cov[5,:] = np.arange(num_vars)**2
在许多情况下,(但可能不是这个确切的情况),您想要从现有阵列构建输出。您可以使用vstack
/ hstack
/ column_stack
/ tile
以及许多其他类似的功能。
一个很好的例子是,如果我们为多项式的线性反演设置矩阵:
import numpy as np
num = 10
x = np.random.random(num) # Observation locations
# "Green's functions" for a second-order polynomial
# at our observed locations
A = np.column_stack([x**i for i in range(3)])
但是,这将构建几个临时数组(在本例中为三个)。如果我们使用10000维多项式进行10 ^ 6次观测,则上述方法将使用太多RAM。因此,您可以改为迭代列:
ndim = 2
A = np.zeros((x.size, ndim + 1), dtype=float)
for j in range(ndim + 1):
A[:,j] = x**j
在大多数情况下,不要担心临时阵列。基于colum_stack
的示例是正确的方法,除非您使用相对较大的数组。
如果没有更多信息,我们就无法利用任何形式的对称性。最通用的方法是迭代。通常,您会想要避免这种方法,但有时它是不可避免的(特别是如果计算取决于以前的值)。
速度方面,这与嵌套for循环相同,但使用np.ndindex
而不是多个for循环更容易(特别是对于> 2D数组):
import numpy as np
num_vars = 10**4
cov = np.zeros((num_vars, num_vars), dtype=float)
for i, j in np.ndindex(cov.shape):
# Logic presumably in some function...
cov[i, j] = calculate_value(i, j)
如果情况很多,您可以对基于索引的计算进行矢量化。换句话说,直接在输出索引的数组上操作。
我们说我们的代码看起来像:
import numpy as np
cov = np.zeros((10, 10)), dtype=float)
for i, j in np.ndindex(cov.shape):
cov[i,j] = i*j - i
我们可以用以下内容代替:
i, j = np.mgrid[:10, :10]
cov = i*j - i
作为另一个例子,让我们建立一个100 x 100倒立锥体#34;值:
# The complex numbers in "mgrid" give the number of increments
# mgrid[min:max:num*1j, min:max:num*1j] is similar to
# meshgrid(linspace(min, max, num), linspace(min, max, num))
y, x = np.mgrid[-5:5:100j, -5:5:100j]
# Our "inverted cone" is just the distance from 0
r = np.hypot(x, y)
这是一个很容易被矢量化的好例子。如果我正确地阅读您的示例,您需要类似的内容:
import numpy as np
st = np.mgrid[1:101, 1:101]
s, t = st
cov = st.min(axis=0) - s * t
总的来说,我只涉及了一些一般模式。但是,希望这能让你指出正确的方向。