Saltar al contenido

Ajustar un gaussiano bidimensional a un conjunto de píxeles 2D

Alicia, miembro de este staff, nos hizo el favor de crear este enunciado ya que domina muy bien este tema.

Solución:

La respuesta de Sjoerd aplica el poder de MathematicaSon herramientas de ajuste de modelos muy generales. Aquí hay una solución de menor tecnología.

Si desea ajustar una distribución gaussiana a un conjunto de datos, puede encontrar su matriz media y de covarianza, y la gaussiana que desea es la que tiene los mismos parámetros. Para los gaussianos, este es en realidad el ajuste óptimo en el sentido de ser el estimador de máxima verosimilitud; para otras distribuciones, esto puede no funcionar igualmente bien, por lo que querrá NonlinearModelFit.

Una arruga es que sus datos no caen a cero sino a algo como Min[data] $ approx 0.0387 $, pero podemos deshacernos de eso fácilmente simplemente restándolo. A continuación, normalizo el array para sumar $ 1 $, de modo que pueda tratarlo como una distribución de probabilidad discreta. (Todo lo que esto realmente hace es permitirme evitar dividir entre Total[data, Infinity] cada vez en lo siguiente.)

min = Min[data];
sum = Total[data - min, Infinity];
p = (data - min)/sum;

Ahora encontramos la media y la covarianza. MathematicaLas funciones de ‘no parecen funcionar con datos ponderados, así que simplemente lanzaremos las nuestras.

m, n = Dimensions[p];
mean = Sum[i, j p[[i, j]], i, 1, m, j, 1, n];
cov = Sum[Outer[Times, i, j - mean, i, j - mean] p[[i, j]], i, 1, m, j, 1, m];

Podemos obtener fácilmente la distribución de probabilidad para el gaussiano con esta media y covarianza. Por supuesto, si queremos hacer coincidir los datos originales, tenemos que reescalarlos y retrocederlos.

f[i_, j_] := PDF[MultinormalDistribution[mean, cov], i, j] // Evaluate;
g[i_, j_] := f[i, j] sum + min;

La coincidencia no es tan mala, aunque los datos tienen dos jorobas donde el gaussiano tiene uno. También puede comparar el ajuste a través de un gráfico de contorno. (Utilice la información sobre herramientas para comparar niveles de contorno).

Show[ListPlot3D[data, PlotStyle -> None], 
 Plot3D[g[i, j], j, 1, 9, i, 1, 9, MeshStyle -> None, 
  PlotStyle -> Opacity[0.8]], PlotRange -> All]
Show[ListContourPlot[data, Contours -> Range[0.05, 0.25, 0.025], 
  ContourShading -> None, ContourStyle -> ColorData[1, 1], InterpolationOrder -> 3], 
 ContourPlot[g[i, j], j, 1, 9, i, 1, 9, Contours -> Range[0.05, 0.25, 0.025], 
  ContourShading -> None, ContourStyle -> ColorData[1, 2]]]

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

Las varianzas a lo largo de los ejes principales son los valores propios de la matriz de covarianza, y las desviaciones estándar (que supongo que llama semiejes) son sus raíces cuadradas.

[email protected][cov]
(* 1.86325, 1.50567 *)

data3D = Flatten[MapIndexed[#2[[1]], #2[[2]], #1 &, data, 2], 1];

fm = NonlinearModelFit[data3D, 
        a E^(-(((-my + y) Cos[b] - (-mx + x) Sin[b])^2/(2 sy^2)) - 
               ((-mx + x) Cos[b] + (-my + y) Sin[b])^2/(2 sx^2)), 
        a, 0.1, b, 0, mx, 4.5, my, 4.5, sx, 3, sy, 3, 
        x, y
     ]

Show[
   ListPlot3D[data3D, PlotStyle -> None, MeshStyle -> Red],
   Plot3D[fm["BestFit"], x, 1, 9, y, 1, 9, PlotRange -> All, 
          PlotStyle -> Opacity[0.9], Mesh -> None]
]

ingrese la descripción de la imagen aquí

fm["BestFitParameters"]

a -> 0.1871830545, b -> -0.4853901689, mx -> 5.152549499, my -> 5.092511036, sx -> 2.756524919, sy -> 2.072163433

Comenzando con sus datos, trazaría los datos de esta manera:

data3D = Flatten[MapIndexed[#2[[1]], #2[[2]], #1 &, data, 2], 1]

y luego cuéntelo como:

data2 = Flatten[Table[#[[1]], #[[2]], 100 #[[3]]] & /@ data3D, 1];

y luego usa esta función:

FindDistributionParameters[data2, 
MultinormalDistribution[a, b, c, d, e, f]]

para encontrar los medios y la cobertura de los datos. Y luego podría hacer otras cosas con la distribución, como crear un objeto de distribución usando:

edist = EstimatedDistribution[data2, 
MultinormalDistribution[a, b, c, d, e, f]]

y luego verifique la distribución con los datos, usando:

dtest = DistributionFitTest[data2, edist, "HypothesisTestData"]

y cree una tabla de los resultados de la prueba, usando:

N[dtest["TestDataTable", All]]

o individualmente

AndersonDarlingTest[data2, edist, "TestConclusion"]
CramerVonMisesTest[data2, edist, "TestConclusion"]
JarqueBeraALMTest[data2, "TestConclusion"]
MardiaKurtosisTest[data2, "TestConclusion"]
MardiaSkewnessTest[data2, "TestConclusion"]
PearsonChiSquareTest[data2, edist, "TestConclusion"]
ShapiroWilkTest[data2, "TestConclusion"]

Ahora, no soy un estadístico, y probablemente solo sé suficientes estadísticas para ser peligroso, y no estoy familiarizado con todas las pruebas enumeradas en la tabla, pero sospecho que uno de esos números pequeños es significativo para medir qué tan cerca los datos reales se ajustan a la distribución, es decir, qué tan “gaussiano” es el conjunto de puntos.

También podría trazar los datos de la siguiente manera y juzgar visualmente la gaussiness de los datos usando estas funciones (según la respuesta de VLC a la pregunta 2984)

Show[DensityHistogram[d, .2, ColorFunction -> (Opacity[0] &), 
Method -> "DistributionAxes" -> "Histogram"], ListPlot[d]]

o estos:

GraphicsColumn[
Table[SmoothDensityHistogram[d, ColorFunction -> "DarkRainbow", 
Method -> "DistributionAxes" -> p, ImageSize -> 500, 
BaseStyle -> FontFamily -> "Helvetica", 
LabelStyle -> Bold], p, True, "SmoothHistogram", "BoxWhisker"]]

Aquí puedes ver las reseñas y valoraciones de los usuarios

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *