numpy中数组表示法的数组不清楚



我正在了解计算(和绘制(Julia集的矢量化方法。在网上,我发现了以下代码(注释主要是我的,基于我对代码背后思想的不断理解(:

import numpy as np
import matplotlib.pyplot as plt
c = -0.74543+0.11301j                                           # Example value for this picture (Julia set)
n = 512                                                         # Maximum number of iterations
x = np.linspace(-1.5, 1.5, 2000).reshape((1, 2000))             # 1 row, 2000 columns
y = np.linspace(-1.2, 1.2, 1600).reshape((1600, 1))             # 1600 rows, 1 column
z = x + 1j*y                                                    # z is an array with 1600 * 2000 complex entries
c = np.full(z.shape, c)             # c is a complex number matrix to be added for the iteration
diverge = np.zeros(z.shape)         # 1600 * 2000 zeroes (0s), contains divergent iteration counts
m = np.full(z.shape, True)          # 1600 * 2000 True, used as a kind of mask (convergent values)
for i in range(0,n):          # Do at most n iterations
z[m] = z[m]**2 + c[m]     # Matrix op: Complex iteration for fixed c (Julia set perspective)
m[np.abs(z) > 2] = False  # threshold for convergence of absolute(z) is 2
diverge[m] = i
plt.imshow(diverge, cmap='magma')   # Color map "magma" applied to the iterations for each point
plt.show()                          # Display image plotted

我不懂这条线的原理diverge[m] = i我推测m是布尔值的1600*2000元素数组。似乎m被用作一种掩码,使其仅代表divide[]中的那些值,其中m中的相应元素为True。然而,我想更详细地理解这个概念。语法CCD_ 2似乎暗示数组被用作某种广义的";索引";到另一个数组(divert(,我可以帮助理解这个概念。(代码按预期运行,我只是在理解它的工作时遇到了问题。(

谢谢。

是的,您可以使用一个数组来索引另一个数组。在许多方面。这是一个复杂的问题。即使我现在很得意地理解了numpy,我有时还是会遇到数组索引,这让我在理解之前有点挠头。

但这种情况并不是一个非常复杂的

M=np.array([[1,2,3], 
[4,5,6],
[7,8,9]])
msk=np.array([[True,  False,  True],
[True,  True,   True],
[False, True,   False]])
M[msk]

返回array([1, 3, 4, 5, 6, 8])。我相信,你可以很容易地理解其中的逻辑。

但更重要的是,指数化是一个l值。这意味着M[msk]可以在=的左侧。然后M的值受到的影响

因此,这意味着

M[msk]=0
M

显示

array([[0, 2, 0],
[0, 0, 0],
[7, 0, 9]])

同样,

M=np.array([[1,2,3], 
[4,5,6],
[7,8,9]])
A=np.array([[2,2,4],
[4,6,6],
[8,8,8]])
msk=np.array([[True,  False,  True],
[True,  True,   True],
[False, True,   False]])
M[msk] = M[msk]+A[msk]
M

结果是

array([[ 3,  2,  7],
[ 8, 11, 12],
[ 7, 16,  9]])

回到你的案子,

z[m] = z[m]**2 + c[m]     # Matrix op: Complex iteration for fixed c (Julia set perspective)

在某种程度上只是一种优化。您也可以只使用z=z**2+c。但是,为什么即使在已经发生溢出的情况下也要计算呢。因此,它只在还没有溢出的地方计算z=z**2+c

m[np.abs(z) > 2] = False  # threshold for convergence of absolute(z) is 2

np.abs(s)>2是真/假值的2d数组。m被设置为False;像素";其中CCD_ 9。m的其他值保持不变。因此,如果他们已经是假的,他们就会保持虚假。请注意,这个有点过于复杂。由于前一行的原因,z在变为>2后不会改变,因此实际上,没有np.abs(z)<=2m已经为False的像素。所以

m=np.abs(z)<=2

也会起作用。而且它不会更慢,因为最初的版本无论如何都是这样计算的。事实上,它会更快,因为我们省去了指数化/影响操作。在我的电脑上,我的版本比原来的运行速度快1.3秒(计算时间为12秒。大约10%(但原始版本的优点是使下一行更容易理解,因为它明确了一点:m从所有True值开始,然后只要算法运行,一些值就会变为False,但没有一个值再变为True。

diverge[m] = i

m是尚未发散的像素的掩码(它从所有True开始,只要我们迭代,m的值就会越来越多(。因此,在任何地方更新divert到i都没有发生divert(变量的名称不是最相关的(。

因此,z值变为>2,因此其m值在迭代50变为False,将被更新为1,然后是2,然后是3,然后是4。。。,然后是48,然后是49。但不到50,51。。。

所以在最后;"发散";是最后一个我,我仍然是真的。这是算法仍在收敛的最后一个i。或者,在1个单位移位时,算法发散的第一个单位移位。

最新更新