J'ai quelques observations, et je veux imiter l'échantillonnage basé sur ces observations. Ici, je considère un modèle non paramétrique, en particulier, j'utilise le lissage du noyau pour estimer un CDF à partir des observations limitées.Puis je tire des valeurs au hasard à partir du CDF obtenu.Le code suivant est (l'idée est d'obtenir au hasard un cumulatif probabilité en utilisant une distribution uniforme, et prendre l'inverse du CDF par rapport à la valeur de probabilité)
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)
Comme indiqué dans le code, j'ai utilisé un exemple synthétique pour tester ma procédure, mais le résultat n'est pas satisfaisant, comme illustré par les deux figures ci-dessous (la première est pour les observations simulées, et la deuxième figure montre l'histogramme tiré de CDF estimé) :
Y a-t-il quelqu'un qui sait où est le problème? Merci d'avance.
la source
Réponses:
Un estimateur de densité de noyau (KDE) produit une distribution qui est un mélange d'emplacements de la distribution de noyau, donc pour tirer une valeur de l'estimation de densité de noyau, tout ce que vous devez faire est (1) de tirer une valeur de la densité de noyau, puis (2) sélectionnez indépendamment l'un des points de données au hasard et ajoutez sa valeur au résultat de (1).
Voici le résultat de cette procédure appliquée à un ensemble de données comme celui de la question.
L'histogramme à gauche représente l'échantillon. Pour référence, la courbe noire représente la densité à partir de laquelle l'échantillon a été prélevé. La courbe rouge trace le KDE de l'échantillon (en utilisant une bande passante étroite). (Ce n'est pas un problème, ni même inattendu, que les pics rouges sont plus courts que les pics noirs: le KDE répartit les choses, donc les pics s'abaissent pour compenser.)
L'histogramme à droite représente un échantillon (de la même taille) du KDE. Les courbes noires et rouges sont les mêmes qu'avant.
De toute évidence, la procédure utilisée pour échantillonner à partir de la densité fonctionne. C'est aussi extrêmement rapide: l'
R
implémentation ci-dessous génère des millions de valeurs par seconde à partir de n'importe quel KDE. Je l'ai fortement commenté pour aider au portage vers Python ou d'autres langages. L'algorithme d'échantillonnage lui-même est implémenté dans la fonctionrdens
avec les lignesrkernel
dessine desn
échantillons iid à partir de la fonction noyau tandis quesample
dessine desn
échantillons avec remplacement à partir des donnéesx
. L'opérateur "+" ajoute les deux tableaux d'échantillons composant par composant.comme revendiqué.
la source
Vous échantillonnez à partir du CDF d'abord en l'inversant. Le CDF inverse est appelé la fonction quantile; c'est une mise en correspondance de [0,1] avec le domaine du RV. Vous échantillonnez ensuite des RV uniformes aléatoires en tant que centiles et les passez à la fonction quantile pour obtenir un échantillon aléatoire à partir de cette distribution.
la source
Ici, je veux également publier le code Matlab suivant l'idée décrite par whuber, pour aider ceux qui connaissent mieux Matlab que R.
Le résultat est le suivant:
Veuillez me dire si quelqu'un trouve un problème avec ma compréhension et le code. Je vous remercie.
la source
Sans regarder de trop près dans votre implémentation, je n'obtiens pas entièrement votre procédure d'indexation à tirer de l'ICDF. Je pense que vous tirez du CDF, pas son inverse. Voici ma mise en œuvre:
la source