Arrays Python 3.7:使用Numpy网格和数组对二维高斯方程进行建模,而无需迭代每个点

Arrays Python 3.7:使用Numpy网格和数组对二维高斯方程进行建模,而无需迭代每个点,arrays,python-3.x,numpy,matrix,Arrays,Python 3.x,Numpy,Matrix,我目前正在尝试编写自己的2D高斯函数作为编码练习,并能够创建以下脚本: import numpy as np import matplotlib.pyplot as plt def Gaussian2D_v1(coords=None, # x and y coordinates for each image. amplitude=1, # Highest intensity in image. xo=0, # x-c

我目前正在尝试编写自己的2D高斯函数作为编码练习,并能够创建以下脚本:

import numpy as np
import matplotlib.pyplot as plt

def Gaussian2D_v1(coords=None,  # x and y coordinates for each image.
                  amplitude=1,  # Highest intensity in image.
                  xo=0,  # x-coordinate of peak centre.
                  yo=0,  # y-coordinate of peak centre.
                  sigma_x=1,  # Standard deviation in x.
                  sigma_y=1,  # Standard deviation in y.
                  rho=0,  # Correlation coefficient.
                  offset=0):  # Offset from zero (background radiation).
    x, y = coords

    xo = float(xo)
    yo = float(yo)

    # Create covariance matrix
    mat_cov = [[sigma_x**2, rho * sigma_x * sigma_y],
               [rho * sigma_x * sigma_y, sigma_y**2]]
    mat_cov = np.asarray(mat_cov)
    # Find its inverse
    mat_cov_inv = np.linalg.inv(mat_cov)

    G_array = []
    # Calculate pixel by pixel
    # Iterate through row last
    for i in range(0, np.shape(y)[0]):
        # Iterate through column first
        for j in range(0, np.shape(x)[1]):
            mat_coords = np.asarray([[x[i, j]-xo],
                                     [y[i, j]-xo]])
            G = (amplitude * np.exp(-0.5*np.matmul(np.matmul(mat_coords.T,
                                                             mat_cov_inv),
                                                   mat_coords)) + offset)
            G_array.append(G)

    G_array = np.asarray(G_array)
    G_array = G_array.reshape(64, 64)
    return G_array.ravel()


coords = np.meshgrid(np.arange(0, 64), np.arange(0, 64))
model_1 = Gaussian2D_v1(coords,
                        amplitude=20,
                        xo=32,
                        yo=32,
                        sigma_x=6,
                        sigma_y=3,
                        rho=0.8,
                        offset=20).reshape(64, 64)

plt.figure(figsize=(5, 5)).add_axes([0,
                                     0,
                                     1,
                                     1])
plt.contourf(model_1)
代码可以正常工作,但正如您所看到的,我现在一次迭代网格中的一个点,并将每个点添加到一个列表中,然后将其转换为数组并重新成形,以获得二维高斯分布

<>如何使用嵌套的“OF”循环修改脚本放弃,程序是否考虑整个网格计算矩阵?这种方法可行吗


谢谢

当然有一个解决方案,numpy是关于数组操作和代码矢量化的
np.matmul
可以采用两个以上维度的参数,并仅在最后两个轴上应用矩阵乘法(此计算与其他轴并行)。然而,确保正确的轴顺序可能会变得棘手

以下是您编辑的代码:

import numpy as np
import matplotlib.pyplot as plt

def Gaussian2D_v1(coords,  # x and y coordinates for each image.
                  amplitude=1,  # Highest intensity in image.
                  xo=0,  # x-coordinate of peak centre.
                  yo=0,  # y-coordinate of peak centre.
                  sigma_x=1,  # Standard deviation in x.
                  sigma_y=1,  # Standard deviation in y.
                  rho=0,  # Correlation coefficient.
                  offset=0):  # Offset from zero (background radiation).
    x, y = coords

    xo = float(xo)
    yo = float(yo)

    # Create covariance matrix
    mat_cov = [[sigma_x**2, rho * sigma_x * sigma_y],
               [rho * sigma_x * sigma_y, sigma_y**2]]
    mat_cov = np.asarray(mat_cov)
    # Find its inverse
    mat_cov_inv = np.linalg.inv(mat_cov)

    # PB We stack the coordinates along the last axis
    mat_coords = np.stack((x - xo, y - yo), axis=-1)

    G = amplitude * np.exp(-0.5*np.matmul(np.matmul(mat_coords[:, :, np.newaxis, :],
                                                    mat_cov_inv),
                                          mat_coords[..., np.newaxis])) + offset
    return G.squeeze()



coords = np.meshgrid(np.arange(0, 64), np.arange(0, 64))
model_1 = Gaussian2D_v1(coords,
                        amplitude=20,
                        xo=32,
                        yo=32,
                        sigma_x=6,
                        sigma_y=3,
                        rho=0.8,
                        offset=20)
plt.figure(figsize=(5, 5)).add_axes([0, 0, 1, 1])
plt.contourf(model_1)
方程是exp(-0.5*(X-µ)'Cinv(X-µ)),其中X是坐标矩阵,µ是平均值(x0,y0),Cinv是逆协方差矩阵(和'是转置)。在代码中,我将两个网格堆叠到一个新矩阵中,这样:
mat_-coords
的形状为(Ny,Nx,2)。在第一个
np.matmul
调用中,我添加了一个新的轴,使形状如下:(Ny,Nx,1,2)*(2,2)=(Ny,Nx,1,2)。如您所见,矩阵乘法在最后两个轴上进行,在另一个轴上并行。然后,我添加一个新的轴,以便:(Ny,Nx,1,2)*(Ny,Nx,2,1)=(Ny,Nx,1,1)。
np.squence()
调用返回一个没有最后两个单体轴的版本。

非常感谢您的回复!我刚刚玩了一下代码,它运行得很好。然而,我对np.stack、np.matmul和np.squence的理解仍然很差。如果我理解正确的话,np.stack将x和y网格放在彼此的顶部,以创建64 x 64组坐标对。当您使用np.newaxis()时,您是否在处理64 x 64网格中坐标对的布局(行向量格式和列向量格式)?最后,这是否意味着np.matmul只处理最后两个轴上的二维操作?谢谢您对np.stack()的理解很好!使用np.newaxis在我们的例子中确实起到了某种转置的作用,通过在好位置添加一个长度为1的轴a,使得最后2个轴的矩阵是行或列。是的,np.matmul只作用于最后两个轴,用更高维数组调用它与在更高维上迭代并重新叠加结果是一样的(就像您之前所做的那样)。感谢您的快速响应!我仍然发现
np.newaxis
函数的实现很难可视化。假设我们放大64 x 64阵列中的一个点。如果我们使用
mat_-coords[:,:,np.newaxis,:]
,那么可以将这两个值分组为
[1,2]
(行向量),而使用
mat_-coords[:,:,:,np.newaxis]
,它会变成
[1],[2]
(列向量)吗?我希望很快收到你的回音!就我所理解的你的例子而言,是的!小补丁,第一种情况,
mat_-coords[i,j,np.newaxis,:]
宁愿是
[[1,2]
,一个(1,2)形状。(另外,据你自己所知,
np.newaxis
是它的一个明确版本,但它的计算结果是
None
,因此
mat_coords[i,j,None,:]
具有完全相同的效果,只是不太清楚)。这太好了,谢谢你用如此平易近人的术语向我解释它,以及演示如何将
None
用于数组操作。我真的很感谢你花了这么多时间。