繁体   English   中英

使用python从指数分布和模型生成随机数

[英]Generate random numbers from exponential distribution and model using python

我的目标是创建一个随机点数据集,其直方图看起来像一个指数衰减函数,然后通过这些点绘制指数衰减函数。

首先,我试图从指数分布中创建一系列随机数(但是没有成功,因为这些应该是点,而不是数字)。

from pylab import *
from scipy.optimize import curve_fit
import random
import numpy as np
import pandas as pd

testx = pd.DataFrame(range(10)).astype(float)
testx = testx[0]

for i in range(1,11):
   x = random.expovariate(15) # rate = 15 arrivals per second
   data[i] = [x]

testy = pd.DataFrame(data).T.astype(float)
testy = testy[0]; testy

plot(testx, testy, 'ko')

结果看起来像这样。

在此输入图像描述

然后我定义了一个函数来绘制一条直线:

def func(x, a, e):
return a*np.exp(-a*x)+e

popt, pcov = curve_fit(f=func, xdata=testx, ydata=testy, p0 = None, sigma = None) 

print popt # parameters
print pcov # covariance

plot(testx, testy, 'ko')

xx = np.linspace(0, 15, 1000)
plot(xx, func(xx,*popt))

plt.show()

我正在寻找的是:(1)从指数(衰变)分布创建随机数组的更优雅方式,以及(2)如何测试我的函数确实通过数据点。

在此输入图像描述

我猜想以下内容接近你想要的。 您可以使用numpy生成从指数分布中提取的一些随机数,

data = numpy.random.exponential(5, size=1000)

然后,您可以使用numpy.hist创建它们的直方图,并将直方图值绘制到绘图中。 你可以决定把箱子的中间作为点的位置(这个假设当然是错误的,但是你使用的垃圾箱越多越有效)。

拟合工作与问题的代码一样。 然后,您将发现我们的拟合粗略地找到用于数据生成的参数(在这种情况下低于~5)。

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

data = np.random.exponential(5, size=1000)

hist,edges = np.histogram(data,bins="auto",density=True )

x = edges[:-1]+np.diff(edges)/2.
plt.scatter(x,hist)

func = lambda x,beta: 1./beta*np.exp(-x/beta)

popt, pcov = curve_fit(f=func, xdata=x, ydata=hist) 

print(popt)

xx = np.linspace(0, x.max(), 101)
plt.plot(xx, func(xx,*popt), ls="--", color="k", 
         label="fit, $beta = ${}".format(popt))
plt.legend()
plt.show()

在此输入图像描述

我认为你实际上是在询问回归问题 ,这正是Praveen所暗示的。

你有一个沼泽标准指数衰减到达y轴约为y = 0.27。 因此,其方程为y = 0.27*exp(-0.27*x) 我可以围绕此函数的值建模高斯误差,并使用以下代码绘制结果。

import matplotlib.pyplot as plt
from math import exp
from scipy.stats import norm


x = range(0, 16)
Y = [0.27*exp(-0.27*_) for _ in x]
error = norm.rvs(0, scale=0.05, size=9)
simulated_data = [max(0, y+e) for (y,e) in zip(Y[:9],error)]

plt.plot(x, Y, 'b-')
plt.plot(x[:9], simulated_data, 'r.')
plt.show()

print (x[:9])
print (simulated_data)

这是情节。 请注意,我保存输出值以供后续使用。

指数衰减与噪音

现在我可以计算自变量上受噪声污染的指数衰减值的非线性回归,这就是curve_fit作用。

from math import exp
from scipy.optimize import curve_fit
import numpy as np

def model(x, p):
    return p*np.exp(-p*x)

x = list(range(9))
Y = [0.22219001972988275, 0.15537454187341937, 0.15864069451825827, 0.056411162886672819, 0.037398831058143338, 0.10278251869912845, 0.03984605649260467, 0.0035360087611421981, 0.075855255999424692]

popt, pcov = curve_fit(model, x, Y)
print (popt[0])
print (pcov)

奖金是,不仅curve_fit计算参数的估计- 0.207962159793 -它也提供了这种估计的方差的估计- 0.00086071 -作为一个元素pcov 考虑到样本量小,这似乎是一个相当小的值。

以下是如何计算残差。 请注意,每个残差是数据值与使用参数估计从x估计的值之间的差值。

residuals = [y-model(_, popt[0]) for (y, _) in zip(Y, x)]
print (residuals)

如果你想进一步“测试我的函数确实通过数据点”,那么我建议在残差中寻找模式。 但是这样的讨论可能超出了对stackoverflow的欢迎:QQ和PP图,残差与yx ,等等。

我同意@ImportanceOfBeingErnes的解决方案,但我想为发行版添加一个(众所周知的?)通用解决方案。 如果你有一个带有积分F的分布函数f (即f = dF / dx ),那么你可以通过用inv F映射随机数得到所需的分布,即积分的反函数。 在指数函数的情况下,积分再次是指数,而倒数是对数。 所以可以这样做:

import matplotlib.pyplot as plt
import numpy as np
from random import random


def gen( a ):
    y=random()
    return( -np.log( y ) / a )


def dist_func( x, a ):
    return( a * np.exp( -a * x) )


data = [ gen(3.14) for x in range(20000) ]
fig = plt.figure()
ax = fig.add_subplot( 1, 1, 1 )
ax.hist(data, bins=80, normed=True, histtype="step") 
ax.plot(np.linspace(0,5,150), dist_func( np.linspace(0,5,150), 3.14 ) )
plt.show()

由逆积分映射

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM