如何创建 Rician 随机变量?
How to create a Rician random variable?
我正在尝试使用 Sympy 对信号检测问题建模,并且需要两个随机变量。一种采用瑞利分布对噪声进行建模,另一种采用莱斯分布对信号+噪声进行建模。 Sympy provides a Rayleigh distribution,但不是 Rician——或者至少不是那个名字的人。
创建一个的最佳方法是什么?它是否以不同的名称存在?有没有办法将现有的分布操纵成一个 Rician?
根据@asmeurer 的建议,我实现了自己的 Rice 分发,如下所示:
from sympy.stats.crv_types import rv
from sympy.stats.crv import SingleContinuousDistribution
class RicianDistribution(SingleContinuousDistribution):
_argnames=('nu','sigma')
@property
def set(self): return Interval(0,oo)
def pdf(self,x):
nu,sigma=self.nu, self.sigma
return (x/sigma**2)*exp(-(x**2+nu**2)/(2*sigma**2))*besseli(0,x*nu/sigma**2)
def Rician(name,nu,sigma):
return rv(name,RicianDistribution,(nu,sigma))
分布似乎与 Wikipedia and Scipy, but oddly I'm getting different results than Scipy. I'll ask that question separately ().
附带说明一下,以下行可以对包含贝塞尔函数的密度函数进行 lambdify:
printing.lambdarepr.LambdaPrinter._print_besseli=(lambda self,expr: 'i0(%s)'%expr.argument)
它并未推广到所有贝塞尔函数,但适用于莱斯分布中使用的第一类零阶修正贝塞尔函数。
是的,您可以从卡方和泊松生成 Rice。查看任何彻底的 Rice 讨论,例如 https://en.wikipedia.org/wiki/Rice_distribution:
Another case where Rice(nu,sigma) comes from the following steps:
- Generate P having a Poisson distribution with parameter (also mean, for a Poisson) lambda = nu^2 / (2*sigma^2).
- Generate X having a chi-squared distribution with 2P + 2 degrees of freedom.
- Set R = sigma * sqrt(X).
如果您了解 pdf 功能,使用 sympy.stats 创建新发行版会很容易。查看 sympy source 中的现有分布。您只需要继承 SingleContinuousDistribution
并定义一些方法。例如,这是正态分布(删除了文档字符串):
class NormalDistribution(SingleContinuousDistribution):
_argnames = ('mean', 'std')
@staticmethod
def check(mean, std):
_value_check(std > 0, "Standard deviation must be positive")
def pdf(self, x):
return exp(-(x - self.mean)**2 / (2*self.std**2)) / (sqrt(2*pi)*self.std)
def sample(self):
return random.normalvariate(self.mean, self.std)
def Normal(name, mean, std):
return rv(name, NormalDistribution, (mean, std))
我正在尝试使用 Sympy 对信号检测问题建模,并且需要两个随机变量。一种采用瑞利分布对噪声进行建模,另一种采用莱斯分布对信号+噪声进行建模。 Sympy provides a Rayleigh distribution,但不是 Rician——或者至少不是那个名字的人。
创建一个的最佳方法是什么?它是否以不同的名称存在?有没有办法将现有的分布操纵成一个 Rician?
根据@asmeurer 的建议,我实现了自己的 Rice 分发,如下所示:
from sympy.stats.crv_types import rv
from sympy.stats.crv import SingleContinuousDistribution
class RicianDistribution(SingleContinuousDistribution):
_argnames=('nu','sigma')
@property
def set(self): return Interval(0,oo)
def pdf(self,x):
nu,sigma=self.nu, self.sigma
return (x/sigma**2)*exp(-(x**2+nu**2)/(2*sigma**2))*besseli(0,x*nu/sigma**2)
def Rician(name,nu,sigma):
return rv(name,RicianDistribution,(nu,sigma))
分布似乎与 Wikipedia and Scipy, but oddly I'm getting different results than Scipy. I'll ask that question separately (
附带说明一下,以下行可以对包含贝塞尔函数的密度函数进行 lambdify:
printing.lambdarepr.LambdaPrinter._print_besseli=(lambda self,expr: 'i0(%s)'%expr.argument)
它并未推广到所有贝塞尔函数,但适用于莱斯分布中使用的第一类零阶修正贝塞尔函数。
是的,您可以从卡方和泊松生成 Rice。查看任何彻底的 Rice 讨论,例如 https://en.wikipedia.org/wiki/Rice_distribution:
Another case where Rice(nu,sigma) comes from the following steps:
- Generate P having a Poisson distribution with parameter (also mean, for a Poisson) lambda = nu^2 / (2*sigma^2).
- Generate X having a chi-squared distribution with 2P + 2 degrees of freedom.
- Set R = sigma * sqrt(X).
如果您了解 pdf 功能,使用 sympy.stats 创建新发行版会很容易。查看 sympy source 中的现有分布。您只需要继承 SingleContinuousDistribution
并定义一些方法。例如,这是正态分布(删除了文档字符串):
class NormalDistribution(SingleContinuousDistribution):
_argnames = ('mean', 'std')
@staticmethod
def check(mean, std):
_value_check(std > 0, "Standard deviation must be positive")
def pdf(self, x):
return exp(-(x - self.mean)**2 / (2*self.std**2)) / (sqrt(2*pi)*self.std)
def sample(self):
return random.normalvariate(self.mean, self.std)
def Normal(name, mean, std):
return rv(name, NormalDistribution, (mean, std))