python高斯噪声函数_Python高斯拟合模拟高斯噪声数据

I need to interpolate data coming from an instrument using a gaussian fit. To this end I thought about using the curve_fit function from scipy.

Since I'd like to test this functionality on fake data before trying it on the instrument I wrote the following code to generate noisy gaussian data and to fit it:

from scipy.optimize import curve_fit

import numpy

import pylab

# Create a gaussian function

def gaussian(x, a, b, c):

val = a * numpy.exp(-(x - b)**2 / (2*c**2))

return val

# Generate fake data.

zMinEntry = 80.0*1E-06

zMaxEntry = 180.0*1E-06

zStepEntry = 0.2*1E-06

x = numpy.arange(zMinEntry,

zMaxEntry,

zStepEntry,

dtype = numpy.float64)

n = len(x)

meanY = zMinEntry + (zMaxEntry - zMinEntry)/2

sigmaY = 10.0E-06

a = 1.0/(sigmaY*numpy.sqrt(2*numpy.pi))

y = gaussian(x, a, meanY, sigmaY) + a*0.1*numpy.random.normal(0, 1, size=len(x))

# Fit

popt, pcov = curve_fit(gaussian, x, y)

# Print results

print("Scale = %.3f +/- %.3f" % (popt[0], numpy.sqrt(pcov[0, 0])))

print("Offset = %.3f +/- %.3f" % (popt[1], numpy.sqrt(pcov[1, 1])))

print("Sigma = %.3f +/- %.3f" % (popt[2], numpy.sqrt(pcov[2, 2])))

pylab.plot(x, y, 'ro')

pylab.plot(x, gaussian(x, popt[0], popt[1], popt[2]))

pylab.grid(True)

pylab.show()

Unfortunately this does not work properly, the output of the code is the following:

Scale = 6174.816 +/- 7114424813.672

Offset = 429.319 +/- 3919751917.830

Sigma = 1602.869 +/- 17923909301.176

And the plotted result is (blue is the fit function, red dots is the noisy input data):

I also tried to look at this answer, but couldn't figure out where my problem is.

Am I missing something here? Or am I using the curve_fit function in the wrong way? Thanks in advance!

解决方案

I agree with Olaf in so far as it is a question of scale. The optimal parameters differ by many orders of magnitude. However, scaling the parameters with which you generated your toy data does not seem to solve the problem for your actual application. curve_fit uses lestsq, which numerically approximates the Jacobian, where numerical problems arise because of the differences in scale (try to use the full_output keyword in curve_fit).

In my experience it is often best to use fmin which does not rely on approximated derivatives but uses only function values. You now have to write your own least-squares function that is to be optimized.

Starting values are still important. In your case you can make sufficiently good guesses by taking the maximum amplitude for a and the corresponding x-values for band c.

In code, it looks like this:

from scipy.optimize import curve_fit,fmin

import numpy

import pylab

# Create a gaussian function

def gaussian(x, a, b, c):

val = a * numpy.exp(-(x - b)**2 / (2*c**2))

return val

# Generate fake data.

zMinEntry = 80.0*1E-06

zMaxEntry = 180.0*1E-06

zStepEntry = 0.2*1E-06

x = numpy.arange(zMinEntry,

zMaxEntry,

zStepEntry,

dtype = numpy.float64)

n = len(x)

meanY = zMinEntry + (zMaxEntry - zMinEntry)/2

sigmaY = 10.0E-06

a = 1.0/(sigmaY*numpy.sqrt(2*numpy.pi))

y = gaussian(x, a, meanY, sigmaY) + a*0.1*numpy.random.normal(0, 1, size=len(x))

print a, meanY, sigmaY

# estimate starting values from the data

a = y.max()

b = x[numpy.argmax(a)]

c = b

# define a least squares function to optimize

def minfunc(params):

return sum((y-gaussian(x,params[0],params[1],params[2]))**2)

# fit

popt = fmin(minfunc,[a,b,c])

# Print results

print("Scale = %.3f" % (popt[0]))

print("Offset = %.3f" % (popt[1]))

print("Sigma = %.3f" % (popt[2]))

pylab.plot(x, y, 'ro')

pylab.plot(x, gaussian(x, popt[0], popt[1], popt[2]),lw = 2)

pylab.xlim(x.min(),x.max())

pylab.grid(True)

pylab.show()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值