在 python 中:缺少随机性(分数布朗运动)
In python: missing randomness (fractional Brownian motion)
我是 Python 的新手。我有两个脚本用于生成和绘制 2D 晶格,其值以分形图像的形式表示空间分布的属性。第一个脚本包含生成分形的函数(正统名称:具有傅里叶逆变换的光谱合成),而第二个脚本只是调用函数,绘图它,广告将其写入 .csv 文件。 函数依赖多次random.gauss(0.0, sigma)
调用来获得正态分布的随机数。它还调用 random.random()
因为它需要其他随机数。 下面是代码。 感谢任何愿意提供帮助的人!
问题:情节总是显示相同的模式,因此让我觉得代码中有些东西不是随机的。我的意图是每次 运行 代码时都获得不同的分形图像。是什么让它不是随机的?是第二个脚本中的 seed=122
吗?
PS:请注意,由于该过程引入了给定程度的周期性,并且由于我不希望显示该周期性,因此绘制的点阵小于生成的点阵.特别是,我使用 size(plotted)=101x101,而 size(generated)=256x256.
第一个脚本:函数本身
from __future__ import division #Avoids the floor of the mathematical result of division if the args are ints or longs
import numpy
import random
import math
import pylab
def SpectralSynthesisFM2D(max_level, sigma, H, seed=0, normalise=True, bounds=[0,1]):
"""
________________________________________________________________________
Args:
max_level : Maximum number of recursions (N = 2^max_level)
sigma : Initial standard deviation
H : Roughness constant (Hurst exponent), varies form 0.0 to 1.0
H=0.8 is a good representation of many natural phenomena (Voss, 1985)
seed : seed value for random number generator
normalise : normalizes the data using bound
bounds : used for normalization of the grid data
Result:
Output is given in the form of an array (grid) which holds surface
values for a square region.
_________________________________________________________________________
"""
N = int(2**max_level)
A = numpy.zeros((N,N), dtype = complex)
random.seed() #Seeds the random number generator
PI = 3.141592
for i in range(0,int((N-1)/2)):
for j in range(0,int((N-1)/2)):
phase = 2*PI*random.random() #/random.randrange(1,Arand)
if i != 0 or j != 0:
rad = pow((i*i + j*j),(-(H+1)/2) )*random.gauss(0.0, sigma)
else:
rad = 0.0
A[i][j] = rad*math.cos(phase) + rad*math.sin(phase)*j
if i ==0:
i0 = 0
else:
i0 = N - i
if j==0:
j0 = 0
else:
j0 = N - j
A[i0][j0] = rad * math.cos(phase) - rad*math.sin(phase)*j
for i in range(1,int((N-1)/2)):
for j in range(1,int((N-1)/2)):
phase = 2*PI*random.random() #/random.randrange(1,Arand)
rad = pow((i*i + j*j),(-(H+1)/2) )*random.gauss(0.0, sigma)
A[i][N-j] = rad * math.cos(phase) + rad* math.sin(phase)*j
A[N-i][j] = rad * math.cos(phase) - rad* math.sin(phase)*j
Grid = numpy.real(pylab.ifft2(( A ))) #Implements the Discrete Inverse Fast Fourier Transform on a 2D lattice (grid)
if(normalise):
Grid += numpy.amin(Grid)*-1 + bounds[0]
Grid = (Grid/numpy.amax(Grid)) * bounds[1]
return Grid
第二个脚本:绘制函数并获取分形图像:
from __future__ import division #Avoids the floor of the mathematical result of division if the args are ints or longs
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as mc
import SSFM2D
#Parameter assignments
max_level=8 #This is the exponent controlling the grid size. In this case N=2^8=256. Use only integers.
N=2**max_level
sigma=1 #Variation for random Gauss generation (standardised normal distribution)
H=0.8 #Hurst exponent (0.8 is a recommended value for natural phenomena)
seed=122 #Setting the seed for random Gauss generation
print ('The lattice size is '+str(N)+'x'+str(N))
#Lattice initialization
Lattice=np.zeros((256,256))
#Calling Spectral fBm function
Lattice=SSFM2D.SpectralSynthesisFM2D(max_level, sigma, H, seed, normalise=True, bounds=[0,1])
#Plotting the lattice
M=np.zeros((101,101)) #Lattice to be plotted. Size(M) != size(Lattice) to minimize visual fBm periodic features.
for i in range(0,101):
for j in range(0,101):
M[i][j]=Lattice[i][j]
#Lattice statistics
print M[-101:,-101:].sum()
print M[-101:,-101:].max()
print M[-101:,-101:].min()
print M[-101:,-101:].mean()
#Writing X, Y and values to a .csv file from scratch
import numpy
import csv
with open('C:\Users\Francesco\Desktop\Python_files\csv\fBm_256x256.csv', 'w') as f: # Change directory if necessary
writer = csv.writer(f)
writer.writerow(['X', 'Y', 'Value'])
for (x, y), val in numpy.ndenumerate(M):
writer.writerow([x, y, val])
# Plotting - Showing interpolation of randomization
plt.imshow(M[-101:,-101:].T, origin='lower',interpolation='nearest',cmap='Blues', norm=mc.Normalize(vmin=0,vmax=M.max()))
title_string=('fBm: Inverse FFT on Spectral Synthesis')
subtitle_string=('Lattice size: 101x101')
plt.suptitle(title_string, y=0.99, fontsize=17)
plt.title(subtitle_string, fontsize=9)
plt.show()
# Makes a custom list of tick mark intervals for colour bar (assumes minimum is always zero)
numberOfTicks = 5
ticksListIncrement = M.max()/(numberOfTicks)
ticksList = []
for i in range((numberOfTicks+1)):
ticksList.append(ticksListIncrement * i)
cb=plt.colorbar(orientation='horizontal', format='%0.2f', ticks=ticksList)
cb.set_label('Values')
plt.show()
plt.xlim(0, 100)
plt.xlabel('Easting (Cells)')
plt.ylim(100, 0)
plt.ylabel('Northing (Cells)')
通常一个seed
用于初始化一个随机数生成器。 same seed
-> 相同的随机数序列(这对测试非常有用)。
import random
random.seed(22)
for i in range(10):
print(random.randint(0, 100))
所以无论你运行那个程序多少次(甚至在什么机器上),输出总是一样的。
但是当你想要 'real' 随机性(或至少更好的随机性)时,你最好调用
random.seed() # or: random.seed(None)
没有参数。 python 然后使用当前系统时间调用 seed
- 这提供了一些随机性的来源。
因为我不知道你的图书馆,所以我不能确定,但我敢打赌它以类似的方式工作。您可以尝试设置 seed=None
或 seed=random.randint(something)
.
无论如何:一定要阅读你的库的 api 文档并检查 seed
做了什么。
我是 Python 的新手。我有两个脚本用于生成和绘制 2D 晶格,其值以分形图像的形式表示空间分布的属性。第一个脚本包含生成分形的函数(正统名称:具有傅里叶逆变换的光谱合成),而第二个脚本只是调用函数,绘图它,广告将其写入 .csv 文件。 函数依赖多次random.gauss(0.0, sigma)
调用来获得正态分布的随机数。它还调用 random.random()
因为它需要其他随机数。 下面是代码。 感谢任何愿意提供帮助的人!
问题:情节总是显示相同的模式,因此让我觉得代码中有些东西不是随机的。我的意图是每次 运行 代码时都获得不同的分形图像。是什么让它不是随机的?是第二个脚本中的 seed=122
吗?
PS:请注意,由于该过程引入了给定程度的周期性,并且由于我不希望显示该周期性,因此绘制的点阵小于生成的点阵.特别是,我使用 size(plotted)=101x101,而 size(generated)=256x256.
第一个脚本:函数本身
from __future__ import division #Avoids the floor of the mathematical result of division if the args are ints or longs
import numpy
import random
import math
import pylab
def SpectralSynthesisFM2D(max_level, sigma, H, seed=0, normalise=True, bounds=[0,1]):
"""
________________________________________________________________________
Args:
max_level : Maximum number of recursions (N = 2^max_level)
sigma : Initial standard deviation
H : Roughness constant (Hurst exponent), varies form 0.0 to 1.0
H=0.8 is a good representation of many natural phenomena (Voss, 1985)
seed : seed value for random number generator
normalise : normalizes the data using bound
bounds : used for normalization of the grid data
Result:
Output is given in the form of an array (grid) which holds surface
values for a square region.
_________________________________________________________________________
"""
N = int(2**max_level)
A = numpy.zeros((N,N), dtype = complex)
random.seed() #Seeds the random number generator
PI = 3.141592
for i in range(0,int((N-1)/2)):
for j in range(0,int((N-1)/2)):
phase = 2*PI*random.random() #/random.randrange(1,Arand)
if i != 0 or j != 0:
rad = pow((i*i + j*j),(-(H+1)/2) )*random.gauss(0.0, sigma)
else:
rad = 0.0
A[i][j] = rad*math.cos(phase) + rad*math.sin(phase)*j
if i ==0:
i0 = 0
else:
i0 = N - i
if j==0:
j0 = 0
else:
j0 = N - j
A[i0][j0] = rad * math.cos(phase) - rad*math.sin(phase)*j
for i in range(1,int((N-1)/2)):
for j in range(1,int((N-1)/2)):
phase = 2*PI*random.random() #/random.randrange(1,Arand)
rad = pow((i*i + j*j),(-(H+1)/2) )*random.gauss(0.0, sigma)
A[i][N-j] = rad * math.cos(phase) + rad* math.sin(phase)*j
A[N-i][j] = rad * math.cos(phase) - rad* math.sin(phase)*j
Grid = numpy.real(pylab.ifft2(( A ))) #Implements the Discrete Inverse Fast Fourier Transform on a 2D lattice (grid)
if(normalise):
Grid += numpy.amin(Grid)*-1 + bounds[0]
Grid = (Grid/numpy.amax(Grid)) * bounds[1]
return Grid
第二个脚本:绘制函数并获取分形图像:
from __future__ import division #Avoids the floor of the mathematical result of division if the args are ints or longs
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as mc
import SSFM2D
#Parameter assignments
max_level=8 #This is the exponent controlling the grid size. In this case N=2^8=256. Use only integers.
N=2**max_level
sigma=1 #Variation for random Gauss generation (standardised normal distribution)
H=0.8 #Hurst exponent (0.8 is a recommended value for natural phenomena)
seed=122 #Setting the seed for random Gauss generation
print ('The lattice size is '+str(N)+'x'+str(N))
#Lattice initialization
Lattice=np.zeros((256,256))
#Calling Spectral fBm function
Lattice=SSFM2D.SpectralSynthesisFM2D(max_level, sigma, H, seed, normalise=True, bounds=[0,1])
#Plotting the lattice
M=np.zeros((101,101)) #Lattice to be plotted. Size(M) != size(Lattice) to minimize visual fBm periodic features.
for i in range(0,101):
for j in range(0,101):
M[i][j]=Lattice[i][j]
#Lattice statistics
print M[-101:,-101:].sum()
print M[-101:,-101:].max()
print M[-101:,-101:].min()
print M[-101:,-101:].mean()
#Writing X, Y and values to a .csv file from scratch
import numpy
import csv
with open('C:\Users\Francesco\Desktop\Python_files\csv\fBm_256x256.csv', 'w') as f: # Change directory if necessary
writer = csv.writer(f)
writer.writerow(['X', 'Y', 'Value'])
for (x, y), val in numpy.ndenumerate(M):
writer.writerow([x, y, val])
# Plotting - Showing interpolation of randomization
plt.imshow(M[-101:,-101:].T, origin='lower',interpolation='nearest',cmap='Blues', norm=mc.Normalize(vmin=0,vmax=M.max()))
title_string=('fBm: Inverse FFT on Spectral Synthesis')
subtitle_string=('Lattice size: 101x101')
plt.suptitle(title_string, y=0.99, fontsize=17)
plt.title(subtitle_string, fontsize=9)
plt.show()
# Makes a custom list of tick mark intervals for colour bar (assumes minimum is always zero)
numberOfTicks = 5
ticksListIncrement = M.max()/(numberOfTicks)
ticksList = []
for i in range((numberOfTicks+1)):
ticksList.append(ticksListIncrement * i)
cb=plt.colorbar(orientation='horizontal', format='%0.2f', ticks=ticksList)
cb.set_label('Values')
plt.show()
plt.xlim(0, 100)
plt.xlabel('Easting (Cells)')
plt.ylim(100, 0)
plt.ylabel('Northing (Cells)')
通常一个seed
用于初始化一个随机数生成器。 same seed
-> 相同的随机数序列(这对测试非常有用)。
import random
random.seed(22)
for i in range(10):
print(random.randint(0, 100))
所以无论你运行那个程序多少次(甚至在什么机器上),输出总是一样的。
但是当你想要 'real' 随机性(或至少更好的随机性)时,你最好调用
random.seed() # or: random.seed(None)
没有参数。 python 然后使用当前系统时间调用 seed
- 这提供了一些随机性的来源。
因为我不知道你的图书馆,所以我不能确定,但我敢打赌它以类似的方式工作。您可以尝试设置 seed=None
或 seed=random.randint(something)
.
无论如何:一定要阅读你的库的 api 文档并检查 seed
做了什么。