Dis que j'ai plusieurs histogrammes, chacun avec des comptes à différents emplacements de bacs forts> (sur un axe réel).
par exemple Comment puis-je normaliser ces histogrammes afin que je reçois pdfs fort> où l'intégration de chaque pdf forte> ajoute à un dans une donnée gamme (par exemple 0 et 100)? p> Nous pouvons supposer que l'histogramme compte les événements sur la plupart des implémentations que j'ai vues sont basées, par exemple, par exemple, sur Notez que toutes les réponses actuelles supposent que nous sommes En regardant une variable aléatoire qui vit (-inf, + inf). C'est bien comme une approximation approximative, mais cela peut ne pas être le cas en fonction de l'application, où la variable peut être définie dans une autre plage Scikit-apprendre < / code>
) qui commencent par les données. Dans mon cas, je dois le faire à partir des histogrammes, car je n'ai pas accès aux données d'origine. P> Mise à jour: H2>
[A, B] code> (par exemple, 0 et 100 dans le cas ci-dessus. ) p> p>
3 Réponses :
Le point principal de la délicatesse est défini sur ce qui entraînerait des parcelles comme les suivantes (une pour chaque histogramme):
p> p> bin_edges code> car, techniquement, ils pourraient être n'importe où. J'ai choisi le milieu entre chaque paire de centres de bacs. Il y a probablement d'autres moyens de faire cela, mais voici un:
Je suis confus. Qu'est-ce que c'est censé calculer? Quand j'exécute cela, je reçois un tableau complet de 0s pour bin_counts code>.
Désolé, faites votre bin_counts code> avoir dtype de flotteur en premier. Je vais éditerai.
Merci - quel code exactement de votre réponse vous avez utilisé pour générer la parcelle inférieure? (qui ressemble à peu près à droite). Était-ce celui utilisant des données "fausses"?
Tout cela, courir ensemble. Assurez-vous d'exécuter la partie «KDE» avant de normaliser le tableau code> bin_counts code> (car je normalisé en place) et les poids de KDE utilisant np.repeat code> et nécessitent les comptes pour être entiers . Notez que la KDE a une probabilité finie en dehors du domaine.
Merci - bien que ce ne soit toujours pas clair pour moi. Souhaitez-vous peut-être réorganiser la réponse à montrer quelle extrait de code vous exécutez de bout en bout b> pour obtenir la parcelle?
Désolé. Edité --- Exécutez maintenant tout le code formaté, dans l'ordre et que vous devriez obtenir la parcelle. (Après avoir créé la liste code> Liste des histogrammes aléatoires, bien sûr). Cela vient de parcourir la dernière entrée dans Histeurs code>. Mettez le
PLT code> Fonctions à l'intérieur de la boucle si vous souhaitez tracer chacun.
Hmm je n'obtiens pas le même résultat. Je pense que vous normalisez le bin_counts code> avant
plt.step code> de sorte que la plage est à peu près équivalente. Comment avez-vous normalisé les comptes?
Oh désolé, changé de nom avariable. plt.step code> avec
bin_density code> maintenant
J'ai mis à jour votre réponse pour refléter ce changement. J'espère que ça ne vous dérange pas
Merci de l'acceptation. Je pense avoir la contrainte totale sur sur [A, B] code>, vous devrez faire un ajustement des moindres carrés ou quelque chose avec la contrainte que l'intégration est égale à une. La question est alors quelle fonctionnelle pour affronteriez-vous (ici, c'est une constante par étapes ou une somme de Gaussiens).
Oui - je viens de gérer aussi SeaNorn Code> a>. J'ai utilisé par exemple leur
violonplots code>, qui semblait estimer un PDF à partir de données d'histogramme. Je ne sais pas ce qui est sous le capot.
Voici une possibilité. Je ne suis pas si fou de ça, mais cela fonctionne en quelque sorte. Notez que les histogrammes sont un peu étrange, car la largeur de la corbeille est assez variable.
import numpy as np from matplotlib import pyplot from sklearn.mixture.gmm import GMM from sklearn.grid_search import GridSearchCV def generate_random_histogram(): # Random bin locations between 0 and 100 bin_locations = np.random.rand(10,) * 100 bin_locations.sort() # Random counts on those locations bin_counts = np.random.randint(50, size=len(bin_locations)) return {'loc': bin_locations, 'count':bin_counts} def bin_widths(loc): widths = [] for i in range(len(loc)-1): widths.append(loc[i+1] - loc[i]) widths.append(widths[-1]) widths = np.array(widths) return widths def sample_from_hist(loc, count, size): n = len(loc) tot = np.sum(count) widths = bin_widths(loc) lowers = loc - widths uppers = loc + widths probs = count / float(tot) bins = np.argmax(np.random.multinomial(n=1, pvals=probs, size=(size,)),1) return np.random.uniform(lowers[bins], uppers[bins]) # Generate the histogram hist = generate_random_histogram() # Sample from the histogram sample = sample_from_hist(hist['loc'],hist['count'],np.sum(hist['count'])) # Fit a GMM param_grid = [{'n_components':[1,2,3,4,5]}] def scorer(est, X, y=None): return np.sum(est.score(X)) grid_search = GridSearchCV(GMM(), param_grid, scoring=scorer).fit(np.reshape(sample,(len(sample),1))) gmm = grid_search.best_estimator_ # Sample from the GMM gmm_sample = gmm.sample(np.sum(hist['count'])) # Plot the resulting histograms and mixture distribution fig = pyplot.figure() ax1 = fig.add_subplot(311) widths = bin_widths(hist['loc']) ax1.bar(hist['loc'], hist['count'], width=widths) ax2 = fig.add_subplot(312, sharex=ax1) ax2.hist(gmm_sample, bins=hist['loc']) x = np.arange(min(sample), max(sample), .1) y = np.exp(gmm.score(x)) ax3 = fig.add_subplot(313, sharex=ax1) ax3.plot(x, y) pyplot.show()
C'est une excellente réponse. Merci@jcrudy. Je Certainement b> serait intéressé à voir une solution avec PYMC.
Voici un moyen de le faire avec PYMC. Cette méthode utilise un nombre fixe de composants (N_Components) dans le modèle de mélange. Vous pouvez essayer de joindre un antérieur à N_Components et d'échantillonner à ce sujet avant. Sinon, vous pouvez simplement choisir quelque chose de raisonnable ou utiliser la technique de recherche de la grille de mon autre réponse pour estimer le nombre de composants. Dans le code ci-dessous, j'ai utilisé 10000 itérations avec une gravure de 9 000, mais cela pourrait ne pas être suffisant pour obtenir de bons résultats. Je suggérerais d'utiliser une brûlure beaucoup plus importante. J'ai aussi choisi les prores un peu arbitrairement, de sorte que celles-ci pourraient être quelque chose à regarder. Vous devrez expérimenter avec elle. Bonne chance à vous. Voici le code.
import numpy as np import pymc as mc import scipy.stats as stats from matplotlib import pyplot def generate_random_histogram(): # Random bin locations between 0 and 100 bin_locations = np.random.rand(10,) * 100 bin_locations.sort() # Random counts on those locations bin_counts = np.random.randint(50, size=len(bin_locations)) return {'loc': bin_locations, 'count':bin_counts} def bin_widths(loc): widths = [] for i in range(len(loc)-1): widths.append(loc[i+1] - loc[i]) widths.append(widths[-1]) widths = np.array(widths) return widths def mixer(name, weights, value=None): n = value.shape[0] def logp(value, weights): vals = np.zeros(shape=(n, weights.shape[1]), dtype=int) vals[:, value.astype(int)] = 1 return mc.multinomial_like(x = vals, n=1, p=weights) def random(weights): return np.argmax(np.random.multinomial(n=1, pvals=weights[0,:], size=n), 1) result = mc.Stochastic(logp = logp, doc = 'A kernel smoothing density node.', name = name, parents = {'weights': weights}, random = random, trace = True, value = value, dtype = int, observed = False, cache_depth = 2, plot = False, verbose = 0) return result def create_model(lowers, uppers, count, n_components): n = np.sum(count) lower = min(lowers) upper = min(uppers) locations = mc.Uniform(name='locations', lower=lower, upper=upper, value=np.random.uniform(lower, upper, size=n_components), observed=False) precisions = mc.Gamma(name='precisions', alpha=1, beta=1, value=.001*np.ones(n_components), observed=False) weights = mc.CompletedDirichlet('weights', mc.Dirichlet(name='weights_ind', theta=np.ones(n_components))) choice = mixer('choice', weights, value=np.ones(n).astype(int)) @mc.observed def histogram_data(value=count, locations=locations, precisions=precisions, weights=weights): if hasattr(weights, 'value'): weights = weights.value lower_cdfs = sum([weights[0,i]*stats.norm.cdf(lowers, loc=locations[i], scale=np.sqrt(1.0/precisions[i])) for i in range(len(weights))]) upper_cdfs = sum([weights[0,i]*stats.norm.cdf(uppers, loc=locations[i], scale=np.sqrt(1.0/precisions[i])) for i in range(len(weights))]) bin_probs = upper_cdfs - lower_cdfs bin_probs = np.array(list(upper_cdfs - lower_cdfs) + [1.0 - np.sum(bin_probs)]) n = np.sum(count) return mc.multinomial_like(x=np.array(list(count) + [0]), n=n, p=bin_probs) @mc.deterministic def location(locations=locations, choice=choice): return locations[choice.astype(int)] @mc.deterministic def dispersion(precisions=precisions, choice=choice): return precisions[choice.astype(int)] data_generator = mc.Normal('data', mu=location, tau=dispersion) return locals() # Generate the histogram hist = generate_random_histogram() loc = hist['loc'] count = hist['count'] widths = bin_widths(hist['loc']) lowers = loc - widths uppers = loc + widths # Create the model model = create_model(lowers, uppers, count, 5) # Initialize to the MAP estimate model = mc.MAP(model) model.fit(method ='fmin') # Now sample with MCMC model = mc.MCMC(model) model.sample(iter=10000, burn=9000, thin=300) # Plot the mu and tau traces mc.Matplot.plot(model.trace('locations')) pyplot.show() # Get the samples from the fitted pdf sample = np.ravel(model.trace('data')[:]) # Plot the original histogram, sampled histogram, and pdf lower = min(lowers) upper = min(uppers) kde = stats.gaussian_kde(sample) x = np.arange(0,100,.1) y = kde(x) fig = pyplot.figure() ax1 = fig.add_subplot(311) pyplot.xlim(lower,upper) ax1.bar(loc, count, width=widths) ax2 = fig.add_subplot(312, sharex=ax1) ax2.hist(sample, bins=loc) ax3 = fig.add_subplot(313, sharex=ax1) ax3.plot(x, y) pyplot.show()
C'est une réponse très intéressante. Quelque chose que je ne comprends pas, d'un point de vue statistique, pourquoi la réponse de l'Askewchan peut s'en tirer sans devoir estimer le nombre de mélanges. Utilise-t-il une méthode bayésienne non paramétrique? Comment votre réponse a-t-elle relativement à son?
Il semble certainement utiliser une méthode non paramétrique. Cela m'a fait me demander, PYMC incluait-il les intégrés à modéliser des distributions non paramétriques?
Je n'ai pas regardé la réponse de @ Askewchan en détail, mais si je comprends bien, il définit implicitement un GMM avec un composant pour chaque barre de l'histogramme, où le poids de ce composant est le nombre de points de données contribuant à cette barre et La variance est déterminée par la bande passante de la KDE. Dans cette réponse, je choisis simplement le nombre de composants dans le mélange arbitrairement. Dans mon autre réponse, j'utilise une recherche de grille pour trouver le nombre de composants. Je pense que PYMC a maintenant un nœud stochastique basé sur la densité de noyau disponible. Voir Stackoverflow.com/a/17934913/1572508 .
D'un point de vue statistique, je ne suis pas sûr de la manière dont aucune de ces trois méthodes peut être justifiée. La question à poser est la suivante: quelle taille peut-on dire que le PDF estimé est au PDF des données qui ont généré l'histogramme d'origine? Avec ces histogrammes, je pense qu'il n'y a pas beaucoup d'espoir d'une reconstruction fiable, simplement parce que les bacs sont larges et qu'il n'y a pas de points de données. Cependant, ils ne sont que des exemples. Un histogramme avec des bacs plus étroits et plus de données feraient mieux. La façon de savoir serait de faire des simulations avec des PDF connus.
Merci @aaronhall j'ai corrigé l'OP.
Je pense que c'est une très bonne question, je voterais, mais je suis à court de voix pour la journée. Je suis d'accord, je ne pense pas que vous devriez commencer avec l'hypothèse de la normalité.
Un KDE (gaussien ou autre) fonctionne de manière intrinsèquement sur les données, de sorte que cela ne vous aidera pas dans votre cas.
À quoi sert le PDF? Y a-t-il des contraintes à ce sujet (telles que les limites inférieures ou supérieures connues sur les données)? Savez-vous autre chose à propos de la distribution de ces données? Dans tous les cas, je pense que vous devriez penser dans le sens des distributions de mélange. Lequel que vous utilisez spécifiquement dépendrait des réponses à ces questions.
Merci @jcrudy, j'ai probablement un mélange de gaussiens, mais je ne connais pas le nombre de mélanges. Est ce que ça aide?
Vous attendez-vous à ce que
bin_locations code> décrit les centres des bacs? Sinon, (s'ils sont des bords des bacs), vous devriez avoir
len (bin_counts) = len (bin_locations) - 1 code>
@ASKEWCHAN OUI,
bin_locations code> sont les emplacements centraux
Il y avait un fil sur ce sujet sur la liste de diffusion SCIKIT apprendre il y a un moment. Voici un lien: Sourceforge.net/p/scikit-learn/mailman/ Message / 31984328
Lorsque vous dites "avoir la même gamme de x" voulez-vous dire que tous les
bin_locations code> doivent être identiques ou pourrez-vous dire simplement
plage code> comme dans la plage
Code> Mot-clé Arg to
np.histogramme code> qui indique juste les limites inférieure et supérieure du domaine?
@ASKEWCHAN: Ce que je veux dire, c'est que nous pouvons supposer que toute la probabilité est contenue dans une plage spécifiée (
0 code> à
100 code> dans l'OP) pour chaque histogramme.
Vous l'avez édité légèrement, mais pour moi "PDF" n'est toujours pas bien défini dans votre question. Voulez-vous une vraie fonction définie sur l'ensemble du domaine (comme ce que
gaussian_kde code> ou une interpolation reviendrait)? Ou est-ce correct d'avoir un fichier PDF semblable à une matrice avec des valeurs à
bin_locations code>, tant qu'il est correctement normalisé sur le domaine? Ou peut-être que vous voulez quelque chose entre entre-temps, dites-vous des bacs uniformément espacés standardisés que les valeurs de tous les histogrammes sont données à (comme
np.linspace (0.100) code>)?
@ASKEWCHAN Je veux un vrai PDF défini sur une plage pré-spécifiée, dans ce cas
[0.100] code>. Pour que ce soit un PDF, l'intégrale du PDF dans la plage devrait être 1. Puisque nous travaillons sur le domaine réel, je devrais être capable de le discrétiser à des intervalles réguliers (par exemple, en utilisant
np.linspace code>).
Si le PDF s'intègre à 1 sur [0, 100], il n'est pas un mélange de Gaussiens. Voulez-vous dire que cela signifie qu'un soutien de [0, 100] est une contrainte difficile, ou n'essayez-vous que d'illustrer que cela doit être un véritable PDF pour une distribution continue avec support inclut [0,100]?
@jcrudy - Vous êtes correct, ils ne seraient pas un mélange de gaussiens, mais si vous avez la contrainte que la densité est contrainte dans
[A, B] code> est trop difficile, nous pouvons détendre la contrainte pour
(- INF, INF) code>
Ensuite, vous devez interpoler. Il existe de nombreuses options et sans plus d'informations supplémentaires, il n'y a aucun moyen de maximiser l'entropie. Le KDE I a affiché plus tôt s'intègre à 1 sur (-Inf, Inf) et le réseau normalisé s'intègre à 1 sur [0,100], mais je supposais que vous avez trouvé ceux-ci insatisfaisants.
"Nous pouvons supposer que l'histogramme compte les événements sur la taille de la corbeille prédéfinie (par exemple 10)" Nous ne pouvons pas si vous donnez des centres de bacs aléatoires. Comment ces
BIN_LOCATIONS CODE> ont-ils une binsisation uniforme:
[. 1 , 5, 50, 90] code>?
Je viens de poster une possibilité GMM. C'est un peu faible car cela implique de se réaménager à partir de l'histogramme, puis de fixer une GMM aux données rénovées. Avez-vous envisagé d'utiliser PYMC? Avec PYMC, il pourrait être possible de faire quelque chose d'un peu plus efficace (statistiquement parlant). Cependant, l'inférence bayésienne peut être un trou de lapin.
@ASKEWCHAN Nous pouvons faire le
bin_size code> beaucoup plus petit si cela provoque un problème. Techniquement parlant, pour rendre le problème bien défini, les numéros d'histogramme doivent correspondent à b> correspondant à intervalles b> (sinon, il n'a pas de sens de parler de PDFS). Ces données sont fausses après tout, mais chaque compte doit correspondre à un intervalle bien défini.
Merci @jcrudy - Je le regarde maintenant. Oui - T a étiqueté la question avec
PYMC code>, puisque je pensais
pymc code> pourrait aider avec elle.
Oh, je n'avais pas remarqué la balise. Je verrai si je peux préparer un exemple de PYMC rapide.