Random 半圆上的冯·米塞斯分布?

Random 半圆上的冯·米塞斯分布?,random,scipy,distribution,scipy.stats,Random,Scipy,Distribution,Scipy.stats,我试图找出定义缠绕在半圆上的冯·米塞斯分布的最佳方法(我用它来画不同浓度下的无方向线)。我目前正在使用SciPy的vonmises.rvs()。本质上,我希望能够输入,比方说,pi/2的平均方向,并将分布截短到两边不超过pi/2 我可以使用截断的正态分布,但我将失去von mises的包装(如果我想要平均方向为0) 我在研究光纤方向映射的研究论文中看到了这一点,但我不知道如何实现它(在python中)。我有点不知道从哪里开始 如果我的von Mesis定义为(来自numpy.vonmises):

我试图找出定义缠绕在半圆上的冯·米塞斯分布的最佳方法(我用它来画不同浓度下的无方向线)。我目前正在使用SciPy的vonmises.rvs()。本质上,我希望能够输入,比方说,pi/2的平均方向,并将分布截短到两边不超过pi/2

我可以使用截断的正态分布,但我将失去von mises的包装(如果我想要平均方向为0)

我在研究光纤方向映射的研究论文中看到了这一点,但我不知道如何实现它(在python中)。我有点不知道从哪里开始

如果我的von Mesis定义为(来自numpy.vonmises):

与:

我该如何改变它,改为使用环绕半圆的环绕线


有这方面经验的人能提供一些指导吗?

您可以通过numpy的过滤(
theta=theta[(theta>=0)和(theta-np.pi,theta-np.pi,theta))
)丢弃所需范围之外的值。正如@SeverinPappadeux所指出的,这样会改变分布,可能不是所需的

导入matplotlib.pyplot作为plt
从matplotlib.collections导入LineCollection
将numpy作为np导入
从scipy.stats导入vonmises
mu=np.pi/2
卡帕=4
原始值=vonmises.rvs(kappa,loc=mu,size=(10000))
图,轴=plt.子批次(ncols=2,sharex=True,sharey=True,figsize=(12,4))
对于轴中的ax:
θ=原点θ。复制()
如果ax==轴[0]:
ax.set_title(f“$Von Mises,\\mu={mu:.2f},\\kappa={kappa}$”)
其他:

θ=θ[(θ>=0)&(θ对于直接数值逆CDF采样非常有用,它对于有界域的分布应该非常有用。下面是代码示例,构建PDF和CDF表,并使用逆CDF方法进行采样。当然可以优化和矢量化

代码,Python 3.8,x64 Windows 10

import numpy as np
import matplotlib.pyplot as plt
import scipy.integrate as integrate

def PDF(x, μ, κ):
    return np.exp(κ*np.cos(x - μ))

N = 201

μ = np.pi/2.0
κ = 4.0

xlo = μ - np.pi/2.0
xhi = μ + np.pi/2.0

# PDF normaliztion

I = integrate.quad(lambda x: PDF(x, μ, κ), xlo, xhi)
print(I)
I = I[0]

x = np.linspace(xlo, xhi, N, dtype=np.float64)
step = (xhi-xlo)/(N-1)

p = PDF(x, μ, κ)/I # PDF table

# making CDF table
c = np.zeros(N, dtype=np.float64)

for k in range(1, N):
    c[k] = integrate.quad(lambda x: PDF(x, μ, κ), xlo, x[k])[0] / I

c[N-1] = 1.0 # so random() in [0...1) range would work right

#%%
# sampling from tabular CDF via insverse CDF method

def InvCDFsample(c, x, gen):
    r = gen.random()
    i = np.searchsorted(c, r, side='right')
    q = (r - c[i-1]) / (c[i] - c[i-1])
    return (1.0 - q) * x[i-1] + q * x[i]

# sampling test
RNG = np.random.default_rng()

s = np.empty(20000)

for k in range(0, len(s)):
    s[k] = InvCDFsample(c, x, RNG)

# plotting PDF, CDF and sampling density
plt.plot(x, p, 'b^') # PDF
plt.plot(x, c, 'r.') # CDF
n, bins, patches = plt.hist(s, x, density = True, color ='green', alpha = 0.7)
plt.show()
并用PDF、CDF和抽样直方图绘制图表


我相信,加/减是错误的。它不会再遵循冯·米塞斯的形状了。是的,你是对的,尾巴会变得太胖。我错误地认为它们的分布会相似。我会更新答案。谢谢你这么详细的回答!我希望有一种简单的方法来改变方程式,使其在半个转弯时结束。我忘了加/减在上,输出必须始终是相同数量的元素。使用拒绝采样是否合适?从vonmises.rvs中请求一个值,然后根据它是否在与所需平均值的pi/2距离内接受或拒绝它?出于速度考虑,我确实会生成太多的采样,然后进行子采样。
theta=vonmises.rvs(kappa,loc=mu,size=(15000))
然后
theta=theta[(theta>=0)&(theta感谢您如此详细的回复。这对我的案例非常有效,我将致力于优化它(尽管我只需要每~3秒执行一次操作!)。我在论坛上看到过()通过询问其他人,我可以将我的角度乘以2,使其绕成一个半圆。我不确定我是否理解这一点,我肯定会将角度除以2?我想知道你对此是否有任何评论,但我承认你已经给出了一个很好的答案!@mscone
感谢你如此详细的回答
我们l、 你可以接受这个答案,也可以挑战它,或者两者兼而有之。我读过讨论,总是这样的类比。你没有冯·米塞斯分布,周期。任何你认为可能来自冯·米塞斯的东西,或者任何其他人声称它会起作用,因为它对冯·米塞斯起作用,都需要进行测试。这实际上是我编写的代码的美妙之处。F.e.JohanC建议镜像角度-好的,镜像它并根据数字PDF绘图,进行Q-Q绘图,K-S测试等。如果有人想划分角度(是的,将角度减半)-试着用数字PDF绘图。关于所有建议:我认为,角度减半不起作用。我认为约翰的镜像/加/减不起作用。我认为接受/拒绝会起作用。但你无法安全地测试各种参数(μ,kappa)的所有可能性看看这一切是如何进行的。即使有人会给你带来魔盒,声称它能根据你想要的发行版生成房车,你也可以检查一下。你说得对,我可以测试它们,我一直都是。我只是对这个地区有点不熟悉,需要一些指导。谢谢你的代码、帮助和时间。
mu, kappa = 0, 4.0

x = np.linspace(-np.pi, np.pi, num=51)
import numpy as np
import matplotlib.pyplot as plt
import scipy.integrate as integrate

def PDF(x, μ, κ):
    return np.exp(κ*np.cos(x - μ))

N = 201

μ = np.pi/2.0
κ = 4.0

xlo = μ - np.pi/2.0
xhi = μ + np.pi/2.0

# PDF normaliztion

I = integrate.quad(lambda x: PDF(x, μ, κ), xlo, xhi)
print(I)
I = I[0]

x = np.linspace(xlo, xhi, N, dtype=np.float64)
step = (xhi-xlo)/(N-1)

p = PDF(x, μ, κ)/I # PDF table

# making CDF table
c = np.zeros(N, dtype=np.float64)

for k in range(1, N):
    c[k] = integrate.quad(lambda x: PDF(x, μ, κ), xlo, x[k])[0] / I

c[N-1] = 1.0 # so random() in [0...1) range would work right

#%%
# sampling from tabular CDF via insverse CDF method

def InvCDFsample(c, x, gen):
    r = gen.random()
    i = np.searchsorted(c, r, side='right')
    q = (r - c[i-1]) / (c[i] - c[i-1])
    return (1.0 - q) * x[i-1] + q * x[i]

# sampling test
RNG = np.random.default_rng()

s = np.empty(20000)

for k in range(0, len(s)):
    s[k] = InvCDFsample(c, x, RNG)

# plotting PDF, CDF and sampling density
plt.plot(x, p, 'b^') # PDF
plt.plot(x, c, 'r.') # CDF
n, bins, patches = plt.hist(s, x, density = True, color ='green', alpha = 0.7)
plt.show()