Trouver le P optimal (X | Y) étant donné que j'ai un modèle qui a de bonnes performances lorsqu'il est formé sur P (Y | X)

11

Des données d'entrée:

X -> caractéristiques du t-shirt (couleur, logo, etc.)

Y -> marge bénéficiaire

J'ai formé une forêt aléatoire sur les et ci-dessus et j'ai atteint une précision raisonnable sur les données d'un test. Donc j'aiXY

P(Y|X) .

Maintenant, je voudrais trouver c'est-à-dire la distribution de probabilité des caractéristiques étant donné que je m'attends à une telle marge bénéficiaire.P(X|Y)X

Comment faire cela avec une forêt aléatoire (ou tout autre modèle discriminant)?

Une suggestion pour moi pourrait être de commencer par un modèle génératif plutôt qu'un modèle discriminant. Mais, ma compréhension est que le modèle génératif nécessite généralement beaucoup de données pour s'entraîner, à moins que cela ne fasse des hypothèses très restrictives telles que l'indépendance conditionnelle des dans le cas de Naive Bayes?X

Une autre suggestion pourrait être de simplement commuter et et de former un modèle discriminant. Maintenant, sera la marge bénéficiaire et sera les caractéristiques d'un maillot. me donnera directement la distribution de probabilité des caractéristiques du t-shirt, compte tenu d'une marge bénéficiaire cible. Mais cette approche ne me semble pas juste, car j'ai toujours pensé à comme variables occasionnelles et à pour être un effet.XYXYP(Y|X)XY

De plus, d'après ce que j'ai entendu, une question similaire a été posée pour la découverte de médicaments et des algorithmes ont été conçus pour proposer de nouveaux médicaments candidats qui ont un haut degré de succès. Quelqu'un peut-il me diriger vers des recherches dans ce domaine?

Mise à jour:

Je suis tombé sur ceci et cela qui parle des GAN utilisés pour la découverte de médicaments. Les réseaux adverses génératifs semblent être un bon choix pour mon énoncé de problème, j'ai donc lu à leur sujet. Mais une chose que j'ai comprise est que GAN génère des échantillons de manière non supervisée. Ils essaient de produire un échantillon, ce qui revient à capturer d'abord la distribution sous-jacente de X, puis à échantillonner à partir de cette distribution. Mais je m'intéresse à X | Y. X et Y sont définis ci-dessus. Dois-je explorer autre chose que les GAN? Des pointeurs s'il vous plaît?

Question de suivi:

Imaginez que j'ai un GAN formé qui a appris à fabriquer des t-shirts (échantillon de sortie Xs). Comment puis-je obtenir les 5 meilleures chemises pour un Y donné?

claudius
la source
Ceci est étroitement lié au problème du sac à dos ou à ses variantes stochastiques. Serait-il possible de le reformuler en tant que tel sous certaines hypothèses raisonnables concernant votre domaine d'entrée?
mjul
@mjul. Sry ne t'a pas compris. Veuillez développer. La proposition d'une approche différente pour résoudre le problème est toujours la bienvenue!
claudius
1
Le problème du sac à dos est un problème d'optimisation combinatoire, dont le but est d'identifier l'ensemble de fonctionnalités le plus rentable (pour vos t-shirts) en supposant que vous connaissez la valeur et le coût des fonctionnalités individuelles. Il suppose que les valeurs sont exactes et non stochastiques. Cependant, sous des hypothèses d'indépendance raisonnables, vous pourriez être en mesure de reformuler votre problème comme le problème du sac à dos ou comme l'une des variantes stochastiques qui ont également été étudiées au fil des ans. Cependant, sans plus d'informations, il n'est pas immédiatement clair que cela est possible dans votre cas.
mjul

Réponses:

10

Cette réponse a été considérablement modifiée par rapport à sa forme d'origine. Les défauts de ma réponse d'origine seront discutés ci-dessous, mais si vous souhaitez voir à peu près à quoi ressemblait cette réponse avant de faire le gros montage, jetez un œil au cahier suivant: https://nbviewer.jupyter.org/github /dmarx/data_generation_demo/blob/54be78fb5b68218971d2568f1680b4f783c0a79a/demo.ipynb

TL; DR: Utilisez un KDE (ou la procédure de votre choix) pour approximer , puis utilisez MCMC pour tirer des échantillons de , où est donné par votre modèle. À partir de ces échantillons, vous pouvez estimer le «optimal» en ajustant un deuxième KDE aux échantillons que vous avez générés et en sélectionnant l'observation qui maximise le KDE comme estimation maximale a posteriori (MAP).P(X)P(X|Y)P(Y|X)P(X)P(Y|X)X

Estimation de vraisemblance maximale

... et pourquoi cela ne fonctionne pas ici

Dans ma réponse d'origine, la technique que j'ai suggérée était d'utiliser MCMC pour effectuer une estimation du maximum de vraisemblance. Généralement, le MLE est une bonne approche pour trouver les solutions "optimales" aux probabilités conditionnelles, mais nous avons un problème ici: parce que nous utilisons un modèle discriminant (une forêt aléatoire dans ce cas), nos probabilités sont calculées par rapport aux limites de décision . En fait, cela n'a pas de sens de parler d'une solution "optimale" à un modèle comme celui-ci, car une fois que nous nous éloignerons suffisamment de la frontière de classe, le modèle ne fera que prédire celles pour tout. Si nous avons suffisamment de classes, certaines d'entre elles pourraient être complètement «entourées», auquel cas ce ne sera pas un problème, mais les classes à la frontière de nos données seront «maximisées» par des valeurs qui ne sont pas nécessairement réalisables.

Pour démontrer, je vais tirer parti du code de commodité que vous pouvez trouver ici , qui fournit la GenerativeSamplerclasse qui encapsule le code de ma réponse d'origine, du code supplémentaire pour cette meilleure solution et des fonctionnalités supplémentaires avec lesquelles je jouais (certaines fonctionnent , certains qui ne le font pas) que je n'entrerai probablement pas ici.

np.random.seed(123)
sampler = GenerativeSampler(model=RFC, X=X, y=y, 
                            target_class=2, 
                            prior=None, 
                            class_err_prob=0.05, # <-- the score we use for candidates that aren't predicted as the target class
                            rw_std=.05,          # <-- controls the step size of the random walk proposal
                            verbose=True, 
                            use_empirical=False)
samples, _ = sampler.run_chain(n=5000)

burn = 1000
thin = 20
X_s = pca.transform(samples[burn::thin,:])

# Plot the iris data
col=['r','b','g']
for i in range(3):
    plt.scatter(*X_r[y==i,:].T, c=col[i], marker='x')
plt.plot(*X_s.T, 'k')
plt.scatter(*X_s.T, c=np.arange(X_s.shape[0]))
plt.colorbar()
plt.show()

entrez la description de l'image ici

Dans cette visualisation, les x sont les vraies données et la classe qui nous intéresse est verte. Les points connectés aux lignes sont les échantillons que nous avons dessinés, et leur couleur correspond à l'ordre dans lequel ils ont été échantillonnés, avec leur position de séquence "amincie" donnée par l'étiquette de la barre de couleur à droite.

Comme vous pouvez le voir, l'échantillonneur a divergé assez rapidement des données, puis se bloque essentiellement assez loin des valeurs de l'espace des fonctionnalités qui correspondent à toutes les observations réelles. C'est clairement un problème.

Une façon de tricher consiste à modifier notre fonction de proposition pour autoriser uniquement les entités à prendre des valeurs que nous avons réellement observées dans les données. Essayons cela et voyons comment cela change le comportement de notre résultat.

np.random.seed(123)
sampler = GenerativeSampler(model=RFC, X=X, y=y, 
                            target_class=2, 
                            prior=None, 
                            class_err_prob=0.05, 
                            verbose=True, 
                            use_empirical=True) # <-- magic happening under the hood
samples, _ = sampler.run_chain(n=5000)

X_s = pca.transform(samples[burn::thin,:])

# Constrain attention to just the target class this time
i=2
plt.scatter(*X_r[y==i,:].T, c='k', marker='x')
plt.scatter(*X_s.T, c='g', alpha=0.3)
#plt.colorbar()
plt.show()


sns.kdeplot(X_s, cmap=sns.dark_palette('green', as_cmap=True))
plt.scatter(*X_r[y==i,:].T, c='k', marker='x')
plt.show()

entrez la description de l'image ici

entrez la description de l'image ici

C'est certainement une amélioration significative et le mode de notre distribution correspond à peu près à ce que nous recherchons, mais il est clair que nous générons encore beaucoup d'observations qui ne correspondent pas aux valeurs réalisables de donc nous ne devrions pas vraiment faites confiance à cette distribution non plus.X

La solution évidente ici est d'incorporer manière ou d'une autre pour ancrer notre processus d'échantillonnage aux régions de l'espace caractéristique que les données sont susceptibles de prendre. Prenons donc un échantillon de la probabilité conjointe de la probabilité donnée par le modèle, , et une estimation numérique de donnée par un ajustement KDE sur l'ensemble de données entier. Alors maintenant, nous ... échantillonnage à partir de ... ....P(X)P(Y|X)P(X)P(Y|X)P(X)

Entrez la règle de Bayes

Après que vous m'ayez harcelé pour être moins agité avec les maths ici, j'ai beaucoup joué avec cela (donc je construis la GenerativeSamplerchose), et j'ai rencontré les problèmes que j'ai exposés ci-dessus. Je me sentais vraiment, vraiment stupide quand j'ai fait cette prise de conscience, mais évidemment ce que vous demandez appelle une application de la règle de Bayes et je m'excuse d'être dédaigneux plus tôt.

Si vous n'êtes pas familier avec la règle bayes, cela ressemble à ceci:

P(B|A)=P(A|B)P(B)P(A)

Dans de nombreuses applications, le dénominateur est une constante qui agit comme un terme d'échelle pour garantir que le numérateur s'intègre à 1, de sorte que la règle est souvent reformulée ainsi:

P(B|A)P(A|B)P(B)

Ou en langage simple: "le postérieur est proportionnel aux temps antérieurs à la probabilité".

Semble familier? Et maintenant:

P(X|Y)P(Y|X)P(X)

Oui, c'est exactement ce que nous avons travaillé plus tôt en construisant une estimation pour le MLE qui est ancrée à la distribution observée des données. Je n'ai jamais pensé à la règle Bayes de cette façon, mais cela a du sens, alors merci de me donner l'opportunité de découvrir cette nouvelle perspective.

Pour revenir en arrière un peu, MCMC est l'une de ces applications de la règle bayésienne où nous pouvons ignorer le dénominateur. Lorsque nous calculons le ratio d'acceptation, prendra la même valeur à la fois au numérateur et au dénominateur, annulant et nous permettant de tirer des échantillons de distributions de probabilité non normalisées.P(Y)

Donc, après avoir fait cette idée que nous devons incorporer un prior pour les données, faisons-le en ajustant un KDE standard et voyons comment cela change notre résultat.

np.random.seed(123)
sampler = GenerativeSampler(model=RFC, X=X, y=y, 
                            target_class=2, 
                            prior='kde',         # <-- the new hotness
                            class_err_prob=0.05,
                            rw_std=.05,          # <-- back to the random walk proposal
                            verbose=True, 
                            use_empirical=False)
samples, _ = sampler.run_chain(n=5000)

burn = 1000
thin = 20
X_s = pca.transform(samples[burn::thin,:])

# Plot the iris data
col=['r','b','g']
for i in range(3):
    plt.scatter(*X_r[y==i,:].T, c=col[i], marker='x')
plt.plot(*X_s.T, 'k--')
plt.scatter(*X_s.T, c=np.arange(X_s.shape[0]), alpha=0.2)
plt.colorbar()
plt.show()

entrez la description de l'image ici

Bien mieux! Maintenant, nous pouvons estimer votre valeur "optimale" en utilisant ce qu'on appelle l'estimation "maximum a posteriori", ce qui est une façon élégante de dire que nous ajustons un deuxième KDE - mais à nos échantillons cette fois - et de trouver la valeur qui maximise le KDE, c'est-à-dire la valeur correspondant au mode de .P ( X | Y )XP(X|Y)

# MAP estimation

from sklearn.neighbors import KernelDensity
from sklearn.model_selection import GridSearchCV
from scipy.optimize import minimize

grid = GridSearchCV(KernelDensity(), {'bandwidth': np.linspace(0.1, 1.0, 30)}, cv=10, refit=True)
kde = grid.fit(samples[burn::thin,:]).best_estimator_

def map_objective(x):
    try:
        score = kde.score_samples(x)
    except ValueError:
        score = kde.score_samples(x.reshape(1,-1))
    return -score

x_map = minimize(map_objective, samples[-1,:].reshape(1,-1)).x

print(x_map)

x_map_r = pca.transform(x_map.reshape(1,-1))[0]
col=['r','b','g']
for i in range(3):
    plt.scatter(*X_r[y==i,:].T, c=col[i], marker='x')
sns.kdeplot(*X_s.T, cmap=sns.dark_palette('green', as_cmap=True))
plt.scatter(x_map_r[0], x_map_r[1], c='k', marker='x', s=150)
plt.show()

entrez la description de l'image ici

Et voilà: le grand «X» noir est notre estimation MAP (ces contours sont le KDE du postérieur).

David Marx
la source
Merci pour votre réponse. J'ai une question. alpha = np.min ([f (nouveau) / f (ancien), 1]) ..... ici f (nouveau) est P (Y = 0 | X = nouveau) car nous utilisons model.predict_proba qui donne distribution de Y étant donné X ...... mais de en.wikipedia.org/wiki/Metropolis –Hastings_algorithm ce que je pourrais comprendre est alpha devrait être min (P (X = nouveau | y = 0) / P (X = ancien | y = 0), 1). Ai-je mal compris quelque chose?
claudius
Vous avez également mentionné dans la note TLDR "Utilisez MCMC pour générer des échantillons à partir de p (X | Y) en évaluant les valeurs X candidates par rapport à la probabilité conditionnelle de classe fournie par votre modèle." Mais model.predict_proba ne donne-t-il pas une probabilité de classe donnée X. Comment pouvez-vous dire P (X1 | Y = 0)> P (X2 | Y = 0) juste parce que model.predict_proba (X1) [0,0]> model .predict_proba (X2) [0,0]. J'ai lu la relation de model.predict_proba comme P (Y = 0 | X1)> P (Y = 0 | X2). s'il vous plaît laissez-moi savoir où je me trompe.
claudius
Une autre question de suivi ... Quelle est la fonction de distribution symétrique des propositions ici? Merci David de m'avoir aidé !!
claudius
La proposition symétrique est une marche aléatoire gaussienne. Je prévois de mettre à jour cela bientôt avec une démo d'une fonction "empirique". En ce qui concerne les mathématiques MCMC, ne vous y attardez pas trop. En maintenant Y fixe et en exécutant X candidats contre p (Y | X), le MCMC se rapproche du MLE pour X dans p (Y = 0 | X), c'est-à-dire que la fonction que j'échantillonne ici n'est pas p (Y | X ) (sinon je générerais une séquence d'étiquettes de classe), c'est L (X; Y). Cela me donne effectivement une distribution sur p (X | Y = 0). La fonction de notation dans le rapport de la métropole est p (Y | X), mais la façon dont je l'utilise produit des échantillons à partir de p (X | Y).
David Marx
Salut David. Pouvez-vous s'il vous plaît écrire les mathématiques pour cela. J'ai du mal à me convaincre des mathématiques. J'ai vérifié votre profil pour constater que vous êtes diplômé en statistique. Veuillez développer vos points pour aider de simples mortels comme moi: P. Surtout "En maintenant Y fixe et en exécutant X candidats contre p (Y | X), le MCMC se rapproche du MLE pour X dans p (Y = 0 | X), c'est-à-dire que la fonction que j'échantillonne d'ici n'est pas p (Y | X) (sinon je générerais une séquence d'étiquettes de classe), c'est L (X; Y). Cela me donne effectivement une distribution sur p (X | Y = 0). "Merci d'avance!
claudius
0

Une façon d'aller de l'avant pourrait être:

Créez un réseau de neurones à action directe qui, étant donné Y (vous voulez probablement le normaliser), prédit le X. Ainsi, la sortie du modèle (la dernière couche) serait un ensemble de neurones softmax pour chaque entité. Donc, si la fonction 1 (par exemple la couleur) a 4 options, vous appliquerez le softmax sur quatre neurones, et ferez de même pour chaque fonction.

Votre fonction de perte pourrait alors être la somme (ou une combinaison linéaire si vous préférez) de l'entropie croisée pour chaque caractéristique.

Escachator
la source
merci pour votre réponse! Mais, je cherche une réponse qui suggère plusieurs approches et mentionne les avantages et les inconvénients de chaque approche.
claudius