Tengo algunas observaciones y quiero imitar el muestreo basado en estas observaciones. Aquí considero un modelo no paramétrico, específicamente, utilizo el suavizado del núcleo para estimar un CDF a partir de las observaciones limitadas. Luego dibujo valores al azar del CDF obtenido. El siguiente es mi código, (la idea es obtener aleatoriamente un resultado acumulativo probabilidad usando distribución uniforme, y tome el inverso de la CDF con respecto al valor de probabilidad)
x = [randn(100, 1); rand(100, 1)+4; rand(100, 1)+8];
[f, xi] = ksdensity(x, 'Function', 'cdf', 'NUmPoints', 300);
cdf = [xi', f'];
nbsamp = 100;
rndval = zeros(nbsamp, 1);
for i = 1:nbsamp
p = rand;
[~, idx] = sort(abs(cdf(:, 2) - p));
rndval(i, 1) = cdf(idx(1), 1);
end
figure(1);
hist(x, 40)
figure(2);
hist(rndval, 40)
Como se muestra en el código, utilicé un ejemplo sintético para probar mi procedimiento, pero el resultado es insatisfactorio, como se ilustra en las dos figuras a continuación (la primera es para las observaciones simuladas y la segunda muestra el histograma extraído del CDF estimado) :
¿Hay alguien que sepa dónde está el problema? Gracias de antemano.
fuente
Respuestas:
Un estimador de densidad de kernel (KDE) produce una distribución que es una mezcla de ubicación de la distribución de kernel, por lo que para dibujar un valor de la estimación de densidad de kernel, todo lo que necesita hacer es (1) dibujar un valor de la densidad de kernel y luego (2) seleccione independientemente uno de los puntos de datos al azar y agregue su valor al resultado de (1).
Aquí está el resultado de este procedimiento aplicado a un conjunto de datos como el de la pregunta.
El histograma a la izquierda representa la muestra. Como referencia, la curva negra traza la densidad de la que se extrajo la muestra. La curva roja traza el KDE de la muestra (usando un ancho de banda estrecho). (No es un problema, ni siquiera inesperado, que los picos rojos sean más cortos que los negros: el KDE extiende las cosas, por lo que los picos se reducirán para compensar).
El histograma de la derecha muestra una muestra (del mismo tamaño) del KDE. Las curvas negras y rojas son las mismas que antes.
Evidentemente, el procedimiento utilizado para tomar muestras de la densidad funciona. También es extremadamente rápido: la
R
implementación a continuación genera millones de valores por segundo desde cualquier KDE. Lo he comentado mucho para ayudar a portar a Python u otros idiomas. El algoritmo de muestreo en sí se implementa en la funciónrdens
con las líneas.rkernel
dibujan
muestras iid de la función del kernel mientrassample
dibujan
muestras con reemplazo de los datosx
. El operador "+" agrega las dos matrices de muestras componente por componente.Para aquellos que desean una demostración formal de corrección, la ofrezco aquí. Deje que represente la distribución del núcleo con CDF y deje que los datos sean . Según la definición de una estimación del núcleo, el CDF de KDE esF K x = ( x 1 , x 2 , … , x n )K FK x=(x1,x2,…,xn)
La receta anterior dice que se extrae de la distribución empírica de los datos (es decir, se alcanza el valor con probabilidad para cada ), se extrae independientemente una variable aleatoria de la distribución del núcleo y se suma. Te debo una prueba de que la función de distribución de es la de KDE. Comencemos con la definición y veamos a dónde lleva. Deje ser cualquier número real. Condicionamiento en dax i 1 / n i Y X + Y x XX xi 1/n i Y X+Y x X
según lo reclamado.
fuente
Primero toma muestras del CDF invirtiéndolo. El CDF inverso se llama función cuantil; es un mapeo desde [0,1] al dominio de la RV. Luego se muestrean RVs aleatorias uniformes como percentiles y se pasan a la función cuantil para obtener una muestra aleatoria de esa distribución.
fuente
Aquí, también quiero publicar el código de Matlab siguiendo la idea descrita por whuber, para ayudar a aquellos que están más familiarizados con Matlab que con R.
El siguiente es el resultado:
Por favor, dígame si alguien encuentra algún problema con mi comprensión y el código. Gracias.
fuente
Sin mirar demasiado de cerca su implementación, no entiendo completamente su procedimiento de indexación para extraer del ICDF. Creo que sacas del CDF, no es inverso. Aquí está mi implementación:
fuente