es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Dificultad para ajustarse a la distribución gaussiana

Se me han dado dos secuencias finitas (largas) (es decir, matrices numpy) ‘x’ e ‘y’ de la misma longitud. Su gráfico se muestra aquí:

aquí.

La matriz ‘x’ utiliza el eje x y es monótonamente creciente. Mi objetivo es ajustar el gráfico con una distribución gaussiana de manera que se preserve el “pico principal”, que se ve algo así:

esto.

Aquí está una parte de mi código:

import numpy as np
import matplotlib.pyplot as plt
from astropy import modeling

fitter = modeling.fitting.LevMarLSQFitter()
model = modeling.models.Gaussian1D(amplitude = np.max(y), mean = y[np.argmax(x)],stddev = 1) #(1)
fitted_model = fitter(model, x, y)
plt.plot(x,fitted_model(x),linewidth=0.7, color = 'black')

plt.plot(x,y,linewidth=0.1, color = 'black')
plt.savefig('result.png', dpi = 1200)

Mi código resulta en lo siguiente:

lo siguiente.

Permanece igual si cambio la desviación estándar en la línea (1). Supongo que debo haber cometido algunos errores en la línea (1), pero no tengo idea de por qué no está funcionando. Si esto no es posible en ‘astropy’, ¿hay alguna solución alternativa?

Actualizar:

Como se menciona en un comentario, creo que la distribución Gaussiana puede no ser la mejor opción. De hecho, creo que estoy buscando algo similar a una curva de perfusión. (En la imagen, AUC significa “área bajo la curva para tiempo infinito” y “mTT” significa “tiempo promedio de tránsito”). La ecuación en la imagen no es precisa. El objetivo es asegurarse de que el pico esté mejor ajustado. La curva no necesita seguir los datos originales muy de cerca cuando ‘x’ está cerca de cero o infinito. Solo necesita mantener la suavidad y bajar aproximadamente a cero (como en el caso de la Gaussiana). Necesito pistas sobre qué tipo de función puede satisfacer mejor tal demanda.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Primero, abordemos el problema con el ajuste gaussiano. La línea (1) en tu código ajusta una función gaussiana unidimensional a tus datos, lo cual puede no ser la mejor elección dependiendo de las características de tus datos. Un problema con el ajuste gaussiano es que no tiene límites, lo que significa que eventualmente tenderá hacia el infinito a medida que x tienda hacia el infinito. En contraste, tus datos parecen acercarse a cero a medida que x aumenta, por lo que una gaussiana puede no ser la mejor elección.

    Una alternativa podría ser ajustar una función logística a tus datos, que está limitada entre 0 y 1 y tiene una forma similar a una gaussiana. Puedes definir una función logística en Python de la siguiente manera:

    def logistico(x, a, b, c, d):
        return a / (1 + np.exp(-c * (x - d))) + b
    

    Esta función tiene cuatro parámetros: a determina el valor máximo, b determina el valor mínimo, c determina la pendiente de la curva y d determina el punto medio de la curva.

    Para ajustar esta función a tus datos, puedes usar el mismo código que antes pero reemplazar modeling.models.Gaussian1D por logistico:

    ajustador = modeling.fitting.LevMarLSQFitter()
    modelo = modeling.models.custom_model(logistico, independent_vars=['x'])
    modelo_ajustado = ajustador(modelo, x, y, nan_policy='omit')
    plt.plot(x, modelo_ajustado(x), linewidth=0.7, color='negro')
    

    Esto debería darte un ajuste mejor que está limitado y sigue la forma general de tus datos.

    Ahora, en cuanto a la curva de perfusión, existen muchas funciones que podrían ajustarse a este tipo de datos, dependiendo de cómo quieras utilizar el ajuste. Una posibilidad es usar una distribución gamma, que se utiliza comúnmente para modelar tiempos de espera y tiempos de transición en sistemas. La distribución gamma tiene dos parámetros, k y θ, que se pueden estimar a partir de tus datos utilizando la estimación de máxima verosimilitud.

    Aquí tienes un ejemplo de cómo ajustar una distribución gamma a tus datos usando scipy:

    from scipy.stats import gamma
    
    # Ajustar distribución gamma a los datos
    params = gamma.fit(y)
    k, θ = params
    
    # Generar curva gamma
    rango_x = np.linspace(0, np.max(x), 100)
    rango_y = gamma.pdf(rango_x, k, 0, θ) * np.max(y)
    
    # Graficar datos originales y curva gamma
    plt.plot(x, y, linewidth=0.1, color='negro')
    plt.plot(rango_x, rango_y, linewidth=0.7, color='rojo')
    plt.savefig('resultado.png', dpi=1200)
    

    Esto debería darte una curva gamma que se ajusta bien a tus datos y tiene una forma similar a la curva de perfusión que publicaste.

    Por supuesto, la elección de la distribución depende de tu aplicación específica y de lo que quieras hacer con el ajuste. Puede haber otras distribuciones que se ajusten mejor a tus datos, o puede que desees utilizar un método no paramétrico como la estimación de densidad de kernel. Todo depende de lo que estés intentando lograr.

Comments are closed.