Estoy tratando de hacer un ajuste gaussiano sobre muchos puntos de datos. P.ej. Tengo una matriz de datos de 256 x 262144. Donde los 256 puntos deben ajustarse a una distribución gaussiana, y necesito 262144 de ellos.¿Cómo puedo realizar un ajuste de mínimos cuadrados sobre múltiples conjuntos de datos rápidamente?
A veces, el pico de la distribución gaussiana está fuera del rango de datos, por lo que para obtener un resultado de curva de resultado medio exacto es el mejor enfoque. Incluso si el pico está dentro del rango, el ajuste de curva da una sigma mejor porque otros datos no están en el rango.
Tengo esto funcionando para un punto de datos, usando el código de http://www.scipy.org/Cookbook/FittingData.
He tratado de repetir este algoritmo, pero parece que va a tomar algo del orden de 43 minutos para resolverlo. ¿Existe una forma rápida ya escrita de hacerlo en paralelo o de manera más eficiente?
from scipy import optimize
from numpy import *
import numpy
# Fitting code taken from: http://www.scipy.org/Cookbook/FittingData
class Parameter:
def __init__(self, value):
self.value = value
def set(self, value):
self.value = value
def __call__(self):
return self.value
def fit(function, parameters, y, x = None):
def f(params):
i = 0
for p in parameters:
p.set(params[i])
i += 1
return y - function(x)
if x is None: x = arange(y.shape[0])
p = [param() for param in parameters]
optimize.leastsq(f, p)
def nd_fit(function, parameters, y, x = None, axis=0):
"""
Tries to an n-dimensional array to the data as though each point is a new dataset valid across the appropriate axis.
"""
y = y.swapaxes(0, axis)
shape = y.shape
axis_of_interest_len = shape[0]
prod = numpy.array(shape[1:]).prod()
y = y.reshape(axis_of_interest_len, prod)
params = numpy.zeros([len(parameters), prod])
for i in range(prod):
print "at %d of %d"%(i, prod)
fit(function, parameters, y[:,i], x)
for p in range(len(parameters)):
params[p, i] = parameters[p]()
shape[0] = len(parameters)
params = params.reshape(shape)
return params
Tenga en cuenta que los datos no es necesariamente 256x262144 y he hecho algunas vueltas en fudging nd_fit para hacer este trabajo.
El código que utilizo para conseguir que esto funcione es
from curve_fitting import *
import numpy
frames = numpy.load("data.npy")
y = frames[:,0,0,20,40]
x = range(0, 512, 2)
mu = Parameter(x[argmax(y)])
height = Parameter(max(y))
sigma = Parameter(50)
def f(x): return height() * exp (-((x - mu())/sigma()) ** 2)
ls_data = nd_fit(f, [mu, sigma, height], frames, x, 0)
Nota: La solución publicado por debajo @JoeKington es grande y resuelve muy rápido. Sin embargo, no parece funcionar a menos que el área significativa del gaussiano esté dentro del área apropiada. Tendré que probar si la media todavía es precisa, ya que es lo principal para lo que uso esto.
¿Podría publicar el código que utilizó? –