如何将带有网格和数组的Matlab代码转换为Python代码?
我正试图写一个程序来构造一个矩阵,并对其进行奇异值分解。我正在网格上评估函数ax^2+bx+1。然后,我将如何将带有网格和数组的Matlab代码转换为Python代码?,python,matlab,numpy,Python,Matlab,Numpy,我正试图写一个程序来构造一个矩阵,并对其进行奇异值分解。我正在网格上评估函数ax^2+bx+1。然后,我将a和b组成一个统一的网格。矩阵的行对应于不同的二次系数,而每列对应于计算函数的网格点 matlab代码如下所示: % Collect data x = linspace(-1,1,100); [a,b] = meshgrid(0:0.1:1,0:0.1:1); D=zeros(numel(x),numel(a)); sz = size(D) % Build “Dose” matrix
a
和b
组成一个统一的网格。矩阵的行对应于不同的二次系数,而每列对应于计算函数的网格点
matlab代码如下所示:
% Collect data
x = linspace(-1,1,100);
[a,b] = meshgrid(0:0.1:1,0:0.1:1);
D=zeros(numel(x),numel(a));
sz = size(D)
% Build “Dose” matrix
for i=1:numel(a)
D(:,i) = a(i)*x.^2+b(i)*x+1;
end
% Do the SVD:
[U,S,V]=svd(D,'econ');
D_reconstructed = U*S*V';
plot(diag(S))
scatter3(a(:),b(:),V(:,1))
这是我尝试的解决方案:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-1, 1, 100)
def f(x, a, b):
return a*x*x + b*x + 1
a, b = np.mgrid[0:1:0.1,0:1:0.1]
#a = b = np.arange(0,1,0.01)
D = np.zeros((x.size, a.size))
for i in range(a.size):
D[i] = a[i]*x*x +b[i]*x +1
U, S, V = np.linalg.svd(D)
plt.plot(np.diag(S))
fig = plt.figure()
ax = plt.axes(projection="3d")
ax.scatter(a, b, V[0])
但我总是会遇到广播错误,我不知道如何修复。首先,在MATLAB中,您将分配给
D(:,I)
,但在python中,您将分配给D[I]
。后者相当于D[i,…]
,在您的例子中是D[i,:]
。相反,您似乎需要D[:,i]
其次,在MATLAB中,使用二维数组的线性索引(即a
和b
)将为您提供平坦视图。如果您使用numpy执行此操作,则会得到数组的切片,就像我在D[I]
中提到的那样
通过.ravel
ling(或重塑)您的a
和b
阵列,您可以取消循环并获得所需的2d阵列:
x = np.linspace(-1, 1, 100)[:, None] # inject trailing singleton for broadcasting
a, b = np.mgrid[0:1:0.1, 0:1:0.1]
D = a.ravel() * x**2 + b.ravel() * x + 1
其工作方式是,在我们注入一个尾随单体后,x
具有形状(100,1)
(在MATLAB中,尾随单体是隐含的,在numpy的前导单体中),并且a.ravel()
和b.ravel()
都具有形状(10*10,)
,这与(1,10*10)兼容,使广播成为可能的形状(100,10*10)
。您还可以将对ravel
的调用替换为
a, b = np.mgrid[...].reshape(2, -1)
这是我有时使用的技巧,但是如果你不熟悉这个模式,这就很难理解了
旁注:最好在维度大小不同的情况下使用示例数据,以便注意是否有东西最终被转置。首先,在MATLAB中,您将赋值给D(:,i)
,但在python中,您将赋值给D[i]
。后者相当于D[i,…]
,在您的例子中是D[i,:]
。相反,您似乎需要D[:,i]
其次,在MATLAB中,使用二维数组的线性索引(即a
和b
)将为您提供平坦视图。如果您使用numpy执行此操作,则会得到数组的切片,就像我在D[I]
中提到的那样
通过.ravel
ling(或重塑)您的a
和b
阵列,您可以取消循环并获得所需的2d阵列:
x = np.linspace(-1, 1, 100)[:, None] # inject trailing singleton for broadcasting
a, b = np.mgrid[0:1:0.1, 0:1:0.1]
D = a.ravel() * x**2 + b.ravel() * x + 1
其工作方式是,在我们注入一个尾随单体后,x
具有形状(100,1)
(在MATLAB中,尾随单体是隐含的,在numpy的前导单体中),并且a.ravel()
和b.ravel()
都具有形状(10*10,)
,这与(1,10*10)兼容,使广播成为可能的形状(100,10*10)
。您还可以将对ravel
的调用替换为
a, b = np.mgrid[...].reshape(2, -1)
这是我有时使用的技巧,但是如果你不熟悉这个模式,这就很难理解了
旁注:最好在维度大小不同的情况下使用示例数据,以便您注意到是否有东西最终被转置。不确定您想用什么:对于范围内的i(a.size):D[i]=a[i]*x*x+b[i]*x+1,但您的问题是a和b是10,10,但D是100100,x是100,1.x是100x1向量,而a是10x10矩阵。试试x.shape,a.shape来检查。嗨,Paula,我希望我的D矩阵是一个m x n矩阵,其中a是我拥有的a和b系数的数量,n是我拥有的x点的数量。每行对应一个不同的值a,b,而每列对应一个网格点,在该网格点上计算二次曲线。为什么它在Matlab而不是Python中工作?但我总是收到广播错误,请分享整个错误消息。你看过NumPy文件了吗?这将是一个合乎逻辑的起点,不是吗?不确定你想要做什么:对于范围内的i(a.size):D[i]=a[i]*x*x+b[i]*x+1,但你的问题是a和b是10,10,但D是100100,x是100,1.x是100x1向量,而a是10x10矩阵。试试x.shape,a.shape来检查。嗨,Paula,我希望我的D矩阵是一个m x n矩阵,其中a是我拥有的a和b系数的数量,n是我拥有的x点的数量。每行对应一个不同的值a,b,而每列对应一个网格点,在该网格点上计算二次曲线。为什么它在Matlab而不是Python中工作?但我总是收到广播错误,请分享整个错误消息。你看过NumPy文件了吗?这是一个合乎逻辑的开始,不是吗?谢谢,我不会想到使用ravel
。有一个问题,在matlab和python中,D
数组中的元素似乎略有不同。你知道为什么吗?@pythonraptor原因可能是浮点运算不精确,一个可能的来源是meshgrid/mgrid调用。0.1是出了名的不可精确表示的(参见例如,0.1*3==0.3
不是双精度的),并且可能涉及到两种实现之间不同的优化(例如)。或者,linspace
也有类似的区别。或者,双值的打印可能不同。无论哪种方法,你都会在最新的svd
阶段得到数值上的差异。@pythonraptor哦,是的,还有一件重要的事情:在MATLAB中,线性索引逐列进行,但在numpy中,线性索引逐行进行。这可能意味着您可能必须使用a.T.ravel()
等来获得与MATLAB中相同的D
中的项目顺序。您可以通过为mgrid
中的两个参数使用不同的范围来确保,最好使用不同的大小,以及c